]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/recovery.c
Merge pull request #190 from Dikay900/fs_free_space
[bcachefs-tools-debian] / libbcachefs / recovery.c
index 130274b195e21621c391ad89d965440cf077816c..69b49845a730e612062a1e3b8aa3ed210480a466 100644 (file)
@@ -159,20 +159,24 @@ static int bch2_journal_replay(struct bch_fs *c)
                        goto err;
        }
 
+       BUG_ON(!atomic_read(&keys->ref));
+
        /*
         * First, attempt to replay keys in sorted order. This is more
-        * efficient, but some might fail if that would cause a journal
-        * deadlock.
+        * efficient - better locality of btree access -  but some might fail if
+        * that would cause a journal deadlock.
         */
        for (size_t i = 0; i < keys->nr; i++) {
                cond_resched();
 
                struct journal_key *k = keys->d + i;
 
-               ret = commit_do(trans, NULL, NULL,
-                               BCH_TRANS_COMMIT_no_enospc|
-                               BCH_TRANS_COMMIT_journal_reclaim|
-                               (!k->allocated ? BCH_TRANS_COMMIT_no_journal_res : 0),
+               /* Skip fastpath if we're low on space in the journal */
+               ret = c->journal.watermark ? -1 :
+                       commit_do(trans, NULL, NULL,
+                                 BCH_TRANS_COMMIT_no_enospc|
+                                 BCH_TRANS_COMMIT_journal_reclaim|
+                                 (!k->allocated ? BCH_TRANS_COMMIT_no_journal_res : 0),
                             bch2_journal_replay_key(trans, k));
                BUG_ON(!ret && !k->overwritten);
                if (ret) {
@@ -211,17 +215,22 @@ static int bch2_journal_replay(struct bch_fs *c)
                BUG_ON(!k->overwritten);
        }
 
+       /*
+        * We need to put our btree_trans before calling flush_all_pins(), since
+        * that will use a btree_trans internally
+        */
        bch2_trans_put(trans);
        trans = NULL;
 
+       if (!c->opts.keep_journal)
+               bch2_journal_keys_put_initial(c);
+
        replay_now_at(j, j->replay_journal_seq_end);
        j->replay_journal_seq = 0;
 
        bch2_journal_set_replay_done(j);
-       bch2_journal_flush_all_pins(j);
-       ret = bch2_journal_error(j);
 
-       if (keys->nr && !ret)
+       if (keys->nr)
                bch2_journal_log_msg(c, "journal replay finished");
 err:
        if (trans)
@@ -295,8 +304,6 @@ static int journal_replay_entry_early(struct bch_fs *c,
                struct bch_dev *ca = bch_dev_bkey_exists(c, le32_to_cpu(u->dev));
                unsigned i, nr_types = jset_entry_dev_usage_nr_types(u);
 
-               ca->usage_base->buckets_ec              = le64_to_cpu(u->buckets_ec);
-
                for (i = 0; i < min_t(unsigned, nr_types, BCH_DATA_NR); i++) {
                        ca->usage_base->d[i].buckets    = le64_to_cpu(u->d[i].buckets);
                        ca->usage_base->d[i].sectors    = le64_to_cpu(u->d[i].sectors);
@@ -525,8 +532,8 @@ static int bch2_set_may_go_rw(struct bch_fs *c)
        move_gap(keys->d, keys->nr, keys->size, keys->gap, keys->nr);
        keys->gap = keys->nr;
 
-       set_bit(BCH_FS_MAY_GO_RW, &c->flags);
-       if (keys->nr)
+       set_bit(BCH_FS_may_go_rw, &c->flags);
+       if (keys->nr || c->opts.fsck)
                return bch2_fs_read_write_early(c);
        return 0;
 }
@@ -652,13 +659,13 @@ static int bch2_run_recovery_pass(struct bch_fs *c, enum bch_recovery_pass pass)
                struct recovery_pass_fn *p = recovery_pass_fns + pass;
 
                if (!(p->when & PASS_SILENT))
-                       printk(KERN_INFO bch2_log_msg(c, "%s..."),
-                              bch2_recovery_passes[pass]);
+                       bch2_print(c, KERN_INFO bch2_log_msg(c, "%s..."),
+                                  bch2_recovery_passes[pass]);
                ret = p->fn(c);
                if (ret)
                        return ret;
                if (!(p->when & PASS_SILENT))
-                       printk(KERN_CONT " done\n");
+                       bch2_print(c, KERN_CONT " done\n");
 
                c->recovery_passes_complete |= BIT_ULL(pass);
        }
@@ -871,11 +878,13 @@ use_clean:
 
        /* If we fixed errors, verify that fs is actually clean now: */
        if (IS_ENABLED(CONFIG_BCACHEFS_DEBUG) &&
-           test_bit(BCH_FS_ERRORS_FIXED, &c->flags) &&
-           !test_bit(BCH_FS_ERRORS_NOT_FIXED, &c->flags) &&
-           !test_bit(BCH_FS_ERROR, &c->flags)) {
+           test_bit(BCH_FS_errors_fixed, &c->flags) &&
+           !test_bit(BCH_FS_errors_not_fixed, &c->flags) &&
+           !test_bit(BCH_FS_error, &c->flags)) {
+               bch2_flush_fsck_errs(c);
+
                bch_info(c, "Fixed errors, running fsck a second time to verify fs is clean");
-               clear_bit(BCH_FS_ERRORS_FIXED, &c->flags);
+               clear_bit(BCH_FS_errors_fixed, &c->flags);
 
                c->curr_recovery_pass = BCH_RECOVERY_PASS_check_alloc_info;
 
@@ -883,13 +892,13 @@ use_clean:
                if (ret)
                        goto err;
 
-               if (test_bit(BCH_FS_ERRORS_FIXED, &c->flags) ||
-                   test_bit(BCH_FS_ERRORS_NOT_FIXED, &c->flags)) {
+               if (test_bit(BCH_FS_errors_fixed, &c->flags) ||
+                   test_bit(BCH_FS_errors_not_fixed, &c->flags)) {
                        bch_err(c, "Second fsck run was not clean");
-                       set_bit(BCH_FS_ERRORS_NOT_FIXED, &c->flags);
+                       set_bit(BCH_FS_errors_not_fixed, &c->flags);
                }
 
-               set_bit(BCH_FS_ERRORS_FIXED, &c->flags);
+               set_bit(BCH_FS_errors_fixed, &c->flags);
        }
 
        if (enabled_qtypes(c)) {
@@ -906,14 +915,14 @@ use_clean:
                write_sb = true;
        }
 
-       if (!test_bit(BCH_FS_ERROR, &c->flags)) {
+       if (!test_bit(BCH_FS_error, &c->flags)) {
                c->disk_sb.sb->compat[0] |= cpu_to_le64(1ULL << BCH_COMPAT_alloc_info);
                write_sb = true;
        }
 
        if (c->opts.fsck &&
-           !test_bit(BCH_FS_ERROR, &c->flags) &&
-           !test_bit(BCH_FS_ERRORS_NOT_FIXED, &c->flags)) {
+           !test_bit(BCH_FS_error, &c->flags) &&
+           !test_bit(BCH_FS_errors_not_fixed, &c->flags)) {
                SET_BCH_SB_HAS_ERRORS(c->disk_sb.sb, 0);
                SET_BCH_SB_HAS_TOPOLOGY_ERRORS(c->disk_sb.sb, 0);
                write_sb = true;
@@ -929,8 +938,12 @@ use_clean:
 
                bch2_move_stats_init(&stats, "recovery");
 
-               bch_info(c, "scanning for old btree nodes");
-               ret =   bch2_fs_read_write(c) ?:
+               struct printbuf buf = PRINTBUF;
+               bch2_version_to_text(&buf, c->sb.version_min);
+               bch_info(c, "scanning for old btree nodes: min_version %s", buf.buf);
+               printbuf_exit(&buf);
+
+               ret =   bch2_fs_read_write_early(c) ?:
                        bch2_scan_old_btree_nodes(c, &stats);
                if (ret)
                        goto err;
@@ -943,17 +956,15 @@ use_clean:
 
        ret = 0;
 out:
-       set_bit(BCH_FS_FSCK_DONE, &c->flags);
+       set_bit(BCH_FS_fsck_done, &c->flags);
        bch2_flush_fsck_errs(c);
 
        if (!c->opts.keep_journal &&
-           test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags)) {
-               bch2_journal_keys_free(&c->journal_keys);
-               bch2_journal_entries_free(c);
-       }
+           test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags))
+               bch2_journal_keys_put_initial(c);
        kfree(clean);
 
-       if (!ret && test_bit(BCH_FS_NEED_DELETE_DEAD_SNAPSHOTS, &c->flags)) {
+       if (!ret && test_bit(BCH_FS_need_delete_dead_snapshots, &c->flags)) {
                bch2_fs_read_write_early(c);
                bch2_delete_dead_snapshots_async(c);
        }
@@ -992,8 +1003,8 @@ int bch2_fs_initialize(struct bch_fs *c)
        mutex_unlock(&c->sb_lock);
 
        c->curr_recovery_pass = ARRAY_SIZE(recovery_pass_fns);
-       set_bit(BCH_FS_MAY_GO_RW, &c->flags);
-       set_bit(BCH_FS_FSCK_DONE, &c->flags);
+       set_bit(BCH_FS_may_go_rw, &c->flags);
+       set_bit(BCH_FS_fsck_done, &c->flags);
 
        for (i = 0; i < BTREE_ID_NR; i++)
                bch2_btree_root_alloc(c, i);