|
@@ -8108,21 +8108,47 @@ reada:
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * 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);
|
|
|
|
|
@@ -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;
|
|
|
}
|
|
@@ -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,
|
|
@@ -8288,6 +8316,11 @@ walk_down:
|
|
|
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) {
|