From 645d72aa366e51259296cfc02e37c802d7b78493 Mon Sep 17 00:00:00 2001
From: Kent Overstreet <kent.overstreet@gmail.com>
Date: Mon, 26 Oct 2020 14:45:20 -0400
Subject: [PATCH] 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>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
---
 fs/bcachefs/btree_cache.c       |  2 +-
 fs/bcachefs/btree_iter.c        |  2 +-
 fs/bcachefs/btree_iter.h        |  5 +++--
 fs/bcachefs/btree_update_leaf.c | 13 ++++++++++---
 4 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/fs/bcachefs/btree_cache.c b/fs/bcachefs/btree_cache.c
index 90d884b18b70d..c503d76bab3ba 100644
--- a/fs/bcachefs/btree_cache.c
+++ b/fs/bcachefs/btree_cache.c
@@ -949,7 +949,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 7501556c0988f..b561d0353d77b 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 bd9ec3ec9a92a..f80e09255f68c 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 9c33a8be2c580..839dba099cac2 100644
--- a/fs/bcachefs/btree_update_leaf.c
+++ b/fs/bcachefs/btree_update_leaf.c
@@ -690,6 +690,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)
@@ -707,12 +714,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;
 	}
 
@@ -996,7 +1003,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;
 
 	/*
-- 
2.30.2