diff options
-rw-r--r-- | fs/bcachefs/fsck.c | 5 | ||||
-rw-r--r-- | fs/bcachefs/fsck.h | 6 | ||||
-rw-r--r-- | fs/bcachefs/str_hash.c | 23 |
3 files changed, 28 insertions, 6 deletions
diff --git a/fs/bcachefs/fsck.c b/fs/bcachefs/fsck.c index 8e07a365b24c..950fa9685d3e 100644 --- a/fs/bcachefs/fsck.c +++ b/fs/bcachefs/fsck.c @@ -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); diff --git a/fs/bcachefs/fsck.h b/fs/bcachefs/fsck.h index 574948278cd4..e5fe7cf7b251 100644 --- a/fs/bcachefs/fsck.h +++ b/fs/bcachefs/fsck.h @@ -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, diff --git a/fs/bcachefs/str_hash.c b/fs/bcachefs/str_hash.c index bfd4346a4d93..f101ca8581d9 100644 --- a/fs/bcachefs/str_hash.c +++ b/fs/bcachefs/str_hash.c @@ -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) ?: |