Skip to content

Commit 04e9089

Browse files
author
Kent Overstreet
committed
bcachefs: Run bch2_check_dirent_target() at lookup time
More on the "full online self healing" project: We now run most of the dirent <-> inode consistency checks, with repair code, at runtime - the exact same check and repair code that fsck runs. This will allow us to repair the "dirent points to inode that does not point back" inconsistencies that have been popping up at runtime. Signed-off-by: Kent Overstreet <[email protected]>
1 parent 9b0d00a commit 04e9089

File tree

1 file changed

+17
-15
lines changed

1 file changed

+17
-15
lines changed

fs/bcachefs/fs.c

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,9 @@ static struct bch_inode_info *bch2_lookup_trans(struct btree_trans *trans,
641641
if (ret)
642642
return ERR_PTR(ret);
643643

644-
ret = bch2_dirent_read_target(trans, dir, bkey_s_c_to_dirent(k), &inum);
644+
struct bkey_s_c_dirent d = bkey_s_c_to_dirent(k);
645+
646+
ret = bch2_dirent_read_target(trans, dir, d, &inum);
645647
if (ret > 0)
646648
ret = -ENOENT;
647649
if (ret)
@@ -651,30 +653,30 @@ static struct bch_inode_info *bch2_lookup_trans(struct btree_trans *trans,
651653
if (inode)
652654
goto out;
653655

656+
/*
657+
* Note: if check/repair needs it, we commit before
658+
* bch2_inode_hash_init_insert(), as after that point we can't take a
659+
* restart - not in the top level loop with a commit_do(), like we
660+
* usually do:
661+
*/
662+
654663
struct bch_subvolume subvol;
655664
struct bch_inode_unpacked inode_u;
656665
ret = bch2_subvolume_get(trans, inum.subvol, true, &subvol) ?:
657666
bch2_inode_find_by_inum_nowarn_trans(trans, inum, &inode_u) ?:
667+
bch2_check_dirent_target(trans, &dirent_iter, d, &inode_u, false) ?:
668+
bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc) ?:
658669
PTR_ERR_OR_ZERO(inode = bch2_inode_hash_init_insert(trans, inum, &inode_u, &subvol));
659670

671+
/*
672+
* don't remove it: check_inodes might find another inode that points
673+
* back to this dirent
674+
*/
660675
bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT),
661676
c, "dirent to missing inode:\n %s",
662-
(bch2_bkey_val_to_text(&buf, c, k), buf.buf));
677+
(bch2_bkey_val_to_text(&buf, c, d.s_c), buf.buf));
663678
if (ret)
664679
goto err;
665-
666-
/* regular files may have hardlinks: */
667-
if (bch2_fs_inconsistent_on(bch2_inode_should_have_single_bp(&inode_u) &&
668-
!bkey_eq(k.k->p, POS(inode_u.bi_dir, inode_u.bi_dir_offset)),
669-
c,
670-
"dirent points to inode that does not point back:\n %s",
671-
(bch2_bkey_val_to_text(&buf, c, k),
672-
prt_printf(&buf, "\n "),
673-
bch2_inode_unpacked_to_text(&buf, &inode_u),
674-
buf.buf))) {
675-
ret = -ENOENT;
676-
goto err;
677-
}
678680
out:
679681
bch2_trans_iter_exit(trans, &dirent_iter);
680682
printbuf_exit(&buf);

0 commit comments

Comments
 (0)