ffs: restore backward compatibility of newfs and makefs with older binaries
The previous change to CGSIZE had the unintended side-effect of allowing
newfs and makefs to create file systems that would fail validation when
examined by older commands and kernels, by allowing newfs/makefs to pack
slightly more blocks into a CG than those older binaries think is valid.
Fix this by having newfs/makefs artificially restrict the number of blocks
in a CG to the slightly smaller value that those older binaries will accept.
The validation code will continue to accept the slightly larger value
that the current newfs/makefs (before this change) could create.
Fixes: 0a6e34e950
Reviewed by: mckusick
MFC after: 3 days
Sponsored by: Netflix
This commit is contained in:
parent
8164032a49
commit
d464a7698d
@ -76,6 +76,23 @@ __FBSDID("$FreeBSD$");
|
||||
#define UMASK 0755
|
||||
#define POWEROF2(num) (((num) & ((num) - 1)) == 0)
|
||||
|
||||
/*
|
||||
* The definition of "struct cg" used to contain an extra field at the end
|
||||
* to represent the variable-length data that followed the fixed structure.
|
||||
* This had the effect of artificially limiting the number of blocks that
|
||||
* newfs would put in a CG, since newfs thought that the fixed-size header
|
||||
* was bigger than it really was. When we started validating that the CG
|
||||
* header data actually fit into one fs block, the placeholder field caused
|
||||
* a problem because it caused struct cg to be a different size depending on
|
||||
* platform. The placeholder field was later removed, but this caused a
|
||||
* backward compatibility problem with older binaries that still thought
|
||||
* struct cg was larger, and a new file system could fail validation if
|
||||
* viewed by the older binaries. To avoid this compatibility problem, we
|
||||
* now artificially reduce the amount of space that the variable-length data
|
||||
* can use such that new file systems will pass validation by older binaries.
|
||||
*/
|
||||
#define CGSIZEFUDGE 8
|
||||
|
||||
static struct csum *fscs;
|
||||
#define sblock disk.d_fs
|
||||
#define acg disk.d_cg
|
||||
@ -369,7 +386,8 @@ mkfs(struct partition *pp, char *fsys)
|
||||
sblock.fs_fpg = minfpg;
|
||||
sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
|
||||
INOPB(&sblock));
|
||||
if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize)
|
||||
if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize -
|
||||
CGSIZEFUDGE)
|
||||
break;
|
||||
density -= sblock.fs_fsize;
|
||||
}
|
||||
@ -388,9 +406,11 @@ mkfs(struct partition *pp, char *fsys)
|
||||
if (Oflag > 1 || (Oflag == 1 && sblock.fs_ipg <= 0x7fff)) {
|
||||
if (sblock.fs_size / sblock.fs_fpg < MINCYLGRPS)
|
||||
break;
|
||||
if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize)
|
||||
if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize -
|
||||
CGSIZEFUDGE)
|
||||
continue;
|
||||
if (CGSIZE(&sblock) == (unsigned long)sblock.fs_bsize)
|
||||
if (CGSIZE(&sblock) == (unsigned long)sblock.fs_bsize -
|
||||
CGSIZEFUDGE)
|
||||
break;
|
||||
}
|
||||
sblock.fs_fpg -= sblock.fs_frag;
|
||||
|
@ -80,6 +80,23 @@ static int count_digits(int);
|
||||
#define UMASK 0755
|
||||
#define POWEROF2(num) (((num) & ((num) - 1)) == 0)
|
||||
|
||||
/*
|
||||
* The definition of "struct cg" used to contain an extra field at the end
|
||||
* to represent the variable-length data that followed the fixed structure.
|
||||
* This had the effect of artificially limiting the number of blocks that
|
||||
* newfs would put in a CG, since newfs thought that the fixed-size header
|
||||
* was bigger than it really was. When we started validating that the CG
|
||||
* header data actually fit into one fs block, the placeholder field caused
|
||||
* a problem because it caused struct cg to be a different size depending on
|
||||
* platform. The placeholder field was later removed, but this caused a
|
||||
* backward compatibility problem with older binaries that still thought
|
||||
* struct cg was larger, and a new file system could fail validation if
|
||||
* viewed by the older binaries. To avoid this compatibility problem, we
|
||||
* now artificially reduce the amount of space that the variable-length data
|
||||
* can use such that new file systems will pass validation by older binaries.
|
||||
*/
|
||||
#define CGSIZEFUDGE 8
|
||||
|
||||
static union {
|
||||
struct fs fs;
|
||||
char pad[SBLOCKSIZE];
|
||||
@ -347,7 +364,8 @@ ffs_mkfs(const char *fsys, const fsinfo_t *fsopts, time_t tstamp)
|
||||
sblock.fs_fpg = minfpg;
|
||||
sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
|
||||
INOPB(&sblock));
|
||||
if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize)
|
||||
if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize -
|
||||
CGSIZEFUDGE)
|
||||
break;
|
||||
density -= sblock.fs_fsize;
|
||||
}
|
||||
@ -366,9 +384,11 @@ ffs_mkfs(const char *fsys, const fsinfo_t *fsopts, time_t tstamp)
|
||||
INOPB(&sblock));
|
||||
if (sblock.fs_size / sblock.fs_fpg < 1)
|
||||
break;
|
||||
if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize)
|
||||
if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize -
|
||||
CGSIZEFUDGE)
|
||||
continue;
|
||||
if (CGSIZE(&sblock) == (unsigned long)sblock.fs_bsize)
|
||||
if (CGSIZE(&sblock) == (unsigned long)sblock.fs_bsize -
|
||||
CGSIZEFUDGE)
|
||||
break;
|
||||
sblock.fs_fpg -= sblock.fs_frag;
|
||||
sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
|
||||
|
Loading…
Reference in New Issue
Block a user