@@ -2689,19 +2689,13 @@ int bch2_check_subvolume_structure(struct bch_fs *c)
26892689 return ret ;
26902690}
26912691
2692- struct pathbuf_entry {
2693- u64 inum ;
2694- u32 snapshot ;
2695- };
2696-
2697- typedef DARRAY (struct pathbuf_entry ) pathbuf ;
2698-
2699- static int bch2_bi_depth_renumber_one (struct btree_trans * trans , struct pathbuf_entry * p ,
2692+ static int bch2_bi_depth_renumber_one (struct btree_trans * trans ,
2693+ u64 inum , u32 snapshot ,
27002694 u32 new_depth )
27012695{
27022696 struct btree_iter iter ;
27032697 struct bkey_s_c k = bch2_bkey_get_iter (trans , & iter , BTREE_ID_inodes ,
2704- SPOS (0 , p -> inum , p -> snapshot ), 0 );
2698+ SPOS (0 , inum , snapshot ), 0 );
27052699
27062700 struct bch_inode_unpacked inode ;
27072701 int ret = bkey_err (k ) ?:
@@ -2720,14 +2714,15 @@ static int bch2_bi_depth_renumber_one(struct btree_trans *trans, struct pathbuf_
27202714 return ret ;
27212715}
27222716
2723- static int bch2_bi_depth_renumber (struct btree_trans * trans , pathbuf * path , u32 new_bi_depth )
2717+ static int bch2_bi_depth_renumber (struct btree_trans * trans , darray_u64 * path ,
2718+ u32 snapshot , u32 new_bi_depth )
27242719{
27252720 u32 restart_count = trans -> restart_count ;
27262721 int ret = 0 ;
27272722
27282723 darray_for_each_reverse (* path , i ) {
27292724 ret = nested_lockrestart_do (trans ,
2730- bch2_bi_depth_renumber_one (trans , i , new_bi_depth ));
2725+ bch2_bi_depth_renumber_one (trans , * i , snapshot , new_bi_depth ));
27312726 bch_err_fn (trans -> c , ret );
27322727 if (ret )
27332728 break ;
@@ -2738,26 +2733,19 @@ static int bch2_bi_depth_renumber(struct btree_trans *trans, pathbuf *path, u32
27382733 return ret ?: trans_was_restarted (trans , restart_count );
27392734}
27402735
2741- static bool path_is_dup (pathbuf * p , u64 inum , u32 snapshot )
2742- {
2743- darray_for_each (* p , i )
2744- if (i -> inum == inum &&
2745- i -> snapshot == snapshot )
2746- return true;
2747- return false;
2748- }
2749-
27502736static int check_path_loop (struct btree_trans * trans , struct bkey_s_c inode_k )
27512737{
27522738 struct bch_fs * c = trans -> c ;
27532739 struct btree_iter inode_iter = {};
2754- pathbuf path = {};
2740+ darray_u64 path = {};
27552741 struct printbuf buf = PRINTBUF ;
27562742 u32 snapshot = inode_k .k -> p .snapshot ;
27572743 bool redo_bi_depth = false;
27582744 u32 min_bi_depth = U32_MAX ;
27592745 int ret = 0 ;
27602746
2747+ struct bpos start = inode_k .k -> p ;
2748+
27612749 struct bch_inode_unpacked inode ;
27622750 ret = bch2_inode_unpack (inode_k , & inode );
27632751 if (ret )
@@ -2766,9 +2754,9 @@ static int check_path_loop(struct btree_trans *trans, struct bkey_s_c inode_k)
27662754 while (!inode .bi_subvol ) {
27672755 struct btree_iter dirent_iter ;
27682756 struct bkey_s_c_dirent d ;
2769- u32 parent_snapshot = snapshot ;
27702757
2771- d = inode_get_dirent (trans , & dirent_iter , & inode , & parent_snapshot );
2758+ d = dirent_get_by_pos (trans , & dirent_iter ,
2759+ SPOS (inode .bi_dir , inode .bi_dir_offset , snapshot ));
27722760 ret = bkey_err (d .s_c );
27732761 if (ret && !bch2_err_matches (ret , ENOENT ))
27742762 goto out ;
@@ -2786,15 +2774,10 @@ static int check_path_loop(struct btree_trans *trans, struct bkey_s_c inode_k)
27862774
27872775 bch2_trans_iter_exit (trans , & dirent_iter );
27882776
2789- ret = darray_push (& path , ((struct pathbuf_entry ) {
2790- .inum = inode .bi_inum ,
2791- .snapshot = snapshot ,
2792- }));
2777+ ret = darray_push (& path , inode .bi_inum );
27932778 if (ret )
27942779 return ret ;
27952780
2796- snapshot = parent_snapshot ;
2797-
27982781 bch2_trans_iter_exit (trans , & inode_iter );
27992782 inode_k = bch2_bkey_get_iter (trans , & inode_iter , BTREE_ID_inodes ,
28002783 SPOS (0 , inode .bi_dir , snapshot ), 0 );
@@ -2816,15 +2799,22 @@ static int check_path_loop(struct btree_trans *trans, struct bkey_s_c inode_k)
28162799 break ;
28172800
28182801 inode = parent_inode ;
2819- snapshot = inode_k .k -> p .snapshot ;
28202802 redo_bi_depth = true;
28212803
2822- if (path_is_dup ( & path , inode .bi_inum , snapshot )) {
2804+ if (darray_find ( path , inode .bi_inum )) {
28232805 printbuf_reset (& buf );
2824- prt_printf (& buf , "directory structure loop:\n" );
2825- darray_for_each_reverse (path , i )
2826- prt_printf (& buf , "%llu:%u " , i -> inum , i -> snapshot );
2827- prt_printf (& buf , "%llu:%u" , inode .bi_inum , snapshot );
2806+ prt_printf (& buf , "directory structure loop in snapshot %u: " ,
2807+ snapshot );
2808+
2809+ ret = bch2_inum_snapshot_to_path (trans , start .offset , start .snapshot , NULL , & buf );
2810+ if (ret )
2811+ goto out ;
2812+
2813+ if (c -> opts .verbose ) {
2814+ prt_newline (& buf );
2815+ darray_for_each (path , i )
2816+ prt_printf (& buf , "%llu " , * i );
2817+ }
28282818
28292819 if (fsck_err (trans , dir_loop , "%s" , buf .buf )) {
28302820 ret = remove_backpointer (trans , & inode );
@@ -2844,7 +2834,7 @@ static int check_path_loop(struct btree_trans *trans, struct bkey_s_c inode_k)
28442834 min_bi_depth = 0 ;
28452835
28462836 if (redo_bi_depth )
2847- ret = bch2_bi_depth_renumber (trans , & path , min_bi_depth );
2837+ ret = bch2_bi_depth_renumber (trans , & path , snapshot , min_bi_depth );
28482838out :
28492839fsck_err :
28502840 bch2_trans_iter_exit (trans , & inode_iter );
0 commit comments