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)
This commit is contained in:
Kirk McKusick 2025-03-19 16:32:39 -07:00
parent ff9c290648
commit ae15f8ceaa
2 changed files with 86 additions and 68 deletions

View file

@ -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);
}

View file

@ -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