@@ -832,11 +832,13 @@ struct inode_walker {
832
832
struct bpos last_pos ;
833
833
834
834
DARRAY (struct inode_walker_entry ) inodes ;
835
+ snapshot_id_list deletes ;
835
836
};
836
837
837
838
static void inode_walker_exit (struct inode_walker * w )
838
839
{
839
840
darray_exit (& w -> inodes );
841
+ darray_exit (& w -> deletes );
840
842
}
841
843
842
844
static struct inode_walker inode_walker_init (void )
@@ -960,19 +962,23 @@ static int get_visible_inodes(struct btree_trans *trans,
960
962
int ret ;
961
963
962
964
w -> inodes .nr = 0 ;
965
+ w -> deletes .nr = 0 ;
963
966
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 ),
965
968
BTREE_ITER_all_snapshots , k , ret ) {
966
969
if (k .k -> p .offset != inum )
967
970
break ;
968
971
969
972
if (!ref_visible (c , s , s -> pos .snapshot , k .k -> p .snapshot ))
970
973
continue ;
971
974
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 ;
974
977
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 )
976
982
break ;
977
983
}
978
984
bch2_trans_iter_exit (trans , & iter );
@@ -2380,6 +2386,30 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
2380
2386
if (ret )
2381
2387
goto err ;
2382
2388
}
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
+ }
2383
2413
}
2384
2414
2385
2415
ret = bch2_trans_commit (trans , NULL , NULL , BCH_TRANS_COMMIT_no_enospc );
0 commit comments