@@ -205,6 +205,36 @@ static int __remove_dirent(struct btree_trans *trans, struct bpos pos)
205
205
return ret ;
206
206
}
207
207
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
+
208
238
/* Get lost+found, create if it doesn't exist: */
209
239
static int lookup_lostfound (struct btree_trans * trans , u32 snapshot ,
210
240
struct bch_inode_unpacked * lostfound ,
@@ -223,19 +253,24 @@ static int lookup_lostfound(struct btree_trans *trans, u32 snapshot,
223
253
if (ret )
224
254
return ret ;
225
255
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 ;
227
263
228
264
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 );
232
267
if (ret )
233
268
return ret ;
234
269
235
270
if (!subvol .inode ) {
236
271
struct btree_iter iter ;
237
272
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 ),
239
274
0 , subvolume );
240
275
ret = PTR_ERR_OR_ZERO (subvol );
241
276
if (ret )
@@ -245,13 +280,16 @@ static int lookup_lostfound(struct btree_trans *trans, u32 snapshot,
245
280
bch2_trans_iter_exit (trans , & iter );
246
281
}
247
282
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
+ };
249
287
250
288
struct bch_inode_unpacked root_inode ;
251
289
struct bch_hash_info root_hash_info ;
252
290
ret = lookup_inode (trans , root_inum .inum , snapshot , & root_inode );
253
291
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 );
255
293
if (ret )
256
294
return ret ;
257
295
0 commit comments