aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorArne Jansen <sensille@gmx.net>2011-09-14 09:44:05 -0400
committerJan Schmidt <list.btrfs@jan-o-sch.net>2012-07-12 04:54:39 -0400
commitc556723794b3487a79de1ecd6354975b1389f5ff (patch)
tree99b363645203df002ab421bbd7be3b56dbd1e6ef /fs/btrfs
parent546adb0d817c34dc2be3a7cb5bba8771f837a562 (diff)
Btrfs: hooks to reserve qgroup space
Like block reserves, reserve a small piece of space on each transaction start and for delalloc. These are the hooks that can actually return EDQUOT to the user. The amount of space reserved is tracked in the transaction handle. Signed-off-by: Arne Jansen <sensille@gmx.net>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/extent-tree.c12
-rw-r--r--fs/btrfs/transaction.c16
-rw-r--r--fs/btrfs/transaction.h1
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 {
50struct btrfs_trans_handle { 50struct 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;