svn commit: r362358 - in head: sbin/newfs stand/libsa sys/geom/journal sys/geom/label sys/ufs/ffs usr.sbin/fstyp usr.sbin/quot

Kirk McKusick mckusick at FreeBSD.org
Fri Jun 19 01:02:56 UTC 2020


Author: mckusick
Date: Fri Jun 19 01:02:53 2020
New Revision: 362358
URL: https://svnweb.freebsd.org/changeset/base/362358

Log:
  Move the pointers stored in the superblock into a separate
  fs_summary_info structure. This change was originally done
  by the CheriBSD project as they need larger pointers that
  do not fit in the existing superblock.
  
  This cleanup of the superblock eases the task of the commit
  that immediately follows this one.
  
  Suggested by: brooks
  Reviewed by:  kib
  PR:           246983
  Sponsored by: Netflix

Modified:
  head/sbin/newfs/mkfs.c
  head/stand/libsa/ufs.c
  head/sys/geom/journal/g_journal_ufs.c
  head/sys/geom/label/g_label_ufs.c
  head/sys/ufs/ffs/ffs_snapshot.c
  head/sys/ufs/ffs/ffs_subr.c
  head/sys/ufs/ffs/ffs_vfsops.c
  head/sys/ufs/ffs/fs.h
  head/usr.sbin/fstyp/ufs.c
  head/usr.sbin/quot/quot.c

Modified: head/sbin/newfs/mkfs.c
==============================================================================
--- head/sbin/newfs/mkfs.c	Fri Jun 19 00:45:29 2020	(r362357)
+++ head/sbin/newfs/mkfs.c	Fri Jun 19 01:02:53 2020	(r362358)
@@ -134,6 +134,10 @@ mkfs(struct partition *pp, char *fsys)
 		utime = 1000000000;
 	else
 		time(&utime);
+	if ((sblock.fs_si = malloc(sizeof(struct fs_summary_info))) == NULL) {
+		printf("Superblock summary info allocation failed.\n");
+		exit(18);
+	}
 	sblock.fs_old_flags = FS_FLAGS_UPDATED;
 	sblock.fs_flags = 0;
 	if (Uflag)
@@ -548,6 +552,10 @@ restart:
 			}
 		}
 	}
+	/*
+	 * Reference the summary information so it will also be written.
+	 */
+	sblock.fs_csp = fscs;
 	if (!Nflag && sbput(disk.d_fd, &disk.d_fs, 0) != 0)
 		err(1, "sbput: %s", disk.d_error);
 	if (Xflag == 1) {
@@ -611,10 +619,6 @@ restart:
 		printf("** Exiting on Xflag 3\n");
 		exit(0);
 	}
-	/*
-	 * Reference the summary information so it will also be written.
-	 */
-	sblock.fs_csp = fscs;
 	if (sbput(disk.d_fd, &disk.d_fs, 0) != 0)
 		err(1, "sbput: %s", disk.d_error);
 	/*

Modified: head/stand/libsa/ufs.c
==============================================================================
--- head/stand/libsa/ufs.c	Fri Jun 19 00:45:29 2020	(r362357)
+++ head/stand/libsa/ufs.c	Fri Jun 19 01:02:53 2020	(r362358)
@@ -678,7 +678,11 @@ out:
 	if (rc) {
 		if (fp->f_buf)
 			free(fp->f_buf);
-		free(fp->f_fs);
+		if (fp->f_fs != NULL) {
+			free(fp->f_fs->fs_csp);
+			free(fp->f_fs->fs_si);
+			free(fp->f_fs);
+		}
 		free(fp);
 	}
 	return (rc);
@@ -723,7 +727,11 @@ ufs_close(f)
 	}
 	if (fp->f_buf)
 		free(fp->f_buf);
-	free(fp->f_fs);
+	if (fp->f_fs != NULL) {
+		free(fp->f_fs->fs_csp);
+		free(fp->f_fs->fs_si);
+		free(fp->f_fs);
+	}
 	free(fp);
 	return (0);
 }

Modified: head/sys/geom/journal/g_journal_ufs.c
==============================================================================
--- head/sys/geom/journal/g_journal_ufs.c	Fri Jun 19 00:45:29 2020	(r362357)
+++ head/sys/geom/journal/g_journal_ufs.c	Fri Jun 19 01:02:53 2020	(r362358)
@@ -68,6 +68,7 @@ g_journal_ufs_clean(struct mount *mp)
 static void
 g_journal_ufs_dirty(struct g_consumer *cp)
 {
+	struct fs_summary_info *fs_si;
 	struct fs *fs;
 	int error;
 
@@ -83,8 +84,12 @@ g_journal_ufs_dirty(struct g_consumer *cp)
 	GJ_DEBUG(0, "clean=%d flags=0x%x", fs->fs_clean, fs->fs_flags);
 	fs->fs_clean = 0;
 	fs->fs_flags |= FS_NEEDSFSCK | FS_UNCLEAN;
+	fs_si = fs->fs_si;
+	fs->fs_si = NULL;
 	error = ffs_sbput(cp, fs, fs->fs_sblockloc, g_use_g_write_data);
+	fs->fs_si = fs_si;
 	g_free(fs->fs_csp);
+	g_free(fs->fs_si);
 	g_free(fs);
 	if (error != 0) {
 		GJ_DEBUG(0, "Cannot mark file system %s as dirty "

Modified: head/sys/geom/label/g_label_ufs.c
==============================================================================
--- head/sys/geom/label/g_label_ufs.c	Fri Jun 19 00:45:29 2020	(r362357)
+++ head/sys/geom/label/g_label_ufs.c	Fri Jun 19 01:02:53 2020	(r362358)
@@ -122,6 +122,7 @@ g_label_ufs_taste_common(struct g_consumer *cp, char *
 	}
 out:
 	g_free(fs->fs_csp);
+	g_free(fs->fs_si);
 	g_free(fs);
 }
 

Modified: head/sys/ufs/ffs/ffs_snapshot.c
==============================================================================
--- head/sys/ufs/ffs/ffs_snapshot.c	Fri Jun 19 00:45:29 2020	(r362357)
+++ head/sys/ufs/ffs/ffs_snapshot.c	Fri Jun 19 01:02:53 2020	(r362358)
@@ -480,6 +480,8 @@ restart:
 	 */
 	copy_fs = malloc((u_long)fs->fs_bsize, M_UFSMNT, M_WAITOK);
 	bcopy(fs, copy_fs, fs->fs_sbsize);
+	copy_fs->fs_si = malloc(sizeof(struct fs_summary_info), M_UFSMNT,
+	    M_ZERO | M_WAITOK);
 	if ((fs->fs_flags & (FS_UNCLEAN | FS_NEEDSFSCK)) == 0)
 		copy_fs->fs_clean = 1;
 	size = fs->fs_bsize < SBLOCKSIZE ? fs->fs_bsize : SBLOCKSIZE;
@@ -501,6 +503,7 @@ restart:
 		    len, KERNCRED, &bp)) != 0) {
 			brelse(bp);
 			free(copy_fs->fs_csp, M_UFSMNT);
+			free(copy_fs->fs_si, M_UFSMNT);
 			free(copy_fs, M_UFSMNT);
 			copy_fs = NULL;
 			goto out1;
@@ -611,6 +614,7 @@ loop:
 		vdrop(xvp);
 		if (error) {
 			free(copy_fs->fs_csp, M_UFSMNT);
+			free(copy_fs->fs_si, M_UFSMNT);
 			free(copy_fs, M_UFSMNT);
 			copy_fs = NULL;
 			MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
@@ -624,6 +628,7 @@ loop:
 		error = softdep_journal_lookup(mp, &xvp);
 		if (error) {
 			free(copy_fs->fs_csp, M_UFSMNT);
+			free(copy_fs->fs_si, M_UFSMNT);
 			free(copy_fs, M_UFSMNT);
 			copy_fs = NULL;
 			goto out1;
@@ -842,6 +847,7 @@ out1:
 	}
 done:
 	free(copy_fs->fs_csp, M_UFSMNT);
+	free(copy_fs->fs_si, M_UFSMNT);
 	free(copy_fs, M_UFSMNT);
 	copy_fs = NULL;
 out:

Modified: head/sys/ufs/ffs/ffs_subr.c
==============================================================================
--- head/sys/ufs/ffs/ffs_subr.c	Fri Jun 19 00:45:29 2020	(r362357)
+++ head/sys/ufs/ffs/ffs_subr.c	Fri Jun 19 01:02:53 2020	(r362358)
@@ -158,6 +158,7 @@ ffs_sbget(void *devfd, struct fs **fsp, off_t altsbloc
     int (*readfunc)(void *devfd, off_t loc, void **bufp, int size))
 {
 	struct fs *fs;
+	struct fs_summary_info *fs_si;
 	int i, error, size, blks;
 	uint8_t *space;
 	int32_t *lp;
@@ -201,7 +202,14 @@ ffs_sbget(void *devfd, struct fs **fsp, off_t altsbloc
 		size += fs->fs_ncg * sizeof(int32_t);
 	size += fs->fs_ncg * sizeof(u_int8_t);
 	/* When running in libufs or libsa, UFS_MALLOC may fail */
+	if ((fs_si = UFS_MALLOC(sizeof(*fs_si), filltype, M_WAITOK)) == NULL) {
+		UFS_FREE(fs, filltype);
+		return (ENOSPC);
+	}
+	bzero(fs_si, sizeof(*fs_si));
+	fs->fs_si = fs_si;
 	if ((space = UFS_MALLOC(size, filltype, M_WAITOK)) == NULL) {
+		UFS_FREE(fs->fs_si, filltype);
 		UFS_FREE(fs, filltype);
 		return (ENOSPC);
 	}
@@ -217,6 +225,7 @@ ffs_sbget(void *devfd, struct fs **fsp, off_t altsbloc
 			if (buf != NULL)
 				UFS_FREE(buf, filltype);
 			UFS_FREE(fs->fs_csp, filltype);
+			UFS_FREE(fs->fs_si, filltype);
 			UFS_FREE(fs, filltype);
 			return (error);
 		}
@@ -299,7 +308,7 @@ readsuper(void *devfd, struct fs **fsp, off_t sblocklo
 		/* Have to set for old filesystems that predate this field */
 		fs->fs_sblockactualloc = sblockloc;
 		/* Not yet any summary information */
-		fs->fs_csp = NULL;
+		fs->fs_si = NULL;
 		return (0);
 	}
 	return (ENOENT);
@@ -325,7 +334,7 @@ ffs_sbput(void *devfd, struct fs *fs, off_t loc,
 	 * If there is summary information, write it first, so if there
 	 * is an error, the superblock will not be marked as clean.
 	 */
-	if (fs->fs_csp != NULL) {
+	if (fs->fs_si != NULL && fs->fs_csp != NULL) {
 		blks = howmany(fs->fs_cssize, fs->fs_fsize);
 		space = (uint8_t *)fs->fs_csp;
 		for (i = 0; i < blks; i += fs->fs_frag) {

Modified: head/sys/ufs/ffs/ffs_vfsops.c
==============================================================================
--- head/sys/ufs/ffs/ffs_vfsops.c	Fri Jun 19 00:45:29 2020	(r362357)
+++ head/sys/ufs/ffs/ffs_vfsops.c	Fri Jun 19 01:02:53 2020	(r362358)
@@ -885,14 +885,11 @@ ffs_reload(struct mount *mp, struct thread *td, int fl
 			return (EIO);		/* XXX needs translation */
 	}
 	/*
-	 * Copy pointer fields back into superblock before copying in	XXX
-	 * new superblock. These should really be in the ufsmount.	XXX
-	 * Note that important parameters (eg fs_ncg) are unchanged.
+	 * Preserve the summary information, read-only status, and
+	 * superblock location by copying these fields into our new
+	 * superblock before using it to update the existing superblock.
 	 */
-	newfs->fs_csp = fs->fs_csp;
-	newfs->fs_maxcluster = fs->fs_maxcluster;
-	newfs->fs_contigdirs = fs->fs_contigdirs;
-	newfs->fs_active = fs->fs_active;
+	newfs->fs_si = fs->fs_si;
 	newfs->fs_ronly = fs->fs_ronly;
 	sblockloc = fs->fs_sblockloc;
 	bcopy(newfs, fs, (u_int)fs->fs_sbsize);
@@ -1309,6 +1306,7 @@ ffs_mountfs(odevvp, mp, td)
 out:
 	if (fs != NULL) {
 		free(fs->fs_csp, M_UFSMNT);
+		free(fs->fs_si, M_UFSMNT);
 		free(fs, M_UFSMNT);
 	}
 	if (cp != NULL) {
@@ -1546,6 +1544,7 @@ ffs_unmount(mp, mntflags)
 		mp->mnt_gjprovider = NULL;
 	}
 	free(fs->fs_csp, M_UFSMNT);
+	free(fs->fs_si, M_UFSMNT);
 	free(fs, M_UFSMNT);
 	if (ump->um_fsfail_task != NULL)
 		free(ump->um_fsfail_task, M_UFSMNT);
@@ -2294,10 +2293,7 @@ ffs_use_bwrite(void *devfd, off_t loc, void *buf, int 
 	bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
 	fs = (struct fs *)bp->b_data;
 	ffs_oldfscompat_write(fs, ump);
-	/*
-	 * Because we may have made changes to the superblock, we need to
-	 * recompute its check-hash.
-	 */
+	/* Recalculate the superblock hash */
 	fs->fs_ckhash = ffs_calc_sbhash(fs);
 	if (devfdp->suspended)
 		bp->b_flags |= B_VALIDSUSPWRT;

Modified: head/sys/ufs/ffs/fs.h
==============================================================================
--- head/sys/ufs/ffs/fs.h	Fri Jun 19 00:45:29 2020	(r362357)
+++ head/sys/ufs/ffs/fs.h	Fri Jun 19 01:02:53 2020	(r362358)
@@ -132,16 +132,18 @@
  * of pointers to blocks of struct csum; now there are just a few
  * pointers and the remaining space is padded with fs_ocsp[].
  *
- * NOCSPTRS determines the size of this padding. One pointer (fs_csp)
- * is taken away to point to a contiguous array of struct csum for
- * all cylinder groups; a second (fs_maxcluster) points to an array
- * of cluster sizes that is computed as cylinder groups are inspected,
- * and the third points to an array that tracks the creation of new
- * directories. A fourth pointer, fs_active, is used when creating
- * snapshots; it points to a bitmap of cylinder groups for which the
- * free-block bitmap has changed since the snapshot operation began.
+ * NOCSPTRS determines the size of this padding. Historically this
+ * space was used to store pointers to structures that summaried
+ * filesystem usage and layout information. However, these pointers
+ * left various kernel pointers in the superblock which made otherwise
+ * identical superblocks appear to have differences. So, all the
+ * pointers in the superblock were moved to a fs_summary_info structure
+ * reducing the superblock to having only a single pointer to this
+ * structure. When writing the superblock to disk, this pointer is
+ * temporarily NULL'ed out so that the kernel pointer will not appear
+ * in the on-disk copy of the superblock.
  */
-#define	NOCSPTRS	((128 / sizeof(void *)) - 4)
+#define	NOCSPTRS	((128 / sizeof(void *)) - 1)
 
 /*
  * A summary of contiguous blocks of various sizes is maintained
@@ -270,6 +272,32 @@ struct csum_total {
 };
 
 /*
+ * Pointers to super block summary information. Placed in a separate
+ * structure so there is just one pointer in the superblock.
+ *
+ * The pointers in this structure are used as follows:
+ *   fs_contigdirs references an array that tracks the creation of new
+ *	directories
+ *   fs_csp references a contiguous array of struct csum for
+ *	all cylinder groups
+ *   fs_maxcluster references an array of cluster sizes that is computed
+ *	as cylinder groups are inspected
+ *   fs_active is used when creating snapshots; it points to a bitmap
+ *	of cylinder groups for which the free-block bitmap has changed
+ *	since the snapshot operation began.
+ */
+struct fs_summary_info {
+	uint8_t	*si_contigdirs;		/* (u) # of contig. allocated dirs */
+	struct	csum *si_csp;		/* (u) cg summary info buffer */
+	int32_t	*si_maxcluster;		/* (u) max cluster in each cyl group */
+	u_int	*si_active;		/* (u) used by snapshots to track fs */
+};
+#define fs_contigdirs	fs_si->si_contigdirs
+#define fs_csp		fs_si->si_csp
+#define fs_maxcluster	fs_si->si_maxcluster
+#define fs_active	fs_si->si_active
+
+/*
  * Super block for an FFS filesystem.
  */
 struct fs {
@@ -340,10 +368,7 @@ struct fs {
 /* these fields retain the current block allocation info */
 	int32_t	 fs_cgrotor;		/* last cg searched */
 	void 	*fs_ocsp[NOCSPTRS];	/* padding; was list of fs_cs buffers */
-	u_int8_t *fs_contigdirs;	/* (u) # of contig. allocated dirs */
-	struct	csum *fs_csp;		/* (u) cg summary info buffer */
-	int32_t	*fs_maxcluster;		/* (u) max cluster in each cyl group */
-	u_int	*fs_active;		/* (u) used by snapshots to track fs */
+	struct	 fs_summary_info *fs_si;/* In-core pointer to summary info */
 	int32_t	 fs_old_cpc;		/* cyl per cycle in postbl */
 	int32_t	 fs_maxbsize;		/* maximum blocking factor permitted */
 	int64_t	 fs_unrefs;		/* number of unreferenced inodes */

Modified: head/usr.sbin/fstyp/ufs.c
==============================================================================
--- head/usr.sbin/fstyp/ufs.c	Fri Jun 19 00:45:29 2020	(r362357)
+++ head/usr.sbin/fstyp/ufs.c	Fri Jun 19 01:02:53 2020	(r362358)
@@ -53,6 +53,9 @@ fstyp_ufs(FILE *fp, char *label, size_t labelsize)
 	switch (sbget(fileno(fp), &fs, STDSB)) {
 	case 0:
 		strlcpy(label, fs->fs_volname, labelsize);
+		free(fs->fs_csp);
+		free(fs->fs_si);
+		free(fs);
 		return (0);
 	case ENOENT:
 		/* Cannot find file system superblock */

Modified: head/usr.sbin/quot/quot.c
==============================================================================
--- head/usr.sbin/quot/quot.c	Fri Jun 19 00:45:29 2020	(r362357)
+++ head/usr.sbin/quot/quot.c	Fri Jun 19 01:02:53 2020	(r362358)
@@ -567,6 +567,9 @@ quot(char *name, char *mp)
 		printf(" (%s)",mp);
 	putchar('\n');
 	(*func)(fd, fs, name);
+	free(fs->fs_csp);
+	free(fs->fs_si);
+	free(fs);
 	close(fd);
 }
 


More information about the svn-src-head mailing list