142 lines
4.9 KiB
Diff
142 lines
4.9 KiB
Diff
From 1f3c4ab3fbb3400f5527087427c590632a4a75df Mon Sep 17 00:00:00 2001
|
|
From: Kent Overstreet <kent.overstreet@linux.dev>
|
|
Date: Thu, 14 Nov 2024 21:34:43 -0500
|
|
Subject: [PATCH 109/233] bcachefs: New backpointers helpers
|
|
Content-Type: text/plain; charset="utf-8"
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
- bch2_backpointer_del()
|
|
- bch2_backpointer_maybe_flush()
|
|
|
|
Kill a bit of open coding and make sure we're properly handling the
|
|
btree write buffer.
|
|
|
|
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
|
|
Signed-off-by: Alexander Miroshnichenko <alex@millerson.name>
|
|
---
|
|
fs/bcachefs/backpointers.c | 58 +++++++++++++++++++++++++++++---------
|
|
1 file changed, 45 insertions(+), 13 deletions(-)
|
|
|
|
diff --git a/fs/bcachefs/backpointers.c b/fs/bcachefs/backpointers.c
|
|
index 620fa67db7a6..cfd9b9ead473 100644
|
|
--- a/fs/bcachefs/backpointers.c
|
|
+++ b/fs/bcachefs/backpointers.c
|
|
@@ -199,6 +199,22 @@ int bch2_bucket_backpointer_mod_nowritebuffer(struct btree_trans *trans,
|
|
return ret;
|
|
}
|
|
|
|
+static int bch2_backpointer_del(struct btree_trans *trans, struct bpos pos)
|
|
+{
|
|
+ return likely(!bch2_backpointers_no_use_write_buffer)
|
|
+ ? bch2_btree_delete_at_buffered(trans, BTREE_ID_backpointers, pos)
|
|
+ : bch2_btree_delete(trans, BTREE_ID_backpointers, pos, 0);
|
|
+}
|
|
+
|
|
+static int bch2_backpointers_maybe_flush(struct btree_trans *trans,
|
|
+ struct bkey_s_c visiting_k,
|
|
+ struct bkey_buf *last_flushed)
|
|
+{
|
|
+ return likely(!bch2_backpointers_no_use_write_buffer)
|
|
+ ? bch2_btree_write_buffer_maybe_flush(trans, visiting_k, last_flushed)
|
|
+ : 0;
|
|
+}
|
|
+
|
|
static void backpointer_target_not_found(struct btree_trans *trans,
|
|
struct bkey_s_c_backpointer bp,
|
|
struct bkey_s_c target_k)
|
|
@@ -300,9 +316,12 @@ struct btree *bch2_backpointer_get_node(struct btree_trans *trans,
|
|
return b;
|
|
}
|
|
|
|
-static int bch2_check_btree_backpointer(struct btree_trans *trans, struct btree_iter *bp_iter,
|
|
- struct bkey_s_c k)
|
|
+static int bch2_check_backpointer_has_valid_bucket(struct btree_trans *trans, struct bkey_s_c k,
|
|
+ struct bkey_buf *last_flushed)
|
|
{
|
|
+ if (k.k->type != KEY_TYPE_backpointer)
|
|
+ return 0;
|
|
+
|
|
struct bch_fs *c = trans->c;
|
|
struct btree_iter alloc_iter = { NULL };
|
|
struct bkey_s_c alloc_k;
|
|
@@ -311,10 +330,14 @@ static int bch2_check_btree_backpointer(struct btree_trans *trans, struct btree_
|
|
|
|
struct bpos bucket;
|
|
if (!bp_pos_to_bucket_nodev_noerror(c, k.k->p, &bucket)) {
|
|
+ ret = bch2_backpointers_maybe_flush(trans, k, last_flushed);
|
|
+ if (ret)
|
|
+ goto out;
|
|
+
|
|
if (fsck_err(trans, backpointer_to_missing_device,
|
|
"backpointer for missing device:\n%s",
|
|
(bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
|
|
- ret = bch2_btree_delete_at(trans, bp_iter, 0);
|
|
+ ret = bch2_backpointer_del(trans, k.k->p);
|
|
goto out;
|
|
}
|
|
|
|
@@ -323,13 +346,16 @@ static int bch2_check_btree_backpointer(struct btree_trans *trans, struct btree_
|
|
if (ret)
|
|
goto out;
|
|
|
|
- if (fsck_err_on(alloc_k.k->type != KEY_TYPE_alloc_v4,
|
|
- trans, backpointer_to_missing_alloc,
|
|
- "backpointer for nonexistent alloc key: %llu:%llu:0\n%s",
|
|
- alloc_iter.pos.inode, alloc_iter.pos.offset,
|
|
- (bch2_bkey_val_to_text(&buf, c, k), buf.buf))) {
|
|
- ret = bch2_btree_delete_at(trans, bp_iter, 0);
|
|
- goto out;
|
|
+ if (alloc_k.k->type != KEY_TYPE_alloc_v4) {
|
|
+ ret = bch2_backpointers_maybe_flush(trans, k, last_flushed);
|
|
+ if (ret)
|
|
+ goto out;
|
|
+
|
|
+ if (fsck_err(trans, backpointer_to_missing_alloc,
|
|
+ "backpointer for nonexistent alloc key: %llu:%llu:0\n%s",
|
|
+ alloc_iter.pos.inode, alloc_iter.pos.offset,
|
|
+ (bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
|
|
+ ret = bch2_backpointer_del(trans, k.k->p);
|
|
}
|
|
out:
|
|
fsck_err:
|
|
@@ -341,11 +367,17 @@ static int bch2_check_btree_backpointer(struct btree_trans *trans, struct btree_
|
|
/* verify that every backpointer has a corresponding alloc key */
|
|
int bch2_check_btree_backpointers(struct bch_fs *c)
|
|
{
|
|
+ struct bkey_buf last_flushed;
|
|
+ bch2_bkey_buf_init(&last_flushed);
|
|
+ bkey_init(&last_flushed.k->k);
|
|
+
|
|
int ret = bch2_trans_run(c,
|
|
for_each_btree_key_commit(trans, iter,
|
|
BTREE_ID_backpointers, POS_MIN, 0, k,
|
|
NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
|
|
- bch2_check_btree_backpointer(trans, &iter, k)));
|
|
+ bch2_check_backpointer_has_valid_bucket(trans, k, &last_flushed)));
|
|
+
|
|
+ bch2_bkey_buf_exit(&last_flushed, c);
|
|
bch_err_fn(c, ret);
|
|
return ret;
|
|
}
|
|
@@ -874,7 +906,7 @@ static int check_one_backpointer(struct btree_trans *trans,
|
|
return ret;
|
|
|
|
if (!k.k) {
|
|
- ret = bch2_btree_write_buffer_maybe_flush(trans, bp.s_c, last_flushed);
|
|
+ ret = bch2_backpointers_maybe_flush(trans, bp.s_c, last_flushed);
|
|
if (ret)
|
|
goto out;
|
|
|
|
@@ -882,7 +914,7 @@ static int check_one_backpointer(struct btree_trans *trans,
|
|
"backpointer for missing %s\n %s",
|
|
bp.v->level ? "btree node" : "extent",
|
|
(bch2_bkey_val_to_text(&buf, c, bp.s_c), buf.buf))) {
|
|
- ret = bch2_btree_delete_at_buffered(trans, BTREE_ID_backpointers, bp.k->p);
|
|
+ ret = bch2_backpointer_del(trans, bp.k->p);
|
|
goto out;
|
|
}
|
|
}
|
|
--
|
|
2.45.2
|
|
|