bcachefs: Normal update/commit path now works before going RW
authorKent Overstreet <kent.overstreet@gmail.com>
Sat, 19 Feb 2022 07:48:27 +0000 (02:48 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:25 +0000 (17:09 -0400)
This improves __bch2_trans_commit - early in the recovery process, when
we're running btree_gc and before we want to go RW, it now uses
bch2_journal_key_insert() to add the update to the list of updates for
journal replay to do, instead of btree_gc having to use separate
interfaces depending on whether we're running at bringup or, later,
runtime.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
fs/bcachefs/bcachefs.h
fs/bcachefs/btree_gc.c
fs/bcachefs/btree_update_leaf.c
fs/bcachefs/buckets.c
fs/bcachefs/recovery.c

index c5d972b16b3992462a123134f3c143c48f635ca9..378061712c7684cf1f0e8043093cf7cf2b80eda9 100644 (file)
@@ -515,6 +515,7 @@ enum {
        BCH_FS_TOPOLOGY_REPAIR_DONE,
        BCH_FS_FSCK_DONE,
        BCH_FS_STARTED,
+       BCH_FS_MAY_GO_RW,
        BCH_FS_RW,
        BCH_FS_WAS_RW,
 
index ba22c36e30a1dc43e30ef0dac08084027363a6a3..fbd54ac790ba0cae1926845f56b0c08094b1111b 100644 (file)
@@ -753,7 +753,8 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id,
                        atomic64_set(&c->key_version, k->k->version.lo);
        }
 
-       ret = bch2_mark_key(trans, old, *k, flags);
+       ret = __bch2_trans_do(trans, NULL, NULL, 0,
+                       bch2_mark_key(trans, old, *k, flags));
 fsck_err:
 err:
        if (ret)
@@ -1259,7 +1260,7 @@ static int bch2_gc_start(struct bch_fs *c,
 
 static int bch2_alloc_write_key(struct btree_trans *trans,
                                struct btree_iter *iter,
-                               bool initial, bool metadata_only)
+                               bool metadata_only)
 {
        struct bch_fs *c = trans->c;
        struct bch_dev *ca = bch_dev_bkey_exists(c, iter->pos.inode);
@@ -1327,14 +1328,12 @@ static int bch2_alloc_write_key(struct btree_trans *trans,
        if (IS_ERR(a))
                return PTR_ERR(a);
 
-       ret = initial
-               ? bch2_journal_key_insert(c, BTREE_ID_alloc, 0, &a->k)
-               : bch2_trans_update(trans, iter, &a->k, BTREE_TRIGGER_NORUN);
+       ret = bch2_trans_update(trans, iter, &a->k, BTREE_TRIGGER_NORUN);
 fsck_err:
        return ret;
 }
 
-static int bch2_gc_alloc_done(struct bch_fs *c, bool initial, bool metadata_only)
+static int bch2_gc_alloc_done(struct bch_fs *c, bool metadata_only)
 {
        struct btree_trans trans;
        struct btree_iter iter;
@@ -1356,7 +1355,7 @@ static int bch2_gc_alloc_done(struct bch_fs *c, bool initial, bool metadata_only
                        ret = __bch2_trans_do(&trans, NULL, NULL,
                                              BTREE_INSERT_LAZY_RW,
                                        bch2_alloc_write_key(&trans, &iter,
-                                                            initial, metadata_only));
+                                                            metadata_only));
                        if (ret)
                                break;
                }
@@ -1373,7 +1372,7 @@ static int bch2_gc_alloc_done(struct bch_fs *c, bool initial, bool metadata_only
        return ret;
 }
 
-static int bch2_gc_alloc_start(struct bch_fs *c, bool initial, bool metadata_only)
+static int bch2_gc_alloc_start(struct bch_fs *c, bool metadata_only)
 {
        struct bch_dev *ca;
        unsigned i;
@@ -1397,7 +1396,7 @@ static int bch2_gc_alloc_start(struct bch_fs *c, bool initial, bool metadata_onl
        return bch2_alloc_read(c, true, metadata_only);
 }
 
-static void bch2_gc_alloc_reset(struct bch_fs *c, bool initial, bool metadata_only)
+static void bch2_gc_alloc_reset(struct bch_fs *c, bool metadata_only)
 {
        struct bch_dev *ca;
        unsigned i;
@@ -1418,8 +1417,7 @@ static void bch2_gc_alloc_reset(struct bch_fs *c, bool initial, bool metadata_on
        };
 }
 
-static int bch2_gc_reflink_done(struct bch_fs *c, bool initial,
-                               bool metadata_only)
+static int bch2_gc_reflink_done(struct bch_fs *c, bool metadata_only)
 {
        struct btree_trans trans;
        struct btree_iter iter;
@@ -1466,23 +1464,13 @@ static int bch2_gc_reflink_done(struct bch_fs *c, bool initial,
 
                        bkey_reassemble(new, k);
 
-                       if (!r->refcount) {
+                       if (!r->refcount)
                                new->k.type = KEY_TYPE_deleted;
-                               /*
-                                * XXX ugly: bch2_journal_key_insert() queues up
-                                * the key for the journal replay code, which
-                                * doesn't run the extent overwrite pass
-                                */
-                               if (initial)
-                                       new->k.size = 0;
-                       } else {
+                       else
                                *bkey_refcount(new) = cpu_to_le64(r->refcount);
-                       }
 
-                       ret = initial
-                              ? bch2_journal_key_insert(c, BTREE_ID_stripes, 0, new)
-                              : __bch2_trans_do(&trans, NULL, NULL, 0,
-                                       __bch2_btree_insert(&trans, BTREE_ID_reflink, new));
+                       ret = __bch2_trans_do(&trans, NULL, NULL, 0,
+                               __bch2_btree_insert(&trans, BTREE_ID_reflink, new));
                        kfree(new);
 
                        if (ret)
@@ -1496,7 +1484,7 @@ fsck_err:
        return ret;
 }
 
-static int bch2_gc_reflink_start(struct bch_fs *c, bool initial,
+static int bch2_gc_reflink_start(struct bch_fs *c,
                                 bool metadata_only)
 {
        struct btree_trans trans;
@@ -1535,8 +1523,7 @@ static int bch2_gc_reflink_start(struct bch_fs *c, bool initial,
        return ret;
 }
 
-static void bch2_gc_reflink_reset(struct bch_fs *c, bool initial,
-                                 bool metadata_only)
+static void bch2_gc_reflink_reset(struct bch_fs *c, bool metadata_only)
 {
        struct genradix_iter iter;
        struct reflink_gc *r;
@@ -1545,8 +1532,7 @@ static void bch2_gc_reflink_reset(struct bch_fs *c, bool initial,
                r->refcount = 0;
 }
 
-static int bch2_gc_stripes_done(struct bch_fs *c, bool initial,
-                               bool metadata_only)
+static int bch2_gc_stripes_done(struct bch_fs *c, bool metadata_only)
 {
        struct btree_trans trans;
        struct btree_iter iter;
@@ -1594,10 +1580,8 @@ inconsistent:
                        for (i = 0; i < new->v.nr_blocks; i++)
                                stripe_blockcount_set(&new->v, i, m ? m->block_sectors[i] : 0);
 
-                       ret = initial
-                               ? bch2_journal_key_insert(c, BTREE_ID_stripes, 0, &new->k_i)
-                               : __bch2_trans_do(&trans, NULL, NULL, 0,
-                                       __bch2_btree_insert(&trans, BTREE_ID_reflink, &new->k_i));
+                       ret = __bch2_trans_do(&trans, NULL, NULL, 0,
+                               __bch2_btree_insert(&trans, BTREE_ID_reflink, &new->k_i));
                        kfree(new);
                }
        }
@@ -1608,8 +1592,7 @@ fsck_err:
        return ret;
 }
 
-static void bch2_gc_stripes_reset(struct bch_fs *c, bool initial,
-                               bool metadata_only)
+static void bch2_gc_stripes_reset(struct bch_fs *c, bool metadata_only)
 {
        genradix_free(&c->gc_stripes);
 }
@@ -1649,8 +1632,8 @@ int bch2_gc(struct bch_fs *c, bool initial, bool metadata_only)
                           !bch2_btree_interior_updates_nr_pending(c));
 
        ret   = bch2_gc_start(c, metadata_only) ?:
-               bch2_gc_alloc_start(c, initial, metadata_only) ?:
-               bch2_gc_reflink_start(c, initial, metadata_only);
+               bch2_gc_alloc_start(c, metadata_only) ?:
+               bch2_gc_reflink_start(c, metadata_only);
        if (ret)
                goto out;
 again:
@@ -1705,9 +1688,9 @@ again:
                clear_bit(BCH_FS_NEED_ANOTHER_GC, &c->flags);
                __gc_pos_set(c, gc_phase(GC_PHASE_NOT_RUNNING));
 
-               bch2_gc_stripes_reset(c, initial, metadata_only);
-               bch2_gc_alloc_reset(c, initial, metadata_only);
-               bch2_gc_reflink_reset(c, initial, metadata_only);
+               bch2_gc_stripes_reset(c, metadata_only);
+               bch2_gc_alloc_reset(c, metadata_only);
+               bch2_gc_reflink_reset(c, metadata_only);
 
                /* flush fsck errors, reset counters */
                bch2_flush_fsck_errs(c);
@@ -1717,9 +1700,9 @@ out:
        if (!ret) {
                bch2_journal_block(&c->journal);
 
-               ret   = bch2_gc_stripes_done(c, initial, metadata_only) ?:
-                       bch2_gc_reflink_done(c, initial, metadata_only) ?:
-                       bch2_gc_alloc_done(c, initial, metadata_only) ?:
+               ret   = bch2_gc_stripes_done(c, metadata_only) ?:
+                       bch2_gc_reflink_done(c, metadata_only) ?:
+                       bch2_gc_alloc_done(c, metadata_only) ?:
                        bch2_gc_done(c, initial, metadata_only);
 
                bch2_journal_unblock(&c->journal);
index 9d41711c4e9b0a9c63ee63701c9946637524dc0c..fcc56235ae9075e2ff35cb941eb5f27e7d75e97c 100644 (file)
@@ -968,6 +968,27 @@ static int bch2_trans_commit_run_triggers(struct btree_trans *trans)
        return 0;
 }
 
+/*
+ * This is for updates done in the early part of fsck - btree_gc - before we've
+ * gone RW. we only add the new key to the list of keys for journal replay to
+ * do.
+ */
+static noinline int
+do_bch2_trans_commit_to_journal_replay(struct btree_trans *trans)
+{
+       struct bch_fs *c = trans->c;
+       struct btree_insert_entry *i;
+       int ret = 0;
+
+       trans_for_each_update(trans, i) {
+               ret = bch2_journal_key_insert(c, i->btree_id, i->level, i->k);
+               if (ret)
+                       break;
+       }
+
+       return ret;
+}
+
 int __bch2_trans_commit(struct btree_trans *trans)
 {
        struct bch_fs *c = trans->c;
@@ -986,6 +1007,11 @@ int __bch2_trans_commit(struct btree_trans *trans)
        if (ret)
                goto out_reset;
 
+       if (unlikely(!test_bit(BCH_FS_MAY_GO_RW, &c->flags))) {
+               ret = do_bch2_trans_commit_to_journal_replay(trans);
+               goto out_reset;
+       }
+
        if (!(trans->flags & BTREE_INSERT_NOCHECK_RW) &&
            unlikely(!percpu_ref_tryget(&c->writes))) {
                ret = bch2_trans_commit_get_rw_cold(trans);
index edc1918cf140314cb9837eba7fd5632f87452416..1c1266fb80dfb05fd7837788fcb21ba726a8db52 100644 (file)
@@ -1164,9 +1164,11 @@ static int bch2_mark_reservation(struct btree_trans *trans,
        return 0;
 }
 
-static s64 __bch2_mark_reflink_p(struct bch_fs *c, struct bkey_s_c_reflink_p p,
+static s64 __bch2_mark_reflink_p(struct btree_trans *trans,
+                                struct bkey_s_c_reflink_p p,
                                 u64 *idx, unsigned flags, size_t r_idx)
 {
+       struct bch_fs *c = trans->c;
        struct reflink_gc *r;
        int add = !(flags & BTREE_TRIGGER_OVERWRITE) ? 1 : -1;
        s64 ret = 0;
@@ -1199,7 +1201,7 @@ not_found:
                new.k.type      = KEY_TYPE_error;
                new.k.p         = p.k->p;
                new.k.size      = p.k->size;
-               ret = bch2_journal_key_insert(c, BTREE_ID_extents, 0, &new.k_i);
+               ret = __bch2_btree_insert(trans, BTREE_ID_extents, &new.k_i);
        }
 fsck_err:
        return ret;
@@ -1238,7 +1240,7 @@ static int bch2_mark_reflink_p(struct btree_trans *trans,
        }
 
        while (idx < end && !ret)
-               ret = __bch2_mark_reflink_p(c, p, &idx, flags, l++);
+               ret = __bch2_mark_reflink_p(trans, p, &idx, flags, l++);
 
        return ret;
 }
index d33b9e2bb1e39653e6f4d71492a2758831053651..ae9ae1c7138c38199e5b3666868b0a420f57f675 100644 (file)
@@ -1157,6 +1157,7 @@ use_clean:
 
        clear_bit(BCH_FS_REBUILD_REPLICAS, &c->flags);
        set_bit(BCH_FS_INITIAL_GC_DONE, &c->flags);
+       set_bit(BCH_FS_MAY_GO_RW, &c->flags);
 
        /*
         * Skip past versions that might have possibly been used (as nonces),
@@ -1317,6 +1318,7 @@ int bch2_fs_initialize(struct bch_fs *c)
        mutex_unlock(&c->sb_lock);
 
        set_bit(BCH_FS_INITIAL_GC_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++)