@@ -1292,6 +1292,58 @@ int bch2_check_inodes(struct bch_fs *c)
12921292 return ret ;
12931293}
12941294
1295+ static int check_unreachable_inode (struct btree_trans * trans ,
1296+ struct btree_iter * iter ,
1297+ struct bkey_s_c k )
1298+ {
1299+ struct bch_fs * c = trans -> c ;
1300+ struct printbuf buf = PRINTBUF ;
1301+ int ret = 0 ;
1302+
1303+ if (!bkey_is_inode (k .k ))
1304+ return 0 ;
1305+
1306+ struct bch_inode_unpacked inode ;
1307+ BUG_ON (bch2_inode_unpack (k , & inode ));
1308+
1309+ if (inode .bi_subvol )
1310+ return 0 ;
1311+
1312+ if (inode .bi_flags & BCH_INODE_unlinked )
1313+ return 0 ;
1314+
1315+ if (fsck_err_on (!inode .bi_dir ,
1316+ trans , inode_unreachable ,
1317+ "unreachable inode:\n%s" ,
1318+ (printbuf_reset (& buf ),
1319+ bch2_bkey_val_to_text (& buf , c , k ),
1320+ buf .buf )))
1321+ ret = reattach_inode (trans , & inode );
1322+ fsck_err :
1323+ printbuf_exit (& buf );
1324+ return ret ;
1325+ }
1326+
1327+ /*
1328+ * Reattach unreachable (but not unlinked) inodes
1329+ *
1330+ * Run after check_inodes() and check_dirents(), so we node that inode
1331+ * backpointer fields point to valid dirents, and every inode that has a dirent
1332+ * that points to it has its backpointer field set - so we're just looking for
1333+ * non-unlinked inodes without backpointers:
1334+ */
1335+ int bch2_check_unreachable_inodes (struct bch_fs * c )
1336+ {
1337+ int ret = bch2_trans_run (c ,
1338+ for_each_btree_key_commit (trans , iter , BTREE_ID_inodes ,
1339+ POS_MIN ,
1340+ BTREE_ITER_prefetch |BTREE_ITER_all_snapshots , k ,
1341+ NULL , NULL , BCH_TRANS_COMMIT_no_enospc ,
1342+ check_unreachable_inode (trans , & iter , k )));
1343+ bch_err_fn (c , ret );
1344+ return ret ;
1345+ }
1346+
12951347static inline bool btree_matches_i_mode (enum btree_id btree , unsigned mode )
12961348{
12971349 switch (btree ) {
@@ -2450,22 +2502,6 @@ static int check_subvol_path(struct btree_trans *trans, struct btree_iter *iter,
24502502 if (ret )
24512503 break ;
24522504
2453- /*
2454- * We've checked that inode backpointers point to valid dirents;
2455- * here, it's sufficient to check that the subvolume root has a
2456- * dirent:
2457- */
2458- if (fsck_err_on (!subvol_root .bi_dir ,
2459- trans , subvol_unreachable ,
2460- "unreachable subvolume %s" ,
2461- (bch2_bkey_val_to_text (& buf , c , s .s_c ),
2462- prt_newline (& buf ),
2463- bch2_inode_unpacked_to_text (& buf , & subvol_root ),
2464- buf .buf ))) {
2465- ret = reattach_subvol (trans , s );
2466- break ;
2467- }
2468-
24692505 u32 parent = le32_to_cpu (s .v -> fs_path_parent );
24702506
24712507 if (darray_u32_has (& subvol_path , parent )) {
@@ -2526,12 +2562,6 @@ static bool path_is_dup(pathbuf *p, u64 inum, u32 snapshot)
25262562 return false;
25272563}
25282564
2529- /*
2530- * Check that a given inode is reachable from its subvolume root - we already
2531- * verified subvolume connectivity:
2532- *
2533- * XXX: we should also be verifying that inodes are in the right subvolumes
2534- */
25352565static int check_path (struct btree_trans * trans , pathbuf * p , struct bkey_s_c inode_k )
25362566{
25372567 struct bch_fs * c = trans -> c ;
@@ -2545,6 +2575,9 @@ static int check_path(struct btree_trans *trans, pathbuf *p, struct bkey_s_c ino
25452575
25462576 BUG_ON (bch2_inode_unpack (inode_k , & inode ));
25472577
2578+ if (!S_ISDIR (inode .bi_mode ))
2579+ return 0 ;
2580+
25482581 while (!inode .bi_subvol ) {
25492582 struct btree_iter dirent_iter ;
25502583 struct bkey_s_c_dirent d ;
@@ -2559,21 +2592,15 @@ static int check_path(struct btree_trans *trans, pathbuf *p, struct bkey_s_c ino
25592592 bch2_trans_iter_exit (trans , & dirent_iter );
25602593
25612594 if (bch2_err_matches (ret , ENOENT )) {
2562- ret = 0 ;
2563- if (fsck_err (trans , inode_unreachable ,
2564- "unreachable inode\n%s" ,
2565- (printbuf_reset (& buf ),
2566- bch2_bkey_val_to_text (& buf , c , inode_k ),
2567- buf .buf )))
2568- ret = reattach_inode (trans , & inode );
2595+ printbuf_reset (& buf );
2596+ bch2_bkey_val_to_text (& buf , c , inode_k );
2597+ bch_err (c , "unreachable inode in check_directory_structure: %s\n%s" ,
2598+ bch2_err_str (ret ), buf .buf );
25692599 goto out ;
25702600 }
25712601
25722602 bch2_trans_iter_exit (trans , & dirent_iter );
25732603
2574- if (!S_ISDIR (inode .bi_mode ))
2575- break ;
2576-
25772604 ret = darray_push (p , ((struct pathbuf_entry ) {
25782605 .inum = inode .bi_inum ,
25792606 .snapshot = snapshot ,
@@ -2626,9 +2653,8 @@ static int check_path(struct btree_trans *trans, pathbuf *p, struct bkey_s_c ino
26262653}
26272654
26282655/*
2629- * Check for unreachable inodes, as well as loops in the directory structure:
2630- * After bch2_check_dirents(), if an inode backpointer doesn't exist that means it's
2631- * unreachable:
2656+ * Check for loops in the directory structure: all other connectivity issues
2657+ * have been fixed by prior passes
26322658 */
26332659int bch2_check_directory_structure (struct bch_fs * c )
26342660{
@@ -2756,6 +2782,10 @@ static int check_nlinks_find_hardlinks(struct bch_fs *c,
27562782 if (S_ISDIR (u .bi_mode ))
27572783 continue ;
27582784
2785+ /*
2786+ * Previous passes ensured that bi_nlink is nonzero if
2787+ * it had multiple hardlinks:
2788+ */
27592789 if (!u .bi_nlink )
27602790 continue ;
27612791
0 commit comments