summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2018-06-12 13:33:56 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2018-06-27 12:25:13 -0400
commit070a14c9c74365908f187b128a763f2abbfd7ee5 (patch)
tree462629139b89bbf4435af67e1fcc8e6ef423bc7e
parent6c7a497e167f88352cd276b75b0208699856e593 (diff)
bcachefs: btree_node_lock_increment()
-rw-r--r--fs/bcachefs/btree_iter.c44
1 files changed, 28 insertions, 16 deletions
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c
index 33f7b2ec6cb8..e8966c7d686c 100644
--- a/fs/bcachefs/btree_iter.c
+++ b/fs/bcachefs/btree_iter.c
@@ -64,9 +64,28 @@ void __bch2_btree_node_lock_write(struct btree *b, struct btree_iter *iter)
&b->lock.state.counter);
}
-bool __bch2_btree_node_relock(struct btree_iter *iter, unsigned level)
+/*
+ * Lock a btree node if we already have it locked on one of our linked
+ * iterators:
+ */
+static inline bool btree_node_lock_increment(struct btree_iter *iter,
+ struct btree *b, unsigned level,
+ enum btree_node_locked_type want)
{
struct btree_iter *linked;
+
+ for_each_linked_btree_iter(iter, linked)
+ if (linked->l[level].b == b &&
+ btree_node_locked_type(linked, level) >= want) {
+ six_lock_increment(&b->lock, want);
+ return true;
+ }
+
+ return false;
+}
+
+bool __bch2_btree_node_relock(struct btree_iter *iter, unsigned level)
+{
struct btree *b = iter->l[level].b;
int want = __btree_lock_want(iter, level);
int have = btree_node_locked_type(iter, level);
@@ -85,14 +104,11 @@ bool __bch2_btree_node_relock(struct btree_iter *iter, unsigned level)
: six_relock_type(&b->lock, want, iter->lock_seq[level]))
goto success;
- for_each_linked_btree_iter(iter, linked)
- if (linked->l[level].b == b &&
- btree_node_locked_type(linked, level) == want &&
- iter->lock_seq[level] == b->lock.state.seq) {
- btree_node_unlock(iter, level);
- six_lock_increment(&b->lock, want);
- goto success;
- }
+ if (iter->lock_seq[level] >> 1 == b->lock.state.seq >> 1 &&
+ btree_node_lock_increment(iter, b, level, want)) {
+ btree_node_unlock(iter, level);
+ goto success;
+ }
return false;
success:
@@ -158,15 +174,11 @@ bool __bch2_btree_node_lock(struct btree *b, struct bpos pos,
EBUG_ON(type == SIX_LOCK_intent &&
iter->nodes_locked != iter->nodes_intent_locked);
- for_each_linked_btree_iter(iter, linked)
- if (linked->l[level].b == b &&
- btree_node_locked_type(linked, level) == type) {
- six_lock_increment(&b->lock, type);
- return true;
- }
+ if (btree_node_lock_increment(iter, b, level, type))
+ return true;
/*
- * Must lock btree nodes in key order - this case hapens when locking
+ * Must lock btree nodes in key order - this case happens when locking
* the prev sibling in btree node merging:
*/
if (iter->nodes_locked &&