diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2023-02-12 22:25:59 +0300 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-23 00:09:51 +0300 |
commit | 7c057d35098613b2936c361aa8289590fef987ba (patch) | |
tree | 536d52016e7a76e2d749e06c5c6a719c8e9a0e6f /fs/bcachefs/backpointers.c | |
parent | 53b1c6f44b1a98ea6def11b74c1fde9710f2a0b9 (diff) | |
download | linux-7c057d35098613b2936c361aa8289590fef987ba.tar.xz |
fixup bcachefs: New on disk format: Backpointers
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/backpointers.c')
-rw-r--r-- | fs/bcachefs/backpointers.c | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/fs/bcachefs/backpointers.c b/fs/bcachefs/backpointers.c index 3978c0b50f20..3e862da6f15f 100644 --- a/fs/bcachefs/backpointers.c +++ b/fs/bcachefs/backpointers.c @@ -5,6 +5,7 @@ #include "backpointers.h" #include "btree_cache.h" #include "btree_update.h" +#include "btree_write_buffer.h" #include "error.h" #include <linux/mm.h> @@ -553,7 +554,8 @@ static int check_bp_exists(struct btree_trans *trans, struct bch_backpointer bp, struct bkey_s_c orig_k, struct bpos bucket_start, - struct bpos bucket_end) + struct bpos bucket_end, + struct bpos *last_flushed_pos) { struct bch_fs *c = trans->c; struct btree_iter alloc_iter, bp_iter = { NULL }; @@ -597,8 +599,15 @@ static int check_bp_exists(struct btree_trans *trans, goto err; if (bp_k.k->type != KEY_TYPE_backpointer || - memcmp(bkey_s_c_to_backpointer(bp_k).v, &bp, sizeof(bp))) + 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; + ret = bch2_btree_write_buffer_flush_sync(trans) ?: + -BCH_ERR_transaction_restart_write_buffer_flush; + goto out; + } goto missing; + } out: err: fsck_err: @@ -607,6 +616,7 @@ fsck_err: printbuf_exit(&buf); return ret; missing: + prt_printf(&buf, "missing backpointer for btree=%s l=%u ", bch2_btree_ids[bp.btree_id], bp.level); bch2_bkey_val_to_text(&buf, c, orig_k); @@ -628,7 +638,8 @@ missing: static int check_extent_to_backpointers(struct btree_trans *trans, struct btree_iter *iter, struct bpos bucket_start, - struct bpos bucket_end) + struct bpos bucket_end, + struct bpos *last_flushed_pos) { struct bch_fs *c = trans->c; struct bkey_ptrs_c ptrs; @@ -655,7 +666,9 @@ static int check_extent_to_backpointers(struct btree_trans *trans, bch2_extent_ptr_to_bp(c, iter->btree_id, iter->path->level, k, p, &bucket_pos, &bp); - ret = check_bp_exists(trans, bucket_pos, bp, k, bucket_start, bucket_end); + ret = check_bp_exists(trans, bucket_pos, bp, k, + bucket_start, bucket_end, + last_flushed_pos); if (ret) return ret; } @@ -666,7 +679,8 @@ static int check_extent_to_backpointers(struct btree_trans *trans, 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 bucket_end, + struct bpos *last_flushed_pos) { struct bch_fs *c = trans->c; struct btree_iter iter; @@ -698,7 +712,9 @@ static int check_btree_root_to_backpointers(struct btree_trans *trans, bch2_extent_ptr_to_bp(c, iter.btree_id, iter.path->level + 1, k, p, &bucket_pos, &bp); - ret = check_bp_exists(trans, bucket_pos, bp, k, bucket_start, bucket_end); + ret = check_bp_exists(trans, bucket_pos, bp, k, + bucket_start, bucket_end, + last_flushed_pos); if (ret) goto err; } @@ -778,6 +794,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; int ret = 0; for (btree_id = 0; btree_id < BTREE_ID_NR; btree_id++) { @@ -793,7 +810,8 @@ static int bch2_check_extents_to_backpointers_pass(struct btree_trans *trans, BTREE_INSERT_LAZY_RW| BTREE_INSERT_NOFAIL, check_extent_to_backpointers(trans, &iter, - bucket_start, bucket_end)); + bucket_start, bucket_end, + &last_flushed_pos)); if (ret) break; } while (!bch2_btree_iter_advance(&iter)); @@ -807,7 +825,8 @@ static int bch2_check_extents_to_backpointers_pass(struct btree_trans *trans, BTREE_INSERT_LAZY_RW| BTREE_INSERT_NOFAIL, check_btree_root_to_backpointers(trans, btree_id, - bucket_start, bucket_end)); + bucket_start, bucket_end, + &last_flushed_pos)); if (ret) break; } |