summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2018-06-02 20:57:04 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2018-06-03 21:01:03 -0400
commit61d7118155621a9b40a1a105f24bee5e760554e3 (patch)
treeb7fad160cdabde683c800dd077742f8c81fe748a
parent37b6d3515758331ab0cabe4c9d680947bb57fe29 (diff)
bcachefs: drop locks when needed in bch2_btree_node_get_sibling()
-rw-r--r--fs/bcachefs/btree_cache.c16
-rw-r--r--fs/bcachefs/btree_iter.c12
-rw-r--r--fs/bcachefs/btree_locking.h8
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) {