diff options
-rw-r--r-- | fs/btrfs/extent-tree.c | 12 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 16 | ||||
-rw-r--r-- | fs/btrfs/transaction.h | 1 |
3 files changed, 29 insertions, 0 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index c08337a83ace..2ce16f97730a 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -4565,6 +4565,13 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) | |||
4565 | csum_bytes = BTRFS_I(inode)->csum_bytes; | 4565 | csum_bytes = BTRFS_I(inode)->csum_bytes; |
4566 | spin_unlock(&BTRFS_I(inode)->lock); | 4566 | spin_unlock(&BTRFS_I(inode)->lock); |
4567 | 4567 | ||
4568 | if (root->fs_info->quota_enabled) { | ||
4569 | ret = btrfs_qgroup_reserve(root, num_bytes + | ||
4570 | nr_extents * root->leafsize); | ||
4571 | if (ret) | ||
4572 | return ret; | ||
4573 | } | ||
4574 | |||
4568 | ret = reserve_metadata_bytes(root, block_rsv, to_reserve, flush); | 4575 | ret = reserve_metadata_bytes(root, block_rsv, to_reserve, flush); |
4569 | if (ret) { | 4576 | if (ret) { |
4570 | u64 to_free = 0; | 4577 | u64 to_free = 0; |
@@ -4643,6 +4650,11 @@ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes) | |||
4643 | 4650 | ||
4644 | trace_btrfs_space_reservation(root->fs_info, "delalloc", | 4651 | trace_btrfs_space_reservation(root->fs_info, "delalloc", |
4645 | btrfs_ino(inode), to_free, 0); | 4652 | btrfs_ino(inode), to_free, 0); |
4653 | if (root->fs_info->quota_enabled) { | ||
4654 | btrfs_qgroup_free(root, num_bytes + | ||
4655 | dropped * root->leafsize); | ||
4656 | } | ||
4657 | |||
4646 | btrfs_block_rsv_release(root, &root->fs_info->delalloc_block_rsv, | 4658 | btrfs_block_rsv_release(root, &root->fs_info->delalloc_block_rsv, |
4647 | to_free); | 4659 | to_free); |
4648 | } | 4660 | } |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 21c768cb443f..f1e29fbd5317 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -295,6 +295,7 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root, | |||
295 | struct btrfs_transaction *cur_trans; | 295 | struct btrfs_transaction *cur_trans; |
296 | u64 num_bytes = 0; | 296 | u64 num_bytes = 0; |
297 | int ret; | 297 | int ret; |
298 | u64 qgroup_reserved = 0; | ||
298 | 299 | ||
299 | if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) | 300 | if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) |
300 | return ERR_PTR(-EROFS); | 301 | return ERR_PTR(-EROFS); |
@@ -313,6 +314,14 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root, | |||
313 | * the appropriate flushing if need be. | 314 | * the appropriate flushing if need be. |
314 | */ | 315 | */ |
315 | if (num_items > 0 && root != root->fs_info->chunk_root) { | 316 | if (num_items > 0 && root != root->fs_info->chunk_root) { |
317 | if (root->fs_info->quota_enabled && | ||
318 | is_fstree(root->root_key.objectid)) { | ||
319 | qgroup_reserved = num_items * root->leafsize; | ||
320 | ret = btrfs_qgroup_reserve(root, qgroup_reserved); | ||
321 | if (ret) | ||
322 | return ERR_PTR(ret); | ||
323 | } | ||
324 | |||
316 | num_bytes = btrfs_calc_trans_metadata_size(root, num_items); | 325 | num_bytes = btrfs_calc_trans_metadata_size(root, num_items); |
317 | ret = btrfs_block_rsv_add(root, | 326 | ret = btrfs_block_rsv_add(root, |
318 | &root->fs_info->trans_block_rsv, | 327 | &root->fs_info->trans_block_rsv, |
@@ -351,6 +360,7 @@ again: | |||
351 | h->block_rsv = NULL; | 360 | h->block_rsv = NULL; |
352 | h->orig_rsv = NULL; | 361 | h->orig_rsv = NULL; |
353 | h->aborted = 0; | 362 | h->aborted = 0; |
363 | h->qgroup_reserved = qgroup_reserved; | ||
354 | h->delayed_ref_elem.seq = 0; | 364 | h->delayed_ref_elem.seq = 0; |
355 | INIT_LIST_HEAD(&h->qgroup_ref_list); | 365 | INIT_LIST_HEAD(&h->qgroup_ref_list); |
356 | 366 | ||
@@ -524,6 +534,12 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
524 | * end_transaction. Subvolume quota depends on this. | 534 | * end_transaction. Subvolume quota depends on this. |
525 | */ | 535 | */ |
526 | WARN_ON(trans->root != root); | 536 | WARN_ON(trans->root != root); |
537 | |||
538 | if (trans->qgroup_reserved) { | ||
539 | btrfs_qgroup_free(root, trans->qgroup_reserved); | ||
540 | trans->qgroup_reserved = 0; | ||
541 | } | ||
542 | |||
527 | while (count < 2) { | 543 | while (count < 2) { |
528 | unsigned long cur = trans->delayed_ref_updates; | 544 | unsigned long cur = trans->delayed_ref_updates; |
529 | trans->delayed_ref_updates = 0; | 545 | trans->delayed_ref_updates = 0; |
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index 16ba00842c38..2759e0572c5c 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h | |||
@@ -50,6 +50,7 @@ struct btrfs_transaction { | |||
50 | struct btrfs_trans_handle { | 50 | struct btrfs_trans_handle { |
51 | u64 transid; | 51 | u64 transid; |
52 | u64 bytes_reserved; | 52 | u64 bytes_reserved; |
53 | u64 qgroup_reserved; | ||
53 | unsigned long use_count; | 54 | unsigned long use_count; |
54 | unsigned long blocks_reserved; | 55 | unsigned long blocks_reserved; |
55 | unsigned long blocks_used; | 56 | unsigned long blocks_used; |