Skip to content

Commit 82bd101

Browse files
Mark Fashehmasoncl
authored andcommitted
btrfs: qgroup: account shared subtree during snapshot delete
Commit 0ed4792 ('btrfs: qgroup: Switch to new extent-oriented qgroup mechanism.') removed our qgroup accounting during btrfs_drop_snapshot(). Predictably, this results in qgroup numbers going bad shortly after a snapshot is removed. Fix this by adding a dirty extent record when we encounter extents during our shared subtree walk. This effectively restores the functionality we had with the original shared subtree walking code in 1152651 (btrfs: qgroup: account shared subtrees during snapshot delete). The idea with the original patch (and this one) is that shared subtrees can get skipped during drop_snapshot. The shared subtree walk then allows us a chance to visit those extents and add them to the qgroup work for later processing. This ultimately makes the accounting for drop snapshot work. The new qgroup code nicely handles all the other extents during the tree walk via the ref dec/inc functions so we don't have to add actions beyond what we had originally. Signed-off-by: Mark Fasheh <mfasheh@suse.de> Signed-off-by: Chris Mason <clm@fb.com>
1 parent 2d9e977 commit 82bd101

2 files changed

Lines changed: 42 additions & 7 deletions

File tree

fs/btrfs/extent-tree.c

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8108,21 +8108,47 @@ static noinline void reada_walk_down(struct btrfs_trans_handle *trans,
81088108
}
81098109

81108110
/*
8111-
* TODO: Modify related function to add related node/leaf to dirty_extent_root,
8112-
* for later qgroup accounting.
8113-
*
8114-
* Current, this function does nothing.
8111+
* These may not be seen by the usual inc/dec ref code so we have to
8112+
* add them here.
81158113
*/
8114+
static int record_one_subtree_extent(struct btrfs_trans_handle *trans,
8115+
struct btrfs_root *root, u64 bytenr,
8116+
u64 num_bytes)
8117+
{
8118+
struct btrfs_qgroup_extent_record *qrecord;
8119+
struct btrfs_delayed_ref_root *delayed_refs;
8120+
8121+
qrecord = kmalloc(sizeof(*qrecord), GFP_NOFS);
8122+
if (!qrecord)
8123+
return -ENOMEM;
8124+
8125+
qrecord->bytenr = bytenr;
8126+
qrecord->num_bytes = num_bytes;
8127+
qrecord->old_roots = NULL;
8128+
8129+
delayed_refs = &trans->transaction->delayed_refs;
8130+
spin_lock(&delayed_refs->lock);
8131+
if (btrfs_qgroup_insert_dirty_extent(delayed_refs, qrecord))
8132+
kfree(qrecord);
8133+
spin_unlock(&delayed_refs->lock);
8134+
8135+
return 0;
8136+
}
8137+
81168138
static int account_leaf_items(struct btrfs_trans_handle *trans,
81178139
struct btrfs_root *root,
81188140
struct extent_buffer *eb)
81198141
{
81208142
int nr = btrfs_header_nritems(eb);
8121-
int i, extent_type;
8143+
int i, extent_type, ret;
81228144
struct btrfs_key key;
81238145
struct btrfs_file_extent_item *fi;
81248146
u64 bytenr, num_bytes;
81258147

8148+
/* We can be called directly from walk_up_proc() */
8149+
if (!root->fs_info->quota_enabled)
8150+
return 0;
8151+
81268152
for (i = 0; i < nr; i++) {
81278153
btrfs_item_key_to_cpu(eb, &key, i);
81288154

@@ -8141,6 +8167,10 @@ static int account_leaf_items(struct btrfs_trans_handle *trans,
81418167
continue;
81428168

81438169
num_bytes = btrfs_file_extent_disk_num_bytes(eb, fi);
8170+
8171+
ret = record_one_subtree_extent(trans, root, bytenr, num_bytes);
8172+
if (ret)
8173+
return ret;
81448174
}
81458175
return 0;
81468176
}
@@ -8209,8 +8239,6 @@ static int adjust_slots_upwards(struct btrfs_root *root,
82098239

82108240
/*
82118241
* root_eb is the subtree root and is locked before this function is called.
8212-
* TODO: Modify this function to mark all (including complete shared node)
8213-
* to dirty_extent_root to allow it get accounted in qgroup.
82148242
*/
82158243
static int account_shared_subtree(struct btrfs_trans_handle *trans,
82168244
struct btrfs_root *root,
@@ -8288,6 +8316,11 @@ static int account_shared_subtree(struct btrfs_trans_handle *trans,
82888316
btrfs_tree_read_lock(eb);
82898317
btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
82908318
path->locks[level] = BTRFS_READ_LOCK_BLOCKING;
8319+
8320+
ret = record_one_subtree_extent(trans, root, child_bytenr,
8321+
root->nodesize);
8322+
if (ret)
8323+
goto out;
82918324
}
82928325

82938326
if (level == 0) {

fs/btrfs/qgroup.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1462,6 +1462,8 @@ struct btrfs_qgroup_extent_record
14621462
struct btrfs_qgroup_extent_record *entry;
14631463
u64 bytenr = record->bytenr;
14641464

1465+
assert_spin_locked(&delayed_refs->lock);
1466+
14651467
while (*p) {
14661468
parent_node = *p;
14671469
entry = rb_entry(parent_node, struct btrfs_qgroup_extent_record,

0 commit comments

Comments
 (0)