@@ -832,11 +832,13 @@ struct inode_walker {
832832 struct bpos last_pos ;
833833
834834 DARRAY (struct inode_walker_entry ) inodes ;
835+ snapshot_id_list deletes ;
835836};
836837
837838static void inode_walker_exit (struct inode_walker * w )
838839{
839840 darray_exit (& w -> inodes );
841+ darray_exit (& w -> deletes );
840842}
841843
842844static struct inode_walker inode_walker_init (void )
@@ -960,19 +962,23 @@ static int get_visible_inodes(struct btree_trans *trans,
960962 int ret ;
961963
962964 w -> inodes .nr = 0 ;
965+ w -> deletes .nr = 0 ;
963966
964- for_each_btree_key_norestart (trans , iter , BTREE_ID_inodes , POS (0 , inum ),
967+ for_each_btree_key_reverse_norestart (trans , iter , BTREE_ID_inodes , SPOS (0 , inum , s -> pos . snapshot ),
965968 BTREE_ITER_all_snapshots , k , ret ) {
966969 if (k .k -> p .offset != inum )
967970 break ;
968971
969972 if (!ref_visible (c , s , s -> pos .snapshot , k .k -> p .snapshot ))
970973 continue ;
971974
972- if (bkey_is_inode ( k .k ))
973- add_inode ( c , w , k ) ;
975+ if (snapshot_list_has_ancestor ( c , & w -> deletes , k .k -> p . snapshot ))
976+ continue ;
974977
975- if (k .k -> p .snapshot >= s -> pos .snapshot )
978+ ret = bkey_is_inode (k .k )
979+ ? add_inode (c , w , k )
980+ : snapshot_list_add (c , & w -> deletes , k .k -> p .snapshot );
981+ if (ret )
976982 break ;
977983 }
978984 bch2_trans_iter_exit (trans , & iter );
@@ -2380,6 +2386,30 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
23802386 if (ret )
23812387 goto err ;
23822388 }
2389+
2390+ darray_for_each (target -> deletes , i )
2391+ if (fsck_err_on (!snapshot_list_has_id (& s -> ids , * i ),
2392+ trans , dirent_to_overwritten_inode ,
2393+ "dirent points to inode overwritten in snapshot %u:\n%s" ,
2394+ * i ,
2395+ (printbuf_reset (& buf ),
2396+ bch2_bkey_val_to_text (& buf , c , k ),
2397+ buf .buf ))) {
2398+ struct btree_iter delete_iter ;
2399+ bch2_trans_iter_init (trans , & delete_iter ,
2400+ BTREE_ID_dirents ,
2401+ SPOS (k .k -> p .inode , k .k -> p .offset , * i ),
2402+ BTREE_ITER_intent );
2403+ ret = bch2_btree_iter_traverse (& delete_iter ) ?:
2404+ bch2_hash_delete_at (trans , bch2_dirent_hash_desc ,
2405+ hash_info ,
2406+ & delete_iter ,
2407+ BTREE_UPDATE_internal_snapshot_node );
2408+ bch2_trans_iter_exit (trans , & delete_iter );
2409+ if (ret )
2410+ goto err ;
2411+
2412+ }
23832413 }
23842414
23852415 ret = bch2_trans_commit (trans , NULL , NULL , BCH_TRANS_COMMIT_no_enospc );
0 commit comments