@@ -362,9 +362,10 @@ int bch2_inode_peek(struct btree_trans *trans,
362362 return ret ;
363363}
364364
365- int bch2_inode_write (struct btree_trans * trans ,
365+ int bch2_inode_write_flags (struct btree_trans * trans ,
366366 struct btree_iter * iter ,
367- struct bch_inode_unpacked * inode )
367+ struct bch_inode_unpacked * inode ,
368+ enum btree_update_flags flags )
368369{
369370 struct bkey_inode_buf * inode_p ;
370371
@@ -374,7 +375,7 @@ int bch2_inode_write(struct btree_trans *trans,
374375
375376 bch2_inode_pack_inlined (inode_p , inode );
376377 inode_p -> inode .k .p .snapshot = iter -> snapshot ;
377- return bch2_trans_update (trans , iter , & inode_p -> inode .k_i , 0 );
378+ return bch2_trans_update (trans , iter , & inode_p -> inode .k_i , flags );
378379}
379380
380381struct bkey_i * bch2_inode_to_v3 (struct btree_trans * trans , struct bkey_i * k )
@@ -1055,24 +1056,18 @@ int bch2_inode_rm_snapshot(struct btree_trans *trans, u64 inum, u32 snapshot)
10551056 return ret ?: - BCH_ERR_transaction_restart_nested ;
10561057}
10571058
1058- static int may_delete_deleted_inode (struct btree_trans * trans , struct bpos pos )
1059+ static int may_delete_deleted_inode (struct btree_trans * trans ,
1060+ struct btree_iter * iter ,
1061+ struct bpos pos ,
1062+ bool * need_another_pass )
10591063{
10601064 struct bch_fs * c = trans -> c ;
1061- struct btree_iter iter ;
1065+ struct btree_iter inode_iter ;
10621066 struct bkey_s_c k ;
10631067 struct bch_inode_unpacked inode ;
10641068 int ret ;
10651069
1066- if (bch2_snapshot_is_internal_node (c , pos .snapshot ))
1067- return 0 ;
1068-
1069- if (!fsck_err_on (c -> sb .clean , c ,
1070- deleted_inode_but_clean ,
1071- "filesystem marked as clean but have deleted inode %llu:%u" ,
1072- pos .offset , pos .snapshot ))
1073- return 0 ;
1074-
1075- k = bch2_bkey_get_iter (trans , & iter , BTREE_ID_inodes , pos , BTREE_ITER_CACHED );
1070+ k = bch2_bkey_get_iter (trans , & inode_iter , BTREE_ID_inodes , pos , BTREE_ITER_CACHED );
10761071 ret = bkey_err (k );
10771072 if (ret )
10781073 return ret ;
@@ -1086,7 +1081,7 @@ static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos)
10861081
10871082 ret = bch2_inode_unpack (k , & inode );
10881083 if (ret )
1089- goto err ;
1084+ goto out ;
10901085
10911086 if (fsck_err_on (S_ISDIR (inode .bi_mode ), c ,
10921087 deleted_inode_is_dir ,
@@ -1100,20 +1095,57 @@ static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos)
11001095 pos .offset , pos .snapshot ))
11011096 goto delete ;
11021097
1103- return 1 ;
1104- err :
1098+ if (c -> sb .clean &&
1099+ !fsck_err (c ,
1100+ deleted_inode_but_clean ,
1101+ "filesystem marked as clean but have deleted inode %llu:%u" ,
1102+ pos .offset , pos .snapshot )) {
1103+ ret = 0 ;
1104+ goto out ;
1105+ }
1106+
1107+ if (bch2_snapshot_is_internal_node (c , pos .snapshot )) {
1108+ struct bpos new_min_pos ;
1109+
1110+ ret = bch2_propagate_key_to_snapshot_leaves (trans , inode_iter .btree_id , k , & new_min_pos );
1111+ if (ret )
1112+ goto out ;
1113+
1114+ inode .bi_flags &= ~BCH_INODE_UNLINKED ;
1115+
1116+ ret = bch2_inode_write_flags (trans , & inode_iter , & inode ,
1117+ BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE );
1118+ bch_err_msg (c , ret , "clearing inode unlinked flag" );
1119+ if (ret )
1120+ goto out ;
1121+
1122+ /*
1123+ * We'll need another write buffer flush to pick up the new
1124+ * unlinked inodes in the snapshot leaves:
1125+ */
1126+ * need_another_pass = true;
1127+ return 0 ;
1128+ }
1129+
1130+ ret = 1 ;
1131+ out :
11051132fsck_err :
1133+ bch2_trans_iter_exit (trans , & inode_iter );
11061134 return ret ;
11071135delete :
1108- return bch2_btree_bit_mod (trans , BTREE_ID_deleted_inodes , pos , false);
1136+ ret = bch2_btree_bit_mod (trans , BTREE_ID_deleted_inodes , pos , false);
1137+ goto out ;
11091138}
11101139
11111140int bch2_delete_dead_inodes (struct bch_fs * c )
11121141{
11131142 struct btree_trans * trans = bch2_trans_get (c );
11141143 struct btree_iter iter ;
11151144 struct bkey_s_c k ;
1145+ bool need_another_pass ;
11161146 int ret ;
1147+ again :
1148+ need_another_pass = false;
11171149
11181150 ret = bch2_btree_write_buffer_flush_sync (trans );
11191151 if (ret )
@@ -1127,7 +1159,8 @@ int bch2_delete_dead_inodes(struct bch_fs *c)
11271159 */
11281160 for_each_btree_key (trans , iter , BTREE_ID_deleted_inodes , POS_MIN ,
11291161 BTREE_ITER_PREFETCH |BTREE_ITER_ALL_SNAPSHOTS , k , ret ) {
1130- ret = lockrestart_do (trans , may_delete_deleted_inode (trans , k .k -> p ));
1162+ ret = lockrestart_do (trans , may_delete_deleted_inode (trans , & iter , k .k -> p ,
1163+ & need_another_pass ));
11311164 if (ret < 0 )
11321165 break ;
11331166
@@ -1137,12 +1170,17 @@ int bch2_delete_dead_inodes(struct bch_fs *c)
11371170 bch2_fs_lazy_rw (c );
11381171 }
11391172
1173+ bch_verbose (c , "deleting unlinked inode %llu:%u" , k .k -> p .offset , k .k -> p .snapshot );
1174+
11401175 ret = bch2_inode_rm_snapshot (trans , k .k -> p .offset , k .k -> p .snapshot );
11411176 if (ret && !bch2_err_matches (ret , BCH_ERR_transaction_restart ))
11421177 break ;
11431178 }
11441179 }
11451180 bch2_trans_iter_exit (trans , & iter );
1181+
1182+ if (!ret && need_another_pass )
1183+ goto again ;
11461184err :
11471185 bch2_trans_put (trans );
11481186
0 commit comments