aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2011-08-08 13:46:15 -0400
committerJosef Bacik <josef@redhat.com>2011-10-19 15:12:35 -0400
commit907cbcebd4e5f641faf08601f216b1ceb6cb3bdf (patch)
tree2f605e19e8d44360c9eb4033adda940e9e5ab007 /fs/btrfs/inode.c
parent13553e5221d6901a33b3f2157a389de085c161fe (diff)
Btrfs: optimize how we account for space in truncate
Currently we're starting and stopping a transaction for no real reason, so kill that and just reserve enough space as if we can truncate all in one transaction. Also use btrfs_block_rsv_check() for our reserve to minimize the amount of space we may have to allocate for our slack space. Thanks, Signed-off-by: Josef Bacik <josef@redhat.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c58
1 files changed, 29 insertions, 29 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index fe3891e240b3..4d057c084de6 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -6482,6 +6482,7 @@ static int btrfs_truncate(struct inode *inode)
6482 struct btrfs_trans_handle *trans; 6482 struct btrfs_trans_handle *trans;
6483 unsigned long nr; 6483 unsigned long nr;
6484 u64 mask = root->sectorsize - 1; 6484 u64 mask = root->sectorsize - 1;
6485 u64 min_size = btrfs_calc_trans_metadata_size(root, 2);
6485 6486
6486 ret = btrfs_truncate_page(inode->i_mapping, inode->i_size); 6487 ret = btrfs_truncate_page(inode->i_mapping, inode->i_size);
6487 if (ret) 6488 if (ret)
@@ -6530,17 +6531,21 @@ static int btrfs_truncate(struct inode *inode)
6530 if (!rsv) 6531 if (!rsv)
6531 return -ENOMEM; 6532 return -ENOMEM;
6532 6533
6533 trans = btrfs_start_transaction(root, 4); 6534 /*
6535 * 2 for the truncate slack space
6536 * 1 for the orphan item we're going to add
6537 * 1 for the orphan item deletion
6538 * 1 for updating the inode.
6539 */
6540 trans = btrfs_start_transaction(root, 5);
6534 if (IS_ERR(trans)) { 6541 if (IS_ERR(trans)) {
6535 err = PTR_ERR(trans); 6542 err = PTR_ERR(trans);
6536 goto out; 6543 goto out;
6537 } 6544 }
6538 6545
6539 /* 6546 /* Migrate the slack space for the truncate to our reserve */
6540 * Reserve space for the truncate process. Truncate should be adding 6547 ret = btrfs_block_rsv_migrate(&root->fs_info->trans_block_rsv, rsv,
6541 * space, but if there are snapshots it may end up using space. 6548 min_size);
6542 */
6543 ret = btrfs_truncate_reserve_metadata(trans, root, rsv);
6544 BUG_ON(ret); 6549 BUG_ON(ret);
6545 6550
6546 ret = btrfs_orphan_add(trans, inode); 6551 ret = btrfs_orphan_add(trans, inode);
@@ -6549,21 +6554,6 @@ static int btrfs_truncate(struct inode *inode)
6549 goto out; 6554 goto out;
6550 } 6555 }
6551 6556
6552 nr = trans->blocks_used;
6553 btrfs_end_transaction(trans, root);
6554 btrfs_btree_balance_dirty(root, nr);
6555
6556 /*
6557 * Ok so we've already migrated our bytes over for the truncate, so here
6558 * just reserve the one slot we need for updating the inode.
6559 */
6560 trans = btrfs_start_transaction(root, 1);
6561 if (IS_ERR(trans)) {
6562 err = PTR_ERR(trans);
6563 goto out;
6564 }
6565 trans->block_rsv = rsv;
6566
6567 /* 6557 /*
6568 * setattr is responsible for setting the ordered_data_close flag, 6558 * setattr is responsible for setting the ordered_data_close flag,
6569 * but that is only tested during the last file release. That 6559 * but that is only tested during the last file release. That
@@ -6585,20 +6575,30 @@ static int btrfs_truncate(struct inode *inode)
6585 btrfs_add_ordered_operation(trans, root, inode); 6575 btrfs_add_ordered_operation(trans, root, inode);
6586 6576
6587 while (1) { 6577 while (1) {
6578 ret = btrfs_block_rsv_check(trans, root, rsv, min_size, 0);
6579 if (ret) {
6580 /*
6581 * This can only happen with the original transaction we
6582 * started above, every other time we shouldn't have a
6583 * transaction started yet.
6584 */
6585 if (ret == -EAGAIN)
6586 goto end_trans;
6587 err = ret;
6588 break;
6589 }
6590
6588 if (!trans) { 6591 if (!trans) {
6589 trans = btrfs_start_transaction(root, 3); 6592 /* Just need the 1 for updating the inode */
6593 trans = btrfs_start_transaction(root, 1);
6590 if (IS_ERR(trans)) { 6594 if (IS_ERR(trans)) {
6591 err = PTR_ERR(trans); 6595 err = PTR_ERR(trans);
6592 goto out; 6596 goto out;
6593 } 6597 }
6594
6595 ret = btrfs_truncate_reserve_metadata(trans, root,
6596 rsv);
6597 BUG_ON(ret);
6598
6599 trans->block_rsv = rsv;
6600 } 6598 }
6601 6599
6600 trans->block_rsv = rsv;
6601
6602 ret = btrfs_truncate_inode_items(trans, root, inode, 6602 ret = btrfs_truncate_inode_items(trans, root, inode,
6603 inode->i_size, 6603 inode->i_size,
6604 BTRFS_EXTENT_DATA_KEY); 6604 BTRFS_EXTENT_DATA_KEY);
@@ -6613,7 +6613,7 @@ static int btrfs_truncate(struct inode *inode)
6613 err = ret; 6613 err = ret;
6614 break; 6614 break;
6615 } 6615 }
6616 6616end_trans:
6617 nr = trans->blocks_used; 6617 nr = trans->blocks_used;
6618 btrfs_end_transaction(trans, root); 6618 btrfs_end_transaction(trans, root);
6619 trans = NULL; 6619 trans = NULL;