summaryrefslogtreecommitdiff
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorQu Wenruo <wqu@suse.com>2026-08-27 16:25:30 +0930
committerDavid Sterba <dsterba@suse.com>2026-09-14 13:23:36 +0200
commitddfce12cf94208160df06449025a6e847c2ea8f6 (patch)
tree57ff29acef61a3f0ee2aa745a42bf3dfa405d361 /fs/btrfs/extent-tree.c
parent1d7404d4daeacbebe5a75f812dd6e45e3340d340 (diff)
downloadlinux-next-ddfce12cf94208160df06449025a6e847c2ea8f6.tar.gz
linux-next-ddfce12cf94208160df06449025a6e847c2ea8f6.zip
btrfs: avoid long stall when dropping a non-shared large subvolume
Commit 011b46c30476 ("btrfs: skip subtree scan if it's too high to avoid low stall in btrfs_commit_transaction()") introduced a mechanism to skip large subtree during snapshot dropping. But even for a subvolume without any shared tree blocks, we can still queue quite a lot of qgroup records into one transaction, and cause a long qgroup related stall. So also add a check against the subvolume root level, to determine if we need to mark qgroup inconsistent. Reviewed-by: Boris Burkov <boris@bur.io> Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index d6a4390ee34a..a0d5ab03aae2 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -6315,6 +6315,16 @@ int btrfs_drop_snapshot(struct btrfs_root *root, bool update_ref, bool for_reloc
set_bit(BTRFS_ROOT_DELETING, &root->state);
unfinished_drop = test_bit(BTRFS_ROOT_UNFINISHED_DROP, &root->state);
+ /*
+ * For subvolume dropping, check if the subvolume is large enough so
+ * that we need to mark qgroup inconsistent to avoid long qgroup stall.
+ *
+ * Even for a subvolume without any snapshot, there can still be
+ * a lot of qgroup records queued into one transaction.
+ */
+ if (!for_reloc)
+ btrfs_qgroup_check_tree_drop(fs_info, rootid,
+ btrfs_header_level(root->node));
if (btrfs_disk_key_objectid(&root_item->drop_progress) == 0) {
level = btrfs_header_level(root->node);
path->nodes[level] = btrfs_lock_root_node(root);