diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2021-08-23 17:19:17 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2021-08-23 19:21:38 -0400 |
commit | aed9db86aadd385b0d2591e50fde29005b41334e (patch) | |
tree | f0d4a9f29367beab45d0960e6aeb82d877166563 | |
parent | 7eccdf93f782ddf44af6e0df87cfc2605ccd6a48 (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.c | 21 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_leaf.c | 1 |
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); |