bcachefs: bch2_str_hash_check_key() may now be called without snapshots_seen
authorKent Overstreet <kent.overstreet@linux.dev>
Wed, 28 May 2025 20:25:11 +0000 (16:25 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 1 Jun 2025 02:03:17 +0000 (22:03 -0400)
We don't track snapshot overwrites outside of fsck, so for this to be
called at runtime outside of fsck we need to create it on demand, when
we have repair to do.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/fsck.c
fs/bcachefs/fsck.h
fs/bcachefs/str_hash.c

index 8e07a36..950fa96 100644 (file)
@@ -643,11 +643,6 @@ static int reconstruct_inode(struct btree_trans *trans, enum btree_id btree, u32
        return __bch2_fsck_write_inode(trans, &new_inode);
 }
 
-struct snapshots_seen {
-       struct bpos                     pos;
-       snapshot_id_list                ids;
-};
-
 static inline void snapshots_seen_exit(struct snapshots_seen *s)
 {
        darray_exit(&s->ids);
index 5749482..e5fe7cf 100644 (file)
@@ -4,6 +4,12 @@
 
 #include "str_hash.h"
 
+/* recoverds snapshot IDs of overwrites at @pos */
+struct snapshots_seen {
+       struct bpos                     pos;
+       snapshot_id_list                ids;
+};
+
 int bch2_fsck_update_backpointers(struct btree_trans *,
                                  struct snapshots_seen *,
                                  const struct bch_hash_desc,
index bfd4346..f101ca8 100644 (file)
@@ -231,6 +231,7 @@ int __bch2_str_hash_check_key(struct btree_trans *trans,
        struct btree_iter iter = {};
        struct printbuf buf = PRINTBUF;
        struct bkey_s_c k;
+       bool free_snapshots_seen = false;
        int ret = 0;
 
        u64 hash = desc->hash_bkey(hash_info, hash_k);
@@ -256,6 +257,8 @@ int __bch2_str_hash_check_key(struct btree_trans *trans,
 out:
        bch2_trans_iter_exit(trans, &iter);
        printbuf_exit(&buf);
+       if (free_snapshots_seen)
+               darray_exit(&s->ids);
        return ret;
 bad_hash:
        /*
@@ -265,6 +268,22 @@ bad_hash:
        if (ret)
                goto out;
 
+       if (!s) {
+               s = bch2_trans_kmalloc(trans, sizeof(*s));
+               ret = PTR_ERR_OR_ZERO(s);
+               if (ret)
+                       goto out;
+
+               s->pos = k_iter->pos;
+               darray_init(&s->ids);
+
+               ret = bch2_get_snapshot_overwrites(trans, desc->btree_id, k_iter->pos, &s->ids);
+               if (ret)
+                       goto out;
+
+               free_snapshots_seen = true;
+       }
+
        if (fsck_err(trans, hash_table_key_wrong_offset,
                     "hash table key at wrong offset: btree %s inode %llu offset %llu, hashed to %llu\n%s",
                     bch2_btree_id_str(desc->btree_id), hash_k.k->p.inode, hash_k.k->p.offset, hash,
@@ -286,7 +305,9 @@ bad_hash:
                if (k.k)
                        goto duplicate_entries;
 
-               ret =   bch2_hash_delete_at(trans, *desc, hash_info, k_iter,
+               ret =   bch2_insert_snapshot_whiteouts(trans, desc->btree_id,
+                                                      k_iter->pos, new->k.p) ?:
+                       bch2_hash_delete_at(trans, *desc, hash_info, k_iter,
                                            BTREE_ITER_with_updates|
                                            BTREE_UPDATE_internal_snapshot_node) ?:
                        bch2_fsck_update_backpointers(trans, s, *desc, hash_info, new) ?: