From: Zygo Blaxell Date: Thu, 17 Sep 2026 20:50:56 +0000 (-0400) Subject: btrfs: stripe_alloc: say at mount whether the policy is on X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fd90c7b71ead357ed3dd603ad40eb9fa9545e452;p=linux btrfs: stripe_alloc: say at mount whether the policy is on Two paths turn stripe-exclusive allocation on and neither announced it. The mount option sets the flag while btrfs_emit_options() has no entry to print for it, and the btrfs.stripe_alloc property applies later still, when btrfs_fill_super() reads the root directory's inode and its properties. btrfs_enable_stripe_alloc() did print a line, but only on the property path, and even there it is skipped when the option already set the flag, because the function returns early in that case. So the log said nothing. An absent line meant "off" and "on via the mount option" equally well, and the only way to answer the question was to read /proc/mounts on a live filesystem -- no use when the filesystem is someone else's, or when all that is left is a log from before a crash. Analysing a lockup from a filesystem whose btrfs.stripe_alloc property was set, I read that silence as the policy being off and said so, which was wrong twice over: the property was set, and the option would have been just as invisible. State it once in btrfs_fill_super(), after the root inode has been read so the property has had its say, naming which of the two turned it on. The option is sampled before open_ctree(), not merely before that read: the mount context has already reached fs_info by the time btrfs_fill_super() runs, and open_ctree() itself goes far enough into the mount to read the root directory's inode and apply the property, so a sample taken after it reports every property-enabled filesystem as an option-enabled one. The directed test caught exactly that. A remount that changes the flag reports the change as well. The property path keeps its own line for a set on a live filesystem, where there is no mount to report; at mount it now stays quiet so the line is not printed twice. Nothing is printed when the policy is off, which keeps the common mount quiet and makes the absence of the line mean exactly one thing. Assisted-by: Claude:claude-fable-5-1 --- diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c index df152e1ed5dd4..cc44e400fb3ef 100644 --- a/fs/btrfs/block-group.c +++ b/fs/btrfs/block-group.c @@ -2178,10 +2178,16 @@ int btrfs_enable_stripe_alloc(struct btrfs_fs_info *fs_info) * when their caching thread finishes, now that the policy is on. */ stripe_alloc_sweep_groups(fs_info, true); - btrfs_info(fs_info, - "using stripe-exclusive allocation for raid56 data"); - if (live) + /* + * At mount btrfs_fill_super() states the outcome once, for the option + * and the property alike, so repeating it here would only double the + * line. A property set on a live filesystem has no such reporter. + */ + if (live) { + btrfs_info(fs_info, + "using stripe-exclusive allocation for raid56 data (filesystem property)"); queue_work(system_unbound_wq, &fs_info->stripe_alloc_enable_work); + } return 0; } diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 1e0192dcfcf31..dfd51fea28f3c 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -1002,11 +1002,34 @@ static int get_default_subvol_objectid(struct btrfs_fs_info *fs_info, u64 *objec return 0; } +/* + * State whether stripe-exclusive allocation is on, and which of the two things + * that can turn it on did. + * + * Neither path said so before. The mount option sets the flag while + * btrfs_emit_options() has no entry to print for it, and the + * btrfs.stripe_alloc property applies later still, when the root directory's + * inode is read. So nothing in the log distinguished a filesystem running the + * policy from one that was not: silence meant "off" and "on via the mount + * option" equally well, and the only way to answer the question was + * /proc/mounts on a live system -- no use at all when reading a log after a + * crash. Say it once, whatever turned it on. + */ +static void btrfs_emit_stripe_alloc_state(struct btrfs_fs_info *info, + bool from_option) +{ + if (!btrfs_test_opt(info, STRIPE_ALLOC)) + return; + btrfs_info(info, "using stripe-exclusive allocation for raid56 data (%s)", + from_option ? "mount option" : "filesystem property"); +} + static int btrfs_fill_super(struct super_block *sb, struct btrfs_fs_devices *fs_devices) { struct btrfs_inode *inode; struct btrfs_fs_info *fs_info = btrfs_sb(sb); + bool stripe_alloc_from_option; int ret; sb->s_maxbytes = MAX_LFS_FILESIZE; @@ -1027,6 +1050,15 @@ static int btrfs_fill_super(struct super_block *sb, return ret; } + /* + * Sample what the mount option asked for before open_ctree(): the mount + * context has already been copied into fs_info by now, and open_ctree() + * goes far enough into the mount to read the root directory's inode and + * apply btrfs.stripe_alloc from it. Sampling afterwards would report + * every property-enabled filesystem as an option-enabled one. + */ + stripe_alloc_from_option = btrfs_test_opt(fs_info, STRIPE_ALLOC); + ret = open_ctree(sb, fs_devices); if (ret) { btrfs_err(fs_info, "open_ctree failed: %d", ret); @@ -1042,6 +1074,8 @@ static int btrfs_fill_super(struct super_block *sb, goto fail_close; } + btrfs_emit_stripe_alloc_state(fs_info, stripe_alloc_from_option); + sb->s_root = d_make_root(&inode->vfs_inode); if (!sb->s_root) { ret = -ENOMEM; @@ -1636,6 +1670,18 @@ static int btrfs_reconfigure(struct fs_context *fc) fc->sb_flags_mask |= SB_POSIXACL; btrfs_emit_options(fs_info, &old_ctx); + /* + * A remount can only change this through the option; the property path + * reports itself. Say so only when it actually changed. + */ + if (!btrfs_raw_test_opt(old_ctx.mount_opt, STRIPE_ALLOC) != + !btrfs_test_opt(fs_info, STRIPE_ALLOC)) { + if (btrfs_test_opt(fs_info, STRIPE_ALLOC)) + btrfs_emit_stripe_alloc_state(fs_info, true); + else + btrfs_info(fs_info, + "stripe-exclusive allocation for raid56 data is off"); + } wake_up_process(fs_info->transaction_kthread); btrfs_remount_cleanup(fs_info, old_ctx.mount_opt); btrfs_clear_oneshot_options(fs_info);