aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2011-11-10 20:39:08 -0500
committerChris Mason <chris.mason@oracle.com>2011-11-10 20:39:08 -0500
commit2115133f8b9a8dbdb217d14080814df07ce90479 (patch)
tree3b2f3d6839cdb1f6495ae10dd548f7fbfee70266 /fs/btrfs
parent7fd2ae21a42d178982679b86086661292b4afe4a (diff)
Btrfs: tweak the delayed inode reservations again
Josef sent along an incremental to the inode reservation code to make sure we try and fall back to directly updating the inode item if things go horribly wrong. This reworks that patch slightly, adding a fallback function that will always try to update the inode item directly without going through the delayed_inode code. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/delayed-inode.c9
-rw-r--r--fs/btrfs/inode.c64
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
693migrate: 693migrate:
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
701out: 696out:
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);
96static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
97 struct btrfs_root *root, struct inode *inode);
96 98
97static int btrfs_init_inode_security(struct btrfs_trans_handle *trans, 99static 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 */
2429noinline int btrfs_update_inode(struct btrfs_trans_handle *trans, 2431static 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 */
2469noinline 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
2492static 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;
5675out_unlock: 5699out_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,