git: ae15f8ceaa85 - stable/14 - Get consistent updates for UFS superblocks. Formatting and style cleanups.

From: Kirk McKusick <mckusick_at_FreeBSD.org>
Date: Sat, 29 Mar 2025 00:43:41 UTC
The branch stable/14 has been updated by mckusick:

URL: https://cgit.FreeBSD.org/src/commit/?id=ae15f8ceaa85e6e02e056aa151d965d82e1f200e

commit ae15f8ceaa85e6e02e056aa151d965d82e1f200e
Author:     Kirk McKusick <mckusick@FreeBSD.org>
AuthorDate: 2025-03-19 23:32:39 +0000
Commit:     Kirk McKusick <mckusick@FreeBSD.org>
CommitDate: 2025-03-29 00:41:04 +0000

    Get consistent updates for UFS superblocks.
    Formatting and style cleanups.
    
    Differential Revision: https://reviews.freebsd.org/D49276
    Sponsored-by: Netflix
    
    (cherry picked from commit c2cd605e8c8a15e545dfd3e50aef2f660d460b30)
    (cherry picked from commit 16649530b7be02a61a32b34d56e6e937734cd247)
---
 sys/ufs/ffs/ffs_subr.c   | 112 +++++++++++++++++++++++++++++------------------
 sys/ufs/ffs/ffs_vfsops.c |  42 +++++++-----------
 2 files changed, 86 insertions(+), 68 deletions(-)

diff --git a/sys/ufs/ffs/ffs_subr.c b/sys/ufs/ffs/ffs_subr.c
index c0221c8ee2da..7a010da870db 100644
--- a/sys/ufs/ffs/ffs_subr.c
+++ b/sys/ufs/ffs/ffs_subr.c
@@ -343,31 +343,36 @@ ffs_oldfscompat_read(struct fs *fs, ufs2_daddr_t sblockloc)
 		fs->fs_old_flags |= FS_FLAGS_UPDATED;
 		fs->fs_sblockloc = sblockloc;
 	}
-	/*
-	 * If not yet done, update UFS1 superblock with new wider fields.
-	 */
-	if (fs->fs_magic == FS_UFS1_MAGIC && fs->fs_maxbsize != fs->fs_bsize) {
-		fs->fs_maxbsize = fs->fs_bsize;
-		fs->fs_time = fs->fs_old_time;
-		fs->fs_size = fs->fs_old_size;
-		fs->fs_dsize = fs->fs_old_dsize;
-		fs->fs_csaddr = fs->fs_old_csaddr;
-		fs->fs_cstotal.cs_ndir = fs->fs_old_cstotal.cs_ndir;
-		fs->fs_cstotal.cs_nbfree = fs->fs_old_cstotal.cs_nbfree;
-		fs->fs_cstotal.cs_nifree = fs->fs_old_cstotal.cs_nifree;
-		fs->fs_cstotal.cs_nffree = fs->fs_old_cstotal.cs_nffree;
-	}
-	if (fs->fs_magic == FS_UFS1_MAGIC &&
-	    fs->fs_old_inodefmt < FS_44INODEFMT) {
-		fs->fs_maxfilesize = ((uint64_t)1 << 31) - 1;
-		fs->fs_qbmask = ~fs->fs_bmask;
-		fs->fs_qfmask = ~fs->fs_fmask;
-	}
-	if (fs->fs_magic == FS_UFS1_MAGIC) {
+	switch (fs->fs_magic) {
+	case FS_UFS2_MAGIC:
+		/* No changes for now */
+		break;
+
+	case FS_UFS1_MAGIC:
+		/*
+		 * If not yet done, update UFS1 superblock with new wider fields
+		 */
+		if (fs->fs_maxbsize != fs->fs_bsize) {
+			fs->fs_maxbsize = fs->fs_bsize;
+			fs->fs_time = fs->fs_old_time;
+			fs->fs_size = fs->fs_old_size;
+			fs->fs_dsize = fs->fs_old_dsize;
+			fs->fs_csaddr = fs->fs_old_csaddr;
+			fs->fs_cstotal.cs_ndir = fs->fs_old_cstotal.cs_ndir;
+			fs->fs_cstotal.cs_nbfree = fs->fs_old_cstotal.cs_nbfree;
+			fs->fs_cstotal.cs_nifree = fs->fs_old_cstotal.cs_nifree;
+			fs->fs_cstotal.cs_nffree = fs->fs_old_cstotal.cs_nffree;
+		}
+		if (fs->fs_old_inodefmt < FS_44INODEFMT) {
+			fs->fs_maxfilesize = ((uint64_t)1 << 31) - 1;
+			fs->fs_qbmask = ~fs->fs_bmask;
+			fs->fs_qfmask = ~fs->fs_fmask;
+		}
 		fs->fs_save_maxfilesize = fs->fs_maxfilesize;
 		maxfilesize = (uint64_t)0x80000000 * fs->fs_bsize - 1;
 		if (fs->fs_maxfilesize > maxfilesize)
 			fs->fs_maxfilesize = maxfilesize;
+		break;
 	}
 	/* Compatibility for old filesystems */
 	if (fs->fs_avgfilesize <= 0)
@@ -387,16 +392,35 @@ void
 ffs_oldfscompat_write(struct fs *fs)
 {
 
-	/*
-	 * Copy back UFS2 updated fields that UFS1 inspects.
-	 */
-	if (fs->fs_magic == FS_UFS1_MAGIC) {
+	switch (fs->fs_magic) {
+	case FS_UFS1_MAGIC:
+		if (fs->fs_sblockloc != SBLOCK_UFS1 &&
+		    (fs->fs_old_flags & FS_FLAGS_UPDATED) == 0) {
+			printf(
+			"WARNING: %s: correcting fs_sblockloc from %jd to %d\n",
+			    fs->fs_fsmnt, fs->fs_sblockloc, SBLOCK_UFS1);
+			fs->fs_sblockloc = SBLOCK_UFS1;
+		}
+		/*
+		 * Copy back UFS2 updated fields that UFS1 inspects.
+		 */
 		fs->fs_old_time = fs->fs_time;
 		fs->fs_old_cstotal.cs_ndir = fs->fs_cstotal.cs_ndir;
 		fs->fs_old_cstotal.cs_nbfree = fs->fs_cstotal.cs_nbfree;
 		fs->fs_old_cstotal.cs_nifree = fs->fs_cstotal.cs_nifree;
 		fs->fs_old_cstotal.cs_nffree = fs->fs_cstotal.cs_nffree;
-		fs->fs_maxfilesize = fs->fs_save_maxfilesize;
+		if (fs->fs_save_maxfilesize != 0)
+			fs->fs_maxfilesize = fs->fs_save_maxfilesize;
+		break;
+	case FS_UFS2_MAGIC:
+		if (fs->fs_sblockloc != SBLOCK_UFS2 &&
+		    (fs->fs_old_flags & FS_FLAGS_UPDATED) == 0) {
+			printf(
+			"WARNING: %s: correcting fs_sblockloc from %jd to %d\n",
+			    fs->fs_fsmnt, fs->fs_sblockloc, SBLOCK_UFS2);
+			fs->fs_sblockloc = SBLOCK_UFS2;
+		}
+		break;
 	}
 }
 
@@ -410,9 +434,8 @@ static int prttimechgs = 0;
 #ifdef _KERNEL
 SYSCTL_NODE(_vfs, OID_AUTO, ffs, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
     "FFS filesystem");
-
 SYSCTL_INT(_vfs_ffs, OID_AUTO, prttimechgs, CTLFLAG_RWTUN, &prttimechgs, 0,
-	"print UFS1 time changes made to inodes");
+    "print UFS1 time changes made to inodes");
 #endif /* _KERNEL */
 bool
 ffs_oldfscompat_inode_read(struct fs *fs, union dinodep dp, time_t now)
@@ -934,6 +957,7 @@ int
 ffs_sbput(void *devfd, struct fs *fs, off_t loc,
     int (*writefunc)(void *devfd, off_t loc, void *buf, int size))
 {
+	struct fs_summary_info *fs_si;
 	int i, error, blks, size;
 	uint8_t *space;
 
@@ -956,23 +980,27 @@ ffs_sbput(void *devfd, struct fs *fs, off_t loc,
 		}
 	}
 	fs->fs_fmod = 0;
-#ifndef _KERNEL
-	{
-		struct fs_summary_info *fs_si;
-
-		fs->fs_time = time(NULL);
-		/* Clear the pointers for the duration of writing. */
-		fs_si = fs->fs_si;
-		fs->fs_si = NULL;
-		fs->fs_ckhash = ffs_calc_sbhash(fs);
-		error = (*writefunc)(devfd, loc, fs, fs->fs_sbsize);
-		fs->fs_si = fs_si;
-	}
-#else /* _KERNEL */
+	ffs_oldfscompat_write(fs);
+#ifdef _KERNEL
 	fs->fs_time = time_second;
+#else /* User Code */
+	fs->fs_time = time(NULL);
+#endif
+	/* Clear the pointers for the duration of writing. */
+	fs_si = fs->fs_si;
+	fs->fs_si = NULL;
 	fs->fs_ckhash = ffs_calc_sbhash(fs);
 	error = (*writefunc)(devfd, loc, fs, fs->fs_sbsize);
-#endif /* _KERNEL */
+	/*
+	 * A negative error code is returned when a copy of the
+	 * superblock has been made which is discarded when the I/O
+	 * is done. So the fs_si field does not and indeed cannot be
+	 * restored after the write is done. Convert the error code
+	 * back to its usual positive value when returning it.
+	 */
+	if (error < 0)
+		return (-error - 1);
+	fs->fs_si = fs_si;
 	return (error);
 }
 
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index eadd5815eaf7..b387fda14588 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -2034,9 +2034,15 @@ ffs_sbupdate(struct ufsmount *ump, int waitfor, int suspended)
 		panic("ffs_sbupdate: write read-only filesystem");
 	/*
 	 * We use the superblock's buf to serialize calls to ffs_sbupdate().
+	 * Copy superblock to this buffer and have it written out.
 	 */
 	sbbp = getblk(ump->um_devvp, btodb(fs->fs_sblockloc),
 	    (int)fs->fs_sbsize, 0, 0, 0);
+	UFS_LOCK(ump);
+	fs->fs_fmod = 0;
+	bcopy((caddr_t)fs, sbbp->b_data, (uint64_t)fs->fs_sbsize);
+	UFS_UNLOCK(ump);
+	fs = (struct fs *)sbbp->b_data;
 	/*
 	 * Initialize info needed for write function.
 	 */
@@ -2062,7 +2068,8 @@ ffs_use_bwrite(void *devfd, off_t loc, void *buf, int size)
 
 	devfdp = devfd;
 	ump = devfdp->ump;
-	fs = ump->um_fs;
+	bp = devfdp->sbbp;
+	fs = (struct fs *)bp->b_data;
 	/*
 	 * Writing the superblock summary information.
 	 */
@@ -2079,44 +2086,27 @@ ffs_use_bwrite(void *devfd, off_t loc, void *buf, int size)
 	}
 	/*
 	 * Writing the superblock itself. We need to do special checks for it.
+	 * A negative error code is returned to indicate that a copy of the
+	 * superblock has been made and that the copy is discarded when the
+	 * I/O is done. So the the caller should not attempt to restore the
+	 * fs_si field after the write is done. The caller will convert the
+	 * error code back to its usual positive value when returning it.
 	 */
-	bp = devfdp->sbbp;
 	if (ffs_fsfail_cleanup(ump, devfdp->error))
 		devfdp->error = 0;
 	if (devfdp->error != 0) {
 		brelse(bp);
-		return (devfdp->error);
-	}
-	if (fs->fs_magic == FS_UFS1_MAGIC && fs->fs_sblockloc != SBLOCK_UFS1 &&
-	    (fs->fs_old_flags & FS_FLAGS_UPDATED) == 0) {
-		printf("WARNING: %s: correcting fs_sblockloc from %jd to %d\n",
-		    fs->fs_fsmnt, fs->fs_sblockloc, SBLOCK_UFS1);
-		fs->fs_sblockloc = SBLOCK_UFS1;
-	}
-	if (fs->fs_magic == FS_UFS2_MAGIC && fs->fs_sblockloc != SBLOCK_UFS2 &&
-	    (fs->fs_old_flags & FS_FLAGS_UPDATED) == 0) {
-		printf("WARNING: %s: correcting fs_sblockloc from %jd to %d\n",
-		    fs->fs_fsmnt, fs->fs_sblockloc, SBLOCK_UFS2);
-		fs->fs_sblockloc = SBLOCK_UFS2;
+		return (-devfdp->error - 1);
 	}
 	if (MOUNTEDSOFTDEP(ump->um_mountp))
-		softdep_setup_sbupdate(ump, (struct fs *)bp->b_data, bp);
-	UFS_LOCK(ump);
-	bcopy((caddr_t)fs, bp->b_data, (uint64_t)fs->fs_sbsize);
-	UFS_UNLOCK(ump);
-	fs = (struct fs *)bp->b_data;
-	fs->fs_fmod = 0;
-	ffs_oldfscompat_write(fs);
-	fs->fs_si = NULL;
-	/* Recalculate the superblock hash */
-	fs->fs_ckhash = ffs_calc_sbhash(fs);
+		softdep_setup_sbupdate(ump, fs, bp);
 	if (devfdp->suspended)
 		bp->b_flags |= B_VALIDSUSPWRT;
 	if (devfdp->waitfor != MNT_WAIT)
 		bawrite(bp);
 	else if ((error = bwrite(bp)) != 0)
 		devfdp->error = error;
-	return (devfdp->error);
+	return (-devfdp->error - 1);
 }
 
 static int