8
8
#include "fs.h"
9
9
#include "keylist.h"
10
10
#include "str_hash.h"
11
+ #include "subvolume.h"
11
12
12
13
#include <linux/dcache.h>
13
14
@@ -150,8 +151,8 @@ static struct bkey_i_dirent *dirent_create_key(struct btree_trans *trans,
150
151
return dirent ;
151
152
}
152
153
153
- int bch2_dirent_create (struct btree_trans * trans ,
154
- u64 dir_inum , const struct bch_hash_info * hash_info ,
154
+ int bch2_dirent_create (struct btree_trans * trans , subvol_inum dir ,
155
+ const struct bch_hash_info * hash_info ,
155
156
u8 type , const struct qstr * name , u64 dst_inum ,
156
157
u64 * dir_offset , int flags )
157
158
{
@@ -164,7 +165,7 @@ int bch2_dirent_create(struct btree_trans *trans,
164
165
return ret ;
165
166
166
167
ret = bch2_hash_set (trans , bch2_dirent_hash_desc , hash_info ,
167
- dir_inum , & dirent -> k_i , flags );
168
+ dir , & dirent -> k_i , flags );
168
169
* dir_offset = dirent -> k .p .offset ;
169
170
170
171
return ret ;
@@ -223,31 +224,40 @@ int __bch2_dirent_read_target(struct btree_trans *trans,
223
224
return ret ;
224
225
}
225
226
226
- int bch2_dirent_read_target (struct btree_trans * trans ,
227
- struct bkey_s_c_dirent d , u64 * target )
227
+ static int bch2_dirent_read_target (struct btree_trans * trans , subvol_inum dir ,
228
+ struct bkey_s_c_dirent d , subvol_inum * target )
228
229
{
229
- u32 subvol , snapshot ;
230
+ u32 snapshot ;
231
+ int ret = 0 ;
230
232
231
- return __bch2_dirent_read_target (trans , d , & subvol ,
232
- & snapshot , target , false);
233
+ ret = __bch2_dirent_read_target (trans , d , & target -> subvol , & snapshot ,
234
+ & target -> inum , false);
235
+ if (!target -> subvol )
236
+ target -> subvol = dir .subvol ;
237
+
238
+ return ret ;
233
239
}
234
240
235
241
int bch2_dirent_rename (struct btree_trans * trans ,
236
- u64 src_dir , struct bch_hash_info * src_hash ,
237
- u64 dst_dir , struct bch_hash_info * dst_hash ,
238
- const struct qstr * src_name , u64 * src_inum , u64 * src_offset ,
239
- const struct qstr * dst_name , u64 * dst_inum , u64 * dst_offset ,
240
- enum bch_rename_mode mode )
242
+ subvol_inum src_dir , struct bch_hash_info * src_hash ,
243
+ subvol_inum dst_dir , struct bch_hash_info * dst_hash ,
244
+ const struct qstr * src_name , subvol_inum * src_inum , u64 * src_offset ,
245
+ const struct qstr * dst_name , subvol_inum * dst_inum , u64 * dst_offset ,
246
+ enum bch_rename_mode mode )
241
247
{
242
248
struct btree_iter src_iter = { NULL };
243
249
struct btree_iter dst_iter = { NULL };
244
250
struct bkey_s_c old_src , old_dst ;
245
251
struct bkey_i_dirent * new_src = NULL , * new_dst = NULL ;
246
252
struct bpos dst_pos =
247
- POS (dst_dir , bch2_dirent_hash (dst_hash , dst_name ));
253
+ POS (dst_dir . inum , bch2_dirent_hash (dst_hash , dst_name ));
248
254
int ret = 0 ;
249
255
250
- * src_inum = * dst_inum = 0 ;
256
+ if (src_dir .subvol != dst_dir .subvol )
257
+ return - EXDEV ;
258
+
259
+ memset (src_inum , 0 , sizeof (* src_inum ));
260
+ memset (dst_inum , 0 , sizeof (* dst_inum ));
251
261
252
262
/*
253
263
* Lookup dst:
@@ -270,8 +280,12 @@ int bch2_dirent_rename(struct btree_trans *trans,
270
280
if (ret )
271
281
goto out ;
272
282
273
- if (mode != BCH_RENAME )
274
- * dst_inum = le64_to_cpu (bkey_s_c_to_dirent (old_dst ).v -> d_inum );
283
+ if (mode != BCH_RENAME ) {
284
+ ret = bch2_dirent_read_target (trans , dst_dir ,
285
+ bkey_s_c_to_dirent (old_dst ), dst_inum );
286
+ if (ret )
287
+ goto out ;
288
+ }
275
289
if (mode != BCH_RENAME_EXCHANGE )
276
290
* src_offset = dst_iter .pos .offset ;
277
291
@@ -287,7 +301,10 @@ int bch2_dirent_rename(struct btree_trans *trans,
287
301
if (ret )
288
302
goto out ;
289
303
290
- * src_inum = le64_to_cpu (bkey_s_c_to_dirent (old_src ).v -> d_inum );
304
+ ret = bch2_dirent_read_target (trans , src_dir ,
305
+ bkey_s_c_to_dirent (old_src ), src_inum );
306
+ if (ret )
307
+ goto out ;
291
308
292
309
/* Create new dst key: */
293
310
new_dst = dirent_create_key (trans , 0 , dst_name , 0 );
@@ -376,17 +393,22 @@ int bch2_dirent_delete_at(struct btree_trans *trans,
376
393
377
394
int __bch2_dirent_lookup_trans (struct btree_trans * trans ,
378
395
struct btree_iter * iter ,
379
- u64 dir_inum ,
396
+ subvol_inum dir ,
380
397
const struct bch_hash_info * hash_info ,
381
- const struct qstr * name , u64 * inum ,
398
+ const struct qstr * name , subvol_inum * inum ,
382
399
unsigned flags )
383
400
{
384
401
struct bkey_s_c k ;
385
402
struct bkey_s_c_dirent d ;
403
+ u32 snapshot ;
386
404
int ret ;
387
405
406
+ ret = bch2_subvolume_get_snapshot (trans , dir .subvol , & snapshot );
407
+ if (ret )
408
+ return ret ;
409
+
388
410
ret = bch2_hash_lookup (trans , iter , bch2_dirent_hash_desc ,
389
- hash_info , dir_inum , name , flags );
411
+ hash_info , dir , name , flags );
390
412
if (ret )
391
413
return ret ;
392
414
@@ -399,44 +421,49 @@ int __bch2_dirent_lookup_trans(struct btree_trans *trans,
399
421
400
422
d = bkey_s_c_to_dirent (k );
401
423
402
- ret = bch2_dirent_read_target (trans , d , inum );
424
+ ret = bch2_dirent_read_target (trans , dir , d , inum );
403
425
if (ret )
404
426
bch2_trans_iter_exit (trans , iter );
405
427
406
428
return ret ;
407
429
}
408
430
409
- u64 bch2_dirent_lookup (struct bch_fs * c , u64 dir_inum ,
431
+ u64 bch2_dirent_lookup (struct bch_fs * c , subvol_inum dir ,
410
432
const struct bch_hash_info * hash_info ,
411
- const struct qstr * name )
433
+ const struct qstr * name , subvol_inum * inum )
412
434
{
413
435
struct btree_trans trans ;
414
436
struct btree_iter iter ;
415
- u64 inum = 0 ;
416
- int ret = 0 ;
437
+ int ret ;
417
438
418
439
bch2_trans_init (& trans , c , 0 , 0 );
419
440
retry :
420
441
bch2_trans_begin (& trans );
421
- ret = __bch2_dirent_lookup_trans (& trans , & iter , dir_inum , hash_info ,
422
- name , & inum , 0 );
442
+
443
+ ret = __bch2_dirent_lookup_trans (& trans , & iter , dir , hash_info ,
444
+ name , inum , 0 );
423
445
424
446
bch2_trans_iter_exit (& trans , & iter );
425
447
if (ret == - EINTR )
426
448
goto retry ;
427
449
bch2_trans_exit (& trans );
428
- return inum ;
450
+ return ret ;
429
451
}
430
452
431
- int bch2_empty_dir_trans (struct btree_trans * trans , u64 dir_inum )
453
+ int bch2_empty_dir_trans (struct btree_trans * trans , subvol_inum dir )
432
454
{
433
455
struct btree_iter iter ;
434
456
struct bkey_s_c k ;
457
+ u32 snapshot ;
435
458
int ret ;
436
459
460
+ ret = bch2_subvolume_get_snapshot (trans , dir .subvol , & snapshot );
461
+ if (ret )
462
+ return ret ;
463
+
437
464
for_each_btree_key (trans , iter , BTREE_ID_dirents ,
438
- POS ( dir_inum , 0 ), 0 , k , ret ) {
439
- if (k .k -> p .inode > dir_inum )
465
+ SPOS ( dir . inum , 0 , snapshot ), 0 , k , ret ) {
466
+ if (k .k -> p .inode > dir . inum )
440
467
break ;
441
468
442
469
if (k .k -> type == KEY_TYPE_dirent ) {
@@ -449,19 +476,26 @@ int bch2_empty_dir_trans(struct btree_trans *trans, u64 dir_inum)
449
476
return ret ;
450
477
}
451
478
452
- int bch2_readdir (struct bch_fs * c , u64 inum , struct dir_context * ctx )
479
+ int bch2_readdir (struct bch_fs * c , subvol_inum inum , struct dir_context * ctx )
453
480
{
454
481
struct btree_trans trans ;
455
482
struct btree_iter iter ;
456
483
struct bkey_s_c k ;
457
484
struct bkey_s_c_dirent dirent ;
485
+ u32 snapshot ;
458
486
int ret ;
459
487
460
488
bch2_trans_init (& trans , c , 0 , 0 );
489
+ retry :
490
+ bch2_trans_begin (& trans );
491
+
492
+ ret = bch2_subvolume_get_snapshot (& trans , inum .subvol , & snapshot );
493
+ if (ret )
494
+ goto err ;
461
495
462
496
for_each_btree_key (& trans , iter , BTREE_ID_dirents ,
463
- POS (inum , ctx -> pos ), 0 , k , ret ) {
464
- if (k .k -> p .inode > inum )
497
+ SPOS (inum . inum , ctx -> pos , snapshot ), 0 , k , ret ) {
498
+ if (k .k -> p .inode > inum . inum )
465
499
break ;
466
500
467
501
if (k .k -> type != KEY_TYPE_dirent )
@@ -482,6 +516,9 @@ int bch2_readdir(struct bch_fs *c, u64 inum, struct dir_context *ctx)
482
516
ctx -> pos = dirent .k -> p .offset + 1 ;
483
517
}
484
518
bch2_trans_iter_exit (& trans , & iter );
519
+ err :
520
+ if (ret == - EINTR )
521
+ goto retry ;
485
522
486
523
ret = bch2_trans_exit (& trans ) ?: ret ;
487
524
0 commit comments