git: 6a356edd4fc3 - stable/13 - Fix backward compatibility with UFS1 filesystems created before June 2002
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 25 Jan 2025 21:11:00 UTC
The branch stable/13 has been updated by mckusick:
URL: https://cgit.FreeBSD.org/src/commit/?id=6a356edd4fc3c8d7959fcc6a2447c7193d830392
commit 6a356edd4fc3c8d7959fcc6a2447c7193d830392
Author: Kirk McKusick <mckusick@FreeBSD.org>
AuthorDate: 2025-01-16 18:43:48 +0000
Commit: Kirk McKusick <mckusick@FreeBSD.org>
CommitDate: 2025-01-25 21:10:20 +0000
Fix backward compatibility with UFS1 filesystems created before June 2002
See the Pahabricator review for more details.
Reviewed-by: kib
Tested-by: Peter Holm
Differential-Revision: https://reviews.freebsd.org/D48472
(cherry picked from commit 661ca921e8cd56b17fc6615bc7e596e56e0e7c31)
---
sbin/growfs/debug.c | 2 -
sys/ufs/ffs/ffs_extern.h | 2 +-
sys/ufs/ffs/ffs_snapshot.c | 2 +-
sys/ufs/ffs/ffs_softdep.c | 4 +-
sys/ufs/ffs/ffs_subr.c | 81 +++++++++++++++++++++++++++++++++++++-
sys/ufs/ffs/ffs_vfsops.c | 96 +---------------------------------------------
sys/ufs/ffs/fs.h | 5 ++-
7 files changed, 88 insertions(+), 104 deletions(-)
diff --git a/sbin/growfs/debug.c b/sbin/growfs/debug.c
index 456e67dbc5c2..ab4539d06a69 100644
--- a/sbin/growfs/debug.c
+++ b/sbin/growfs/debug.c
@@ -305,8 +305,6 @@ dbg_dump_fs(struct fs *sb, const char *comment)
sb->fs_avgfilesize);
fprintf(dbg_log, "avgfpdir int32_t 0x%08x\n",
sb->fs_avgfpdir);
- fprintf(dbg_log, "save_cgsize int32_t 0x%08x\n",
- sb->fs_save_cgsize);
fprintf(dbg_log, "flags int32_t 0x%08x\n",
sb->fs_flags);
fprintf(dbg_log, "contigsumsize int32_t 0x%08x\n",
diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h
index 89ef325b87e3..2e9b485d482b 100644
--- a/sys/ufs/ffs/ffs_extern.h
+++ b/sys/ufs/ffs/ffs_extern.h
@@ -84,7 +84,7 @@ int ffs_inotovp(struct mount *, ino_t, uint64_t, int, struct vnode **,
int);
int ffs_isblock(struct fs *, uint8_t *, ufs1_daddr_t);
int ffs_isfreeblock(struct fs *, uint8_t *, ufs1_daddr_t);
-void ffs_oldfscompat_write(struct fs *, struct ufsmount *);
+void ffs_oldfscompat_write(struct fs *);
int ffs_own_mount(const struct mount *mp);
int ffs_reallocblks(struct vop_reallocblks_args *);
int ffs_realloccg(struct inode *, ufs2_daddr_t, ufs2_daddr_t,
diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c
index bc4dbdf52e5b..6e2a8d66b54f 100644
--- a/sys/ufs/ffs/ffs_snapshot.c
+++ b/sys/ufs/ffs/ffs_snapshot.c
@@ -840,7 +840,7 @@ resumefs:
copy_fs->fs_fmod = 0;
bpfs = (struct fs *)&nbp->b_data[loc];
bcopy((caddr_t)copy_fs, (caddr_t)bpfs, (uint64_t)fs->fs_sbsize);
- ffs_oldfscompat_write(bpfs, ump);
+ ffs_oldfscompat_write(bpfs);
bpfs->fs_ckhash = ffs_calc_sbhash(bpfs);
bawrite(nbp);
}
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 62af80d7eb40..e14e333f70bb 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -9932,7 +9932,7 @@ clear_unlinked_inodedep( struct inodedep *inodedep)
if (pino == 0) {
bcopy((caddr_t)fs, bp->b_data, (uint64_t)fs->fs_sbsize);
bpfs = (struct fs *)bp->b_data;
- ffs_oldfscompat_write(bpfs, ump);
+ ffs_oldfscompat_write(bpfs);
softdep_setup_sbupdate(ump, bpfs, bp);
/*
* Because we may have made changes to the superblock,
@@ -9964,7 +9964,7 @@ clear_unlinked_inodedep( struct inodedep *inodedep)
(int)fs->fs_sbsize, 0, 0, 0);
bcopy((caddr_t)fs, bp->b_data, (uint64_t)fs->fs_sbsize);
bpfs = (struct fs *)bp->b_data;
- ffs_oldfscompat_write(bpfs, ump);
+ ffs_oldfscompat_write(bpfs);
softdep_setup_sbupdate(ump, bpfs, bp);
/*
* Because we may have made changes to the superblock,
diff --git a/sys/ufs/ffs/ffs_subr.c b/sys/ufs/ffs/ffs_subr.c
index ca595ed5bd80..351559882ca2 100644
--- a/sys/ufs/ffs/ffs_subr.c
+++ b/sys/ufs/ffs/ffs_subr.c
@@ -130,6 +130,7 @@ ffs_update_dinode_ckhash(struct fs *fs, struct ufs2_dinode *dip)
static off_t sblock_try[] = SBLOCKSEARCH;
static int readsuper(void *, struct fs **, off_t, int, int,
int (*)(void *, off_t, void **, int));
+static void ffs_oldfscompat_read(struct fs *, ufs2_daddr_t);
static int validate_sblock(struct fs *, int);
/*
@@ -273,6 +274,7 @@ readsuper(void *devfd, struct fs **fsp, off_t sblockloc, int isaltsblk,
if (fs->fs_magic == FS_UFS1_MAGIC && !isaltsblk &&
fs->fs_bsize == SBLOCK_UFS2 && sblockloc == SBLOCK_UFS2)
return (ENOENT);
+ ffs_oldfscompat_read(fs, sblockloc);
if ((error = validate_sblock(fs, isaltsblk)) > 0)
return (error);
/*
@@ -317,6 +319,83 @@ readsuper(void *devfd, struct fs **fsp, off_t sblockloc, int isaltsblk,
return (0);
}
+/*
+ * Sanity checks for loading old filesystem superblocks.
+ * See ffs_oldfscompat_write below for unwound actions.
+ *
+ * XXX - Parts get retired eventually.
+ * Unfortunately new bits get added.
+ */
+static void
+ffs_oldfscompat_read(struct fs *fs, ufs2_daddr_t sblockloc)
+{
+ uint64_t maxfilesize;
+
+ /*
+ * If not yet done, update fs_flags location and value of fs_sblockloc.
+ */
+ if ((fs->fs_old_flags & FS_FLAGS_UPDATED) == 0) {
+ fs->fs_flags = fs->fs_old_flags;
+ 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) {
+ fs->fs_save_maxfilesize = fs->fs_maxfilesize;
+ maxfilesize = (uint64_t)0x80000000 * fs->fs_bsize - 1;
+ if (fs->fs_maxfilesize > maxfilesize)
+ fs->fs_maxfilesize = maxfilesize;
+ }
+ /* Compatibility for old filesystems */
+ if (fs->fs_avgfilesize <= 0)
+ fs->fs_avgfilesize = AVFILESIZ;
+ if (fs->fs_avgfpdir <= 0)
+ fs->fs_avgfpdir = AFPDIR;
+}
+
+/*
+ * Unwinding superblock updates for old filesystems.
+ * See ffs_oldfscompat_read above for details.
+ *
+ * XXX - Parts get retired eventually.
+ * Unfortunately new bits get added.
+ */
+void
+ffs_oldfscompat_write(struct fs *fs)
+{
+
+ /*
+ * Copy back UFS2 updated fields that UFS1 inspects.
+ */
+ if (fs->fs_magic == FS_UFS1_MAGIC) {
+ 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;
+ }
+}
+
/*
* Verify the filesystem values.
*/
@@ -482,7 +561,7 @@ validate_sblock(struct fs *fs, int isaltsblk)
sizepb *= NINDIR(fs);
maxfilesize += sizepb;
}
- CHK(fs->fs_maxfilesize, !=, maxfilesize, %jd);
+ CHK(fs->fs_maxfilesize, >, maxfilesize, %jd);
/*
* These values have a tight interaction with each other that
* makes it hard to tightly bound them. So we can only check
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index d97f5413c647..62d63210531a 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -85,8 +85,6 @@ static uma_zone_t uma_inode, uma_ufs1, uma_ufs2;
VFS_SMR_DECLARE;
static int ffs_mountfs(struct vnode *, struct mount *, struct thread *);
-static void ffs_oldfscompat_read(struct fs *, struct ufsmount *,
- ufs2_daddr_t);
static void ffs_ifree(struct ufsmount *ump, struct inode *ip);
static int ffs_sync_lazy(struct mount *mp);
static int ffs_use_bread(void *devfd, off_t loc, void **bufp, int size);
@@ -823,7 +821,6 @@ ffs_reload(struct mount *mp, int flags)
free(fs, M_UFSMNT);
fs = VFSTOUFS(mp)->um_fs = newfs;
ump->um_maxsymlinklen = fs->fs_maxsymlinklen;
- ffs_oldfscompat_read(fs, VFSTOUFS(mp), fs->fs_sblockloc);
UFS_LOCK(ump);
if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
printf("WARNING: %s: reload pending error: blocks %jd "
@@ -1040,7 +1037,6 @@ ffs_mountfs(struct vnode *odevvp, struct mount *mp, struct thread *td)
ump->um_check_blkno = NULL;
mtx_init(UFS_MTX(ump), "FFS", "FFS Lock", MTX_DEF);
sx_init(&ump->um_checkpath_lock, "uchpth");
- ffs_oldfscompat_read(fs, ump, fs->fs_sblockloc);
fs->fs_ronly = ronly;
fs->fs_active = NULL;
mp->mnt_data = ump;
@@ -1251,96 +1247,6 @@ ffs_use_bread(void *devfd, off_t loc, void **bufp, int size)
return (0);
}
-static int bigcgs = 0;
-SYSCTL_INT(_debug, OID_AUTO, bigcgs, CTLFLAG_RW, &bigcgs, 0, "");
-
-/*
- * Sanity checks for loading old filesystem superblocks.
- * See ffs_oldfscompat_write below for unwound actions.
- *
- * XXX - Parts get retired eventually.
- * Unfortunately new bits get added.
- */
-static void
-ffs_oldfscompat_read(struct fs *fs,
- struct ufsmount *ump,
- ufs2_daddr_t sblockloc)
-{
- off_t maxfilesize;
-
- /*
- * If not yet done, update fs_flags location and value of fs_sblockloc.
- */
- if ((fs->fs_old_flags & FS_FLAGS_UPDATED) == 0) {
- fs->fs_flags = fs->fs_old_flags;
- 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) {
- ump->um_savedmaxfilesize = fs->fs_maxfilesize;
- maxfilesize = (uint64_t)0x80000000 * fs->fs_bsize - 1;
- if (fs->fs_maxfilesize > maxfilesize)
- fs->fs_maxfilesize = maxfilesize;
- }
- /* Compatibility for old filesystems */
- if (fs->fs_avgfilesize <= 0)
- fs->fs_avgfilesize = AVFILESIZ;
- if (fs->fs_avgfpdir <= 0)
- fs->fs_avgfpdir = AFPDIR;
- if (bigcgs) {
- fs->fs_save_cgsize = fs->fs_cgsize;
- fs->fs_cgsize = fs->fs_bsize;
- }
-}
-
-/*
- * Unwinding superblock updates for old filesystems.
- * See ffs_oldfscompat_read above for details.
- *
- * XXX - Parts get retired eventually.
- * Unfortunately new bits get added.
- */
-void
-ffs_oldfscompat_write(struct fs *fs, struct ufsmount *ump)
-{
-
- /*
- * Copy back UFS2 updated fields that UFS1 inspects.
- */
- if (fs->fs_magic == FS_UFS1_MAGIC) {
- 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 = ump->um_savedmaxfilesize;
- }
- if (bigcgs) {
- fs->fs_cgsize = fs->fs_save_cgsize;
- fs->fs_save_cgsize = 0;
- }
-}
-
/*
* unmount system call
*/
@@ -2224,7 +2130,7 @@ ffs_use_bwrite(void *devfd, off_t loc, void *buf, int size)
UFS_UNLOCK(ump);
fs = (struct fs *)bp->b_data;
fs->fs_fmod = 0;
- ffs_oldfscompat_write(fs, ump);
+ ffs_oldfscompat_write(fs);
fs->fs_si = NULL;
/* Recalculate the superblock hash */
fs->fs_ckhash = ffs_calc_sbhash(fs);
diff --git a/sys/ufs/ffs/fs.h b/sys/ufs/ffs/fs.h
index cc89df9aca66..1c8890fa94ff 100644
--- a/sys/ufs/ffs/fs.h
+++ b/sys/ufs/ffs/fs.h
@@ -374,7 +374,8 @@ struct fs {
int64_t fs_unrefs; /* number of unreferenced inodes */
int64_t fs_providersize; /* size of underlying GEOM provider */
int64_t fs_metaspace; /* size of area reserved for metadata */
- int64_t fs_sparecon64[13]; /* old rotation block list head */
+ uint64_t fs_save_maxfilesize; /* save old UFS1 maxfilesize */
+ int64_t fs_sparecon64[12]; /* old rotation block list head */
int64_t fs_sblockactualloc; /* byte offset of this superblock */
int64_t fs_sblockloc; /* byte offset of standard superblock */
struct csum_total fs_cstotal; /* (u) cylinder summary information */
@@ -387,7 +388,7 @@ struct fs {
uint32_t fs_snapinum[FSMAXSNAP];/* list of snapshot inode numbers */
uint32_t fs_avgfilesize; /* expected average file size */
uint32_t fs_avgfpdir; /* expected # of files per directory */
- int32_t fs_save_cgsize; /* save real cg size to use fs_bsize */
+ uint32_t fs_available_spare; /* old scratch space */
ufs_time_t fs_mtime; /* Last mount or fsck time. */
int32_t fs_sujfree; /* SUJ free list */
int32_t fs_sparecon32[21]; /* reserved for future constants */