Commit c8d5b714 authored by Kent Overstreet's avatar Kent Overstreet

bcachefs: Make sure hash info gets initialized in fsck

We had some bugs with setting/using first_this_inode in the inode
walker in the dirents/xattr code.

This patch changes to not clear first_this_inode until after
initializing the new hash info.

Also, we fix an error message to not print on transaction restart, and
add a comment to related fsck error code.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 1af5227c
......@@ -158,6 +158,11 @@ int bch2_fsck_err(struct bch_fs *c, unsigned flags, const char *fmt, ...)
mutex_lock(&c->fsck_error_lock);
s = fsck_err_get(c, fmt);
if (s) {
/*
* We may be called multiple times for the same error on
* transaction restart - this memoizes instead of asking the user
* multiple times for the same error:
*/
if (s->last_msg && !strcmp(buf.buf, s->last_msg)) {
ret = s->ret;
mutex_unlock(&c->fsck_error_lock);
......
......@@ -673,10 +673,8 @@ static int __walk_inode(struct btree_trans *trans,
pos.snapshot = bch2_snapshot_equiv(c, pos.snapshot);
if (pos.inode == w->cur_inum) {
w->first_this_inode = false;
if (pos.inode == w->cur_inum)
goto lookup_snapshot;
}
w->inodes.nr = 0;
......@@ -862,10 +860,10 @@ static int hash_check_key(struct btree_trans *trans,
(printbuf_reset(&buf),
bch2_bkey_val_to_text(&buf, c, hash_k), buf.buf))) {
ret = hash_redo_key(trans, desc, hash_info, k_iter, hash_k);
if (ret) {
if (ret && !bch2_err_matches(ret, BCH_ERR_transaction_restart))
bch_err(c, "hash_redo_key err %s", bch2_err_str(ret));
if (ret)
return ret;
}
ret = -BCH_ERR_transaction_restart_nested;
}
fsck_err:
......@@ -1639,6 +1637,10 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
if (ret < 0)
goto err;
if (dir->first_this_inode)
*hash_info = bch2_hash_info_init(c, &dir->inodes.data[0].inode);
dir->first_this_inode = false;
if (fsck_err_on(ret == INT_MAX, c,
"dirent in nonexisting directory:\n%s",
(printbuf_reset(&buf),
......@@ -1665,11 +1667,7 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
goto out;
}
if (dir->first_this_inode)
*hash_info = bch2_hash_info_init(c, &dir->inodes.data[0].inode);
ret = hash_check_key(trans, bch2_dirent_hash_desc,
hash_info, iter, k);
ret = hash_check_key(trans, bch2_dirent_hash_desc, hash_info, iter, k);
if (ret < 0)
goto err;
if (ret) {
......@@ -1822,6 +1820,10 @@ static int check_xattr(struct btree_trans *trans, struct btree_iter *iter,
if (ret < 0)
return ret;
if (inode->first_this_inode)
*hash_info = bch2_hash_info_init(c, &inode->inodes.data[0].inode);
inode->first_this_inode = false;
if (fsck_err_on(ret == INT_MAX, c,
"xattr for missing inode %llu",
k.k->p.inode))
......@@ -1832,9 +1834,6 @@ static int check_xattr(struct btree_trans *trans, struct btree_iter *iter,
ret = 0;
if (inode->first_this_inode)
*hash_info = bch2_hash_info_init(c, &inode->inodes.data[0].inode);
ret = hash_check_key(trans, bch2_xattr_hash_desc, hash_info, iter, k);
fsck_err:
if (ret && !bch2_err_matches(ret, BCH_ERR_transaction_restart))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment