]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/recovery.c
Update bcachefs sources to 070ec8d07b bcachefs: Snapshot depth, skiplist fields
[bcachefs-tools-debian] / libbcachefs / recovery.c
index 47adb667a46ab6eaac0f13ca7f81cfa594a03cab..b04e156537a6de2a4c3a71655b91e7b8087d0806 100644 (file)
@@ -594,10 +594,21 @@ static int bch2_journal_replay_key(struct btree_trans *trans,
        unsigned iter_flags =
                BTREE_ITER_INTENT|
                BTREE_ITER_NOT_EXTENTS;
+       unsigned update_flags = BTREE_TRIGGER_NORUN;
        int ret;
 
+       /*
+        * BTREE_UPDATE_KEY_CACHE_RECLAIM disables key cache lookup/update to
+        * keep the key cache coherent with the underlying btree. Nothing
+        * besides the allocator is doing updates yet so we don't need key cache
+        * coherency for non-alloc btrees, and key cache fills for snapshots
+        * btrees use BTREE_ITER_FILTER_SNAPSHOTS, which isn't available until
+        * the snapshots recovery pass runs.
+        */
        if (!k->level && k->btree_id == BTREE_ID_alloc)
                iter_flags |= BTREE_ITER_CACHED;
+       else
+               update_flags |= BTREE_UPDATE_KEY_CACHE_RECLAIM;
 
        bch2_trans_node_iter_init(trans, &iter, k->btree_id, k->k->k.p,
                                  BTREE_MAX_DEPTH, k->level,
@@ -610,7 +621,7 @@ static int bch2_journal_replay_key(struct btree_trans *trans,
        if (k->overwritten)
                goto out;
 
-       ret = bch2_trans_update(trans, &iter, k->k, BTREE_TRIGGER_NORUN);
+       ret = bch2_trans_update(trans, &iter, k->k, update_flags);
 out:
        bch2_trans_iter_exit(trans, &iter);
        return ret;
@@ -1115,6 +1126,7 @@ static void check_version_upgrade(struct bch_fs *c)
        unsigned latest_version = bcachefs_metadata_version_current;
        unsigned old_version = c->sb.version_upgrade_complete ?: c->sb.version;
        unsigned new_version = 0;
+       u64 recovery_passes;
 
        if (old_version < bcachefs_metadata_required_upgrade_below) {
                if (c->opts.version_upgrade == BCH_VERSION_UPGRADE_incompatible ||
@@ -1161,12 +1173,15 @@ static void check_version_upgrade(struct bch_fs *c)
                bch2_version_to_text(&buf, new_version);
                prt_newline(&buf);
 
-               prt_str(&buf, "fsck required");
+               recovery_passes = bch2_upgrade_recovery_passes(c, old_version, new_version);
+               if (recovery_passes) {
+                       prt_str(&buf, "fsck required");
 
-               bch_info(c, "%s", buf.buf);
+                       c->recovery_passes_explicit |= recovery_passes;
+                       c->opts.fix_errors = FSCK_OPT_YES;
+               }
 
-               c->opts.fsck            = true;
-               c->opts.fix_errors      = FSCK_OPT_YES;
+               bch_info(c, "%s", buf.buf);
 
                mutex_lock(&c->sb_lock);
                bch2_sb_upgrade(c, new_version);
@@ -1199,21 +1214,30 @@ static struct recovery_pass_fn recovery_passes[] = {
 #undef x
 };
 
+u64 bch2_fsck_recovery_passes(void)
+{
+       u64 ret = 0;
+
+       for (unsigned i = 0; i < ARRAY_SIZE(recovery_passes); i++)
+               if (recovery_passes[i].when & PASS_FSCK)
+                       ret |= BIT_ULL(i);
+       return ret;
+}
+
 static bool should_run_recovery_pass(struct bch_fs *c, enum bch_recovery_pass pass)
 {
        struct recovery_pass_fn *p = recovery_passes + c->curr_recovery_pass;
 
        if (c->opts.norecovery && pass > BCH_RECOVERY_PASS_snapshots_read)
                return false;
+       if (c->recovery_passes_explicit & BIT_ULL(pass))
+               return true;
        if ((p->when & PASS_FSCK) && c->opts.fsck)
                return true;
        if ((p->when & PASS_UNCLEAN) && !c->sb.clean)
                return true;
        if (p->when & PASS_ALWAYS)
                return true;
-       if (p->when >= PASS_UPGRADE(0) &&
-           bch2_version_upgrading_to(c, p->when >> 4))
-               return true;
        return false;
 }
 
@@ -1297,7 +1321,7 @@ int bch2_fs_recovery(struct bch_fs *c)
                goto err;
        }
 
-       if (!c->opts.nochanges)
+       if (c->opts.fsck || !(c->opts.nochanges && c->opts.norecovery))
                check_version_upgrade(c);
 
        if (c->opts.fsck && c->opts.norecovery) {