From a58603684195ea892da5612580762fd3151b2a7b Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 16 Mar 2024 21:22:47 -0400 Subject: bcachefs: Don't corrupt journal keys gap buffer when dropping alloc info Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_io.c | 2 +- fs/bcachefs/recovery.c | 6 +++++- fs/bcachefs/util.h | 3 +++ 3 files changed, 9 insertions(+), 2 deletions(-) (limited to 'fs/bcachefs') diff --git a/fs/bcachefs/btree_io.c b/fs/bcachefs/btree_io.c index 624c8287deb4..44856f018adf 100644 --- a/fs/bcachefs/btree_io.c +++ b/fs/bcachefs/btree_io.c @@ -1338,7 +1338,7 @@ start: if (saw_error && !btree_node_read_error(b)) { printbuf_reset(&buf); bch2_bpos_to_text(&buf, b->key.k.p); - bch_info(c, "%s: rewriting btree node at btree=%s level=%u %s due to error", + bch_err_ratelimited(c, "%s: rewriting btree node at btree=%s level=%u %s due to error", __func__, bch2_btree_id_str(b->c.btree_id), b->c.level, buf.buf); bch2_btree_node_rewrite_async(c, b); diff --git a/fs/bcachefs/recovery.c b/fs/bcachefs/recovery.c index 2af219aedfdb..03f9d6afe467 100644 --- a/fs/bcachefs/recovery.c +++ b/fs/bcachefs/recovery.c @@ -90,10 +90,12 @@ static void do_reconstruct_alloc(struct bch_fs *c) struct journal_keys *keys = &c->journal_keys; size_t src, dst; + move_gap(keys, keys->nr); + for (src = 0, dst = 0; src < keys->nr; src++) if (!btree_id_is_alloc(keys->data[src].btree_id)) keys->data[dst++] = keys->data[src]; - keys->nr = dst; + keys->nr = keys->gap = dst; } /* @@ -203,6 +205,8 @@ static int bch2_journal_replay(struct bch_fs *c) BUG_ON(!atomic_read(&keys->ref)); + move_gap(keys, keys->nr); + /* * First, attempt to replay keys in sorted order. This is more * efficient - better locality of btree access - but some might fail if diff --git a/fs/bcachefs/util.h b/fs/bcachefs/util.h index 7ffbddb80400..175aee3074c7 100644 --- a/fs/bcachefs/util.h +++ b/fs/bcachefs/util.h @@ -683,6 +683,9 @@ static inline void __move_gap(void *array, size_t element_size, /* Move the gap in a gap buffer: */ #define move_gap(_d, _new_gap) \ do { \ + BUG_ON(_new_gap > (_d)->nr); \ + BUG_ON((_d)->gap > (_d)->nr); \ + \ __move_gap((_d)->data, sizeof((_d)->data[0]), \ (_d)->nr, (_d)->size, (_d)->gap, _new_gap); \ (_d)->gap = _new_gap; \ -- cgit v1.2.3