]> git.hungrycats.org Git - linux/commitdiff
btrfs: stripe_alloc: let the property accept a cache-less filesystem like the mount...
authorZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Thu, 17 Sep 2026 04:16:22 +0000 (00:16 -0400)
committerZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Thu, 17 Sep 2026 04:16:22 +0000 (00:16 -0400)
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
fs/btrfs/block-group.c

index a845947bf085b0a5a1bd0b790b968aaac038373e..df152e1ed5dd47108c56cc47ba1afe8104525a56 100644 (file)
@@ -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)) {