]> www.infradead.org Git - nvme.git/commitdiff
bcachefs: Initialize gc buckets in alloc trigger
authorKent Overstreet <kent.overstreet@linux.dev>
Wed, 29 May 2024 22:54:39 +0000 (18:54 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 14 Jul 2024 23:00:14 +0000 (19:00 -0400)
Needed for online fsck; we need the trigger to initialize newly
allocated buckets and generation number changes while gc is running.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/alloc_background.c
fs/bcachefs/btree_gc.c

index 9bb0dbe134d5f88d0ef0f4a02d6a1540f66227c1..831fd0e2a5bf545ba0758bd50bc065633f3c38ab 100644 (file)
@@ -831,10 +831,9 @@ int bch2_trigger_alloc(struct btree_trans *trans,
 
        struct bch_alloc_v4 old_a_convert;
        const struct bch_alloc_v4 *old_a = bch2_alloc_to_v4(old, &old_a_convert);
+       struct bch_alloc_v4 *new_a = bkey_s_to_alloc_v4(new).v;
 
        if (flags & BTREE_TRIGGER_transactional) {
-               struct bch_alloc_v4 *new_a = bkey_s_to_alloc_v4(new).v;
-
                alloc_data_type_set(new_a, new_a->data_type);
 
                if (bch2_bucket_sectors_total(*new_a) > bch2_bucket_sectors_total(*old_a)) {
@@ -906,7 +905,6 @@ int bch2_trigger_alloc(struct btree_trans *trans,
        }
 
        if ((flags & BTREE_TRIGGER_atomic) && (flags & BTREE_TRIGGER_insert)) {
-               struct bch_alloc_v4 *new_a = bkey_s_to_alloc_v4(new).v;
                u64 journal_seq = trans->journal_res.seq;
                u64 bucket_journal_seq = new_a->journal_seq;
 
@@ -935,11 +933,9 @@ int bch2_trigger_alloc(struct btree_trans *trans,
                                        c->journal.flushed_seq_ondisk,
                                        new.k->p.inode, new.k->p.offset,
                                        bucket_journal_seq);
-                       if (ret) {
-                               bch2_fs_fatal_error(c,
-                                       "setting bucket_needs_journal_commit: %s", bch2_err_str(ret));
+                       if (bch2_fs_fatal_err_on(ret, c,
+                                       "setting bucket_needs_journal_commit: %s", bch2_err_str(ret)))
                                goto err;
-                       }
                }
 
                if (new_a->gen != old_a->gen) {
@@ -974,6 +970,18 @@ int bch2_trigger_alloc(struct btree_trans *trans,
                if (statechange(a->data_type == BCH_DATA_need_gc_gens))
                        bch2_gc_gens_async(c);
        }
+
+       if ((flags & BTREE_TRIGGER_gc) && (flags & BTREE_TRIGGER_insert)) {
+               rcu_read_lock();
+               struct bucket *g = gc_bucket(ca, new.k->p.offset);
+               if (unlikely(!g)) {
+                       rcu_read_unlock();
+                       goto invalid_bucket;
+               }
+               g->gen_valid    = 1;
+               g->gen          = new_a->gen;
+               rcu_read_unlock();
+       }
 err:
        printbuf_exit(&buf);
        bch2_dev_put(ca);
index 22771a861b298dcef738350c06e1db7fb90b4b64..f651a70b2a836bb01c9222d6cd30a8dac3757a72 100644 (file)
@@ -624,7 +624,7 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id,
        }
 
        ret = bch2_key_trigger(trans, btree_id, level, old, unsafe_bkey_s_c_to_s(k),
-                              BTREE_TRIGGER_gc|flags);
+                              BTREE_TRIGGER_gc|BTREE_TRIGGER_insert|flags);
 out:
 fsck_err:
        printbuf_exit(&buf);
@@ -891,14 +891,16 @@ static int bch2_gc_alloc_done(struct bch_fs *c)
 
 static int bch2_gc_alloc_start(struct bch_fs *c)
 {
+       int ret = 0;
+
        for_each_member_device(c, ca) {
                struct bucket_array *buckets = kvmalloc(sizeof(struct bucket_array) +
                                ca->mi.nbuckets * sizeof(struct bucket),
                                GFP_KERNEL|__GFP_ZERO);
                if (!buckets) {
                        bch2_dev_put(ca);
-                       bch_err(c, "error allocating ca->buckets[gc]");
-                       return -BCH_ERR_ENOMEM_gc_alloc_start;
+                       ret = -BCH_ERR_ENOMEM_gc_alloc_start;
+                       break;
                }
 
                buckets->first_bucket   = ca->mi.first_bucket;
@@ -908,27 +910,6 @@ static int bch2_gc_alloc_start(struct bch_fs *c)
                rcu_assign_pointer(ca->buckets_gc, buckets);
        }
 
-       struct bch_dev *ca = NULL;
-       int ret = bch2_trans_run(c,
-               for_each_btree_key(trans, iter, BTREE_ID_alloc, POS_MIN,
-                                        BTREE_ITER_prefetch, k, ({
-                       ca = bch2_dev_iterate(c, ca, k.k->p.inode);
-                       if (!ca) {
-                               bch2_btree_iter_set_pos(&iter, POS(k.k->p.inode + 1, 0));
-                               continue;
-                       }
-
-                       if (bucket_valid(ca, k.k->p.offset)) {
-                               struct bch_alloc_v4 a_convert;
-                               const struct bch_alloc_v4 *a = bch2_alloc_to_v4(k, &a_convert);
-
-                               struct bucket *g = gc_bucket(ca, k.k->p.offset);
-                               g->gen_valid    = 1;
-                               g->gen          = a->gen;
-                       }
-                       0;
-               })));
-       bch2_dev_put(ca);
        bch_err_fn(c, ret);
        return ret;
 }