]> git.hungrycats.org Git - linux/commitdiff
btrfs: stripe_alloc: warn at mount when raid56 metadata is not covered
authorZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Tue, 4 Aug 2026 06:43:20 +0000 (02:43 -0400)
committerZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Fri, 18 Sep 2026 21:36:23 +0000 (17:36 -0400)
stripe_alloc closes the write hole for raid56 data.  It does nothing for
raid56 metadata, which keeps read-modify-write and keeps the hole, and
on a mixed-block-group filesystem it now does nothing at all.  A user
who mounts -o stripe_alloc on -d raid5 -m raid5 has every reason to
believe the filesystem is covered, and finds out otherwise only after a
crash on a degraded array -- with metadata damage, which is worse than
the data damage they were protecting against.

Say it once at mount, after the block groups are read, so the message
reflects what is actually on disk rather than what was asked for.  A
warning, not an error: the data guarantee is real and worth having on
its own, and a filesystem can be converted to raid1c3/raid1c4 metadata
without unmounting.

Assisted-by: Claude:claude-fable-5
fs/btrfs/block-group.c

index e5dd059e18264c9a9a3bd209325993280eb3d494..2b6eca9f39c5f5550e35956890b44cb6f205fead 100644 (file)
@@ -4440,6 +4440,26 @@ static int fill_dummy_bgs(struct btrfs_fs_info *fs_info)
        return ret;
 }
 
+/*
+ * stripe_alloc covers raid56 *data* block groups only.  A filesystem whose
+ * metadata is also raid56 keeps the write hole there.  The data guarantee is
+ * easy to read as a filesystem-wide one, so say once at mount what is not
+ * covered.  (Mixed block groups cannot get here: the mount is refused, see
+ * btrfs_check_mountopts().)
+ */
+static void warn_stripe_alloc_uncovered(struct btrfs_fs_info *info)
+{
+       const u64 meta_bits = info->avail_metadata_alloc_bits |
+                             info->avail_system_alloc_bits;
+
+       if (!btrfs_test_opt(info, STRIPE_ALLOC))
+               return;
+
+       if (meta_bits & BTRFS_BLOCK_GROUP_RAID56_MASK)
+               btrfs_warn(info,
+"stripe_alloc does not cover raid56 metadata: the write hole remains for metadata, consider converting it to raid1c3/raid1c4");
+}
+
 int btrfs_read_block_groups(struct btrfs_fs_info *info)
 {
        struct btrfs_root *root = btrfs_block_group_root(info);
@@ -4536,6 +4556,7 @@ int btrfs_read_block_groups(struct btrfs_fs_info *info)
                        inc_block_group_ro(cache, true);
        }
 
+       warn_stripe_alloc_uncovered(info);
        btrfs_init_global_block_rsv(info);
        ret = check_chunk_block_group_mappings(info);
 error: