aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Fasheh <mfasheh@suse.de>2015-11-05 17:38:00 -0500
committerChris Mason <clm@fb.com>2015-11-25 08:27:33 -0500
commit82bd101b5240d3d1c4078a8017917a40c0dcc514 (patch)
tree0105605d854d46179bd8805b91994510f5b79365
parent2d9e97761087b46192c18181dfd1e7a930defcfd (diff)
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>
-rw-r--r--fs/btrfs/extent-tree.c47
-rw-r--r--fs/btrfs/qgroup.c2
2 files changed, 42 insertions, 7 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index e563e5ab72b4..4b89680a1923 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -8108,21 +8108,47 @@ reada:
8108} 8108}
8109 8109
8110/* 8110/*
8111 * TODO: Modify related function to add related node/leaf to dirty_extent_root, 8111 * These may not be seen by the usual inc/dec ref code so we have to
8112 * for later qgroup accounting. 8112 * add them here.
8113 *
8114 * Current, this function does nothing.
8115 */ 8113 */
8114static 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
8116static int account_leaf_items(struct btrfs_trans_handle *trans, 8138static int account_leaf_items(struct btrfs_trans_handle *trans,
8117 struct btrfs_root *root, 8139 struct btrfs_root *root,
8118 struct extent_buffer *eb) 8140 struct extent_buffer *eb)
8119{ 8141{
8120 int nr = btrfs_header_nritems(eb); 8142 int nr = btrfs_header_nritems(eb);
8121 int i, extent_type; 8143 int i, extent_type, ret;
8122 struct btrfs_key key; 8144 struct btrfs_key key;
8123 struct btrfs_file_extent_item *fi; 8145 struct btrfs_file_extent_item *fi;
8124 u64 bytenr, num_bytes; 8146 u64 bytenr, num_bytes;
8125 8147
8148 /* We can be called directly from walk_up_proc() */
8149 if (!root->fs_info->quota_enabled)
8150 return 0;
8151
8126 for (i = 0; i < nr; i++) { 8152 for (i = 0; i < nr; i++) {
8127 btrfs_item_key_to_cpu(eb, &key, i); 8153 btrfs_item_key_to_cpu(eb, &key, i);
8128 8154
@@ -8141,6 +8167,10 @@ static int account_leaf_items(struct btrfs_trans_handle *trans,
8141 continue; 8167 continue;
8142 8168
8143 num_bytes = btrfs_file_extent_disk_num_bytes(eb, fi); 8169 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;
8144 } 8174 }
8145 return 0; 8175 return 0;
8146} 8176}
@@ -8209,8 +8239,6 @@ static int adjust_slots_upwards(struct btrfs_root *root,
8209 8239
8210/* 8240/*
8211 * root_eb is the subtree root and is locked before this function is called. 8241 * 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.
8214 */ 8242 */
8215static int account_shared_subtree(struct btrfs_trans_handle *trans, 8243static int account_shared_subtree(struct btrfs_trans_handle *trans,
8216 struct btrfs_root *root, 8244 struct btrfs_root *root,
@@ -8288,6 +8316,11 @@ walk_down:
8288 btrfs_tree_read_lock(eb); 8316 btrfs_tree_read_lock(eb);
8289 btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); 8317 btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
8290 path->locks[level] = BTRFS_READ_LOCK_BLOCKING; 8318 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;
8291 } 8324 }
8292 8325
8293 if (level == 0) { 8326 if (level == 0) {
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index fd0a196c8f74..5279fdae7142 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -1462,6 +1462,8 @@ struct btrfs_qgroup_extent_record
1462 struct btrfs_qgroup_extent_record *entry; 1462 struct btrfs_qgroup_extent_record *entry;
1463 u64 bytenr = record->bytenr; 1463 u64 bytenr = record->bytenr;
1464 1464
1465 assert_spin_locked(&delayed_refs->lock);
1466
1465 while (*p) { 1467 while (*p) {
1466 parent_node = *p; 1468 parent_node = *p;
1467 entry = rb_entry(parent_node, struct btrfs_qgroup_extent_record, 1469 entry = rb_entry(parent_node, struct btrfs_qgroup_extent_record,