From fe9cdf61cc7cb791c40d076503d8910fc0727310 Mon Sep 17 00:00:00 2001
From: Kent Overstreet <kent.overstreet@gmail.com>
Date: Sun, 22 Sep 2019 17:48:25 -0400
Subject: [PATCH] bcachefs: Count iterators for reflink_p overwrites correctly

In order to avoid trying to allocate too many btree iterators,
bch2_extent_atomic_end() needs to count how many iterators are going to
be needed for insertions and overwrites - but we weren't counting the
iterators for deleting a reflink_v when the refcount goes to 0.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
---
 fs/bcachefs/extents.c | 35 +++++++++++++++++++++++++----------
 1 file changed, 25 insertions(+), 10 deletions(-)

diff --git a/fs/bcachefs/extents.c b/fs/bcachefs/extents.c
index 859b1e8206bdb..35abcde4bca2c 100644
--- a/fs/bcachefs/extents.c
+++ b/fs/bcachefs/extents.c
@@ -935,12 +935,13 @@ static unsigned bch2_bkey_nr_alloc_ptrs(struct bkey_s_c k)
 	return ret;
 }
 
-static int __bch2_extent_atomic_end(struct btree_trans *trans,
-				    struct bkey_s_c k,
-				    unsigned offset,
-				    struct bpos *end,
-				    unsigned *nr_iters,
-				    unsigned max_iters)
+static int count_iters_for_insert(struct btree_trans *trans,
+				  struct bkey_s_c k,
+				  unsigned offset,
+				  struct bpos *end,
+				  unsigned *nr_iters,
+				  unsigned max_iters,
+				  bool overwrite)
 {
 	int ret = 0;
 
@@ -970,6 +971,20 @@ static int __bch2_extent_atomic_end(struct btree_trans *trans,
 				break;
 
 			*nr_iters += 1;
+
+			if (overwrite &&
+			    k.k->type == KEY_TYPE_reflink_v) {
+				struct bkey_s_c_reflink_v r = bkey_s_c_to_reflink_v(k);
+
+				if (le64_to_cpu(r.v->refcount) == 1)
+					*nr_iters += bch2_bkey_nr_alloc_ptrs(k);
+			}
+
+			/*
+			 * if we're going to be deleting an entry from
+			 * the reflink btree, need more iters...
+			 */
+
 			if (*nr_iters >= max_iters) {
 				struct bpos pos = bkey_start_pos(k.k);
 				pos.offset += r_k.k->p.offset - idx;
@@ -1004,8 +1019,8 @@ int bch2_extent_atomic_end(struct btree_iter *iter,
 
 	*end = bpos_min(insert->k.p, b->key.k.p);
 
-	ret = __bch2_extent_atomic_end(trans, bkey_i_to_s_c(insert),
-				       0, end, &nr_iters, 10);
+	ret = count_iters_for_insert(trans, bkey_i_to_s_c(insert),
+				     0, end, &nr_iters, 10, false);
 	if (ret)
 		return ret;
 
@@ -1024,8 +1039,8 @@ int bch2_extent_atomic_end(struct btree_iter *iter,
 			offset = bkey_start_offset(&insert->k) -
 				bkey_start_offset(k.k);
 
-		ret = __bch2_extent_atomic_end(trans, k, offset,
-					       end, &nr_iters, 20);
+		ret = count_iters_for_insert(trans, k, offset,
+					     end, &nr_iters, 20, true);
 		if (ret)
 			return ret;
 
-- 
2.30.2