21
21
#include <linux/bsearch.h>
22
22
#include <linux/dcache.h> /* struct qstr */
23
23
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
+
24
67
/*
25
68
* XXX: this is handling transaction restarts without returning
26
69
* -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
371
414
return ret ;
372
415
373
416
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" );
375
419
if (ret )
376
420
return ret ;
377
421
@@ -900,21 +944,6 @@ static struct bkey_s_c_dirent inode_get_dirent(struct btree_trans *trans,
900
944
return dirent_get_by_pos (trans , iter , SPOS (inode -> bi_dir , inode -> bi_dir_offset , * snapshot ));
901
945
}
902
946
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
-
918
947
static int check_inode_deleted_list (struct btree_trans * trans , struct bpos p )
919
948
{
920
949
struct btree_iter iter ;
@@ -924,13 +953,14 @@ static int check_inode_deleted_list(struct btree_trans *trans, struct bpos p)
924
953
return ret ;
925
954
}
926
955
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 ,
928
957
struct bch_inode_unpacked * inode ,
929
- u32 inode_snapshot , bool * write_inode )
958
+ bool * write_inode )
930
959
{
931
960
struct bch_fs * c = trans -> c ;
932
961
struct printbuf buf = PRINTBUF ;
933
962
963
+ u32 inode_snapshot = inode -> bi_snapshot ;
934
964
struct btree_iter dirent_iter = {};
935
965
struct bkey_s_c_dirent d = inode_get_dirent (trans , & dirent_iter , inode , & inode_snapshot );
936
966
int ret = bkey_err (d );
@@ -940,13 +970,13 @@ static int check_inode_dirent_inode(struct btree_trans *trans, struct bkey_s_c i
940
970
if (fsck_err_on (ret ,
941
971
trans , inode_points_to_missing_dirent ,
942
972
"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 ),
945
975
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 ))) {
950
980
/*
951
981
* We just clear the backpointer fields for now. If we find a
952
982
* dirent that points to this inode in check_dirents(), we'll
@@ -1145,7 +1175,7 @@ static int check_inode(struct btree_trans *trans,
1145
1175
}
1146
1176
1147
1177
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 );
1149
1179
if (ret )
1150
1180
goto err ;
1151
1181
}
@@ -2474,10 +2504,8 @@ static int check_path(struct btree_trans *trans, pathbuf *p, struct bkey_s_c ino
2474
2504
if (ret && !bch2_err_matches (ret , ENOENT ))
2475
2505
break ;
2476
2506
2477
- if (!ret && ! dirent_points_to_inode (d , & inode )) {
2507
+ if (!ret && ( ret = dirent_points_to_inode (c , d , & inode )))
2478
2508
bch2_trans_iter_exit (trans , & dirent_iter );
2479
- ret = - BCH_ERR_ENOENT_dirent_doesnt_match_inode ;
2480
- }
2481
2509
2482
2510
if (bch2_err_matches (ret , ENOENT )) {
2483
2511
ret = 0 ;
0 commit comments