summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-12-21 15:06:09 -0500
committerKent Overstreet <kent.overstreet@gmail.com>2021-12-23 16:59:03 -0500
commite027d73ebc0ed5b0c28868f6612a275ea8f092de (patch)
treedf9f5590a11ab031c054b7351e9501447131aa6a
parent7d679fb274b1a05bf06894c681e7ab6393f4742f (diff)
bcachefs: Fix for iterator not being traverse at commit timebcachefs-v4.19-backport-2019-hotfix
Custumer system is hitting a BUG_ON() at btree_update_leaf +692: btree iterator is not uptodate, meaning we dropped locks somewhere. A proper backported fix is not possible, but we can re-traverse the iterator, ensuring it is uptodate before calling bch2_trans_commit(). Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--fs/bcachefs/btree_update_leaf.c34
1 files changed, 23 insertions, 11 deletions
diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c
index cd699c257244..af408861a5d4 100644
--- a/fs/bcachefs/btree_update_leaf.c
+++ b/fs/bcachefs/btree_update_leaf.c
@@ -679,17 +679,20 @@ bch2_trans_commit_get_rw_cold(struct btree_trans *trans)
return 0;
}
-static void bch2_trans_update2(struct btree_trans *trans,
- struct btree_iter *iter,
- struct bkey_i *insert)
+static int bch2_trans_update2(struct btree_trans *trans,
+ struct btree_iter *iter,
+ struct bkey_i *insert)
{
struct btree_insert_entry *i, n = (struct btree_insert_entry) {
.iter = iter, .k = insert
};
+ int ret;
btree_insert_entry_checks(trans, n.iter, n.k);
- BUG_ON(iter->uptodate > BTREE_ITER_NEED_PEEK);
+ ret = bch2_btree_iter_traverse(iter);
+ if (ret)
+ return ret;
EBUG_ON(trans->nr_updates2 >= trans->nr_iters);
@@ -698,7 +701,7 @@ static void bch2_trans_update2(struct btree_trans *trans,
trans_for_each_update2(trans, i) {
if (btree_iter_cmp(n.iter, i->iter) == 0) {
*i = n;
- return;
+ return 0;
}
if (btree_iter_cmp(n.iter, i->iter) <= 0)
@@ -707,6 +710,7 @@ static void bch2_trans_update2(struct btree_trans *trans,
array_insert_item(trans->updates2, trans->nr_updates2,
i - trans->updates2, n);
+ return 0;
}
static int extent_update_to_keys(struct btree_trans *trans,
@@ -729,9 +733,9 @@ static int extent_update_to_keys(struct btree_trans *trans,
iter->flags |= BTREE_ITER_INTENT;
__bch2_btree_iter_set_pos(iter, insert->k.p, false);
- bch2_trans_update2(trans, iter, insert);
+ ret = bch2_trans_update2(trans, iter, insert);
bch2_trans_iter_put(trans, iter);
- return 0;
+ return ret;
}
static int extent_handle_overwrites(struct btree_trans *trans,
@@ -767,8 +771,10 @@ static int extent_handle_overwrites(struct btree_trans *trans,
bch2_cut_back(start, update);
__bch2_btree_iter_set_pos(update_iter, update->k.p, false);
- bch2_trans_update2(trans, update_iter, update);
+ ret = bch2_trans_update2(trans, update_iter, update);
bch2_trans_iter_put(trans, update_iter);
+ if (ret)
+ goto err;
}
if (bkey_cmp(k.k->p, end) > 0) {
@@ -784,8 +790,10 @@ static int extent_handle_overwrites(struct btree_trans *trans,
bch2_cut_front(end, update);
__bch2_btree_iter_set_pos(update_iter, update->k.p, false);
- bch2_trans_update2(trans, update_iter, update);
+ ret = bch2_trans_update2(trans, update_iter, update);
bch2_trans_iter_put(trans, update_iter);
+ if (ret)
+ goto err;
} else {
update_iter = bch2_trans_copy_iter(trans, iter);
if ((ret = PTR_ERR_OR_ZERO(update_iter)))
@@ -801,8 +809,10 @@ static int extent_handle_overwrites(struct btree_trans *trans,
update->k.size = 0;
__bch2_btree_iter_set_pos(update_iter, update->k.p, false);
- bch2_trans_update2(trans, update_iter, update);
+ ret = bch2_trans_update2(trans, update_iter, update);
bch2_trans_iter_put(trans, update_iter);
+ if (ret)
+ goto err;
}
k = bch2_btree_iter_next_with_updates(iter);
@@ -912,7 +922,9 @@ int __bch2_trans_commit(struct btree_trans *trans)
if (ret)
goto out;
} else {
- bch2_trans_update2(trans, i->iter, i->k);
+ ret = bch2_trans_update2(trans, i->iter, i->k);
+ if (ret)
+ goto out;
}
}