summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-08-23 17:19:17 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2021-08-23 19:21:38 -0400
commitaed9db86aadd385b0d2591e50fde29005b41334e (patch)
treef0d4a9f29367beab45d0960e6aeb82d877166563
parent7eccdf93f782ddf44af6e0df87cfc2605ccd6a48 (diff)
bcachefs: Free iterator if we have duplicate
This helps - but does not fully fix - the outstanding "transaction iterator overflow" bugs. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--fs/bcachefs/btree_iter.c21
-rw-r--r--fs/bcachefs/btree_update_leaf.c1
2 files changed, 20 insertions, 2 deletions
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c
index 1da314b6e5a6..302b8539bf0e 100644
--- a/fs/bcachefs/btree_iter.c
+++ b/fs/bcachefs/btree_iter.c
@@ -2196,6 +2196,22 @@ static inline void __bch2_trans_iter_free(struct btree_trans *trans,
trans->iters_touched &= ~(1ULL << idx);
}
+static bool have_iter_at_pos(struct btree_trans *trans,
+ struct btree_iter *iter)
+{
+ struct btree_iter *n;
+
+ n = prev_btree_iter(trans, iter);
+ if (n && !btree_iter_cmp(n, iter))
+ return true;
+
+ n = next_btree_iter(trans, iter);
+ if (n && !btree_iter_cmp(n, iter))
+ return true;
+
+ return false;
+}
+
int bch2_trans_iter_put(struct btree_trans *trans,
struct btree_iter *iter)
{
@@ -2209,8 +2225,9 @@ int bch2_trans_iter_put(struct btree_trans *trans,
ret = btree_iter_err(iter);
- if (!(trans->iters_touched & (1ULL << iter->idx)) &&
- !(iter->flags & BTREE_ITER_KEEP_UNTIL_COMMIT))
+ if (!(iter->flags & BTREE_ITER_KEEP_UNTIL_COMMIT) &&
+ (!(trans->iters_touched & (1ULL << iter->idx)) ||
+ have_iter_at_pos(trans, iter)))
__bch2_trans_iter_free(trans, iter->idx);
trans->iters_live &= ~(1ULL << iter->idx);
diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c
index 7e9909e2dcaf..bfb568025a2a 100644
--- a/fs/bcachefs/btree_update_leaf.c
+++ b/fs/bcachefs/btree_update_leaf.c
@@ -1019,6 +1019,7 @@ int bch2_trans_update(struct btree_trans *trans, struct btree_iter *iter,
n.iter = bch2_trans_get_iter(trans, n.btree_id, n.k->k.p,
BTREE_ITER_INTENT|
BTREE_ITER_NOT_EXTENTS);
+ n.iter->flags |= BTREE_ITER_KEEP_UNTIL_COMMIT;
ret = bch2_btree_iter_traverse(n.iter);
bch2_trans_iter_put(trans, n.iter);