aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2011-04-06 14:53:07 -0400
committerJosef Bacik <josef@redhat.com>2011-04-08 13:00:41 -0400
commit16d299ac7446b5a75c5683a9ae11d7907d444c86 (patch)
tree95358c2fdd7af672ec68c18fb43e2e90a7cd4551
parent1ae399382512b3e4d6c923e53da9e45935577040 (diff)
Btrfs: reuse the extent_map we found when calling btrfs_get_extent
In btrfs_get_block_direct we call btrfs_get_extent to lookup the extent for the range that we are looking for. If we don't find an extent, btrfs_get_extent will insert a extent_map for that area and mark it as a hole. So it does the job of allocating a new extent map and inserting it into the io tree. But if we're creating a new extent we free it up and redo all of that work. So instead pass the em to btrfs_new_extent_direct(), and if it will work just allocate the disk space and set it up properly and bypass the freeing/allocating of a new extent map and the expensive operation of inserting the thing into the io_tree. Thanks, Signed-off-by: Josef Bacik <josef@redhat.com>
-rw-r--r--fs/btrfs/inode.c36
1 files changed, 28 insertions, 8 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 2bb76c6157a4..24310c9cb14f 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -5445,17 +5445,30 @@ out:
5445} 5445}
5446 5446
5447static struct extent_map *btrfs_new_extent_direct(struct inode *inode, 5447static struct extent_map *btrfs_new_extent_direct(struct inode *inode,
5448 struct extent_map *em,
5448 u64 start, u64 len) 5449 u64 start, u64 len)
5449{ 5450{
5450 struct btrfs_root *root = BTRFS_I(inode)->root; 5451 struct btrfs_root *root = BTRFS_I(inode)->root;
5451 struct btrfs_trans_handle *trans; 5452 struct btrfs_trans_handle *trans;
5452 struct extent_map *em;
5453 struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; 5453 struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
5454 struct btrfs_key ins; 5454 struct btrfs_key ins;
5455 u64 alloc_hint; 5455 u64 alloc_hint;
5456 int ret; 5456 int ret;
5457 bool insert = false;
5457 5458
5458 btrfs_drop_extent_cache(inode, start, start + len - 1, 0); 5459 /*
5460 * Ok if the extent map we looked up is a hole and is for the exact
5461 * range we want, there is no reason to allocate a new one, however if
5462 * it is not right then we need to free this one and drop the cache for
5463 * our range.
5464 */
5465 if (em->block_start != EXTENT_MAP_HOLE || em->start != start ||
5466 em->len != len) {
5467 free_extent_map(em);
5468 em = NULL;
5469 insert = true;
5470 btrfs_drop_extent_cache(inode, start, start + len - 1, 0);
5471 }
5459 5472
5460 trans = btrfs_join_transaction(root, 0); 5473 trans = btrfs_join_transaction(root, 0);
5461 if (IS_ERR(trans)) 5474 if (IS_ERR(trans))
@@ -5471,10 +5484,12 @@ static struct extent_map *btrfs_new_extent_direct(struct inode *inode,
5471 goto out; 5484 goto out;
5472 } 5485 }
5473 5486
5474 em = alloc_extent_map(GFP_NOFS);
5475 if (!em) { 5487 if (!em) {
5476 em = ERR_PTR(-ENOMEM); 5488 em = alloc_extent_map(GFP_NOFS);
5477 goto out; 5489 if (!em) {
5490 em = ERR_PTR(-ENOMEM);
5491 goto out;
5492 }
5478 } 5493 }
5479 5494
5480 em->start = start; 5495 em->start = start;
@@ -5484,9 +5499,15 @@ static struct extent_map *btrfs_new_extent_direct(struct inode *inode,
5484 em->block_start = ins.objectid; 5499 em->block_start = ins.objectid;
5485 em->block_len = ins.offset; 5500 em->block_len = ins.offset;
5486 em->bdev = root->fs_info->fs_devices->latest_bdev; 5501 em->bdev = root->fs_info->fs_devices->latest_bdev;
5502
5503 /*
5504 * We need to do this because if we're using the original em we searched
5505 * for, we could have EXTENT_FLAG_VACANCY set, and we don't want that.
5506 */
5507 em->flags = 0;
5487 set_bit(EXTENT_FLAG_PINNED, &em->flags); 5508 set_bit(EXTENT_FLAG_PINNED, &em->flags);
5488 5509
5489 while (1) { 5510 while (insert) {
5490 write_lock(&em_tree->lock); 5511 write_lock(&em_tree->lock);
5491 ret = add_extent_mapping(em_tree, em); 5512 ret = add_extent_mapping(em_tree, em);
5492 write_unlock(&em_tree->lock); 5513 write_unlock(&em_tree->lock);
@@ -5704,8 +5725,7 @@ must_cow:
5704 * it above 5725 * it above
5705 */ 5726 */
5706 len = bh_result->b_size; 5727 len = bh_result->b_size;
5707 free_extent_map(em); 5728 em = btrfs_new_extent_direct(inode, em, start, len);
5708 em = btrfs_new_extent_direct(inode, start, len);
5709 if (IS_ERR(em)) 5729 if (IS_ERR(em))
5710 return PTR_ERR(em); 5730 return PTR_ERR(em);
5711 len = min(len, em->len - (start - em->start)); 5731 len = min(len, em->len - (start - em->start));