Skip to content

Commit

Permalink
btrfs: qgroup: account shared subtree during snapshot delete
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Chris Mason <[email protected]>
  • Loading branch information
Mark Fasheh authored and masoncl committed Nov 25, 2015
1 parent 2d9e977 commit 82bd101
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 7 deletions.
47 changes: 40 additions & 7 deletions fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -8108,21 +8108,47 @@ static noinline void reada_walk_down(struct btrfs_trans_handle *trans,
}

/*
* TODO: Modify related function to add related node/leaf to dirty_extent_root,
* for later qgroup accounting.
*
* Current, this function does nothing.
* These may not be seen by the usual inc/dec ref code so we have to
* add them here.
*/
static int record_one_subtree_extent(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u64 bytenr,
u64 num_bytes)
{
struct btrfs_qgroup_extent_record *qrecord;
struct btrfs_delayed_ref_root *delayed_refs;

qrecord = kmalloc(sizeof(*qrecord), GFP_NOFS);
if (!qrecord)
return -ENOMEM;

qrecord->bytenr = bytenr;
qrecord->num_bytes = num_bytes;
qrecord->old_roots = NULL;

delayed_refs = &trans->transaction->delayed_refs;
spin_lock(&delayed_refs->lock);
if (btrfs_qgroup_insert_dirty_extent(delayed_refs, qrecord))
kfree(qrecord);
spin_unlock(&delayed_refs->lock);

return 0;
}

static int account_leaf_items(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct extent_buffer *eb)
{
int nr = btrfs_header_nritems(eb);
int i, extent_type;
int i, extent_type, ret;
struct btrfs_key key;
struct btrfs_file_extent_item *fi;
u64 bytenr, num_bytes;

/* We can be called directly from walk_up_proc() */
if (!root->fs_info->quota_enabled)
return 0;

for (i = 0; i < nr; i++) {
btrfs_item_key_to_cpu(eb, &key, i);

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

num_bytes = btrfs_file_extent_disk_num_bytes(eb, fi);

ret = record_one_subtree_extent(trans, root, bytenr, num_bytes);
if (ret)
return ret;
}
return 0;
}
Expand Down Expand Up @@ -8209,8 +8239,6 @@ static int adjust_slots_upwards(struct btrfs_root *root,

/*
* root_eb is the subtree root and is locked before this function is called.
* TODO: Modify this function to mark all (including complete shared node)
* to dirty_extent_root to allow it get accounted in qgroup.
*/
static int account_shared_subtree(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
Expand Down Expand Up @@ -8288,6 +8316,11 @@ static int account_shared_subtree(struct btrfs_trans_handle *trans,
btrfs_tree_read_lock(eb);
btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
path->locks[level] = BTRFS_READ_LOCK_BLOCKING;

ret = record_one_subtree_extent(trans, root, child_bytenr,
root->nodesize);
if (ret)
goto out;
}

if (level == 0) {
Expand Down
2 changes: 2 additions & 0 deletions fs/btrfs/qgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -1462,6 +1462,8 @@ struct btrfs_qgroup_extent_record
struct btrfs_qgroup_extent_record *entry;
u64 bytenr = record->bytenr;

assert_spin_locked(&delayed_refs->lock);

while (*p) {
parent_node = *p;
entry = rb_entry(parent_node, struct btrfs_qgroup_extent_record,
Expand Down

0 comments on commit 82bd101

Please sign in to comment.