diff options
author | Josef Bacik <josef@redhat.com> | 2011-08-08 13:46:15 -0400 |
---|---|---|
committer | Josef Bacik <josef@redhat.com> | 2011-10-19 15:12:35 -0400 |
commit | 907cbcebd4e5f641faf08601f216b1ceb6cb3bdf (patch) | |
tree | 2f605e19e8d44360c9eb4033adda940e9e5ab007 /fs/btrfs/inode.c | |
parent | 13553e5221d6901a33b3f2157a389de085c161fe (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.c | 58 |
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 | 6616 | end_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; |