aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2013-08-14 14:02:47 -0400
committerChris Mason <chris.mason@fusionio.com>2013-09-01 08:05:05 -0400
commit00361589d2eebd90fca022148c763e40d3e90871 (patch)
tree161dfa7f29d5aa907de0fee6bdc487f9a2bcb342 /fs/btrfs/extent-tree.c
parent9ffba8cda917c0158857426f0e74b64d0206aaa9 (diff)
Btrfs: avoid starting a transaction in the write path
I noticed while looking at a deadlock that we are always starting a transaction in cow_file_range(). This isn't really needed since we only need a transaction if we are doing an inline extent, or if the allocator needs to allocate a chunk. So push down all the transaction start stuff to be closer to where we actually need a transaction in all of these cases. This will hopefully reduce our write latency when we are committing often. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com> Signed-off-by: Chris Mason <chris.mason@fusionio.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c35
1 files changed, 22 insertions, 13 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 277d2c26b034..f1c1694d34b7 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -6121,8 +6121,7 @@ enum btrfs_loop_type {
6121 * ins->offset == number of blocks 6121 * ins->offset == number of blocks
6122 * Any available blocks before search_start are skipped. 6122 * Any available blocks before search_start are skipped.
6123 */ 6123 */
6124static noinline int find_free_extent(struct btrfs_trans_handle *trans, 6124static noinline int find_free_extent(struct btrfs_root *orig_root,
6125 struct btrfs_root *orig_root,
6126 u64 num_bytes, u64 empty_size, 6125 u64 num_bytes, u64 empty_size,
6127 u64 hint_byte, struct btrfs_key *ins, 6126 u64 hint_byte, struct btrfs_key *ins,
6128 u64 flags) 6127 u64 flags)
@@ -6345,10 +6344,10 @@ refill_cluster:
6345 block_group->full_stripe_len); 6344 block_group->full_stripe_len);
6346 6345
6347 /* allocate a cluster in this block group */ 6346 /* allocate a cluster in this block group */
6348 ret = btrfs_find_space_cluster(trans, root, 6347 ret = btrfs_find_space_cluster(root, block_group,
6349 block_group, last_ptr, 6348 last_ptr, search_start,
6350 search_start, num_bytes, 6349 num_bytes,
6351 aligned_cluster); 6350 aligned_cluster);
6352 if (ret == 0) { 6351 if (ret == 0) {
6353 /* 6352 /*
6354 * now pull our allocation out of this 6353 * now pull our allocation out of this
@@ -6479,17 +6478,28 @@ loop:
6479 index = 0; 6478 index = 0;
6480 loop++; 6479 loop++;
6481 if (loop == LOOP_ALLOC_CHUNK) { 6480 if (loop == LOOP_ALLOC_CHUNK) {
6481 struct btrfs_trans_handle *trans;
6482
6483 trans = btrfs_join_transaction(root);
6484 if (IS_ERR(trans)) {
6485 ret = PTR_ERR(trans);
6486 goto out;
6487 }
6488
6482 ret = do_chunk_alloc(trans, root, flags, 6489 ret = do_chunk_alloc(trans, root, flags,
6483 CHUNK_ALLOC_FORCE); 6490 CHUNK_ALLOC_FORCE);
6484 /* 6491 /*
6485 * Do not bail out on ENOSPC since we 6492 * Do not bail out on ENOSPC since we
6486 * can do more things. 6493 * can do more things.
6487 */ 6494 */
6488 if (ret < 0 && ret != -ENOSPC) { 6495 if (ret < 0 && ret != -ENOSPC)
6489 btrfs_abort_transaction(trans, 6496 btrfs_abort_transaction(trans,
6490 root, ret); 6497 root, ret);
6498 else
6499 ret = 0;
6500 btrfs_end_transaction(trans, root);
6501 if (ret)
6491 goto out; 6502 goto out;
6492 }
6493 } 6503 }
6494 6504
6495 if (loop == LOOP_NO_EMPTY_SIZE) { 6505 if (loop == LOOP_NO_EMPTY_SIZE) {
@@ -6553,8 +6563,7 @@ again:
6553 up_read(&info->groups_sem); 6563 up_read(&info->groups_sem);
6554} 6564}
6555 6565
6556int btrfs_reserve_extent(struct btrfs_trans_handle *trans, 6566int btrfs_reserve_extent(struct btrfs_root *root,
6557 struct btrfs_root *root,
6558 u64 num_bytes, u64 min_alloc_size, 6567 u64 num_bytes, u64 min_alloc_size,
6559 u64 empty_size, u64 hint_byte, 6568 u64 empty_size, u64 hint_byte,
6560 struct btrfs_key *ins, int is_data) 6569 struct btrfs_key *ins, int is_data)
@@ -6566,8 +6575,8 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans,
6566 flags = btrfs_get_alloc_profile(root, is_data); 6575 flags = btrfs_get_alloc_profile(root, is_data);
6567again: 6576again:
6568 WARN_ON(num_bytes < root->sectorsize); 6577 WARN_ON(num_bytes < root->sectorsize);
6569 ret = find_free_extent(trans, root, num_bytes, empty_size, 6578 ret = find_free_extent(root, num_bytes, empty_size, hint_byte, ins,
6570 hint_byte, ins, flags); 6579 flags);
6571 6580
6572 if (ret == -ENOSPC) { 6581 if (ret == -ENOSPC) {
6573 if (!final_tried) { 6582 if (!final_tried) {
@@ -6955,7 +6964,7 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
6955 if (IS_ERR(block_rsv)) 6964 if (IS_ERR(block_rsv))
6956 return ERR_CAST(block_rsv); 6965 return ERR_CAST(block_rsv);
6957 6966
6958 ret = btrfs_reserve_extent(trans, root, blocksize, blocksize, 6967 ret = btrfs_reserve_extent(root, blocksize, blocksize,
6959 empty_size, hint, &ins, 0); 6968 empty_size, hint, &ins, 0);
6960 if (ret) { 6969 if (ret) {
6961 unuse_block_rsv(root->fs_info, block_rsv, blocksize); 6970 unuse_block_rsv(root->fs_info, block_rsv, blocksize);