On Sun, Jun 04, 2017 at 06:32:49PM -0400, Theodore Ts'o wrote: > On Sun, Jun 04, 2017 at 10:58:38PM +0100, Al Viro wrote: > > > > ought to calculate the right thing for modern UFS variants; I would > > leave the anything other than UFS_MOUNT_UFSTYPE_44BSD and > > UFS_MOUNT_UFSTYPE_UFS2 alone. > > If anyone wants to spend time worrying about ancient UFS > incompatilities, or wants to find someone who might care, there's the > The Unix Heritage Society mailing list[1]. (Don't bother trying to > post the list without subscribing first, the list is run even more > strictly than DaveM, and postings from people who aren't subscribers > get unceremoniously dropped on the floor.) > > [1] http://minnie.tuhs.org/mailman/listinfo/tuhs > > Among other things, recents discussion on this list discuss security > vulnerabilities (stack buffer overruns, et.al) on V6 and V7 Unix, and > there are people on that list who will bring up historical versions of > Unix on emulators, et. al. > > More seriously, many of UFS variants don't have any way of > distinguishing between what version they are, or are safe to mount on > which version of Unix. There's a reason why ext2/3/4 has rather > feature compatibility masks; UFS demonstrated the joys of what happens > when you don't bother with that kind of compatibility markers in file > systems. So focusing just on what FreeBSD and other modern BSD > implementation use is a completely fair thing to do. The enthusiasts > on TUHS are perfectly capable of sending patches if they care about V6 > Unix <-> Linux compatibility. :-) FFS and derivatives postdate v7, let alone v6, as you bloody well know ;-) Anyway, there are two issues - access on Linux not getting unhappy and *BSD kernels being OK with created huge files. After rereading that code, for UFS2 the function I'd posted would do the right thing; for UFS1 there's an additional complication - on-disk ui_blocks (in units of 512 bytes) being only 32bit. So for UFS1 we need to make sure we won't overflow that thing, making for hard limit a bit below 2^41 bytes, in addition to the limit imposed by the tree structure. How about this: diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 131b2b77c818..eefa48499a6e 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -746,6 +746,23 @@ static void ufs_put_super(struct super_block *sb) return; } +static u64 ufs_max_bytes(struct super_block *sb) +{ + struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; + int bits = uspi->s_apbshift; + u64 res; + + if (bits > 21) + res = ~0ULL; + else + res = UFS_NDADDR + (1LL << bits) + (1LL << (2*bits)) + + (1LL << (3*bits)); + + if (res >= (MAX_LFS_FILESIZE >> uspi->s_bshift)) + return MAX_LFS_FILESIZE; + return res << uspi->s_bshift; +} + static int ufs_fill_super(struct super_block *sb, void *data, int silent) { struct ufs_sb_info * sbi; @@ -823,6 +840,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) uspi->s_fshift = 9; uspi->s_sbsize = super_block_size = 1536; uspi->s_sbbase = 0; + sb->s_maxbytes = min(ufs_max_bytes(sb),1ULL<<40); flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; break; case UFS_MOUNT_UFSTYPE_UFS2: @@ -833,6 +851,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) uspi->s_fshift = 9; uspi->s_sbsize = super_block_size = 1536; uspi->s_sbbase = 0; + sb->s_maxbytes = ufs_max_bytes(sb); flags |= UFS_TYPE_UFS2 | UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD; break;