]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
btrfs: simplify support block size check
authorQu Wenruo <wqu@suse.com>
Sat, 9 Aug 2025 04:40:48 +0000 (14:10 +0930)
committerDavid Sterba <dsterba@suse.com>
Mon, 22 Sep 2025 08:54:31 +0000 (10:54 +0200)
Currently we manually check the block size against 3 different values:

- 4K
- PAGE_SIZE
- MIN_BLOCKSIZE

Those 3 values can match or differ from each other.  This makes it
pretty complex to output the supported block sizes.

Considering we're going to add block size > page size support soon, this
can make the support block size sysfs attribute much harder to
implement.

To make it easier, factor out a helper, btrfs_supported_blocksize() to
do a simple check for the block size.

Then utilize it in the two locations:

- btrfs_validate_super()
  This is very straightforward

- supported_sectorsizes_show()
  Iterate through all valid block sizes, and only output supported ones.

  This is to make future full range block sizes support much easier.

Reviewed-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/disk-io.c
fs/btrfs/fs.c
fs/btrfs/fs.h
fs/btrfs/sysfs.c

index 70fc4e7cc5a0e6cd8885df91c3959455322eb6d0..123c397ca8f88f536f65a149a68120c96033a181 100644 (file)
@@ -2438,21 +2438,7 @@ int btrfs_validate_super(const struct btrfs_fs_info *fs_info,
                ret = -EINVAL;
        }
 
-       /*
-        * We only support at most 3 sectorsizes: 4K, PAGE_SIZE, MIN_BLOCKSIZE.
-        *
-        * For 4K page sized systems with non-debug builds, all 3 matches (4K).
-        * For 4K page sized systems with debug builds, there are two block sizes
-        * supported. (4K and 2K)
-        *
-        * We can support 16K sectorsize with 64K page size without problem,
-        * but such sectorsize/pagesize combination doesn't make much sense.
-        * 4K will be our future standard, PAGE_SIZE is supported from the very
-        * beginning.
-        */
-       if (sectorsize > PAGE_SIZE || (sectorsize != SZ_4K &&
-                                      sectorsize != PAGE_SIZE &&
-                                      sectorsize != BTRFS_MIN_BLOCKSIZE)) {
+       if (!btrfs_supported_blocksize(sectorsize)) {
                btrfs_err(fs_info,
                        "sectorsize %llu not yet supported for page size %lu",
                        sectorsize, PAGE_SIZE);
index b2bb86f8d7cf0c66dbb24a980ad55df960bac97c..8b118c03cdb88148242141625fb04d327bd26a16 100644 (file)
@@ -54,6 +54,33 @@ size_t __attribute_const__ btrfs_get_num_csums(void)
        return ARRAY_SIZE(btrfs_csums);
 }
 
+/*
+ * We support the following block sizes for all systems:
+ *
+ * - 4K
+ *   This is the most common block size. For PAGE SIZE > 4K cases the subage
+ *   mode is used.
+ *
+ * - PAGE_SIZE
+ *   The straightforward block size to support.
+ *
+ * And extra support for the following block sizes based on the kernel config:
+ *
+ * - MIN_BLOCKSIZE
+ *   This is either 4K (regular builds) or 2K (debug builds)
+ *   This allows testing subpage routines on x86_64.
+ */
+bool __attribute_const__ btrfs_supported_blocksize(u32 blocksize)
+{
+       /* @blocksize should be validated first. */
+       ASSERT(is_power_of_2(blocksize) && blocksize >= BTRFS_MIN_BLOCKSIZE &&
+              blocksize <= BTRFS_MAX_BLOCKSIZE);
+
+       if (blocksize == PAGE_SIZE || blocksize == SZ_4K || blocksize == BTRFS_MIN_BLOCKSIZE)
+               return true;
+       return false;
+}
+
 /*
  * Start exclusive operation @type, return true on success.
  */
index 8cc07cc70b128357b7950c83b5e438a1f431e500..f0b090d4ac0466fbd2caa01526ca61274867be7f 100644 (file)
@@ -59,6 +59,8 @@ struct btrfs_space_info;
 #define BTRFS_MIN_BLOCKSIZE    (SZ_4K)
 #endif
 
+#define BTRFS_MAX_BLOCKSIZE    (SZ_64K)
+
 #define BTRFS_MAX_EXTENT_SIZE SZ_128M
 
 #define BTRFS_OLDEST_GENERATION        0ULL
@@ -997,6 +999,7 @@ static inline unsigned int btrfs_blocks_per_folio(const struct btrfs_fs_info *fs
        return folio_size(folio) >> fs_info->sectorsize_bits;
 }
 
+bool __attribute_const__ btrfs_supported_blocksize(u32 blocksize);
 bool btrfs_exclop_start(struct btrfs_fs_info *fs_info,
                        enum btrfs_exclusive_operation type);
 bool btrfs_exclop_start_try_lock(struct btrfs_fs_info *fs_info,
index 9d398f7a36addb5ea8974abdd48dbef44b2952cf..81f52c1f55ce57f8d090e5b96436c747b8dba27a 100644 (file)
@@ -409,13 +409,17 @@ static ssize_t supported_sectorsizes_show(struct kobject *kobj,
                                          char *buf)
 {
        ssize_t ret = 0;
+       bool has_output = false;
 
-       if (BTRFS_MIN_BLOCKSIZE != SZ_4K && BTRFS_MIN_BLOCKSIZE != PAGE_SIZE)
-               ret += sysfs_emit_at(buf, ret, "%u ", BTRFS_MIN_BLOCKSIZE);
-       if (PAGE_SIZE > SZ_4K)
-               ret += sysfs_emit_at(buf, ret, "%u ", SZ_4K);
-       ret += sysfs_emit_at(buf, ret, "%lu\n", PAGE_SIZE);
-
+       for (u32 cur = BTRFS_MIN_BLOCKSIZE; cur <= BTRFS_MAX_BLOCKSIZE; cur *= 2) {
+               if (!btrfs_supported_blocksize(cur))
+                       continue;
+               if (has_output)
+                       ret += sysfs_emit_at(buf, ret, " ");
+               ret += sysfs_emit_at(buf, ret, "%u", cur);
+               has_output = true;
+       }
+       ret += sysfs_emit_at(buf, ret, "\n");
        return ret;
 }
 BTRFS_ATTR(static_feature, supported_sectorsizes,