summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2022-12-11 19:14:30 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2023-01-06 19:48:01 -0500
commit4a48d62e0965c06d7f6b0f765f1b71143598f1d2 (patch)
treeb7ce0ed068c7817f4060195e4d181c3c796f0352
parent1305f68102096cf26c5229f3075247e5c6995162 (diff)
bcachefs: Go RW before check_alloc_info()
It's possible to do btree updates before going RW by adding them to the list of updates for journal replay to do, but this is limited by what fits in RAM. This patch switches the second alloc info phase to run after going RW - btree_gc has already ensured the alloc btree itself is correct - and tweaks the allocation path to deal with the potential small inconsistencies. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--fs/bcachefs/alloc_background.c32
-rw-r--r--fs/bcachefs/alloc_foreground.c41
-rw-r--r--fs/bcachefs/backpointers.c9
-rw-r--r--fs/bcachefs/bcachefs.h1
-rw-r--r--fs/bcachefs/recovery.c17
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 2f407cc76ef8..d289b2b003bf 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 ea2984c27955..ace45a09b237 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);