diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/delayed-inode.c | 9 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 64 |
2 files changed, 47 insertions, 26 deletions
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 313ee14cf3b7..6a1a6800776c 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c | |||
@@ -692,11 +692,6 @@ static int btrfs_delayed_inode_reserve_metadata( | |||
692 | 692 | ||
693 | migrate: | 693 | migrate: |
694 | ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes); | 694 | ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes); |
695 | if (unlikely(ret)) { | ||
696 | /* This shouldn't happen */ | ||
697 | BUG_ON(release); | ||
698 | return ret; | ||
699 | } | ||
700 | 695 | ||
701 | out: | 696 | out: |
702 | /* | 697 | /* |
@@ -712,9 +707,11 @@ out: | |||
712 | * reservation here. I think it may be time for a documentation page on | 707 | * reservation here. I think it may be time for a documentation page on |
713 | * how block rsvs. work. | 708 | * how block rsvs. work. |
714 | */ | 709 | */ |
710 | if (!ret) | ||
711 | node->bytes_reserved = num_bytes; | ||
712 | |||
715 | if (release) | 713 | if (release) |
716 | btrfs_block_rsv_release(root, src_rsv, num_bytes); | 714 | btrfs_block_rsv_release(root, src_rsv, num_bytes); |
717 | node->bytes_reserved = num_bytes; | ||
718 | 715 | ||
719 | return ret; | 716 | return ret; |
720 | } | 717 | } |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 2b920596c126..7d394335bcb5 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -93,6 +93,8 @@ static noinline int cow_file_range(struct inode *inode, | |||
93 | struct page *locked_page, | 93 | struct page *locked_page, |
94 | u64 start, u64 end, int *page_started, | 94 | u64 start, u64 end, int *page_started, |
95 | unsigned long *nr_written, int unlock); | 95 | unsigned long *nr_written, int unlock); |
96 | static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans, | ||
97 | struct btrfs_root *root, struct inode *inode); | ||
96 | 98 | ||
97 | static int btrfs_init_inode_security(struct btrfs_trans_handle *trans, | 99 | static int btrfs_init_inode_security(struct btrfs_trans_handle *trans, |
98 | struct inode *inode, struct inode *dir, | 100 | struct inode *inode, struct inode *dir, |
@@ -1741,7 +1743,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
1741 | trans = btrfs_join_transaction(root); | 1743 | trans = btrfs_join_transaction(root); |
1742 | BUG_ON(IS_ERR(trans)); | 1744 | BUG_ON(IS_ERR(trans)); |
1743 | trans->block_rsv = &root->fs_info->delalloc_block_rsv; | 1745 | trans->block_rsv = &root->fs_info->delalloc_block_rsv; |
1744 | ret = btrfs_update_inode(trans, root, inode); | 1746 | ret = btrfs_update_inode_fallback(trans, root, inode); |
1745 | BUG_ON(ret); | 1747 | BUG_ON(ret); |
1746 | } | 1748 | } |
1747 | goto out; | 1749 | goto out; |
@@ -1791,7 +1793,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
1791 | 1793 | ||
1792 | ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent); | 1794 | ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent); |
1793 | if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) { | 1795 | if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) { |
1794 | ret = btrfs_update_inode(trans, root, inode); | 1796 | ret = btrfs_update_inode_fallback(trans, root, inode); |
1795 | BUG_ON(ret); | 1797 | BUG_ON(ret); |
1796 | } | 1798 | } |
1797 | ret = 0; | 1799 | ret = 0; |
@@ -2426,7 +2428,7 @@ static void fill_inode_item(struct btrfs_trans_handle *trans, | |||
2426 | /* | 2428 | /* |
2427 | * copy everything in the in-memory inode into the btree. | 2429 | * copy everything in the in-memory inode into the btree. |
2428 | */ | 2430 | */ |
2429 | noinline int btrfs_update_inode(struct btrfs_trans_handle *trans, | 2431 | static noinline int btrfs_update_inode_item(struct btrfs_trans_handle *trans, |
2430 | struct btrfs_root *root, struct inode *inode) | 2432 | struct btrfs_root *root, struct inode *inode) |
2431 | { | 2433 | { |
2432 | struct btrfs_inode_item *inode_item; | 2434 | struct btrfs_inode_item *inode_item; |
@@ -2434,21 +2436,6 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans, | |||
2434 | struct extent_buffer *leaf; | 2436 | struct extent_buffer *leaf; |
2435 | int ret; | 2437 | int ret; |
2436 | 2438 | ||
2437 | /* | ||
2438 | * If the inode is a free space inode, we can deadlock during commit | ||
2439 | * if we put it into the delayed code. | ||
2440 | * | ||
2441 | * The data relocation inode should also be directly updated | ||
2442 | * without delay | ||
2443 | */ | ||
2444 | if (!btrfs_is_free_space_inode(root, inode) | ||
2445 | && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) { | ||
2446 | ret = btrfs_delayed_update_inode(trans, root, inode); | ||
2447 | if (!ret) | ||
2448 | btrfs_set_inode_last_trans(trans, inode); | ||
2449 | return ret; | ||
2450 | } | ||
2451 | |||
2452 | path = btrfs_alloc_path(); | 2439 | path = btrfs_alloc_path(); |
2453 | if (!path) | 2440 | if (!path) |
2454 | return -ENOMEM; | 2441 | return -ENOMEM; |
@@ -2477,6 +2464,43 @@ failed: | |||
2477 | } | 2464 | } |
2478 | 2465 | ||
2479 | /* | 2466 | /* |
2467 | * copy everything in the in-memory inode into the btree. | ||
2468 | */ | ||
2469 | noinline int btrfs_update_inode(struct btrfs_trans_handle *trans, | ||
2470 | struct btrfs_root *root, struct inode *inode) | ||
2471 | { | ||
2472 | int ret; | ||
2473 | |||
2474 | /* | ||
2475 | * If the inode is a free space inode, we can deadlock during commit | ||
2476 | * if we put it into the delayed code. | ||
2477 | * | ||
2478 | * The data relocation inode should also be directly updated | ||
2479 | * without delay | ||
2480 | */ | ||
2481 | if (!btrfs_is_free_space_inode(root, inode) | ||
2482 | && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) { | ||
2483 | ret = btrfs_delayed_update_inode(trans, root, inode); | ||
2484 | if (!ret) | ||
2485 | btrfs_set_inode_last_trans(trans, inode); | ||
2486 | return ret; | ||
2487 | } | ||
2488 | |||
2489 | return btrfs_update_inode_item(trans, root, inode); | ||
2490 | } | ||
2491 | |||
2492 | static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans, | ||
2493 | struct btrfs_root *root, struct inode *inode) | ||
2494 | { | ||
2495 | int ret; | ||
2496 | |||
2497 | ret = btrfs_update_inode(trans, root, inode); | ||
2498 | if (ret == -ENOSPC) | ||
2499 | return btrfs_update_inode_item(trans, root, inode); | ||
2500 | return ret; | ||
2501 | } | ||
2502 | |||
2503 | /* | ||
2480 | * unlink helper that gets used here in inode.c and in the tree logging | 2504 | * unlink helper that gets used here in inode.c and in the tree logging |
2481 | * recovery code. It remove a link in a directory with a given name, and | 2505 | * recovery code. It remove a link in a directory with a given name, and |
2482 | * also drops the back refs in the inode to the directory | 2506 | * also drops the back refs in the inode to the directory |
@@ -5632,7 +5656,7 @@ again: | |||
5632 | if (test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags)) { | 5656 | if (test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags)) { |
5633 | ret = btrfs_ordered_update_i_size(inode, 0, ordered); | 5657 | ret = btrfs_ordered_update_i_size(inode, 0, ordered); |
5634 | if (!ret) | 5658 | if (!ret) |
5635 | err = btrfs_update_inode(trans, root, inode); | 5659 | err = btrfs_update_inode_fallback(trans, root, inode); |
5636 | goto out; | 5660 | goto out; |
5637 | } | 5661 | } |
5638 | 5662 | ||
@@ -5670,7 +5694,7 @@ again: | |||
5670 | add_pending_csums(trans, inode, ordered->file_offset, &ordered->list); | 5694 | add_pending_csums(trans, inode, ordered->file_offset, &ordered->list); |
5671 | ret = btrfs_ordered_update_i_size(inode, 0, ordered); | 5695 | ret = btrfs_ordered_update_i_size(inode, 0, ordered); |
5672 | if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags)) | 5696 | if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags)) |
5673 | btrfs_update_inode(trans, root, inode); | 5697 | btrfs_update_inode_fallback(trans, root, inode); |
5674 | ret = 0; | 5698 | ret = 0; |
5675 | out_unlock: | 5699 | out_unlock: |
5676 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, ordered->file_offset, | 5700 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, ordered->file_offset, |