Skip to content

Commit 15a3836

Browse files
author
Kent Overstreet
committed
bcachefs: Repair mismatches in inode hash seed, type
Different versions of the same inode (same inode number, different snapshot ID) must have the same hash seed and type - lookups require this, since they see keys from different snapshots simultaneously. To repair we only need to make the inodes consistent, hash_check_key() will do the rest. Signed-off-by: Kent Overstreet <[email protected]>
1 parent d8e8793 commit 15a3836

File tree

1 file changed

+39
-10
lines changed

1 file changed

+39
-10
lines changed

fs/bcachefs/fsck.c

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,10 +1096,36 @@ static int check_inode_dirent_inode(struct btree_trans *trans,
10961096
return ret;
10971097
}
10981098

1099+
static int get_snapshot_root_inode(struct btree_trans *trans,
1100+
struct bch_inode_unpacked *root,
1101+
u64 inum)
1102+
{
1103+
struct btree_iter iter;
1104+
struct bkey_s_c k;
1105+
int ret = 0;
1106+
1107+
for_each_btree_key_reverse_norestart(trans, iter, BTREE_ID_inodes,
1108+
SPOS(0, inum, U32_MAX),
1109+
BTREE_ITER_all_snapshots, k, ret) {
1110+
if (k.k->p.offset != inum)
1111+
break;
1112+
if (bkey_is_inode(k.k))
1113+
goto found_root;
1114+
}
1115+
if (ret)
1116+
goto err;
1117+
BUG();
1118+
found_root:
1119+
BUG_ON(bch2_inode_unpack(k, root));
1120+
err:
1121+
bch2_trans_iter_exit(trans, &iter);
1122+
return ret;
1123+
}
1124+
10991125
static int check_inode(struct btree_trans *trans,
11001126
struct btree_iter *iter,
11011127
struct bkey_s_c k,
1102-
struct bch_inode_unpacked *prev,
1128+
struct bch_inode_unpacked *snapshot_root,
11031129
struct snapshots_seen *s)
11041130
{
11051131
struct bch_fs *c = trans->c;
@@ -1123,16 +1149,19 @@ static int check_inode(struct btree_trans *trans,
11231149

11241150
BUG_ON(bch2_inode_unpack(k, &u));
11251151

1126-
if (prev->bi_inum != u.bi_inum)
1127-
*prev = u;
1152+
if (snapshot_root->bi_inum != u.bi_inum) {
1153+
ret = get_snapshot_root_inode(trans, snapshot_root, u.bi_inum);
1154+
if (ret)
1155+
goto err;
1156+
}
11281157

1129-
if (fsck_err_on(prev->bi_hash_seed != u.bi_hash_seed ||
1130-
inode_d_type(prev) != inode_d_type(&u),
1158+
if (fsck_err_on(u.bi_hash_seed != snapshot_root->bi_hash_seed ||
1159+
INODE_STR_HASH(&u) != INODE_STR_HASH(snapshot_root),
11311160
trans, inode_snapshot_mismatch,
11321161
"inodes in different snapshots don't match")) {
1133-
bch_err(c, "repair not implemented yet");
1134-
ret = -BCH_ERR_fsck_repair_unimplemented;
1135-
goto err_noprint;
1162+
u.bi_hash_seed = snapshot_root->bi_hash_seed;
1163+
SET_INODE_STR_HASH(&u, INODE_STR_HASH(snapshot_root));
1164+
do_update = true;
11361165
}
11371166

11381167
if (u.bi_dir || u.bi_dir_offset) {
@@ -1285,7 +1314,7 @@ static int check_inode(struct btree_trans *trans,
12851314

12861315
int bch2_check_inodes(struct bch_fs *c)
12871316
{
1288-
struct bch_inode_unpacked prev = { 0 };
1317+
struct bch_inode_unpacked snapshot_root = {};
12891318
struct snapshots_seen s;
12901319

12911320
snapshots_seen_init(&s);
@@ -1295,7 +1324,7 @@ int bch2_check_inodes(struct bch_fs *c)
12951324
POS_MIN,
12961325
BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k,
12971326
NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
1298-
check_inode(trans, &iter, k, &prev, &s)));
1327+
check_inode(trans, &iter, k, &snapshot_root, &s)));
12991328

13001329
snapshots_seen_exit(&s);
13011330
bch_err_fn(c, ret);

0 commit comments

Comments
 (0)