diff options
author | Josef Bacik <jbacik@fusionio.com> | 2013-08-14 14:02:47 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2013-09-01 08:05:05 -0400 |
commit | 00361589d2eebd90fca022148c763e40d3e90871 (patch) | |
tree | 161dfa7f29d5aa907de0fee6bdc487f9a2bcb342 /fs/btrfs | |
parent | 9ffba8cda917c0158857426f0e74b64d0206aaa9 (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')
-rw-r--r-- | fs/btrfs/ctree.h | 11 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 35 | ||||
-rw-r--r-- | fs/btrfs/file.c | 11 | ||||
-rw-r--r-- | fs/btrfs/free-space-cache.c | 3 | ||||
-rw-r--r-- | fs/btrfs/free-space-cache.h | 3 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 217 |
6 files changed, 101 insertions, 179 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 063e48587126..7c93d9f13812 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -3165,11 +3165,9 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans, | |||
3165 | struct btrfs_root *root, | 3165 | struct btrfs_root *root, |
3166 | u64 root_objectid, u64 owner, u64 offset, | 3166 | u64 root_objectid, u64 owner, u64 offset, |
3167 | struct btrfs_key *ins); | 3167 | struct btrfs_key *ins); |
3168 | int btrfs_reserve_extent(struct btrfs_trans_handle *trans, | 3168 | int btrfs_reserve_extent(struct btrfs_root *root, u64 num_bytes, |
3169 | struct btrfs_root *root, | 3169 | u64 min_alloc_size, u64 empty_size, u64 hint_byte, |
3170 | u64 num_bytes, u64 min_alloc_size, | 3170 | struct btrfs_key *ins, int is_data); |
3171 | u64 empty_size, u64 hint_byte, | ||
3172 | struct btrfs_key *ins, int is_data); | ||
3173 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 3171 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
3174 | struct extent_buffer *buf, int full_backref, int for_cow); | 3172 | struct extent_buffer *buf, int full_backref, int for_cow); |
3175 | int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 3173 | int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
@@ -3612,8 +3610,7 @@ void btrfs_wait_and_free_delalloc_work(struct btrfs_delalloc_work *work); | |||
3612 | struct extent_map *btrfs_get_extent_fiemap(struct inode *inode, struct page *page, | 3610 | struct extent_map *btrfs_get_extent_fiemap(struct inode *inode, struct page *page, |
3613 | size_t pg_offset, u64 start, u64 len, | 3611 | size_t pg_offset, u64 start, u64 len, |
3614 | int create); | 3612 | int create); |
3615 | noinline int can_nocow_extent(struct btrfs_trans_handle *trans, | 3613 | noinline int can_nocow_extent(struct inode *inode, u64 offset, u64 *len, |
3616 | struct inode *inode, u64 offset, u64 *len, | ||
3617 | u64 *orig_start, u64 *orig_block_len, | 3614 | u64 *orig_start, u64 *orig_block_len, |
3618 | u64 *ram_bytes); | 3615 | u64 *ram_bytes); |
3619 | 3616 | ||
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 | */ |
6124 | static noinline int find_free_extent(struct btrfs_trans_handle *trans, | 6124 | static 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 | ||
6556 | int btrfs_reserve_extent(struct btrfs_trans_handle *trans, | 6566 | int 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); |
6567 | again: | 6576 | again: |
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); |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 8cc941e5b3e1..5e7ea996f105 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -1339,7 +1339,6 @@ fail: | |||
1339 | static noinline int check_can_nocow(struct inode *inode, loff_t pos, | 1339 | static noinline int check_can_nocow(struct inode *inode, loff_t pos, |
1340 | size_t *write_bytes) | 1340 | size_t *write_bytes) |
1341 | { | 1341 | { |
1342 | struct btrfs_trans_handle *trans; | ||
1343 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1342 | struct btrfs_root *root = BTRFS_I(inode)->root; |
1344 | struct btrfs_ordered_extent *ordered; | 1343 | struct btrfs_ordered_extent *ordered; |
1345 | u64 lockstart, lockend; | 1344 | u64 lockstart, lockend; |
@@ -1361,16 +1360,8 @@ static noinline int check_can_nocow(struct inode *inode, loff_t pos, | |||
1361 | btrfs_put_ordered_extent(ordered); | 1360 | btrfs_put_ordered_extent(ordered); |
1362 | } | 1361 | } |
1363 | 1362 | ||
1364 | trans = btrfs_join_transaction(root); | ||
1365 | if (IS_ERR(trans)) { | ||
1366 | unlock_extent(&BTRFS_I(inode)->io_tree, lockstart, lockend); | ||
1367 | return PTR_ERR(trans); | ||
1368 | } | ||
1369 | |||
1370 | num_bytes = lockend - lockstart + 1; | 1363 | num_bytes = lockend - lockstart + 1; |
1371 | ret = can_nocow_extent(trans, inode, lockstart, &num_bytes, NULL, NULL, | 1364 | ret = can_nocow_extent(inode, lockstart, &num_bytes, NULL, NULL, NULL); |
1372 | NULL); | ||
1373 | btrfs_end_transaction(trans, root); | ||
1374 | if (ret <= 0) { | 1365 | if (ret <= 0) { |
1375 | ret = 0; | 1366 | ret = 0; |
1376 | } else { | 1367 | } else { |
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index b21a3cd667d8..25f906fd0221 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
@@ -2525,8 +2525,7 @@ setup_cluster_bitmap(struct btrfs_block_group_cache *block_group, | |||
2525 | * returns zero and sets up cluster if things worked out, otherwise | 2525 | * returns zero and sets up cluster if things worked out, otherwise |
2526 | * it returns -enospc | 2526 | * it returns -enospc |
2527 | */ | 2527 | */ |
2528 | int btrfs_find_space_cluster(struct btrfs_trans_handle *trans, | 2528 | int btrfs_find_space_cluster(struct btrfs_root *root, |
2529 | struct btrfs_root *root, | ||
2530 | struct btrfs_block_group_cache *block_group, | 2529 | struct btrfs_block_group_cache *block_group, |
2531 | struct btrfs_free_cluster *cluster, | 2530 | struct btrfs_free_cluster *cluster, |
2532 | u64 offset, u64 bytes, u64 empty_size) | 2531 | u64 offset, u64 bytes, u64 empty_size) |
diff --git a/fs/btrfs/free-space-cache.h b/fs/btrfs/free-space-cache.h index 894116b71304..4acfb19ba4ee 100644 --- a/fs/btrfs/free-space-cache.h +++ b/fs/btrfs/free-space-cache.h | |||
@@ -98,8 +98,7 @@ u64 btrfs_find_space_for_alloc(struct btrfs_block_group_cache *block_group, | |||
98 | u64 btrfs_find_ino_for_alloc(struct btrfs_root *fs_root); | 98 | u64 btrfs_find_ino_for_alloc(struct btrfs_root *fs_root); |
99 | void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group, | 99 | void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group, |
100 | u64 bytes); | 100 | u64 bytes); |
101 | int btrfs_find_space_cluster(struct btrfs_trans_handle *trans, | 101 | int btrfs_find_space_cluster(struct btrfs_root *root, |
102 | struct btrfs_root *root, | ||
103 | struct btrfs_block_group_cache *block_group, | 102 | struct btrfs_block_group_cache *block_group, |
104 | struct btrfs_free_cluster *cluster, | 103 | struct btrfs_free_cluster *cluster, |
105 | u64 offset, u64 bytes, u64 empty_size); | 104 | u64 offset, u64 bytes, u64 empty_size); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index de7085bc28f6..264feefa0290 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -230,12 +230,13 @@ fail: | |||
230 | * does the checks required to make sure the data is small enough | 230 | * does the checks required to make sure the data is small enough |
231 | * to fit as an inline extent. | 231 | * to fit as an inline extent. |
232 | */ | 232 | */ |
233 | static noinline int cow_file_range_inline(struct btrfs_trans_handle *trans, | 233 | static noinline int cow_file_range_inline(struct btrfs_root *root, |
234 | struct btrfs_root *root, | 234 | struct inode *inode, u64 start, |
235 | struct inode *inode, u64 start, u64 end, | 235 | u64 end, size_t compressed_size, |
236 | size_t compressed_size, int compress_type, | 236 | int compress_type, |
237 | struct page **compressed_pages) | 237 | struct page **compressed_pages) |
238 | { | 238 | { |
239 | struct btrfs_trans_handle *trans; | ||
239 | u64 isize = i_size_read(inode); | 240 | u64 isize = i_size_read(inode); |
240 | u64 actual_end = min(end + 1, isize); | 241 | u64 actual_end = min(end + 1, isize); |
241 | u64 inline_len = actual_end - start; | 242 | u64 inline_len = actual_end - start; |
@@ -256,9 +257,16 @@ static noinline int cow_file_range_inline(struct btrfs_trans_handle *trans, | |||
256 | return 1; | 257 | return 1; |
257 | } | 258 | } |
258 | 259 | ||
260 | trans = btrfs_join_transaction(root); | ||
261 | if (IS_ERR(trans)) | ||
262 | return PTR_ERR(trans); | ||
263 | trans->block_rsv = &root->fs_info->delalloc_block_rsv; | ||
264 | |||
259 | ret = btrfs_drop_extents(trans, root, inode, start, aligned_end, 1); | 265 | ret = btrfs_drop_extents(trans, root, inode, start, aligned_end, 1); |
260 | if (ret) | 266 | if (ret) { |
261 | return ret; | 267 | btrfs_abort_transaction(trans, root, ret); |
268 | goto out; | ||
269 | } | ||
262 | 270 | ||
263 | if (isize > actual_end) | 271 | if (isize > actual_end) |
264 | inline_len = min_t(u64, isize, actual_end); | 272 | inline_len = min_t(u64, isize, actual_end); |
@@ -267,15 +275,18 @@ static noinline int cow_file_range_inline(struct btrfs_trans_handle *trans, | |||
267 | compress_type, compressed_pages); | 275 | compress_type, compressed_pages); |
268 | if (ret && ret != -ENOSPC) { | 276 | if (ret && ret != -ENOSPC) { |
269 | btrfs_abort_transaction(trans, root, ret); | 277 | btrfs_abort_transaction(trans, root, ret); |
270 | return ret; | 278 | goto out; |
271 | } else if (ret == -ENOSPC) { | 279 | } else if (ret == -ENOSPC) { |
272 | return 1; | 280 | ret = 1; |
281 | goto out; | ||
273 | } | 282 | } |
274 | 283 | ||
275 | set_bit(BTRFS_INODE_NEEDS_FULL_SYNC, &BTRFS_I(inode)->runtime_flags); | 284 | set_bit(BTRFS_INODE_NEEDS_FULL_SYNC, &BTRFS_I(inode)->runtime_flags); |
276 | btrfs_delalloc_release_metadata(inode, end + 1 - start); | 285 | btrfs_delalloc_release_metadata(inode, end + 1 - start); |
277 | btrfs_drop_extent_cache(inode, start, aligned_end - 1, 0); | 286 | btrfs_drop_extent_cache(inode, start, aligned_end - 1, 0); |
278 | return 0; | 287 | out: |
288 | btrfs_end_transaction(trans, root); | ||
289 | return ret; | ||
279 | } | 290 | } |
280 | 291 | ||
281 | struct async_extent { | 292 | struct async_extent { |
@@ -343,7 +354,6 @@ static noinline int compress_file_range(struct inode *inode, | |||
343 | int *num_added) | 354 | int *num_added) |
344 | { | 355 | { |
345 | struct btrfs_root *root = BTRFS_I(inode)->root; | 356 | struct btrfs_root *root = BTRFS_I(inode)->root; |
346 | struct btrfs_trans_handle *trans; | ||
347 | u64 num_bytes; | 357 | u64 num_bytes; |
348 | u64 blocksize = root->sectorsize; | 358 | u64 blocksize = root->sectorsize; |
349 | u64 actual_end; | 359 | u64 actual_end; |
@@ -461,25 +471,16 @@ again: | |||
461 | } | 471 | } |
462 | cont: | 472 | cont: |
463 | if (start == 0) { | 473 | if (start == 0) { |
464 | trans = btrfs_join_transaction(root); | ||
465 | if (IS_ERR(trans)) { | ||
466 | ret = PTR_ERR(trans); | ||
467 | trans = NULL; | ||
468 | goto cleanup_and_out; | ||
469 | } | ||
470 | trans->block_rsv = &root->fs_info->delalloc_block_rsv; | ||
471 | |||
472 | /* lets try to make an inline extent */ | 474 | /* lets try to make an inline extent */ |
473 | if (ret || total_in < (actual_end - start)) { | 475 | if (ret || total_in < (actual_end - start)) { |
474 | /* we didn't compress the entire range, try | 476 | /* we didn't compress the entire range, try |
475 | * to make an uncompressed inline extent. | 477 | * to make an uncompressed inline extent. |
476 | */ | 478 | */ |
477 | ret = cow_file_range_inline(trans, root, inode, | 479 | ret = cow_file_range_inline(root, inode, start, end, |
478 | start, end, 0, 0, NULL); | 480 | 0, 0, NULL); |
479 | } else { | 481 | } else { |
480 | /* try making a compressed inline extent */ | 482 | /* try making a compressed inline extent */ |
481 | ret = cow_file_range_inline(trans, root, inode, | 483 | ret = cow_file_range_inline(root, inode, start, end, |
482 | start, end, | ||
483 | total_compressed, | 484 | total_compressed, |
484 | compress_type, pages); | 485 | compress_type, pages); |
485 | } | 486 | } |
@@ -498,10 +499,8 @@ cont: | |||
498 | PAGE_CLEAR_DIRTY | | 499 | PAGE_CLEAR_DIRTY | |
499 | PAGE_SET_WRITEBACK | | 500 | PAGE_SET_WRITEBACK | |
500 | PAGE_END_WRITEBACK); | 501 | PAGE_END_WRITEBACK); |
501 | btrfs_end_transaction(trans, root); | ||
502 | goto free_pages_out; | 502 | goto free_pages_out; |
503 | } | 503 | } |
504 | btrfs_end_transaction(trans, root); | ||
505 | } | 504 | } |
506 | 505 | ||
507 | if (will_compress) { | 506 | if (will_compress) { |
@@ -592,18 +591,6 @@ free_pages_out: | |||
592 | kfree(pages); | 591 | kfree(pages); |
593 | 592 | ||
594 | goto out; | 593 | goto out; |
595 | |||
596 | cleanup_and_out: | ||
597 | extent_clear_unlock_delalloc(inode, start, end, NULL, | ||
598 | EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING | | ||
599 | EXTENT_DEFRAG, PAGE_UNLOCK | | ||
600 | PAGE_CLEAR_DIRTY | PAGE_SET_WRITEBACK | | ||
601 | PAGE_END_WRITEBACK); | ||
602 | if (!trans || IS_ERR(trans)) | ||
603 | btrfs_error(root->fs_info, ret, "Failed to join transaction"); | ||
604 | else | ||
605 | btrfs_abort_transaction(trans, root, ret); | ||
606 | goto free_pages_out; | ||
607 | } | 594 | } |
608 | 595 | ||
609 | /* | 596 | /* |
@@ -617,7 +604,6 @@ static noinline int submit_compressed_extents(struct inode *inode, | |||
617 | { | 604 | { |
618 | struct async_extent *async_extent; | 605 | struct async_extent *async_extent; |
619 | u64 alloc_hint = 0; | 606 | u64 alloc_hint = 0; |
620 | struct btrfs_trans_handle *trans; | ||
621 | struct btrfs_key ins; | 607 | struct btrfs_key ins; |
622 | struct extent_map *em; | 608 | struct extent_map *em; |
623 | struct btrfs_root *root = BTRFS_I(inode)->root; | 609 | struct btrfs_root *root = BTRFS_I(inode)->root; |
@@ -678,20 +664,10 @@ retry: | |||
678 | lock_extent(io_tree, async_extent->start, | 664 | lock_extent(io_tree, async_extent->start, |
679 | async_extent->start + async_extent->ram_size - 1); | 665 | async_extent->start + async_extent->ram_size - 1); |
680 | 666 | ||
681 | trans = btrfs_join_transaction(root); | 667 | ret = btrfs_reserve_extent(root, |
682 | if (IS_ERR(trans)) { | ||
683 | ret = PTR_ERR(trans); | ||
684 | } else { | ||
685 | trans->block_rsv = &root->fs_info->delalloc_block_rsv; | ||
686 | ret = btrfs_reserve_extent(trans, root, | ||
687 | async_extent->compressed_size, | 668 | async_extent->compressed_size, |
688 | async_extent->compressed_size, | 669 | async_extent->compressed_size, |
689 | 0, alloc_hint, &ins, 1); | 670 | 0, alloc_hint, &ins, 1); |
690 | if (ret && ret != -ENOSPC) | ||
691 | btrfs_abort_transaction(trans, root, ret); | ||
692 | btrfs_end_transaction(trans, root); | ||
693 | } | ||
694 | |||
695 | if (ret) { | 671 | if (ret) { |
696 | int i; | 672 | int i; |
697 | 673 | ||
@@ -850,14 +826,13 @@ static u64 get_extent_allocation_hint(struct inode *inode, u64 start, | |||
850 | * required to start IO on it. It may be clean and already done with | 826 | * required to start IO on it. It may be clean and already done with |
851 | * IO when we return. | 827 | * IO when we return. |
852 | */ | 828 | */ |
853 | static noinline int __cow_file_range(struct btrfs_trans_handle *trans, | 829 | static noinline int cow_file_range(struct inode *inode, |
854 | struct inode *inode, | 830 | struct page *locked_page, |
855 | struct btrfs_root *root, | 831 | u64 start, u64 end, int *page_started, |
856 | struct page *locked_page, | 832 | unsigned long *nr_written, |
857 | u64 start, u64 end, int *page_started, | 833 | int unlock) |
858 | unsigned long *nr_written, | ||
859 | int unlock) | ||
860 | { | 834 | { |
835 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
861 | u64 alloc_hint = 0; | 836 | u64 alloc_hint = 0; |
862 | u64 num_bytes; | 837 | u64 num_bytes; |
863 | unsigned long ram_size; | 838 | unsigned long ram_size; |
@@ -878,12 +853,12 @@ static noinline int __cow_file_range(struct btrfs_trans_handle *trans, | |||
878 | /* if this is a small write inside eof, kick off defrag */ | 853 | /* if this is a small write inside eof, kick off defrag */ |
879 | if (num_bytes < 64 * 1024 && | 854 | if (num_bytes < 64 * 1024 && |
880 | (start > 0 || end + 1 < BTRFS_I(inode)->disk_i_size)) | 855 | (start > 0 || end + 1 < BTRFS_I(inode)->disk_i_size)) |
881 | btrfs_add_inode_defrag(trans, inode); | 856 | btrfs_add_inode_defrag(NULL, inode); |
882 | 857 | ||
883 | if (start == 0) { | 858 | if (start == 0) { |
884 | /* lets try to make an inline extent */ | 859 | /* lets try to make an inline extent */ |
885 | ret = cow_file_range_inline(trans, root, inode, | 860 | ret = cow_file_range_inline(root, inode, start, end, 0, 0, |
886 | start, end, 0, 0, NULL); | 861 | NULL); |
887 | if (ret == 0) { | 862 | if (ret == 0) { |
888 | extent_clear_unlock_delalloc(inode, start, end, NULL, | 863 | extent_clear_unlock_delalloc(inode, start, end, NULL, |
889 | EXTENT_LOCKED | EXTENT_DELALLOC | | 864 | EXTENT_LOCKED | EXTENT_DELALLOC | |
@@ -896,7 +871,6 @@ static noinline int __cow_file_range(struct btrfs_trans_handle *trans, | |||
896 | *page_started = 1; | 871 | *page_started = 1; |
897 | goto out; | 872 | goto out; |
898 | } else if (ret < 0) { | 873 | } else if (ret < 0) { |
899 | btrfs_abort_transaction(trans, root, ret); | ||
900 | goto out_unlock; | 874 | goto out_unlock; |
901 | } | 875 | } |
902 | } | 876 | } |
@@ -911,13 +885,11 @@ static noinline int __cow_file_range(struct btrfs_trans_handle *trans, | |||
911 | unsigned long op; | 885 | unsigned long op; |
912 | 886 | ||
913 | cur_alloc_size = disk_num_bytes; | 887 | cur_alloc_size = disk_num_bytes; |
914 | ret = btrfs_reserve_extent(trans, root, cur_alloc_size, | 888 | ret = btrfs_reserve_extent(root, cur_alloc_size, |
915 | root->sectorsize, 0, alloc_hint, | 889 | root->sectorsize, 0, alloc_hint, |
916 | &ins, 1); | 890 | &ins, 1); |
917 | if (ret < 0) { | 891 | if (ret < 0) |
918 | btrfs_abort_transaction(trans, root, ret); | ||
919 | goto out_unlock; | 892 | goto out_unlock; |
920 | } | ||
921 | 893 | ||
922 | em = alloc_extent_map(); | 894 | em = alloc_extent_map(); |
923 | if (!em) { | 895 | if (!em) { |
@@ -963,10 +935,8 @@ static noinline int __cow_file_range(struct btrfs_trans_handle *trans, | |||
963 | BTRFS_DATA_RELOC_TREE_OBJECTID) { | 935 | BTRFS_DATA_RELOC_TREE_OBJECTID) { |
964 | ret = btrfs_reloc_clone_csums(inode, start, | 936 | ret = btrfs_reloc_clone_csums(inode, start, |
965 | cur_alloc_size); | 937 | cur_alloc_size); |
966 | if (ret) { | 938 | if (ret) |
967 | btrfs_abort_transaction(trans, root, ret); | ||
968 | goto out_reserve; | 939 | goto out_reserve; |
969 | } | ||
970 | } | 940 | } |
971 | 941 | ||
972 | if (disk_num_bytes < cur_alloc_size) | 942 | if (disk_num_bytes < cur_alloc_size) |
@@ -1005,37 +975,6 @@ out_unlock: | |||
1005 | goto out; | 975 | goto out; |
1006 | } | 976 | } |
1007 | 977 | ||
1008 | static noinline int cow_file_range(struct inode *inode, | ||
1009 | struct page *locked_page, | ||
1010 | u64 start, u64 end, int *page_started, | ||
1011 | unsigned long *nr_written, | ||
1012 | int unlock) | ||
1013 | { | ||
1014 | struct btrfs_trans_handle *trans; | ||
1015 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
1016 | int ret; | ||
1017 | |||
1018 | trans = btrfs_join_transaction(root); | ||
1019 | if (IS_ERR(trans)) { | ||
1020 | extent_clear_unlock_delalloc(inode, start, end, locked_page, | ||
1021 | EXTENT_LOCKED | EXTENT_DELALLOC | | ||
1022 | EXTENT_DO_ACCOUNTING | | ||
1023 | EXTENT_DEFRAG, PAGE_UNLOCK | | ||
1024 | PAGE_CLEAR_DIRTY | | ||
1025 | PAGE_SET_WRITEBACK | | ||
1026 | PAGE_END_WRITEBACK); | ||
1027 | return PTR_ERR(trans); | ||
1028 | } | ||
1029 | trans->block_rsv = &root->fs_info->delalloc_block_rsv; | ||
1030 | |||
1031 | ret = __cow_file_range(trans, inode, root, locked_page, start, end, | ||
1032 | page_started, nr_written, unlock); | ||
1033 | |||
1034 | btrfs_end_transaction(trans, root); | ||
1035 | |||
1036 | return ret; | ||
1037 | } | ||
1038 | |||
1039 | /* | 978 | /* |
1040 | * work queue call back to started compression on a file and pages | 979 | * work queue call back to started compression on a file and pages |
1041 | */ | 980 | */ |
@@ -1347,9 +1286,9 @@ out_check: | |||
1347 | 1286 | ||
1348 | btrfs_release_path(path); | 1287 | btrfs_release_path(path); |
1349 | if (cow_start != (u64)-1) { | 1288 | if (cow_start != (u64)-1) { |
1350 | ret = __cow_file_range(trans, inode, root, locked_page, | 1289 | ret = cow_file_range(inode, locked_page, |
1351 | cow_start, found_key.offset - 1, | 1290 | cow_start, found_key.offset - 1, |
1352 | page_started, nr_written, 1); | 1291 | page_started, nr_written, 1); |
1353 | if (ret) { | 1292 | if (ret) { |
1354 | btrfs_abort_transaction(trans, root, ret); | 1293 | btrfs_abort_transaction(trans, root, ret); |
1355 | goto error; | 1294 | goto error; |
@@ -1423,9 +1362,8 @@ out_check: | |||
1423 | } | 1362 | } |
1424 | 1363 | ||
1425 | if (cow_start != (u64)-1) { | 1364 | if (cow_start != (u64)-1) { |
1426 | ret = __cow_file_range(trans, inode, root, locked_page, | 1365 | ret = cow_file_range(inode, locked_page, cow_start, end, |
1427 | cow_start, end, | 1366 | page_started, nr_written, 1); |
1428 | page_started, nr_written, 1); | ||
1429 | if (ret) { | 1367 | if (ret) { |
1430 | btrfs_abort_transaction(trans, root, ret); | 1368 | btrfs_abort_transaction(trans, root, ret); |
1431 | goto error; | 1369 | goto error; |
@@ -6344,39 +6282,32 @@ static struct extent_map *btrfs_new_extent_direct(struct inode *inode, | |||
6344 | u64 start, u64 len) | 6282 | u64 start, u64 len) |
6345 | { | 6283 | { |
6346 | struct btrfs_root *root = BTRFS_I(inode)->root; | 6284 | struct btrfs_root *root = BTRFS_I(inode)->root; |
6347 | struct btrfs_trans_handle *trans; | ||
6348 | struct extent_map *em; | 6285 | struct extent_map *em; |
6349 | struct btrfs_key ins; | 6286 | struct btrfs_key ins; |
6350 | u64 alloc_hint; | 6287 | u64 alloc_hint; |
6351 | int ret; | 6288 | int ret; |
6352 | 6289 | ||
6353 | trans = btrfs_join_transaction(root); | ||
6354 | if (IS_ERR(trans)) | ||
6355 | return ERR_CAST(trans); | ||
6356 | |||
6357 | trans->block_rsv = &root->fs_info->delalloc_block_rsv; | ||
6358 | |||
6359 | alloc_hint = get_extent_allocation_hint(inode, start, len); | 6290 | alloc_hint = get_extent_allocation_hint(inode, start, len); |
6360 | ret = btrfs_reserve_extent(trans, root, len, root->sectorsize, 0, | 6291 | ret = btrfs_reserve_extent(root, len, root->sectorsize, 0, |
6361 | alloc_hint, &ins, 1); | 6292 | alloc_hint, &ins, 1); |
6362 | if (ret) { | 6293 | if (ret) |
6363 | em = ERR_PTR(ret); | 6294 | return ERR_PTR(ret); |
6364 | goto out; | ||
6365 | } | ||
6366 | 6295 | ||
6367 | em = create_pinned_em(inode, start, ins.offset, start, ins.objectid, | 6296 | em = create_pinned_em(inode, start, ins.offset, start, ins.objectid, |
6368 | ins.offset, ins.offset, ins.offset, 0); | 6297 | ins.offset, ins.offset, ins.offset, 0); |
6369 | if (IS_ERR(em)) | 6298 | if (IS_ERR(em)) { |
6370 | goto out; | 6299 | btrfs_free_reserved_extent(root, ins.objectid, ins.offset); |
6300 | return em; | ||
6301 | } | ||
6371 | 6302 | ||
6372 | ret = btrfs_add_ordered_extent_dio(inode, start, ins.objectid, | 6303 | ret = btrfs_add_ordered_extent_dio(inode, start, ins.objectid, |
6373 | ins.offset, ins.offset, 0); | 6304 | ins.offset, ins.offset, 0); |
6374 | if (ret) { | 6305 | if (ret) { |
6375 | btrfs_free_reserved_extent(root, ins.objectid, ins.offset); | 6306 | btrfs_free_reserved_extent(root, ins.objectid, ins.offset); |
6376 | em = ERR_PTR(ret); | 6307 | free_extent_map(em); |
6308 | return ERR_PTR(ret); | ||
6377 | } | 6309 | } |
6378 | out: | 6310 | |
6379 | btrfs_end_transaction(trans, root); | ||
6380 | return em; | 6311 | return em; |
6381 | } | 6312 | } |
6382 | 6313 | ||
@@ -6384,11 +6315,11 @@ out: | |||
6384 | * returns 1 when the nocow is safe, < 1 on error, 0 if the | 6315 | * returns 1 when the nocow is safe, < 1 on error, 0 if the |
6385 | * block must be cow'd | 6316 | * block must be cow'd |
6386 | */ | 6317 | */ |
6387 | noinline int can_nocow_extent(struct btrfs_trans_handle *trans, | 6318 | noinline int can_nocow_extent(struct inode *inode, u64 offset, u64 *len, |
6388 | struct inode *inode, u64 offset, u64 *len, | ||
6389 | u64 *orig_start, u64 *orig_block_len, | 6319 | u64 *orig_start, u64 *orig_block_len, |
6390 | u64 *ram_bytes) | 6320 | u64 *ram_bytes) |
6391 | { | 6321 | { |
6322 | struct btrfs_trans_handle *trans; | ||
6392 | struct btrfs_path *path; | 6323 | struct btrfs_path *path; |
6393 | int ret; | 6324 | int ret; |
6394 | struct extent_buffer *leaf; | 6325 | struct extent_buffer *leaf; |
@@ -6406,7 +6337,7 @@ noinline int can_nocow_extent(struct btrfs_trans_handle *trans, | |||
6406 | if (!path) | 6337 | if (!path) |
6407 | return -ENOMEM; | 6338 | return -ENOMEM; |
6408 | 6339 | ||
6409 | ret = btrfs_lookup_file_extent(trans, root, path, btrfs_ino(inode), | 6340 | ret = btrfs_lookup_file_extent(NULL, root, path, btrfs_ino(inode), |
6410 | offset, 0); | 6341 | offset, 0); |
6411 | if (ret < 0) | 6342 | if (ret < 0) |
6412 | goto out; | 6343 | goto out; |
@@ -6471,9 +6402,19 @@ noinline int can_nocow_extent(struct btrfs_trans_handle *trans, | |||
6471 | * look for other files referencing this extent, if we | 6402 | * look for other files referencing this extent, if we |
6472 | * find any we must cow | 6403 | * find any we must cow |
6473 | */ | 6404 | */ |
6474 | if (btrfs_cross_ref_exist(trans, root, btrfs_ino(inode), | 6405 | trans = btrfs_join_transaction(root); |
6475 | key.offset - backref_offset, disk_bytenr)) | 6406 | if (IS_ERR(trans)) { |
6407 | ret = 0; | ||
6476 | goto out; | 6408 | goto out; |
6409 | } | ||
6410 | |||
6411 | ret = btrfs_cross_ref_exist(trans, root, btrfs_ino(inode), | ||
6412 | key.offset - backref_offset, disk_bytenr); | ||
6413 | btrfs_end_transaction(trans, root); | ||
6414 | if (ret) { | ||
6415 | ret = 0; | ||
6416 | goto out; | ||
6417 | } | ||
6477 | 6418 | ||
6478 | /* | 6419 | /* |
6479 | * adjust disk_bytenr and num_bytes to cover just the bytes | 6420 | * adjust disk_bytenr and num_bytes to cover just the bytes |
@@ -6615,7 +6556,6 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, | |||
6615 | u64 start = iblock << inode->i_blkbits; | 6556 | u64 start = iblock << inode->i_blkbits; |
6616 | u64 lockstart, lockend; | 6557 | u64 lockstart, lockend; |
6617 | u64 len = bh_result->b_size; | 6558 | u64 len = bh_result->b_size; |
6618 | struct btrfs_trans_handle *trans; | ||
6619 | int unlock_bits = EXTENT_LOCKED; | 6559 | int unlock_bits = EXTENT_LOCKED; |
6620 | int ret = 0; | 6560 | int ret = 0; |
6621 | 6561 | ||
@@ -6697,16 +6637,7 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, | |||
6697 | len = min(len, em->len - (start - em->start)); | 6637 | len = min(len, em->len - (start - em->start)); |
6698 | block_start = em->block_start + (start - em->start); | 6638 | block_start = em->block_start + (start - em->start); |
6699 | 6639 | ||
6700 | /* | 6640 | if (can_nocow_extent(inode, start, &len, &orig_start, |
6701 | * we're not going to log anything, but we do need | ||
6702 | * to make sure the current transaction stays open | ||
6703 | * while we look for nocow cross refs | ||
6704 | */ | ||
6705 | trans = btrfs_join_transaction(root); | ||
6706 | if (IS_ERR(trans)) | ||
6707 | goto must_cow; | ||
6708 | |||
6709 | if (can_nocow_extent(trans, inode, start, &len, &orig_start, | ||
6710 | &orig_block_len, &ram_bytes) == 1) { | 6641 | &orig_block_len, &ram_bytes) == 1) { |
6711 | if (type == BTRFS_ORDERED_PREALLOC) { | 6642 | if (type == BTRFS_ORDERED_PREALLOC) { |
6712 | free_extent_map(em); | 6643 | free_extent_map(em); |
@@ -6715,24 +6646,20 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, | |||
6715 | block_start, len, | 6646 | block_start, len, |
6716 | orig_block_len, | 6647 | orig_block_len, |
6717 | ram_bytes, type); | 6648 | ram_bytes, type); |
6718 | if (IS_ERR(em)) { | 6649 | if (IS_ERR(em)) |
6719 | btrfs_end_transaction(trans, root); | ||
6720 | goto unlock_err; | 6650 | goto unlock_err; |
6721 | } | ||
6722 | } | 6651 | } |
6723 | 6652 | ||
6724 | ret = btrfs_add_ordered_extent_dio(inode, start, | 6653 | ret = btrfs_add_ordered_extent_dio(inode, start, |
6725 | block_start, len, len, type); | 6654 | block_start, len, len, type); |
6726 | btrfs_end_transaction(trans, root); | ||
6727 | if (ret) { | 6655 | if (ret) { |
6728 | free_extent_map(em); | 6656 | free_extent_map(em); |
6729 | goto unlock_err; | 6657 | goto unlock_err; |
6730 | } | 6658 | } |
6731 | goto unlock; | 6659 | goto unlock; |
6732 | } | 6660 | } |
6733 | btrfs_end_transaction(trans, root); | ||
6734 | } | 6661 | } |
6735 | must_cow: | 6662 | |
6736 | /* | 6663 | /* |
6737 | * this will cow the extent, reset the len in case we changed | 6664 | * this will cow the extent, reset the len in case we changed |
6738 | * it above | 6665 | * it above |
@@ -8495,8 +8422,8 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode, | |||
8495 | 8422 | ||
8496 | cur_bytes = min(num_bytes, 256ULL * 1024 * 1024); | 8423 | cur_bytes = min(num_bytes, 256ULL * 1024 * 1024); |
8497 | cur_bytes = max(cur_bytes, min_size); | 8424 | cur_bytes = max(cur_bytes, min_size); |
8498 | ret = btrfs_reserve_extent(trans, root, cur_bytes, | 8425 | ret = btrfs_reserve_extent(root, cur_bytes, min_size, 0, |
8499 | min_size, 0, *alloc_hint, &ins, 1); | 8426 | *alloc_hint, &ins, 1); |
8500 | if (ret) { | 8427 | if (ret) { |
8501 | if (own_trans) | 8428 | if (own_trans) |
8502 | btrfs_end_transaction(trans, root); | 8429 | btrfs_end_transaction(trans, root); |