Skip to content

Commit bbc3a0b

Browse files
author
Kent Overstreet
committed
bcachefs: fsck: Fix check_directory_structure when no check_dirents
check_directory_structure runs after check_dirents, so it expects that it won't see any inodes with missing backpointers - normally. But online fsck can't run check_dirents yet, or the user might only be running a specific pass, so we need to be careful that this isn't an error. If an inode is unreachable, that's handled by a separate pass. Also, add a new 'bch2_inode_has_backpointer()' helper, since we were doing this inconsistently. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
1 parent e1f0e1a commit bbc3a0b

3 files changed

Lines changed: 19 additions & 7 deletions

File tree

fs/bcachefs/fsck.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,8 @@ static inline bool inode_should_reattach(struct bch_inode_unpacked *inode)
327327
(inode->bi_flags & BCH_INODE_has_child_snapshot))
328328
return false;
329329

330-
return !inode->bi_dir && !(inode->bi_flags & BCH_INODE_unlinked);
330+
return !bch2_inode_has_backpointer(inode) &&
331+
!(inode->bi_flags & BCH_INODE_unlinked);
331332
}
332333

333334
static int maybe_delete_dirent(struct btree_trans *trans, struct bpos d_pos, u32 snapshot)
@@ -514,7 +515,7 @@ static struct bkey_s_c_dirent dirent_get_by_pos(struct btree_trans *trans,
514515
static int remove_backpointer(struct btree_trans *trans,
515516
struct bch_inode_unpacked *inode)
516517
{
517-
if (!inode->bi_dir)
518+
if (!bch2_inode_has_backpointer(inode))
518519
return 0;
519520

520521
u32 snapshot = inode->bi_snapshot;
@@ -1165,13 +1166,14 @@ static int check_inode(struct btree_trans *trans,
11651166
if (ret)
11661167
goto err;
11671168

1168-
if (u.bi_dir || u.bi_dir_offset) {
1169+
if (bch2_inode_has_backpointer(&u)) {
11691170
ret = check_inode_dirent_inode(trans, &u, &do_update);
11701171
if (ret)
11711172
goto err;
11721173
}
11731174

1174-
if (fsck_err_on(u.bi_dir && (u.bi_flags & BCH_INODE_unlinked),
1175+
if (fsck_err_on(bch2_inode_has_backpointer(&u) &&
1176+
(u.bi_flags & BCH_INODE_unlinked),
11751177
trans, inode_unlinked_but_has_dirent,
11761178
"inode unlinked but has dirent\n%s",
11771179
(printbuf_reset(&buf),
@@ -2751,7 +2753,13 @@ static int check_path_loop(struct btree_trans *trans, struct bkey_s_c inode_k)
27512753
if (ret)
27522754
return ret;
27532755

2754-
while (!inode.bi_subvol) {
2756+
/*
2757+
* If we're running full fsck, check_dirents() will have already ran,
2758+
* and we shouldn't see any missing backpointers here - otherwise that's
2759+
* handled separately, by check_unreachable_inodes
2760+
*/
2761+
while (!inode.bi_subvol &&
2762+
bch2_inode_has_backpointer(&inode)) {
27552763
struct btree_iter dirent_iter;
27562764
struct bkey_s_c_dirent d;
27572765

fs/bcachefs/inode.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,11 @@ static inline bool bch2_inode_casefold(struct bch_fs *c, const struct bch_inode_
254254
: c->opts.casefold;
255255
}
256256

257+
static inline bool bch2_inode_has_backpointer(const struct bch_inode_unpacked *bi)
258+
{
259+
return bi->bi_dir || bi->bi_dir_offset;
260+
}
261+
257262
/* i_nlink: */
258263

259264
static inline unsigned nlink_bias(umode_t mode)

fs/bcachefs/namei.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -734,8 +734,7 @@ static int bch2_check_dirent_inode_dirent(struct btree_trans *trans,
734734
if (inode_points_to_dirent(target, d))
735735
return 0;
736736

737-
if (!target->bi_dir &&
738-
!target->bi_dir_offset) {
737+
if (!bch2_inode_has_backpointer(target)) {
739738
fsck_err_on(S_ISDIR(target->bi_mode),
740739
trans, inode_dir_missing_backpointer,
741740
"directory with missing backpointer\n%s",

0 commit comments

Comments
 (0)