2121#include <linux/bsearch.h>
2222#include <linux/dcache.h> /* struct qstr */
2323
24+ static bool inode_points_to_dirent (struct bch_inode_unpacked * inode ,
25+ struct bkey_s_c_dirent d )
26+ {
27+ return inode -> bi_dir == d .k -> p .inode &&
28+ inode -> bi_dir_offset == d .k -> p .offset ;
29+ }
30+
31+ static bool dirent_points_to_inode_nowarn (struct bkey_s_c_dirent d ,
32+ struct bch_inode_unpacked * inode )
33+ {
34+ if (d .v -> d_type == DT_SUBVOL
35+ ? le32_to_cpu (d .v -> d_child_subvol ) == inode -> bi_subvol
36+ : le64_to_cpu (d .v -> d_inum ) == inode -> bi_inum )
37+ return 0 ;
38+ return - BCH_ERR_ENOENT_dirent_doesnt_match_inode ;
39+ }
40+
41+ static void dirent_inode_mismatch_msg (struct printbuf * out ,
42+ struct bch_fs * c ,
43+ struct bkey_s_c_dirent dirent ,
44+ struct bch_inode_unpacked * inode )
45+ {
46+ prt_str (out , "inode points to dirent that does not point back:" );
47+ prt_newline (out );
48+ bch2_bkey_val_to_text (out , c , dirent .s_c );
49+ prt_newline (out );
50+ bch2_inode_unpacked_to_text (out , inode );
51+ }
52+
53+ static int dirent_points_to_inode (struct bch_fs * c ,
54+ struct bkey_s_c_dirent dirent ,
55+ struct bch_inode_unpacked * inode )
56+ {
57+ int ret = dirent_points_to_inode_nowarn (dirent , inode );
58+ if (ret ) {
59+ struct printbuf buf = PRINTBUF ;
60+ dirent_inode_mismatch_msg (& buf , c , dirent , inode );
61+ bch_warn (c , "%s" , buf .buf );
62+ printbuf_exit (& buf );
63+ }
64+ return ret ;
65+ }
66+
2467/*
2568 * XXX: this is handling transaction restarts without returning
2669 * -BCH_ERR_transaction_restart_nested, this is not how we do things anymore:
@@ -371,7 +414,8 @@ static int reattach_subvol(struct btree_trans *trans, struct bkey_s_c_subvolume
371414 return ret ;
372415
373416 ret = remove_backpointer (trans , & inode );
374- bch_err_msg (c , ret , "removing dirent" );
417+ if (!bch2_err_matches (ret , ENOENT ))
418+ bch_err_msg (c , ret , "removing dirent" );
375419 if (ret )
376420 return ret ;
377421
@@ -900,21 +944,6 @@ static struct bkey_s_c_dirent inode_get_dirent(struct btree_trans *trans,
900944 return dirent_get_by_pos (trans , iter , SPOS (inode -> bi_dir , inode -> bi_dir_offset , * snapshot ));
901945}
902946
903- static bool inode_points_to_dirent (struct bch_inode_unpacked * inode ,
904- struct bkey_s_c_dirent d )
905- {
906- return inode -> bi_dir == d .k -> p .inode &&
907- inode -> bi_dir_offset == d .k -> p .offset ;
908- }
909-
910- static bool dirent_points_to_inode (struct bkey_s_c_dirent d ,
911- struct bch_inode_unpacked * inode )
912- {
913- return d .v -> d_type == DT_SUBVOL
914- ? le32_to_cpu (d .v -> d_child_subvol ) == inode -> bi_subvol
915- : le64_to_cpu (d .v -> d_inum ) == inode -> bi_inum ;
916- }
917-
918947static int check_inode_deleted_list (struct btree_trans * trans , struct bpos p )
919948{
920949 struct btree_iter iter ;
@@ -924,13 +953,14 @@ static int check_inode_deleted_list(struct btree_trans *trans, struct bpos p)
924953 return ret ;
925954}
926955
927- static int check_inode_dirent_inode (struct btree_trans * trans , struct bkey_s_c inode_k ,
956+ static int check_inode_dirent_inode (struct btree_trans * trans ,
928957 struct bch_inode_unpacked * inode ,
929- u32 inode_snapshot , bool * write_inode )
958+ bool * write_inode )
930959{
931960 struct bch_fs * c = trans -> c ;
932961 struct printbuf buf = PRINTBUF ;
933962
963+ u32 inode_snapshot = inode -> bi_snapshot ;
934964 struct btree_iter dirent_iter = {};
935965 struct bkey_s_c_dirent d = inode_get_dirent (trans , & dirent_iter , inode , & inode_snapshot );
936966 int ret = bkey_err (d );
@@ -940,13 +970,13 @@ static int check_inode_dirent_inode(struct btree_trans *trans, struct bkey_s_c i
940970 if (fsck_err_on (ret ,
941971 trans , inode_points_to_missing_dirent ,
942972 "inode points to missing dirent\n%s" ,
943- (bch2_bkey_val_to_text (& buf , c , inode_k ), buf .buf )) ||
944- fsck_err_on (!ret && ! dirent_points_to_inode (d , inode ),
973+ (bch2_inode_unpacked_to_text (& buf , inode ), buf .buf )) ||
974+ fsck_err_on (!ret && dirent_points_to_inode_nowarn (d , inode ),
945975 trans , inode_points_to_wrong_dirent ,
946- "inode points to dirent that does not point back:\n %s" ,
947- (bch2_bkey_val_to_text (& buf , c , inode_k ),
948- prt_newline (& buf ),
949- bch2_bkey_val_to_text ( & buf , c , d . s_c ), buf .buf ))) {
976+ "%s" ,
977+ (printbuf_reset (& buf ),
978+ dirent_inode_mismatch_msg (& buf , c , d , inode ),
979+ buf .buf ))) {
950980 /*
951981 * We just clear the backpointer fields for now. If we find a
952982 * dirent that points to this inode in check_dirents(), we'll
@@ -1145,7 +1175,7 @@ static int check_inode(struct btree_trans *trans,
11451175 }
11461176
11471177 if (u .bi_dir || u .bi_dir_offset ) {
1148- ret = check_inode_dirent_inode (trans , k , & u , k . k -> p . snapshot , & do_update );
1178+ ret = check_inode_dirent_inode (trans , & u , & do_update );
11491179 if (ret )
11501180 goto err ;
11511181 }
@@ -2474,10 +2504,8 @@ static int check_path(struct btree_trans *trans, pathbuf *p, struct bkey_s_c ino
24742504 if (ret && !bch2_err_matches (ret , ENOENT ))
24752505 break ;
24762506
2477- if (!ret && ! dirent_points_to_inode (d , & inode )) {
2507+ if (!ret && ( ret = dirent_points_to_inode (c , d , & inode )))
24782508 bch2_trans_iter_exit (trans , & dirent_iter );
2479- ret = - BCH_ERR_ENOENT_dirent_doesnt_match_inode ;
2480- }
24812509
24822510 if (bch2_err_matches (ret , ENOENT )) {
24832511 ret = 0 ;
0 commit comments