summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2020-10-26 14:45:20 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2020-11-05 12:45:14 -0500
commitfe737764ed2073e86cedda7ee4aaa81c8cb5c73f (patch)
tree5741310ac87cd2e0866591c45d6bf748334ac8fd
parent14f498c2fe5b7cc3ae6f483589b45d05df90cf6f (diff)
bcachefs: Fix btree updates when mixing cached and non cached iterators
There was a bug where bch2_trans_update() would incorrectly delete a pending update where the new update did not actually overwrite the existing update, because we were incorrectly using BTREE_ITER_TYPE when sorting pending btree updates. This affects the pending patch to use cached iterators for inode updates. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--fs/bcachefs/btree_cache.c2
-rw-r--r--fs/bcachefs/btree_iter.c2
-rw-r--r--fs/bcachefs/btree_iter.h5
-rw-r--r--fs/bcachefs/btree_update_leaf.c13
4 files changed, 15 insertions, 7 deletions
diff --git a/fs/bcachefs/btree_cache.c b/fs/bcachefs/btree_cache.c
index bb94fa2341ee..45d44c8785bd 100644
--- a/fs/bcachefs/btree_cache.c
+++ b/fs/bcachefs/btree_cache.c
@@ -948,7 +948,7 @@ struct btree *bch2_btree_node_get_sibling(struct bch_fs *c,
* holding other locks that would cause us to deadlock:
*/
trans_for_each_iter(trans, linked)
- if (btree_iter_cmp(iter, linked) < 0)
+ if (btree_iter_lock_cmp(iter, linked) < 0)
__bch2_btree_iter_unlock(linked);
if (sib == btree_prev_sib)
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c
index 6fab76c3220c..ec831dcd6a12 100644
--- a/fs/bcachefs/btree_iter.c
+++ b/fs/bcachefs/btree_iter.c
@@ -1104,7 +1104,7 @@ retry_all:
sorted[nr_sorted++] = iter->idx;
#define btree_iter_cmp_by_idx(_l, _r) \
- btree_iter_cmp(&trans->iters[_l], &trans->iters[_r])
+ btree_iter_lock_cmp(&trans->iters[_l], &trans->iters[_r])
bubble_sort(sorted, nr_sorted, btree_iter_cmp_by_idx);
#undef btree_iter_cmp_by_idx
diff --git a/fs/bcachefs/btree_iter.h b/fs/bcachefs/btree_iter.h
index bd9ec3ec9a92..f80e09255f68 100644
--- a/fs/bcachefs/btree_iter.h
+++ b/fs/bcachefs/btree_iter.h
@@ -177,8 +177,9 @@ void bch2_btree_iter_set_pos_same_leaf(struct btree_iter *, struct bpos);
void __bch2_btree_iter_set_pos(struct btree_iter *, struct bpos, bool);
void bch2_btree_iter_set_pos(struct btree_iter *, struct bpos);
-static inline int btree_iter_cmp(const struct btree_iter *l,
- const struct btree_iter *r)
+/* Sort order for locking btree iterators: */
+static inline int btree_iter_lock_cmp(const struct btree_iter *l,
+ const struct btree_iter *r)
{
return cmp_int(l->btree_id, r->btree_id) ?:
-cmp_int(btree_iter_type(l), btree_iter_type(r)) ?:
diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c
index 49995cd00c16..852cece6d4a5 100644
--- a/fs/bcachefs/btree_update_leaf.c
+++ b/fs/bcachefs/btree_update_leaf.c
@@ -680,6 +680,13 @@ bch2_trans_commit_get_rw_cold(struct btree_trans *trans)
return 0;
}
+static inline int btree_iter_pos_cmp(const struct btree_iter *l,
+ const struct btree_iter *r)
+{
+ return cmp_int(l->btree_id, r->btree_id) ?:
+ bkey_cmp(l->pos, r->pos);
+}
+
static void bch2_trans_update2(struct btree_trans *trans,
struct btree_iter *iter,
struct bkey_i *insert)
@@ -697,12 +704,12 @@ static void bch2_trans_update2(struct btree_trans *trans,
iter->flags |= BTREE_ITER_KEEP_UNTIL_COMMIT;
trans_for_each_update2(trans, i) {
- if (btree_iter_cmp(n.iter, i->iter) == 0) {
+ if (btree_iter_pos_cmp(n.iter, i->iter) == 0) {
*i = n;
return;
}
- if (btree_iter_cmp(n.iter, i->iter) <= 0)
+ if (btree_iter_pos_cmp(n.iter, i->iter) <= 0)
break;
}
@@ -986,7 +993,7 @@ int bch2_trans_update(struct btree_trans *trans, struct btree_iter *iter,
* Pending updates are kept sorted: first, find position of new update:
*/
trans_for_each_update(trans, i)
- if (btree_iter_cmp(iter, i->iter) <= 0)
+ if (btree_iter_pos_cmp(iter, i->iter) <= 0)
break;
/*