summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-06-04 17:17:45 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2021-06-04 22:19:09 -0400
commit34c14d9f8a6a8ff08495356ae68b6a288a0c2b40 (patch)
tree239d9c0d1dc0314f98556017ea0401d349095342
parent71cbe1812d2674e97aff87b246675d6a67a1e76d (diff)
bcachefs: btree_iter->should_be_locked
Add a field to struct btree_iter for tracking whether it should be locked - this fixes spurious transaction restarts in bch2_trans_relock(). Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--fs/bcachefs/btree_iter.c28
-rw-r--r--fs/bcachefs/btree_iter.h1
-rw-r--r--fs/bcachefs/btree_types.h8
3 files changed, 34 insertions, 3 deletions
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c
index 8840531266d7..683a2e37f23a 100644
--- a/fs/bcachefs/btree_iter.c
+++ b/fs/bcachefs/btree_iter.c
@@ -456,12 +456,20 @@ void bch2_trans_downgrade(struct btree_trans *trans)
/* Btree transaction locking: */
+static inline bool btree_iter_should_be_locked(struct btree_trans *trans,
+ struct btree_iter *iter)
+{
+ return (iter->flags & BTREE_ITER_KEEP_UNTIL_COMMIT) ||
+ iter->should_be_locked;
+}
+
bool bch2_trans_relock(struct btree_trans *trans)
{
struct btree_iter *iter;
trans_for_each_iter(trans, iter)
- if (!bch2_btree_iter_relock(iter, _RET_IP_)) {
+ if (!bch2_btree_iter_relock(iter, _RET_IP_) &&
+ btree_iter_should_be_locked(trans, iter)) {
trace_trans_restart_relock(trans->ip, _RET_IP_,
iter->btree_id, &iter->real_pos);
return false;
@@ -1420,9 +1428,16 @@ btree_iter_traverse(struct btree_iter *iter)
int __must_check
bch2_btree_iter_traverse(struct btree_iter *iter)
{
+ int ret;
+
btree_iter_set_search_pos(iter, btree_iter_search_key(iter));
- return btree_iter_traverse(iter);
+ ret = btree_iter_traverse(iter);
+ if (ret)
+ return ret;
+
+ iter->should_be_locked = true;
+ return 0;
}
/* Iterate across nodes (leaf and interior nodes) */
@@ -1448,6 +1463,7 @@ struct btree *bch2_btree_iter_peek_node(struct btree_iter *iter)
iter->pos = iter->real_pos = b->key.k.p;
bch2_btree_iter_verify(iter);
+ iter->should_be_locked = true;
return b;
}
@@ -1504,6 +1520,7 @@ struct btree *bch2_btree_iter_next_node(struct btree_iter *iter)
iter->pos = iter->real_pos = b->key.k.p;
bch2_btree_iter_verify(iter);
+ iter->should_be_locked = true;
return b;
}
@@ -1520,6 +1537,7 @@ static void btree_iter_set_search_pos(struct btree_iter *iter, struct bpos new_p
goto out;
iter->real_pos = new_pos;
+ iter->should_be_locked = false;
if (unlikely(btree_iter_type(iter) == BTREE_ITER_CACHED)) {
btree_node_unlock(iter, 0);
@@ -1679,6 +1697,7 @@ start:
bch2_btree_iter_verify_entry_exit(iter);
bch2_btree_iter_verify(iter);
+ iter->should_be_locked = true;
return k;
}
@@ -1763,6 +1782,7 @@ struct bkey_s_c bch2_btree_iter_peek_prev(struct btree_iter *iter)
out:
bch2_btree_iter_verify_entry_exit(iter);
bch2_btree_iter_verify(iter);
+ iter->should_be_locked = true;
return k;
no_key:
/*
@@ -1862,6 +1882,8 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter)
bch2_btree_iter_verify_entry_exit(iter);
bch2_btree_iter_verify(iter);
+ iter->should_be_locked = true;
+
return k;
}
@@ -1899,6 +1921,8 @@ struct bkey_s_c bch2_btree_iter_peek_cached(struct btree_iter *iter)
bkey_cmp(iter->pos, ck->key.pos));
BUG_ON(!ck->valid);
+ iter->should_be_locked = true;
+
return bkey_i_to_s_c(ck->k);
}
diff --git a/fs/bcachefs/btree_iter.h b/fs/bcachefs/btree_iter.h
index 01b834bf79f7..a2ce711fd61f 100644
--- a/fs/bcachefs/btree_iter.h
+++ b/fs/bcachefs/btree_iter.h
@@ -178,6 +178,7 @@ static inline void bch2_btree_iter_set_pos(struct btree_iter *iter, struct bpos
iter->k.p.offset = iter->pos.offset = new_pos.offset;
iter->k.p.snapshot = iter->pos.snapshot = new_pos.snapshot;
iter->k.size = 0;
+ iter->should_be_locked = false;
}
/* Sort order for locking btree iterators: */
diff --git a/fs/bcachefs/btree_types.h b/fs/bcachefs/btree_types.h
index 172a90f4db4f..bc0f482b53d2 100644
--- a/fs/bcachefs/btree_types.h
+++ b/fs/bcachefs/btree_types.h
@@ -252,7 +252,13 @@ struct btree_iter {
u8 idx;
enum btree_id btree_id:4;
- enum btree_iter_uptodate uptodate:4;
+ enum btree_iter_uptodate uptodate:3;
+ /*
+ * True if we've returned a key (and thus are expected to keep it
+ * locked), false after set_pos - for avoiding spurious transaction
+ * restarts in bch2_trans_relock():
+ */
+ bool should_be_locked:1;
unsigned level:4,
min_depth:4,
locks_want:4,