From: Zygo Blaxell Date: Thu, 17 Sep 2026 04:16:22 +0000 (-0400) Subject: btrfs: stripe_alloc: let the property accept a cache-less filesystem like the mount... X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b72dc2da0d3faf84e85e6d1ca478215d10ea76c2;p=linux btrfs: stripe_alloc: let the property accept a cache-less filesystem like the mount option does The "stripe_alloc" filesystem property and the mount option are meant to be two ways to turn on one policy, and they answer the same questions about the filesystem -- except one. btrfs_check_mountopts() refuses the option only for space_cache=v1: the v1 cache inode is nodatacow and preallocated, so a commit overwrites it in place, a sub-stripe write into committed stripes that no csum would ever show. The free space tree and no cache at all are both fine, and nothing in the allocator reads either. btrfs_stripe_alloc_check_support(), which the property calls, demanded the free space tree instead, so a filesystem mounted with nospace_cache took the option but refused the property, and the error it gave named a requirement the option does not have. Refuse what the mount path refuses: the v1 cache, both the live option and cache inodes still on disk from an earlier mount, which btrfs_read_block_groups() already refuses for the option (the property can arrive on a live filesystem, after that check ran). The two paths now agree, and bg-gate-test.sh's property cases hold them to it. Assisted-by: Claude:claude-fable-5-1 --- diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c index a845947bf085b..df152e1ed5dd4 100644 --- a/fs/btrfs/block-group.c +++ b/fs/btrfs/block-group.c @@ -2023,9 +2023,24 @@ void btrfs_log_settle_stripes(struct btrfs_inode *inode, u64 file_start, */ int btrfs_stripe_alloc_check_support(struct btrfs_fs_info *fs_info) { - if (!btrfs_test_opt(fs_info, FREE_SPACE_TREE)) { + /* + * Mirror btrfs_check_mountopts(): only the v1 space cache is a + * problem. Its cache inode is nodatacow and preallocated, so a + * commit overwrites it in place -- a sub-stripe write into committed + * stripes that no csum would show afterwards. The free space tree + * and no cache at all are both fine; nothing here reads either one. + * The property can arrive on a live filesystem, after + * btrfs_read_block_groups() checked for cache inodes left on disk by + * an earlier mount, so ask again here. + */ + if (btrfs_test_opt(fs_info, SPACE_CACHE)) { btrfs_err(fs_info, - "stripe_alloc requires the free space tree (space_cache=v2)"); + "stripe_alloc is not supported with space_cache=v1"); + return -EINVAL; + } + if (btrfs_free_space_cache_v1_present(fs_info)) { + btrfs_err(fs_info, +"stripe_alloc is not supported while a v1 space cache is present on disk; mount once without stripe_alloc to clear it (-o clear_cache, or space_cache=v2)"); return -EINVAL; } if (btrfs_is_zoned(fs_info)) {