From: Leo Martins Date: Tue, 12 Aug 2025 23:04:41 +0000 (-0700) Subject: btrfs: add mount option for ref_tracker X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=46d33a0cc484ceb11aa47166e66d349ab3074eef;p=users%2Fhch%2Fmisc.git btrfs: add mount option for ref_tracker The ref_tracker infrastructure aids debugging but is not enabled by default as it has a performance impact. Add mount option 'ref_tracker' so it can be selectively enabled on a filesystem. Currently it track references of 'delayed inodes'. Signed-off-by: Leo Martins Reviewed-by: David Sterba Signed-off-by: David Sterba --- diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h index 7f2db9905aea..0d949edc0caf 100644 --- a/fs/btrfs/delayed-inode.h +++ b/fs/btrfs/delayed-inode.h @@ -198,6 +198,9 @@ void btrfs_assert_delayed_root_empty(struct btrfs_fs_info *fs_info); #ifdef CONFIG_BTRFS_DEBUG static inline void btrfs_delayed_node_ref_tracker_dir_init(struct btrfs_delayed_node *node) { + if (!btrfs_test_opt(node->root->fs_info, REF_TRACKER)) + return; + ref_tracker_dir_init(&node->ref_dir.dir, BTRFS_DELAYED_NODE_REF_TRACKER_QUARANTINE_COUNT, "delayed_node"); @@ -205,11 +208,17 @@ static inline void btrfs_delayed_node_ref_tracker_dir_init(struct btrfs_delayed_ static inline void btrfs_delayed_node_ref_tracker_dir_exit(struct btrfs_delayed_node *node) { + if (!btrfs_test_opt(node->root->fs_info, REF_TRACKER)) + return; + ref_tracker_dir_exit(&node->ref_dir.dir); } static inline void btrfs_delayed_node_ref_tracker_dir_print(struct btrfs_delayed_node *node) { + if (!btrfs_test_opt(node->root->fs_info, REF_TRACKER)) + return; + ref_tracker_dir_print(&node->ref_dir.dir, BTRFS_DELAYED_NODE_REF_TRACKER_DISPLAY_LIMIT); } @@ -218,12 +227,18 @@ static inline int btrfs_delayed_node_ref_tracker_alloc(struct btrfs_delayed_node struct btrfs_ref_tracker *tracker, gfp_t gfp) { + if (!btrfs_test_opt(node->root->fs_info, REF_TRACKER)) + return 0; + return ref_tracker_alloc(&node->ref_dir.dir, &tracker->tracker, gfp); } static inline int btrfs_delayed_node_ref_tracker_free(struct btrfs_delayed_node *node, struct btrfs_ref_tracker *tracker) { + if (!btrfs_test_opt(node->root->fs_info, REF_TRACKER)) + return 0; + return ref_tracker_free(&node->ref_dir.dir, &tracker->tracker); } #else diff --git a/fs/btrfs/fs.h b/fs/btrfs/fs.h index 66e08e20ff5a..a84128e991a9 100644 --- a/fs/btrfs/fs.h +++ b/fs/btrfs/fs.h @@ -245,6 +245,7 @@ enum { BTRFS_MOUNT_NOSPACECACHE = (1ULL << 30), BTRFS_MOUNT_IGNOREMETACSUMS = (1ULL << 31), BTRFS_MOUNT_IGNORESUPERFLAGS = (1ULL << 32), + BTRFS_MOUNT_REF_TRACKER = (1ULL << 33), }; /* diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 3bc19989e7fb..4951f50e9823 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -134,6 +134,7 @@ enum { #ifdef CONFIG_BTRFS_DEBUG Opt_fragment, Opt_fragment_data, Opt_fragment_metadata, Opt_fragment_all, Opt_ref_verify, + Opt_ref_tracker, #endif Opt_err, }; @@ -255,6 +256,7 @@ static const struct fs_parameter_spec btrfs_fs_parameters[] = { fsparam_flag_no("enospc_debug", Opt_enospc_debug), #ifdef CONFIG_BTRFS_DEBUG fsparam_enum("fragment", Opt_fragment, btrfs_parameter_fragment), + fsparam_flag("ref_tracker", Opt_ref_tracker), fsparam_flag("ref_verify", Opt_ref_verify), #endif {} @@ -645,6 +647,9 @@ static int btrfs_parse_param(struct fs_context *fc, struct fs_parameter *param) case Opt_ref_verify: btrfs_set_opt(ctx->mount_opt, REF_VERIFY); break; + case Opt_ref_tracker: + btrfs_set_opt(ctx->mount_opt, REF_TRACKER); + break; #endif default: btrfs_err(NULL, "unrecognized mount option '%s'", param->key); @@ -1150,6 +1155,8 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry) #endif if (btrfs_test_opt(info, REF_VERIFY)) seq_puts(seq, ",ref_verify"); + if (btrfs_test_opt(info, REF_TRACKER)) + seq_puts(seq, ",ref_tracker"); seq_printf(seq, ",subvolid=%llu", btrfs_root_id(BTRFS_I(d_inode(dentry))->root)); subvol_name = btrfs_get_subvol_name_from_objectid(info, btrfs_root_id(BTRFS_I(d_inode(dentry))->root));