diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2023-02-25 13:22:37 +0300 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-23 00:09:54 +0300 |
commit | e07cb97460b9dd057c510e6d2294a29e72e60797 (patch) | |
tree | c76994e149223bc755f625edbabc4166d0225801 /fs/bcachefs/backpointers.c | |
parent | 747ded6ddfe88eb9644ee0512c061e46fe2fb09d (diff) | |
download | linux-e07cb97460b9dd057c510e6d2294a29e72e60797.tar.xz |
bcachefs: Flush write buffer as needed in backpointers repair
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/backpointers.c')
-rw-r--r-- | fs/bcachefs/backpointers.c | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/fs/bcachefs/backpointers.c b/fs/bcachefs/backpointers.c index e001f4191671..a40c26125d2a 100644 --- a/fs/bcachefs/backpointers.c +++ b/fs/bcachefs/backpointers.c @@ -932,11 +932,14 @@ static int check_one_backpointer(struct btree_trans *trans, struct bpos bucket, u64 *bp_offset, struct bbpos start, - struct bbpos end) + struct bbpos end, + struct bpos *last_flushed_pos) { + struct bch_fs *c = trans->c; struct btree_iter iter; struct bch_backpointer bp; struct bbpos pos; + struct bpos bp_pos; struct bkey_s_c k; struct printbuf buf = PRINTBUF; int ret; @@ -957,17 +960,31 @@ static int check_one_backpointer(struct btree_trans *trans, if (ret) return ret; - if (fsck_err_on(!k.k, trans->c, + bp_pos = bucket_pos_to_bp(c, bucket, + max(*bp_offset, BACKPOINTER_OFFSET_MAX) - BACKPOINTER_OFFSET_MAX); + + if (!k.k && !bpos_eq(*last_flushed_pos, bp_pos)) { + *last_flushed_pos = bp_pos; + pr_info("flushing at %llu:%llu", + last_flushed_pos->inode, + last_flushed_pos->offset); + + ret = bch2_btree_write_buffer_flush_sync(trans) ?: + -BCH_ERR_transaction_restart_write_buffer_flush; + goto out; + } + + if (fsck_err_on(!k.k, c, "%s backpointer points to missing extent\n%s", *bp_offset < BACKPOINTER_OFFSET_MAX ? "alloc" : "btree", (bch2_backpointer_to_text(&buf, &bp), buf.buf))) { ret = bch2_backpointer_del_by_offset(trans, bucket, *bp_offset, bp); if (ret == -ENOENT) - bch_err(trans->c, "backpointer at %llu not found", *bp_offset); + bch_err(c, "backpointer at %llu not found", *bp_offset); } - - bch2_trans_iter_exit(trans, &iter); +out: fsck_err: + bch2_trans_iter_exit(trans, &iter); printbuf_exit(&buf); return ret; } @@ -978,6 +995,7 @@ static int bch2_check_backpointers_to_extents_pass(struct btree_trans *trans, { struct btree_iter iter; struct bkey_s_c k; + struct bpos last_flushed_pos = SPOS_MAX; int ret = 0; for_each_btree_key(trans, iter, BTREE_ID_alloc, POS_MIN, @@ -987,7 +1005,8 @@ static int bch2_check_backpointers_to_extents_pass(struct btree_trans *trans, while (!(ret = commit_do(trans, NULL, NULL, BTREE_INSERT_LAZY_RW| BTREE_INSERT_NOFAIL, - check_one_backpointer(trans, iter.pos, &bp_offset, start, end))) && + check_one_backpointer(trans, iter.pos, &bp_offset, + start, end, &last_flushed_pos))) && bp_offset < U64_MAX) bp_offset++; |