diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2018-06-02 20:57:04 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2018-06-03 21:01:03 -0400 |
commit | 61d7118155621a9b40a1a105f24bee5e760554e3 (patch) | |
tree | b7fad160cdabde683c800dd077742f8c81fe748a | |
parent | 37b6d3515758331ab0cabe4c9d680947bb57fe29 (diff) |
bcachefs: drop locks when needed in bch2_btree_node_get_sibling()
-rw-r--r-- | fs/bcachefs/btree_cache.c | 16 | ||||
-rw-r--r-- | fs/bcachefs/btree_iter.c | 12 | ||||
-rw-r--r-- | fs/bcachefs/btree_locking.h | 8 |
3 files changed, 18 insertions, 18 deletions
diff --git a/fs/bcachefs/btree_cache.c b/fs/bcachefs/btree_cache.c index 4292dd7fff8e..09bab9ac5d6a 100644 --- a/fs/bcachefs/btree_cache.c +++ b/fs/bcachefs/btree_cache.c @@ -794,33 +794,29 @@ struct btree *bch2_btree_node_get_sibling(struct bch_fs *c, ret = bch2_btree_node_get(c, iter, &tmp.k, level, SIX_LOCK_intent); if (PTR_ERR_OR_ZERO(ret) == -EINTR && may_drop_locks) { + struct btree_iter *linked; + if (!bch2_btree_node_relock(iter, level + 1)) { bch2_btree_iter_set_locks_want(iter, level + 2); return ERR_PTR(-EINTR); } -#if 0 /* - * we might have got -EINTR because trylock failed, and we're + * We might have got -EINTR because trylock failed, and we're * holding other locks that would cause us to deadlock: - * - * to do this correctly, we need a bch2_btree_iter_relock() - * that relocks all linked iters */ - struct btree_iter *linked; - - for_each_linked_btree_iter(iter, linked) { + for_each_linked_btree_iter(iter, linked) if (btree_iter_cmp(iter, linked) < 0) __bch2_btree_iter_unlock(linked); - } -#endif if (sib == btree_prev_sib) btree_node_unlock(iter, level); ret = bch2_btree_node_get(c, iter, &tmp.k, level, SIX_LOCK_intent); + bch2_btree_iter_relock(iter); + if (!bch2_btree_node_relock(iter, level)) { btree_iter_set_dirty(iter, BTREE_ITER_NEED_RELOCK); diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index d047dd656b47..e784c5efd8f3 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.c @@ -268,14 +268,6 @@ bool __bch2_btree_iter_set_locks_want(struct btree_iter *iter, return false; } -static void __bch2_btree_iter_unlock(struct btree_iter *iter) -{ - btree_iter_set_dirty(iter, BTREE_ITER_NEED_RELOCK); - - while (iter->nodes_locked) - btree_node_unlock(iter, __ffs(iter->nodes_locked)); -} - int bch2_btree_iter_unlock(struct btree_iter *iter) { struct btree_iter *linked; @@ -974,6 +966,10 @@ int __must_check bch2_btree_iter_traverse(struct btree_iter *iter) if (iter->uptodate < BTREE_ITER_NEED_RELOCK) return 0; + if (iter->uptodate == BTREE_ITER_NEED_RELOCK && + __bch2_btree_iter_relock(iter)) + return 0; + ret = __bch2_btree_iter_traverse(iter); if (unlikely(ret)) ret = btree_iter_traverse_error(iter, ret); diff --git a/fs/bcachefs/btree_locking.h b/fs/bcachefs/btree_locking.h index f48084bc26ae..a6c55dff1822 100644 --- a/fs/bcachefs/btree_locking.h +++ b/fs/bcachefs/btree_locking.h @@ -98,6 +98,14 @@ static inline void btree_node_unlock(struct btree_iter *iter, unsigned level) mark_btree_node_unlocked(iter, level); } +static inline void __bch2_btree_iter_unlock(struct btree_iter *iter) +{ + btree_iter_set_dirty(iter, BTREE_ITER_NEED_RELOCK); + + while (iter->nodes_locked) + btree_node_unlock(iter, __ffs(iter->nodes_locked)); +} + static inline enum bch_time_stats lock_to_time_stat(enum six_lock_type type) { switch (type) { |