From 0fe1c68e803d575baf26398feee016a490fbc7da Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Thu, 14 May 2009 13:24:30 -0400 Subject: [PATCH] --- yaml --- r: 144927 b: refs/heads/master c: 76a05b35a320e8c968d0fec8f512a1acae227309 h: refs/heads/master i: 144925: 3bd9f5aed44ffdc9cfee9c105fd22b2ec64497bf 144923: 787d4245729299f5eda7ea4988c973951c649ba7 144919: 3ad5319327eb1f076de17c9ad03f6fd58e987e2a 144911: f18166359655ab326511d0766b5699c6898634eb 144895: 81d02912ae2222481f07c9b1e26a6f38f3a7ba8c v: v3 --- [refs] | 2 +- trunk/fs/btrfs/ctree.c | 39 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/[refs] b/[refs] index 64c969be6a21..d94d9f8d4927 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 2757495c906113896b378bf084708846273c87b2 +refs/heads/master: 76a05b35a320e8c968d0fec8f512a1acae227309 diff --git a/trunk/fs/btrfs/ctree.c b/trunk/fs/btrfs/ctree.c index a99f1c2a710d..fedf8b9f03a2 100644 --- a/trunk/fs/btrfs/ctree.c +++ b/trunk/fs/btrfs/ctree.c @@ -1469,6 +1469,7 @@ read_block_for_search(struct btrfs_trans_handle *trans, u32 blocksize; struct extent_buffer *b = *eb_ret; struct extent_buffer *tmp; + int ret; blocknr = btrfs_node_blockptr(b, slot); gen = btrfs_node_ptr_generation(b, slot); @@ -1476,6 +1477,10 @@ read_block_for_search(struct btrfs_trans_handle *trans, tmp = btrfs_find_tree_block(root, blocknr, blocksize); if (tmp && btrfs_buffer_uptodate(tmp, gen)) { + /* + * we found an up to date block without sleeping, return + * right away + */ *eb_ret = tmp; return 0; } @@ -1483,7 +1488,9 @@ read_block_for_search(struct btrfs_trans_handle *trans, /* * reduce lock contention at high levels * of the btree by dropping locks before - * we read. + * we read. Don't release the lock on the current + * level because we need to walk this node to figure + * out which blocks to read. */ btrfs_unlock_up_safe(p, level + 1); btrfs_set_path_blocking(p); @@ -1494,10 +1501,21 @@ read_block_for_search(struct btrfs_trans_handle *trans, reada_for_search(root, p, level, slot, key->objectid); btrfs_release_path(NULL, p); + + ret = -EAGAIN; tmp = read_tree_block(root, blocknr, blocksize, gen); - if (tmp) + if (tmp) { + /* + * If the read above didn't mark this buffer up to date, + * it will never end up being up to date. Set ret to EIO now + * and give up so that our caller doesn't loop forever + * on our EAGAINs. + */ + if (!btrfs_buffer_uptodate(tmp, 0)) + ret = -EIO; free_extent_buffer(tmp); - return -EAGAIN; + } + return ret; } /* @@ -1696,6 +1714,9 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root if (ret == -EAGAIN) goto again; + if (ret == -EIO) + goto done; + if (!p->skip_locking) { int lret; @@ -1738,6 +1759,8 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root */ if (!p->leave_spinning) btrfs_set_path_blocking(p); + if (ret < 0) + btrfs_release_path(root, p); return ret; } @@ -4212,6 +4235,11 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) if (ret == -EAGAIN) goto again; + if (ret < 0) { + btrfs_release_path(root, path); + goto done; + } + if (!path->skip_locking) { ret = btrfs_try_spin_lock(next); if (!ret) { @@ -4246,6 +4274,11 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) if (ret == -EAGAIN) goto again; + if (ret < 0) { + btrfs_release_path(root, path); + goto done; + } + if (!path->skip_locking) { btrfs_assert_tree_locked(path->nodes[level]); ret = btrfs_try_spin_lock(next);