|
@@ -295,6 +295,7 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root,
|
|
|
struct btrfs_transaction *cur_trans;
|
|
|
u64 num_bytes = 0;
|
|
|
int ret;
|
|
|
+ u64 qgroup_reserved = 0;
|
|
|
|
|
|
if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR)
|
|
|
return ERR_PTR(-EROFS);
|
|
@@ -313,6 +314,14 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root,
|
|
|
* the appropriate flushing if need be.
|
|
|
*/
|
|
|
if (num_items > 0 && root != root->fs_info->chunk_root) {
|
|
|
+ if (root->fs_info->quota_enabled &&
|
|
|
+ is_fstree(root->root_key.objectid)) {
|
|
|
+ qgroup_reserved = num_items * root->leafsize;
|
|
|
+ ret = btrfs_qgroup_reserve(root, qgroup_reserved);
|
|
|
+ if (ret)
|
|
|
+ return ERR_PTR(ret);
|
|
|
+ }
|
|
|
+
|
|
|
num_bytes = btrfs_calc_trans_metadata_size(root, num_items);
|
|
|
ret = btrfs_block_rsv_add(root,
|
|
|
&root->fs_info->trans_block_rsv,
|
|
@@ -351,6 +360,7 @@ again:
|
|
|
h->block_rsv = NULL;
|
|
|
h->orig_rsv = NULL;
|
|
|
h->aborted = 0;
|
|
|
+ h->qgroup_reserved = qgroup_reserved;
|
|
|
h->delayed_ref_elem.seq = 0;
|
|
|
INIT_LIST_HEAD(&h->qgroup_ref_list);
|
|
|
|
|
@@ -524,6 +534,12 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
|
|
|
* end_transaction. Subvolume quota depends on this.
|
|
|
*/
|
|
|
WARN_ON(trans->root != root);
|
|
|
+
|
|
|
+ if (trans->qgroup_reserved) {
|
|
|
+ btrfs_qgroup_free(root, trans->qgroup_reserved);
|
|
|
+ trans->qgroup_reserved = 0;
|
|
|
+ }
|
|
|
+
|
|
|
while (count < 2) {
|
|
|
unsigned long cur = trans->delayed_ref_updates;
|
|
|
trans->delayed_ref_updates = 0;
|