diff options
-rw-r--r-- | fs/bcachefs/alloc_background.c | 32 | ||||
-rw-r--r-- | fs/bcachefs/alloc_foreground.c | 41 | ||||
-rw-r--r-- | fs/bcachefs/backpointers.c | 9 | ||||
-rw-r--r-- | fs/bcachefs/bcachefs.h | 1 | ||||
-rw-r--r-- | fs/bcachefs/recovery.c | 17 |
5 files changed, 62 insertions, 38 deletions
diff --git a/fs/bcachefs/alloc_background.c b/fs/bcachefs/alloc_background.c index 0939200e6d1a..ae6ae78a2618 100644 --- a/fs/bcachefs/alloc_background.c +++ b/fs/bcachefs/alloc_background.c @@ -800,6 +800,7 @@ static int bch2_bucket_do_index(struct btree_trans *trans, goto err; if (ca->mi.freespace_initialized && + test_bit(BCH_FS_CHECK_ALLOC_DONE, &c->flags) && bch2_trans_inconsistent_on(old.k->type != old_type, trans, "incorrect key when %s %s btree (got %s should be %s)\n" " for %s", @@ -1649,21 +1650,28 @@ static int bch2_discard_one_bucket(struct btree_trans *trans, goto write; } - if (bch2_trans_inconsistent_on(a->v.journal_seq > c->journal.flushed_seq_ondisk, trans, - "clearing need_discard but journal_seq %llu > flushed_seq %llu\n" - "%s", - a->v.journal_seq, - c->journal.flushed_seq_ondisk, - (bch2_bkey_val_to_text(&buf, c, k), buf.buf))) { - ret = -EIO; + if (a->v.journal_seq > c->journal.flushed_seq_ondisk) { + if (test_bit(BCH_FS_CHECK_ALLOC_DONE, &c->flags)) { + bch2_trans_inconsistent(trans, + "clearing need_discard but journal_seq %llu > flushed_seq %llu\n" + "%s", + a->v.journal_seq, + c->journal.flushed_seq_ondisk, + (bch2_bkey_val_to_text(&buf, c, k), buf.buf)); + ret = -EIO; + } goto out; } - if (bch2_trans_inconsistent_on(a->v.data_type != BCH_DATA_need_discard, trans, - "bucket incorrectly set in need_discard btree\n" - "%s", - (bch2_bkey_val_to_text(&buf, c, k), buf.buf))) { - ret = -EIO; + if (a->v.data_type != BCH_DATA_need_discard) { + if (test_bit(BCH_FS_CHECK_ALLOC_DONE, &c->flags)) { + bch2_trans_inconsistent(trans, + "bucket incorrectly set in need_discard btree\n" + "%s", + (bch2_bkey_val_to_text(&buf, c, k), buf.buf)); + ret = -EIO; + } + goto out; } diff --git a/fs/bcachefs/alloc_foreground.c b/fs/bcachefs/alloc_foreground.c index 86acc7d3b4c6..2010a9af0eb2 100644 --- a/fs/bcachefs/alloc_foreground.c +++ b/fs/bcachefs/alloc_foreground.c @@ -312,28 +312,34 @@ static struct open_bucket *try_alloc_bucket(struct btree_trans *trans, struct bc a = bch2_alloc_to_v4(k, &a_convert); - if (genbits != (alloc_freespace_genbits(*a) >> 56)) { - prt_printf(&buf, "bucket in freespace btree with wrong genbits (got %u should be %llu)\n" - " freespace key ", - genbits, alloc_freespace_genbits(*a) >> 56); + if (a->data_type != BCH_DATA_free) { + if (!test_bit(BCH_FS_CHECK_ALLOC_DONE, &c->flags)) { + ob = NULL; + goto err; + } + + prt_printf(&buf, "non free bucket in freespace btree\n" + " freespace key "); bch2_bkey_val_to_text(&buf, c, freespace_k); prt_printf(&buf, "\n "); bch2_bkey_val_to_text(&buf, c, k); bch2_trans_inconsistent(trans, "%s", buf.buf); ob = ERR_PTR(-EIO); goto err; - } - if (a->data_type != BCH_DATA_free) { - prt_printf(&buf, "non free bucket in freespace btree\n" - " freespace key "); + if (genbits != (alloc_freespace_genbits(*a) >> 56) && + test_bit(BCH_FS_CHECK_ALLOC_DONE, &c->flags)) { + prt_printf(&buf, "bucket in freespace btree with wrong genbits (got %u should be %llu)\n" + " freespace key ", + genbits, alloc_freespace_genbits(*a) >> 56); bch2_bkey_val_to_text(&buf, c, freespace_k); prt_printf(&buf, "\n "); bch2_bkey_val_to_text(&buf, c, k); bch2_trans_inconsistent(trans, "%s", buf.buf); ob = ERR_PTR(-EIO); goto err; + } if (!test_bit(BCH_FS_CHECK_BACKPOINTERS_DONE, &c->flags)) { @@ -506,8 +512,8 @@ static struct open_bucket *bch2_bucket_alloc_trans(struct btree_trans *trans, { struct bch_fs *c = trans->c; struct open_bucket *ob = NULL; - bool freespace_initialized = READ_ONCE(ca->mi.freespace_initialized); - u64 start = freespace_initialized ? 0 : ca->bucket_alloc_trans_early_cursor; + bool freespace = READ_ONCE(ca->mi.freespace_initialized); + u64 start = freespace ? 0 : ca->bucket_alloc_trans_early_cursor; u64 avail; struct bucket_alloc_state s = { .cur_bucket = start }; bool waiting = false; @@ -546,20 +552,25 @@ again: if (ob) return ob; } - - ob = likely(ca->mi.freespace_initialized) +alloc: + ob = likely(freespace) ? bch2_bucket_alloc_freelist(trans, ca, reserve, &s, cl) : bch2_bucket_alloc_early(trans, ca, reserve, &s, cl); if (s.skipped_need_journal_commit * 2 > avail) bch2_journal_flush_async(&c->journal, NULL); - if (!ob && !freespace_initialized && start) { + if (!ob && !freespace && start) { start = s.cur_bucket = 0; - goto again; + goto alloc; + } + + if (!ob && freespace && !test_bit(BCH_FS_CHECK_ALLOC_DONE, &c->flags)) { + freespace = false; + goto alloc; } - if (!freespace_initialized) + if (!freespace) ca->bucket_alloc_trans_early_cursor = s.cur_bucket; err: if (!ob) diff --git a/fs/bcachefs/backpointers.c b/fs/bcachefs/backpointers.c index 7d4367f93b5c..405823d1cfab 100644 --- a/fs/bcachefs/backpointers.c +++ b/fs/bcachefs/backpointers.c @@ -242,6 +242,9 @@ btree: memcmp(bkey_s_c_to_backpointer(k).v, &bp, sizeof(bp))) { struct printbuf buf = PRINTBUF; + if (!test_bit(BCH_FS_CHECK_BACKPOINTERS_DONE, &c->flags)) + goto err; + prt_printf(&buf, "backpointer not found when deleting"); prt_newline(&buf); printbuf_indent_add(&buf, 2); @@ -262,10 +265,8 @@ btree: bch2_bkey_val_to_text(&buf, c, orig_k); bch_err(c, "%s", buf.buf); - if (test_bit(BCH_FS_CHECK_BACKPOINTERS_DONE, &c->flags)) { - bch2_inconsistent_error(c); - ret = -EIO; - } + bch2_inconsistent_error(c); + ret = -EIO; printbuf_exit(&buf); goto err; } diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h index 7f479cdc7069..71f51459872d 100644 --- a/fs/bcachefs/bcachefs.h +++ b/fs/bcachefs/bcachefs.h @@ -549,6 +549,7 @@ enum { /* fsck passes: */ BCH_FS_TOPOLOGY_REPAIR_DONE, BCH_FS_INITIAL_GC_DONE, /* kill when we enumerate fsck passes */ + BCH_FS_CHECK_ALLOC_DONE, BCH_FS_CHECK_LRUS_DONE, BCH_FS_CHECK_BACKPOINTERS_DONE, BCH_FS_CHECK_ALLOC_TO_LRU_REFS_DONE, diff --git a/fs/bcachefs/recovery.c b/fs/bcachefs/recovery.c index aec98a98a39a..0ad2bb2aa039 100644 --- a/fs/bcachefs/recovery.c +++ b/fs/bcachefs/recovery.c @@ -1246,13 +1246,6 @@ use_clean: set_bit(BCH_FS_INITIAL_GC_DONE, &c->flags); - bch_info(c, "checking need_discard and freespace btrees"); - err = "error checking need_discard and freespace btrees"; - ret = bch2_check_alloc_info(c); - if (ret) - goto err; - bch_verbose(c, "done checking need_discard and freespace btrees"); - if (c->sb.version < bcachefs_metadata_version_snapshot_2) { err = "error creating root snapshot node"; ret = bch2_fs_initialize_subvolumes(c); @@ -1277,6 +1270,15 @@ use_clean: if (c->opts.verbose || !c->sb.clean) bch_info(c, "journal replay done"); + bch_info(c, "checking need_discard and freespace btrees"); + err = "error checking need_discard and freespace btrees"; + ret = bch2_check_alloc_info(c); + if (ret) + goto err; + bch_verbose(c, "done checking need_discard and freespace btrees"); + + set_bit(BCH_FS_CHECK_ALLOC_DONE, &c->flags); + bch_info(c, "checking lrus"); err = "error checking lrus"; ret = bch2_check_lrus(c); @@ -1316,6 +1318,7 @@ use_clean: set_bit(BCH_FS_CHECK_ALLOC_TO_LRU_REFS_DONE, &c->flags); } else { set_bit(BCH_FS_INITIAL_GC_DONE, &c->flags); + set_bit(BCH_FS_CHECK_ALLOC_DONE, &c->flags); set_bit(BCH_FS_CHECK_LRUS_DONE, &c->flags); set_bit(BCH_FS_CHECK_BACKPOINTERS_DONE, &c->flags); set_bit(BCH_FS_CHECK_ALLOC_TO_LRU_REFS_DONE, &c->flags); |