summaryrefslogtreecommitdiffstats
path: root/fs/bcachefs/backpointers.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2023-03-14 12:54:21 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:09:57 -0400
commit872c0311675bdb73b29ee74c7f27afc82d4918e9 (patch)
tree400b87f972f1ded45707837a9cf1be91f6dd56a7 /fs/bcachefs/backpointers.c
parentc639c29ce6882f4f77a81d778ef4741d5a5979d9 (diff)
downloadlinux-stable-872c0311675bdb73b29ee74c7f27afc82d4918e9.tar.gz
linux-stable-872c0311675bdb73b29ee74c7f27afc82d4918e9.tar.bz2
linux-stable-872c0311675bdb73b29ee74c7f27afc82d4918e9.zip
bcachefs: Fix bch2_check_extents_to_backpointers()
In rare cases, bch2_check_extents_to_backpointers() would incorrectly flag an extent has having a missing backpointer when we just needed to flush the btree write buffer - we weren't tracking the last flushed position correctly. This adds a level field to the last_flushed pos, fixing a bug where we'd sometimes fail on a new root node. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/backpointers.c')
-rw-r--r--fs/bcachefs/backpointers.c30
1 files changed, 19 insertions, 11 deletions
diff --git a/fs/bcachefs/backpointers.c b/fs/bcachefs/backpointers.c
index a40c26125d2a..8517c5635226 100644
--- a/fs/bcachefs/backpointers.c
+++ b/fs/bcachefs/backpointers.c
@@ -549,13 +549,18 @@ int bch2_check_btree_backpointers(struct bch_fs *c)
bch2_check_btree_backpointer(&trans, &iter, k)));
}
+struct bpos_level {
+ unsigned level;
+ struct bpos pos;
+};
+
static int check_bp_exists(struct btree_trans *trans,
struct bpos bucket_pos,
struct bch_backpointer bp,
struct bkey_s_c orig_k,
struct bpos bucket_start,
struct bpos bucket_end,
- struct bpos *last_flushed_pos)
+ struct bpos_level *last_flushed)
{
struct bch_fs *c = trans->c;
struct btree_iter alloc_iter, bp_iter = { NULL };
@@ -600,8 +605,11 @@ static int check_bp_exists(struct btree_trans *trans,
if (bp_k.k->type != KEY_TYPE_backpointer ||
memcmp(bkey_s_c_to_backpointer(bp_k).v, &bp, sizeof(bp))) {
- if (!bpos_eq(*last_flushed_pos, orig_k.k->p)) {
- *last_flushed_pos = orig_k.k->p;
+ if (last_flushed->level != bp.level ||
+ !bpos_eq(last_flushed->pos, orig_k.k->p)) {
+ last_flushed->level = bp.level;
+ last_flushed->pos = orig_k.k->p;
+
ret = bch2_btree_write_buffer_flush_sync(trans) ?:
-BCH_ERR_transaction_restart_write_buffer_flush;
goto out;
@@ -639,7 +647,7 @@ static int check_extent_to_backpointers(struct btree_trans *trans,
struct btree_iter *iter,
struct bpos bucket_start,
struct bpos bucket_end,
- struct bpos *last_flushed_pos)
+ struct bpos_level *last_flushed)
{
struct bch_fs *c = trans->c;
struct bkey_ptrs_c ptrs;
@@ -668,7 +676,7 @@ static int check_extent_to_backpointers(struct btree_trans *trans,
ret = check_bp_exists(trans, bucket_pos, bp, k,
bucket_start, bucket_end,
- last_flushed_pos);
+ last_flushed);
if (ret)
return ret;
}
@@ -680,7 +688,7 @@ static int check_btree_root_to_backpointers(struct btree_trans *trans,
enum btree_id btree_id,
struct bpos bucket_start,
struct bpos bucket_end,
- struct bpos *last_flushed_pos)
+ struct bpos_level *last_flushed)
{
struct bch_fs *c = trans->c;
struct btree_iter iter;
@@ -709,12 +717,12 @@ static int check_btree_root_to_backpointers(struct btree_trans *trans,
if (p.ptr.cached)
continue;
- bch2_extent_ptr_to_bp(c, iter.btree_id, iter.path->level + 1,
+ bch2_extent_ptr_to_bp(c, iter.btree_id, b->c.level + 1,
k, p, &bucket_pos, &bp);
ret = check_bp_exists(trans, bucket_pos, bp, k,
bucket_start, bucket_end,
- last_flushed_pos);
+ last_flushed);
if (ret)
goto err;
}
@@ -794,7 +802,7 @@ static int bch2_check_extents_to_backpointers_pass(struct btree_trans *trans,
{
struct btree_iter iter;
enum btree_id btree_id;
- struct bpos last_flushed_pos = SPOS_MAX;
+ struct bpos_level last_flushed = { UINT_MAX };
int ret = 0;
for (btree_id = 0; btree_id < BTREE_ID_NR; btree_id++) {
@@ -811,7 +819,7 @@ static int bch2_check_extents_to_backpointers_pass(struct btree_trans *trans,
BTREE_INSERT_NOFAIL,
check_extent_to_backpointers(trans, &iter,
bucket_start, bucket_end,
- &last_flushed_pos));
+ &last_flushed));
if (ret)
break;
} while (!bch2_btree_iter_advance(&iter));
@@ -826,7 +834,7 @@ static int bch2_check_extents_to_backpointers_pass(struct btree_trans *trans,
BTREE_INSERT_NOFAIL,
check_btree_root_to_backpointers(trans, btree_id,
bucket_start, bucket_end,
- &last_flushed_pos));
+ &last_flushed));
if (ret)
break;
}