[PATCH 2/3] btrfs-progs: support 2k block size

Qu Wenruo
2025-02-26T03:59:50Z

Since btrfs only supports block size 4K and PAGE_SIZE, on x86_64 it
means we can not test subpage block size easily.

With the recent kernel change to support 2K block size for debug builds,
also add 2K block size support for btrfs-progs, so that we can do proper
subpage block size testing on x86_64, without acquiring an aarch64
machine.

There is a limit:

- No support for 2K node size
The limit is from the initial mkfs tree root, which can only have
a single leaf to contain all root items.
But 2K leaf can not handle all the root items, thus we have to disable
it.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
common/fsfeatures.c | 11 ++++++++---
kernel-shared/ctree.h | 6 ++++++
kernel-shared/disk-io.c | 11 ++++-------
mkfs/main.c | 7 -------
4 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/common/fsfeatures.c b/common/fsfeatures.c
index 7aaddab6a192..398065dbea86 100644
--- a/common/fsfeatures.c
+++ b/common/fsfeatures.c
@@ -628,7 +628,8 @@ int btrfs_check_sectorsize(u32 sectorsize)
error("invalid sectorsize %u, must be power of 2", sectorsize);
return -EINVAL;
}
- if (sectorsize < SZ_4K || sectorsize > SZ_64K) {
+ if (sectorsize < BTRFS_MIN_BLOCKSIZE ||
+ sectorsize > BTRFS_MAX_METADATA_BLOCKSIZE) {
error("invalid sectorsize %u, expected range is [4K, 64K]",
sectorsize);
return -EINVAL;
@@ -650,9 +651,13 @@ int btrfs_check_sectorsize(u32 sectorsize)
int btrfs_check_nodesize(u32 nodesize, u32 sectorsize,
struct btrfs_mkfs_features *features)
{
- if (nodesize < sectorsize) {
+ if (nodesize < sectorsize || nodesize < SZ_4K) {
+ /*
+ * Although we support 2K block size, we can not support 2K
+ * nodesize, as it's too small to contain all the needed root items.
+ */
error("illegal nodesize %u (smaller than %u)",
- nodesize, sectorsize);
+ nodesize, max_t(u32, sectorsize, SZ_4K));
return -1;
} else if (nodesize > BTRFS_MAX_METADATA_BLOCKSIZE) {
error("illegal nodesize %u (larger than %u)",
diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
index 8c923be96705..c3d66c99c78d 100644
--- a/kernel-shared/ctree.h
+++ b/kernel-shared/ctree.h
@@ -63,6 +63,12 @@ static inline u32 __BTRFS_LEAF_DATA_SIZE(u32 nodesize)
return nodesize - sizeof(struct btrfs_header);
}

+#if EXPERIMENTAL
+#define BTRFS_MIN_BLOCKSIZE (SZ_2K)
+#else
+#define BTRFS_MIN_BLOCKSIZE (SZ_4K)
+#endif
+
#define BTRFS_LEAF_DATA_SIZE(fs_info) (fs_info->leaf_data_size)

#define BTRFS_SUPER_INFO_OFFSET (65536)
diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c
index a4f91d10fa4e..b7d478007ae8 100644
--- a/kernel-shared/disk-io.c
+++ b/kernel-shared/disk-io.c
@@ -1816,13 +1816,10 @@ int btrfs_check_super(struct btrfs_super_block *sb, unsigned sbflags)
error("nodesize unaligned: %u", btrfs_super_nodesize(sb));
goto error_out;
}
- if (btrfs_super_sectorsize(sb) < 4096) {
- error("sectorsize too small: %u < 4096",
- btrfs_super_sectorsize(sb));
- goto error_out;
- }
- if (!IS_ALIGNED(btrfs_super_sectorsize(sb), 4096)) {
- error("sectorsize unaligned: %u", btrfs_super_sectorsize(sb));
+ if (!is_power_of_2(btrfs_super_sectorsize(sb)) ||
+ btrfs_super_sectorsize(sb) < BTRFS_MIN_BLOCKSIZE ||
+ btrfs_super_sectorsize(sb) > BTRFS_MAX_METADATA_BLOCKSIZE) {
+ error("invalid sectorsize: %u", btrfs_super_sectorsize(sb));
goto error_out;
}
if (btrfs_super_total_bytes(sb) == 0) {
diff --git a/mkfs/main.c b/mkfs/main.c
index dc73de47a710..c7968540e8af 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -1669,13 +1669,6 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
if (nodesize > sysconf(_SC_PAGE_SIZE))
features.incompat_flags |= BTRFS_FEATURE_INCOMPAT_BIG_METADATA;

- if (sectorsize < sizeof(struct btrfs_super_block)) {
- error("sectorsize smaller than superblock: %u < %zu",
- sectorsize, sizeof(struct btrfs_super_block));
- ret = 1;
- goto error;
- }
-
min_dev_size = btrfs_min_dev_size(nodesize, mixed,
opt_zoned ? zone_size(file) : 0,
metadata_profile, data_profile);
--
2.48.1