@@ -1379,6 +1379,14 @@ int btrfs_qgroup_record_ref(struct btrfs_trans_handle *trans,
trace_btrfs_qgroup_record_ref(oper);
+ if (type == BTRFS_QGROUP_OPER_ADD_SHARED ||
+ type == BTRFS_QGROUP_OPER_SUB_SHARED) {
+ ret = btrfs_find_all_roots(trans, fs_info, NULL, bytenr, node_seq,
+ &oper->new_roots, 1);
+ if (ret < 0)
+ goto out;
+ }
+
if (type == BTRFS_QGROUP_OPER_SUB_SUBTREE) {
/*
* If any operation for this bytenr/ref_root combo
@@ -1390,8 +1398,8 @@ int btrfs_qgroup_record_ref(struct btrfs_trans_handle *trans,
* drop snapshot.
*/
if (qgroup_oper_exists(fs_info, oper)) {
- kfree(oper);
- return 0;
+ ret = 0;
+ goto out;
}
}
@@ -1399,8 +1407,7 @@ int btrfs_qgroup_record_ref(struct btrfs_trans_handle *trans,
if (ret) {
/* Shouldn't happen so have an assert for developers */
ASSERT(0);
- kfree(oper);
- return ret;
+ goto out;
}
list_add_tail(&oper->list, &trans->qgroup_ref_list);
@@ -1408,6 +1415,11 @@ int btrfs_qgroup_record_ref(struct btrfs_trans_handle *trans,
btrfs_get_tree_mod_seq(fs_info, &oper->elem);
return 0;
+out:
+ if (ret < 0)
+ ulist_free(oper->new_roots);
+ kfree(oper);
+ return ret;
}
/*
One of problems in old qgroup is, we can only get a view on the final results when we are going to adjust qgroup accounting. This makes the following operataion get wrong result: 1. Subvol 257 add an exclusive extent A. 2. Subvol 258 add a shared reference to extent A. 3. Subvol 259 add a shared reference to extent A. 4. Sync Subvol 258 and 259's qgroup data is consistent, but subvol 257 still have exclusive reference on extent A. The problem happens on step 2, where we should decrease exclusive reference number, but old implement just record the operation type, and let qgroup get roots reference number at step 4, where extent A is finally referred by 3 roots. At the time quota running, it can only see the final result, extent A is referred by 3 roots (new_refcnt = 3) and before that, referred by 2 roots(old_refcnt = 2). Quota will only decrease exclusive refer when old_refcnt == old_roots. However in that case, old_refcnt is the final one, not the one in before step 2, causing the exclusive counts of 257 untouched. This patch will records root reference counts at qgroup_record_ref() timing, which will give correct result. Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com> --- fs/btrfs/qgroup.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-)