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 | |
parent | 13553e5221d6901a33b3f2157a389de085c161fe (diff) | |
download | linux-stable-907cbcebd4e5f641faf08601f216b1ceb6cb3bdf.tar.gz linux-stable-907cbcebd4e5f641faf08601f216b1ceb6cb3bdf.tar.bz2 linux-stable-907cbcebd4e5f641faf08601f216b1ceb6cb3bdf.zip |
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')
-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) struct btrfs_trans_handle *trans; unsigned long nr; u64 mask = root->sectorsize - 1; + u64 min_size = btrfs_calc_trans_metadata_size(root, 2); ret = btrfs_truncate_page(inode->i_mapping, inode->i_size); if (ret) @@ -6530,17 +6531,21 @@ static int btrfs_truncate(struct inode *inode) if (!rsv) return -ENOMEM; - trans = btrfs_start_transaction(root, 4); + /* + * 2 for the truncate slack space + * 1 for the orphan item we're going to add + * 1 for the orphan item deletion + * 1 for updating the inode. + */ + trans = btrfs_start_transaction(root, 5); if (IS_ERR(trans)) { err = PTR_ERR(trans); goto out; } - /* - * Reserve space for the truncate process. Truncate should be adding - * space, but if there are snapshots it may end up using space. - */ - ret = btrfs_truncate_reserve_metadata(trans, root, rsv); + /* Migrate the slack space for the truncate to our reserve */ + ret = btrfs_block_rsv_migrate(&root->fs_info->trans_block_rsv, rsv, + min_size); BUG_ON(ret); ret = btrfs_orphan_add(trans, inode); @@ -6549,21 +6554,6 @@ static int btrfs_truncate(struct inode *inode) goto out; } - nr = trans->blocks_used; - btrfs_end_transaction(trans, root); - btrfs_btree_balance_dirty(root, nr); - - /* - * Ok so we've already migrated our bytes over for the truncate, so here - * just reserve the one slot we need for updating the inode. - */ - trans = btrfs_start_transaction(root, 1); - if (IS_ERR(trans)) { - err = PTR_ERR(trans); - goto out; - } - trans->block_rsv = rsv; - /* * setattr is responsible for setting the ordered_data_close flag, * but that is only tested during the last file release. That @@ -6585,20 +6575,30 @@ static int btrfs_truncate(struct inode *inode) btrfs_add_ordered_operation(trans, root, inode); while (1) { + ret = btrfs_block_rsv_check(trans, root, rsv, min_size, 0); + if (ret) { + /* + * This can only happen with the original transaction we + * started above, every other time we shouldn't have a + * transaction started yet. + */ + if (ret == -EAGAIN) + goto end_trans; + err = ret; + break; + } + if (!trans) { - trans = btrfs_start_transaction(root, 3); + /* Just need the 1 for updating the inode */ + trans = btrfs_start_transaction(root, 1); if (IS_ERR(trans)) { err = PTR_ERR(trans); goto out; } - - ret = btrfs_truncate_reserve_metadata(trans, root, - rsv); - BUG_ON(ret); - - trans->block_rsv = rsv; } + trans->block_rsv = rsv; + ret = btrfs_truncate_inode_items(trans, root, inode, inode->i_size, BTRFS_EXTENT_DATA_KEY); @@ -6613,7 +6613,7 @@ static int btrfs_truncate(struct inode *inode) err = ret; break; } - +end_trans: nr = trans->blocks_used; btrfs_end_transaction(trans, root); trans = NULL; |