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>
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);
return 0;
}
+void btrfs_qgroup_check_tree_drop(struct btrfs_fs_info *fs_info, u64 rootid, u8 level)
+{
+ u8 drop_subtree_thres;
+
+ if (btrfs_qgroup_mode(fs_info) != BTRFS_QGROUP_MODE_FULL)
+ return;
+
+ if (!btrfs_is_fstree(rootid))
+ return;
+
+ spin_lock(&fs_info->qgroup_lock);
+ drop_subtree_thres = fs_info->qgroup_drop_subtree_thres;
+ spin_unlock(&fs_info->qgroup_lock);
+
+ if (level >= drop_subtree_thres)
+ qgroup_mark_inconsistent(fs_info, "subtree level reached threshold");
+}
+
static void qgroup_iterator_nested_add(struct list_head *head, struct btrfs_qgroup *qgroup)
{
if (!list_empty(&qgroup->nested_iterator))
int btrfs_qgroup_trace_subtree(struct btrfs_trans_handle *trans,
struct extent_buffer *root_eb,
u64 root_gen, int root_level);
+void btrfs_qgroup_check_tree_drop(struct btrfs_fs_info *fs_info, u64 rootid, u8 level);
int btrfs_qgroup_account_extent(struct btrfs_trans_handle *trans, u64 bytenr,
u64 num_bytes, struct ulist *old_roots,
struct ulist *new_roots);