bdev: add back PAGE_SIZE block size validation for sb_set_blocksize()
authorLuis Chamberlain <mcgrof@kernel.org>
Fri, 7 Mar 2025 02:04:03 +0000 (18:04 -0800)
committerChristian Brauner <brauner@kernel.org>
Fri, 7 Mar 2025 11:56:05 +0000 (12:56 +0100)
The commit titled "block/bdev: lift block size restrictions to 64k"
lifted the block layer's max supported block size to 64k inside the
helper blk_validate_block_size() now that we support large folios.
However in lifting the block size we also removed the silly use
cases many filesystems have to use sb_set_blocksize() to *verify*
that the block size <= PAGE_SIZE. The call to sb_set_blocksize() was
used to check the block size <= PAGE_SIZE since historically we've
always supported userspace to create for example 64k block size
filesystems even on 4k page size systems, but what we didn't allow
was mounting them. Older filesystems have been using the check with
sb_set_blocksize() for years.

While, we could argue that such checks should be filesystem specific,
there are much more users of sb_set_blocksize() than LBS enabled
filesystem on upstream, so just do the easier thing and bring back
the PAGE_SIZE check for sb_set_blocksize() users and only skip it
for LBS enabled filesystems.

This will ensure that tests such as generic/466 when run in a loop
against say, ext4, won't try to try to actually mount a filesystem with
a block size larger than your filesystem supports given your PAGE_SIZE
and in the worst case crash.

Cc: Kent Overstreet <kent.overstreet@linux.dev>
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
Link: https://lore.kernel.org/r/20250307020403.3068567-1-mcgrof@kernel.org
Reviewed-by: Kent Overstreet <kent.overstreet@linux.dev>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>
block/bdev.c
fs/bcachefs/fs.c
fs/xfs/xfs_super.c
include/linux/fs.h

index 3bd948e6438dc7eb1317b5a77b89bfe05bd442f9..4844d1e27b6fbc2535dda62d2c2b2be67803c5bd 100644 (file)
@@ -181,6 +181,8 @@ EXPORT_SYMBOL(set_blocksize);
 
 int sb_set_blocksize(struct super_block *sb, int size)
 {
+       if (!(sb->s_type->fs_flags & FS_LBS) && size > PAGE_SIZE)
+               return 0;
        if (set_blocksize(sb->s_bdev_file, size))
                return 0;
        /* If we get here, we know size is validated */
index 90ade8f648d96b6f1bbb362581f8faa415121a93..e99e378d68ea3d2a2379e82008306f61c2926a8e 100644 (file)
@@ -2396,7 +2396,7 @@ static struct file_system_type bcache_fs_type = {
        .name                   = "bcachefs",
        .init_fs_context        = bch2_init_fs_context,
        .kill_sb                = bch2_kill_sb,
-       .fs_flags               = FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
+       .fs_flags               = FS_REQUIRES_DEV | FS_ALLOW_IDMAP | FS_LBS,
 };
 
 MODULE_ALIAS_FS("bcachefs");
index d92d7a07ea89b8781494ed35e87635602266b4a1..3d8b80165d4812403186d5398900b27376b879e2 100644 (file)
@@ -2118,7 +2118,8 @@ static struct file_system_type xfs_fs_type = {
        .init_fs_context        = xfs_init_fs_context,
        .parameters             = xfs_fs_parameters,
        .kill_sb                = xfs_kill_sb,
-       .fs_flags               = FS_REQUIRES_DEV | FS_ALLOW_IDMAP | FS_MGTIME,
+       .fs_flags               = FS_REQUIRES_DEV | FS_ALLOW_IDMAP | FS_MGTIME |
+                                 FS_LBS,
 };
 MODULE_ALIAS_FS("xfs");
 
index be3ad155ec9f74460d971f11b96445e8db579c6f..f47fbe16b10160214a12d65b852e41d31604b437 100644 (file)
@@ -2604,6 +2604,7 @@ struct file_system_type {
 #define FS_DISALLOW_NOTIFY_PERM        16      /* Disable fanotify permission events */
 #define FS_ALLOW_IDMAP         32      /* FS has been updated to handle vfs idmappings. */
 #define FS_MGTIME              64      /* FS uses multigrain timestamps */
+#define FS_LBS                 128     /* FS supports LBS */
 #define FS_RENAME_DOES_D_MOVE  32768   /* FS will handle d_move() during rename() internally. */
        int (*init_fs_context)(struct fs_context *);
        const struct fs_parameter_spec *parameters;