@@ -1796,6 +1796,26 @@ static int check_existing_refs(struct btrfs_trans_handle *trans,
ulist_free(roots);
btrfs_put_tree_mod_seq(fs_info, &oper->elem);
+ if (ret == 0 && oper->type == BTRFS_QGROUP_OPER_SUB_SHARED) {
+ struct btrfs_qgroup_operation *tmp;
+ struct rb_node *n;
+
+ n = &oper->n;
+ do {
+ spin_lock(&fs_info->qgroup_op_lock);
+ n = rb_next(n);
+ spin_unlock(&fs_info->qgroup_op_lock);
+ if (!n)
+ return 0;
+
+ tmp = rb_entry(n, struct btrfs_qgroup_operation, n);
+
+ if (tmp->bytenr == oper->bytenr &&
+ tmp->ref_root == oper->ref_root)
+ return 1;
+ } while (tmp->bytenr == oper->bytenr);
+ }
+
return ret;
}
As we don't record tree_mod_seq during adding delayed refs, we may get inaccurate results from backref walking, ie. btrfs_find_all_roots. For shared extents made by ioctl 'clone', removing those extents can end up warnings of qgroup accounting. Here is an example, file A and B shares the same extent, both are in "fs tree" 1. remove A and B 2. add delayed ref 'DROP A' and 'DROP B' 3. run delayed ref 'DROP A' 4. qgroup record 'DROP A' 5. run delayed ref 'DROP B' 6. qgroup record 'DROP B' 7. qgroup account on'DROP A', it runs btrfs_find_all_roots() and finds no reference on this extent, and in qgroup_account_deleted_refs() 'DROP B' has the same ref_root and is skipped then. 8. "fs tree"'s reference number is (num - extent_len), exclusive number is (num - extent_len) 9. qgroup account on 'DROP B', it's the last ref on this extent, thus 10."fs tree"'s reference number is (num - extent_len), exclusive number is (num - extent_len) So "fs tree" 's numbers are wrong. This adds an additional check in check_existing_ref() so that we can detect the above case and make it right. Signed-off-by: Liu Bo <bo.li.liu@oracle.com> --- fs/btrfs/qgroup.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)