summaryrefslogtreecommitdiff
path: root/libbcachefs/recovery.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbcachefs/recovery.c')
-rw-r--r--libbcachefs/recovery.c42
1 files changed, 21 insertions, 21 deletions
diff --git a/libbcachefs/recovery.c b/libbcachefs/recovery.c
index 77ab464a..4cde23b9 100644
--- a/libbcachefs/recovery.c
+++ b/libbcachefs/recovery.c
@@ -106,10 +106,11 @@ static int journal_replay_entry_early(struct bch_fs *c,
}
static int verify_superblock_clean(struct bch_fs *c,
- struct bch_sb_field_clean *clean,
+ struct bch_sb_field_clean **cleanp,
struct jset *j)
{
unsigned i;
+ struct bch_sb_field_clean *clean = *cleanp;
int ret = 0;
if (!clean || !j)
@@ -118,8 +119,11 @@ static int verify_superblock_clean(struct bch_fs *c,
if (mustfix_fsck_err_on(j->seq != clean->journal_seq, c,
"superblock journal seq (%llu) doesn't match journal (%llu) after clean shutdown",
le64_to_cpu(clean->journal_seq),
- le64_to_cpu(j->seq)))
- bch2_fs_mark_clean(c, false);
+ le64_to_cpu(j->seq))) {
+ kfree(clean);
+ *cleanp = NULL;
+ return 0;
+ }
mustfix_fsck_err_on(j->read_clock != clean->read_clock, c,
"superblock read clock doesn't match journal after clean shutdown");
@@ -186,6 +190,8 @@ int bch2_fs_recovery(struct bch_fs *c)
LIST_HEAD(journal);
struct jset *j = NULL;
unsigned i;
+ bool run_gc = c->opts.fsck ||
+ !(c->sb.compat & (1ULL << BCH_COMPAT_FEAT_ALLOC_INFO));
int ret;
mutex_lock(&c->sb_lock);
@@ -228,7 +234,7 @@ int bch2_fs_recovery(struct bch_fs *c)
BUG_ON(ret);
}
- ret = verify_superblock_clean(c, clean, j);
+ ret = verify_superblock_clean(c, &clean, j);
if (ret)
goto err;
@@ -270,15 +276,22 @@ int bch2_fs_recovery(struct bch_fs *c)
continue;
err = "invalid btree root pointer";
+ ret = -1;
if (r->error)
goto err;
+ if (i == BTREE_ID_ALLOC &&
+ test_reconstruct_alloc(c))
+ continue;
+
err = "error reading btree root";
- if (bch2_btree_root_read(c, i, &r->key, r->level)) {
+ ret = bch2_btree_root_read(c, i, &r->key, r->level);
+ if (ret) {
if (i != BTREE_ID_ALLOC)
goto err;
mustfix_fsck_err(c, "error reading btree root");
+ run_gc = true;
}
}
@@ -299,8 +312,7 @@ int bch2_fs_recovery(struct bch_fs *c)
set_bit(BCH_FS_ALLOC_READ_DONE, &c->flags);
- if (!(c->sb.compat & (1ULL << BCH_COMPAT_FEAT_ALLOC_INFO)) ||
- c->opts.fsck) {
+ if (run_gc) {
bch_verbose(c, "starting mark and sweep:");
err = "error in recovery";
ret = bch2_gc(c, &journal, true);
@@ -323,24 +335,12 @@ int bch2_fs_recovery(struct bch_fs *c)
goto out;
/*
- * Mark dirty before journal replay, fsck:
- * XXX: after a clean shutdown, this could be done lazily only when fsck
- * finds an error
- */
- bch2_fs_mark_clean(c, false);
-
- /*
* bch2_fs_journal_start() can't happen sooner, or btree_gc_finish()
* will give spurious errors about oldest_gen > bucket_gen -
* this is a hack but oh well.
*/
bch2_fs_journal_start(&c->journal);
- err = "error starting allocator";
- ret = bch2_fs_allocator_start(c);
- if (ret)
- goto err;
-
bch_verbose(c, "starting journal replay:");
err = "journal replay failed";
ret = bch2_journal_replay(c, &journal);
@@ -427,8 +427,8 @@ int bch2_fs_initialize(struct bch_fs *c)
bch2_fs_journal_start(&c->journal);
bch2_journal_set_replay_done(&c->journal);
- err = "error starting allocator";
- ret = bch2_fs_allocator_start(c);
+ err = "error going read write";
+ ret = __bch2_fs_read_write(c, true);
if (ret)
goto err;