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 8e07a365b24c2dbdfd5909b40910502f670fbb8f..950fa9685d3e84c8a6a0faa8d5851591cfe3653c 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 574948278cd4dae9f8a870a6f5dd5ff9101a9e1c..e5fe7cf7b251410cbc180e170f62b929ab8e1955 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 bfd4346a4d9316644b7c7865098526947bbad3d4..f101ca8581d99c8475240626433ba30cd811a6d2 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) ?: