]> www.infradead.org Git - linux.git/commitdiff
bcachefs: reconstruct_alloc cleanup
authorKent Overstreet <kent.overstreet@linux.dev>
Tue, 12 Mar 2024 01:15:26 +0000 (21:15 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Thu, 14 Mar 2024 01:22:26 +0000 (21:22 -0400)
Now that we've got the errors_silent mechanism, we don't have to check
if the reconstruct_alloc option is set all over the place.

Also - users no longer have to explicitly select fsck and fix_errors.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/alloc_background.c
fs/bcachefs/backpointers.c
fs/bcachefs/btree_gc.c
fs/bcachefs/lru.c
fs/bcachefs/recovery.c
fs/bcachefs/sb-downgrade.c
fs/bcachefs/util.h

index ccd6cbfd470ea7f2003e9f4b854acef9a0129177..c47f72f2bd586f6c15bc42e019cc97edc0f6030a 100644 (file)
@@ -1052,14 +1052,13 @@ int bch2_check_alloc_key(struct btree_trans *trans,
        if (ret)
                goto err;
 
-       if (k.k->type != discard_key_type &&
-           (c->opts.reconstruct_alloc ||
-            fsck_err(c, need_discard_key_wrong,
-                     "incorrect key in need_discard btree (got %s should be %s)\n"
-                     "  %s",
-                     bch2_bkey_types[k.k->type],
-                     bch2_bkey_types[discard_key_type],
-                     (bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf)))) {
+       if (fsck_err_on(k.k->type != discard_key_type,
+                       c, need_discard_key_wrong,
+                       "incorrect key in need_discard btree (got %s should be %s)\n"
+                       "  %s",
+                       bch2_bkey_types[k.k->type],
+                       bch2_bkey_types[discard_key_type],
+                       (bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf))) {
                struct bkey_i *update =
                        bch2_trans_kmalloc(trans, sizeof(*update));
 
@@ -1083,15 +1082,14 @@ int bch2_check_alloc_key(struct btree_trans *trans,
        if (ret)
                goto err;
 
-       if (k.k->type != freespace_key_type &&
-           (c->opts.reconstruct_alloc ||
-            fsck_err(c, freespace_key_wrong,
-                     "incorrect key in freespace btree (got %s should be %s)\n"
-                     "  %s",
-                     bch2_bkey_types[k.k->type],
-                     bch2_bkey_types[freespace_key_type],
-                     (printbuf_reset(&buf),
-                      bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf)))) {
+       if (fsck_err_on(k.k->type != freespace_key_type,
+                       c, freespace_key_wrong,
+                       "incorrect key in freespace btree (got %s should be %s)\n"
+                       "  %s",
+                       bch2_bkey_types[k.k->type],
+                       bch2_bkey_types[freespace_key_type],
+                       (printbuf_reset(&buf),
+                        bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf))) {
                struct bkey_i *update =
                        bch2_trans_kmalloc(trans, sizeof(*update));
 
@@ -1115,14 +1113,13 @@ int bch2_check_alloc_key(struct btree_trans *trans,
        if (ret)
                goto err;
 
-       if (a->gen != alloc_gen(k, gens_offset) &&
-           (c->opts.reconstruct_alloc ||
-            fsck_err(c, bucket_gens_key_wrong,
-                     "incorrect gen in bucket_gens btree (got %u should be %u)\n"
-                     "  %s",
-                     alloc_gen(k, gens_offset), a->gen,
-                     (printbuf_reset(&buf),
-                      bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf)))) {
+       if (fsck_err_on(a->gen != alloc_gen(k, gens_offset),
+                       c, bucket_gens_key_wrong,
+                       "incorrect gen in bucket_gens btree (got %u should be %u)\n"
+                       "  %s",
+                       alloc_gen(k, gens_offset), a->gen,
+                       (printbuf_reset(&buf),
+                        bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf))) {
                struct bkey_i_bucket_gens *g =
                        bch2_trans_kmalloc(trans, sizeof(*g));
 
@@ -1174,14 +1171,13 @@ int bch2_check_alloc_hole_freespace(struct btree_trans *trans,
 
        *end = bkey_min(k.k->p, *end);
 
-       if (k.k->type != KEY_TYPE_set &&
-           (c->opts.reconstruct_alloc ||
-            fsck_err(c, freespace_hole_missing,
-                     "hole in alloc btree missing in freespace btree\n"
-                     "  device %llu buckets %llu-%llu",
-                     freespace_iter->pos.inode,
-                     freespace_iter->pos.offset,
-                     end->offset))) {
+       if (fsck_err_on(k.k->type != KEY_TYPE_set,
+                       c, freespace_hole_missing,
+                       "hole in alloc btree missing in freespace btree\n"
+                       "  device %llu buckets %llu-%llu",
+                       freespace_iter->pos.inode,
+                       freespace_iter->pos.offset,
+                       end->offset)) {
                struct bkey_i *update =
                        bch2_trans_kmalloc(trans, sizeof(*update));
 
index f2b33fe40bd8e01d0656bd833a91d048028ce21c..8cb35ea572cb95ce13a956b21a4ec3a40ac39cdb 100644 (file)
@@ -477,8 +477,7 @@ missing:
        prt_printf(&buf, "\nbp pos ");
        bch2_bpos_to_text(&buf, bp_iter.pos);
 
-       if (c->opts.reconstruct_alloc ||
-           fsck_err(c, ptr_to_missing_backpointer, "%s", buf.buf))
+       if (fsck_err(c, ptr_to_missing_backpointer, "%s", buf.buf))
                ret = bch2_bucket_backpointer_mod(trans, bucket, bp, orig_k, true);
 
        goto out;
index 550d71bcedc4b78e738cf61af043ef2786a44d06..584aee7010deaa79df36edd60e5d7e59bcb7a7e3 100644 (file)
@@ -593,16 +593,15 @@ static int bch2_check_fix_ptrs(struct btree_trans *trans, enum btree_id btree_id
                struct bucket *g = PTR_GC_BUCKET(ca, &p.ptr);
                enum bch_data_type data_type = bch2_bkey_ptr_data_type(*k, &entry_c->ptr);
 
-               if (!g->gen_valid &&
-                   (c->opts.reconstruct_alloc ||
-                    fsck_err(c, ptr_to_missing_alloc_key,
-                             "bucket %u:%zu data type %s ptr gen %u missing in alloc btree\n"
-                             "while marking %s",
-                             p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr),
-                             bch2_data_type_str(ptr_data_type(k->k, &p.ptr)),
-                             p.ptr.gen,
-                             (printbuf_reset(&buf),
-                              bch2_bkey_val_to_text(&buf, c, *k), buf.buf)))) {
+               if (fsck_err_on(!g->gen_valid,
+                               c, ptr_to_missing_alloc_key,
+                               "bucket %u:%zu data type %s ptr gen %u missing in alloc btree\n"
+                               "while marking %s",
+                               p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr),
+                               bch2_data_type_str(ptr_data_type(k->k, &p.ptr)),
+                               p.ptr.gen,
+                               (printbuf_reset(&buf),
+                                bch2_bkey_val_to_text(&buf, c, *k), buf.buf))) {
                        if (!p.ptr.cached) {
                                g->gen_valid            = true;
                                g->gen                  = p.ptr.gen;
@@ -611,16 +610,15 @@ static int bch2_check_fix_ptrs(struct btree_trans *trans, enum btree_id btree_id
                        }
                }
 
-               if (gen_cmp(p.ptr.gen, g->gen) > 0 &&
-                   (c->opts.reconstruct_alloc ||
-                    fsck_err(c, ptr_gen_newer_than_bucket_gen,
-                             "bucket %u:%zu data type %s ptr gen in the future: %u > %u\n"
-                             "while marking %s",
-                             p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr),
-                             bch2_data_type_str(ptr_data_type(k->k, &p.ptr)),
-                             p.ptr.gen, g->gen,
-                             (printbuf_reset(&buf),
-                              bch2_bkey_val_to_text(&buf, c, *k), buf.buf)))) {
+               if (fsck_err_on(gen_cmp(p.ptr.gen, g->gen) > 0,
+                               c, ptr_gen_newer_than_bucket_gen,
+                               "bucket %u:%zu data type %s ptr gen in the future: %u > %u\n"
+                               "while marking %s",
+                               p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr),
+                               bch2_data_type_str(ptr_data_type(k->k, &p.ptr)),
+                               p.ptr.gen, g->gen,
+                               (printbuf_reset(&buf),
+                                bch2_bkey_val_to_text(&buf, c, *k), buf.buf))) {
                        if (!p.ptr.cached) {
                                g->gen_valid            = true;
                                g->gen                  = p.ptr.gen;
@@ -633,28 +631,26 @@ static int bch2_check_fix_ptrs(struct btree_trans *trans, enum btree_id btree_id
                        }
                }
 
-               if (gen_cmp(g->gen, p.ptr.gen) > BUCKET_GC_GEN_MAX &&
-                   (c->opts.reconstruct_alloc ||
-                    fsck_err(c, ptr_gen_newer_than_bucket_gen,
-                             "bucket %u:%zu gen %u data type %s: ptr gen %u too stale\n"
-                             "while marking %s",
-                             p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr), g->gen,
-                             bch2_data_type_str(ptr_data_type(k->k, &p.ptr)),
-                             p.ptr.gen,
-                             (printbuf_reset(&buf),
-                              bch2_bkey_val_to_text(&buf, c, *k), buf.buf))))
+               if (fsck_err_on(gen_cmp(g->gen, p.ptr.gen) > BUCKET_GC_GEN_MAX,
+                               c, ptr_gen_newer_than_bucket_gen,
+                               "bucket %u:%zu gen %u data type %s: ptr gen %u too stale\n"
+                               "while marking %s",
+                               p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr), g->gen,
+                               bch2_data_type_str(ptr_data_type(k->k, &p.ptr)),
+                               p.ptr.gen,
+                               (printbuf_reset(&buf),
+                                bch2_bkey_val_to_text(&buf, c, *k), buf.buf)))
                        do_update = true;
 
-               if (!p.ptr.cached && gen_cmp(p.ptr.gen, g->gen) < 0 &&
-                   (c->opts.reconstruct_alloc ||
-                    fsck_err(c, stale_dirty_ptr,
-                             "bucket %u:%zu data type %s stale dirty ptr: %u < %u\n"
-                             "while marking %s",
-                             p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr),
-                             bch2_data_type_str(ptr_data_type(k->k, &p.ptr)),
-                             p.ptr.gen, g->gen,
-                             (printbuf_reset(&buf),
-                              bch2_bkey_val_to_text(&buf, c, *k), buf.buf))))
+               if (fsck_err_on(!p.ptr.cached && gen_cmp(p.ptr.gen, g->gen) < 0,
+                               c, stale_dirty_ptr,
+                               "bucket %u:%zu data type %s stale dirty ptr: %u < %u\n"
+                               "while marking %s",
+                               p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr),
+                               bch2_data_type_str(ptr_data_type(k->k, &p.ptr)),
+                               p.ptr.gen, g->gen,
+                               (printbuf_reset(&buf),
+                                bch2_bkey_val_to_text(&buf, c, *k), buf.buf)))
                        do_update = true;
 
                if (data_type != BCH_DATA_btree && p.ptr.gen != g->gen)
@@ -1411,8 +1407,7 @@ static int bch2_alloc_write_key(struct btree_trans *trans,
        if (gen_after(old->gen, gc.gen))
                return 0;
 
-       if (c->opts.reconstruct_alloc ||
-           fsck_err_on(new.data_type != gc.data_type, c,
+       if (fsck_err_on(new.data_type != gc.data_type, c,
                        alloc_key_data_type_wrong,
                        "bucket %llu:%llu gen %u has wrong data_type"
                        ": got %s, should be %s",
@@ -1423,8 +1418,7 @@ static int bch2_alloc_write_key(struct btree_trans *trans,
                new.data_type = gc.data_type;
 
 #define copy_bucket_field(_errtype, _f)                                        \
-       if (c->opts.reconstruct_alloc ||                                \
-           fsck_err_on(new._f != gc._f, c, _errtype,                   \
+       if (fsck_err_on(new._f != gc._f, c, _errtype,                   \
                        "bucket %llu:%llu gen %u data type %s has wrong " #_f   \
                        ": got %u, should be %u",                       \
                        iter->pos.inode, iter->pos.offset,              \
index ed7577cdb2124c946b54fef45b265d99126032e1..26569043e36803ca290342063f6435f7c71d7b87 100644 (file)
@@ -125,8 +125,7 @@ static int bch2_check_lru_key(struct btree_trans *trans,
                        goto out;
                }
 
-               if (c->opts.reconstruct_alloc ||
-                   fsck_err(c, lru_entry_bad,
+               if (fsck_err(c, lru_entry_bad,
                             "incorrect lru entry: lru %s time %llu\n"
                             "  %s\n"
                             "  for %s",
index 0c579ba8de7802a883759fb745f57186ba43b875..2af219aedfdbefb36d37fe19423d8e26cabf0cdd 100644 (file)
@@ -52,14 +52,47 @@ static bool btree_id_is_alloc(enum btree_id id)
 }
 
 /* for -o reconstruct_alloc: */
-static void drop_alloc_keys(struct journal_keys *keys)
+static void do_reconstruct_alloc(struct bch_fs *c)
 {
+       bch2_journal_log_msg(c, "dropping alloc info");
+       bch_info(c, "dropping and reconstructing all alloc info");
+
+       mutex_lock(&c->sb_lock);
+       struct bch_sb_field_ext *ext = bch2_sb_field_get(c->disk_sb.sb, ext);
+
+       __set_bit_le64(BCH_RECOVERY_PASS_STABLE_check_allocations, ext->recovery_passes_required);
+       __set_bit_le64(BCH_RECOVERY_PASS_STABLE_check_alloc_info, ext->recovery_passes_required);
+       __set_bit_le64(BCH_RECOVERY_PASS_STABLE_check_lrus, ext->recovery_passes_required);
+       __set_bit_le64(BCH_RECOVERY_PASS_STABLE_check_extents_to_backpointers, ext->recovery_passes_required);
+       __set_bit_le64(BCH_RECOVERY_PASS_STABLE_check_alloc_to_lru_refs, ext->recovery_passes_required);
+
+       __set_bit_le64(BCH_FSCK_ERR_ptr_to_missing_alloc_key, ext->errors_silent);
+       __set_bit_le64(BCH_FSCK_ERR_ptr_gen_newer_than_bucket_gen, ext->errors_silent);
+       __set_bit_le64(BCH_FSCK_ERR_stale_dirty_ptr, ext->errors_silent);
+       __set_bit_le64(BCH_FSCK_ERR_alloc_key_data_type_wrong, ext->errors_silent);
+       __set_bit_le64(BCH_FSCK_ERR_alloc_key_gen_wrong, ext->errors_silent);
+       __set_bit_le64(BCH_FSCK_ERR_alloc_key_dirty_sectors_wrong, ext->errors_silent);
+       __set_bit_le64(BCH_FSCK_ERR_alloc_key_stripe_wrong, ext->errors_silent);
+       __set_bit_le64(BCH_FSCK_ERR_alloc_key_stripe_redundancy_wrong, ext->errors_silent);
+       __set_bit_le64(BCH_FSCK_ERR_need_discard_key_wrong, ext->errors_silent);
+       __set_bit_le64(BCH_FSCK_ERR_freespace_key_wrong, ext->errors_silent);
+       __set_bit_le64(BCH_FSCK_ERR_bucket_gens_key_wrong, ext->errors_silent);
+       __set_bit_le64(BCH_FSCK_ERR_freespace_hole_missing, ext->errors_silent);
+       __set_bit_le64(BCH_FSCK_ERR_ptr_to_missing_backpointer, ext->errors_silent);
+       __set_bit_le64(BCH_FSCK_ERR_lru_entry_bad, ext->errors_silent);
+       c->sb.compat &= ~(1ULL << BCH_COMPAT_alloc_info);
+
+       bch2_write_super(c);
+       mutex_unlock(&c->sb_lock);
+
+       c->recovery_passes_explicit |= bch2_recovery_passes_from_stable(le64_to_cpu(ext->recovery_passes_required[0]));
+
+       struct journal_keys *keys = &c->journal_keys;
        size_t src, dst;
 
        for (src = 0, dst = 0; src < keys->nr; src++)
                if (!btree_id_is_alloc(keys->data[src].btree_id))
                        keys->data[dst++] = keys->data[src];
-
        keys->nr = dst;
 }
 
@@ -395,11 +428,8 @@ static int read_btree_roots(struct bch_fs *c)
                if (!r->alive)
                        continue;
 
-               if (btree_id_is_alloc(i) &&
-                   c->opts.reconstruct_alloc) {
-                       c->sb.compat &= ~(1ULL << BCH_COMPAT_alloc_info);
+               if (btree_id_is_alloc(i) && c->opts.reconstruct_alloc)
                        continue;
-               }
 
                if (r->error) {
                        __fsck_err(c,
@@ -930,10 +960,8 @@ use_clean:
        c->journal_replay_seq_start     = last_seq;
        c->journal_replay_seq_end       = blacklist_seq - 1;
 
-       if (c->opts.reconstruct_alloc) {
-               c->sb.compat &= ~(1ULL << BCH_COMPAT_alloc_info);
-               drop_alloc_keys(&c->journal_keys);
-       }
+       if (c->opts.reconstruct_alloc)
+               do_reconstruct_alloc(c);
 
        zero_out_btree_mem_ptr(&c->journal_keys);
 
@@ -968,9 +996,6 @@ use_clean:
        if (ret)
                goto err;
 
-       if (c->opts.reconstruct_alloc)
-               bch2_journal_log_msg(c, "dropping alloc info");
-
        /*
         * Skip past versions that might have possibly been used (as nonces),
         * but hadn't had their pointers written:
index 49bc4951572c81bf2943efebc75a145606c3b9ca..e4396cb0bacb037bac965e1beccd261d4a960789 100644 (file)
@@ -259,7 +259,7 @@ void bch2_sb_set_downgrade(struct bch_fs *c, unsigned new_minor, unsigned old_mi
                                if (e < BCH_SB_ERR_MAX)
                                        __set_bit(e, c->sb.errors_silent);
                                if (e < sizeof(ext->errors_silent) * 8)
-                                       ext->errors_silent[e / 64] |= cpu_to_le64(BIT_ULL(e % 64));
+                                       __set_bit_le64(e, ext->errors_silent);
                        }
                }
        }
index adff17f6f524bce6e5cfaec28772eeaee1522588..4aba415ab5b8d1a339e3d85c0fa4f37b64edd662 100644 (file)
@@ -864,4 +864,9 @@ static inline int copy_from_user_errcode(void *to, const void __user *from, unsi
 
 #endif
 
+static inline void __set_bit_le64(size_t bit, __le64 *addr)
+{
+       addr[bit / 64] |= cpu_to_le64(BIT_ULL(bit % 64));
+}
+
 #endif /* _BCACHEFS_UTIL_H */