@@ -205,6 +205,36 @@ static int __remove_dirent(struct btree_trans *trans, struct bpos pos)
205205 return ret ;
206206}
207207
208+ /*
209+ * Find any subvolume associated with a tree of snapshots
210+ * We can't rely on master_subvol - it might have been deleted.
211+ */
212+ static int find_snapshot_tree_subvol (struct btree_trans * trans ,
213+ u32 tree_id , u32 * subvol )
214+ {
215+ struct btree_iter iter ;
216+ struct bkey_s_c k ;
217+ int ret ;
218+
219+ for_each_btree_key_norestart (trans , iter , BTREE_ID_snapshots , POS_MIN , 0 , k , ret ) {
220+ if (k .k -> type != KEY_TYPE_snapshot )
221+ continue ;
222+
223+ struct bkey_s_c_snapshot s = bkey_s_c_to_snapshot (k );
224+ if (le32_to_cpu (s .v -> tree ) != tree_id )
225+ continue ;
226+
227+ if (s .v -> subvol ) {
228+ * subvol = le32_to_cpu (s .v -> subvol );
229+ goto found ;
230+ }
231+ }
232+ ret = - BCH_ERR_ENOENT_no_snapshot_tree_subvol ;
233+ found :
234+ bch2_trans_iter_exit (trans , & iter );
235+ return ret ;
236+ }
237+
208238/* Get lost+found, create if it doesn't exist: */
209239static int lookup_lostfound (struct btree_trans * trans , u32 snapshot ,
210240 struct bch_inode_unpacked * lostfound ,
@@ -223,19 +253,24 @@ static int lookup_lostfound(struct btree_trans *trans, u32 snapshot,
223253 if (ret )
224254 return ret ;
225255
226- subvol_inum root_inum = { .subvol = le32_to_cpu (st .master_subvol ) };
256+ u32 subvolid ;
257+ ret = find_snapshot_tree_subvol (trans ,
258+ bch2_snapshot_tree (c , snapshot ), & subvolid );
259+ bch_err_msg (c , ret , "finding subvol associated with snapshot tree %u" ,
260+ bch2_snapshot_tree (c , snapshot ));
261+ if (ret )
262+ return ret ;
227263
228264 struct bch_subvolume subvol ;
229- ret = bch2_subvolume_get (trans , le32_to_cpu (st .master_subvol ), false, & subvol );
230- bch_err_msg (c , ret , "looking up root subvol %u for snapshot %u" ,
231- le32_to_cpu (st .master_subvol ), snapshot );
265+ ret = bch2_subvolume_get (trans , subvolid , false, & subvol );
266+ bch_err_msg (c , ret , "looking up subvol %u for snapshot %u" , subvolid , snapshot );
232267 if (ret )
233268 return ret ;
234269
235270 if (!subvol .inode ) {
236271 struct btree_iter iter ;
237272 struct bkey_i_subvolume * subvol = bch2_bkey_get_mut_typed (trans , & iter ,
238- BTREE_ID_subvolumes , POS (0 , le32_to_cpu ( st . master_subvol ) ),
273+ BTREE_ID_subvolumes , POS (0 , subvolid ),
239274 0 , subvolume );
240275 ret = PTR_ERR_OR_ZERO (subvol );
241276 if (ret )
@@ -245,13 +280,16 @@ static int lookup_lostfound(struct btree_trans *trans, u32 snapshot,
245280 bch2_trans_iter_exit (trans , & iter );
246281 }
247282
248- root_inum .inum = le64_to_cpu (subvol .inode );
283+ subvol_inum root_inum = {
284+ .subvol = subvolid ,
285+ .inum = le64_to_cpu (subvol .inode )
286+ };
249287
250288 struct bch_inode_unpacked root_inode ;
251289 struct bch_hash_info root_hash_info ;
252290 ret = lookup_inode (trans , root_inum .inum , snapshot , & root_inode );
253291 bch_err_msg (c , ret , "looking up root inode %llu for subvol %u" ,
254- root_inum .inum , le32_to_cpu ( st . master_subvol ) );
292+ root_inum .inum , subvolid );
255293 if (ret )
256294 return ret ;
257295
0 commit comments