@@ -20,7 +20,10 @@ use url::Url;
20
20
use super :: { BsError , ImportErrorReason , Lvol , LvsError , LvsIter , PropName , PropValue } ;
21
21
22
22
use crate :: {
23
- bdev:: { uri, PtplFileOps } ,
23
+ bdev:: {
24
+ crypto:: { create_crypto_vbdev_on_base_bdev, destroy_crypto_vbdev} ,
25
+ uri, PtplFileOps ,
26
+ } ,
24
27
bdev_api:: { bdev_destroy, BdevError } ,
25
28
core:: {
26
29
logical_volume:: LogicalVolume , snapshot:: LvolSnapshotOps , Bdev , IoType , NvmfShareProps ,
@@ -316,11 +319,19 @@ impl Lvs {
316
319
name : args. name . clone ( ) ,
317
320
} ) ?;
318
321
322
+ // If we are requesting for an encrypted pool, then we should match existing pool(if any)
323
+ // by pool's bdev name as crypto bdev name.
324
+ let pool_bdev_name = if let Some ( c) = args. crypto_vbdev_name . as_ref ( ) {
325
+ c
326
+ } else {
327
+ & parsed. get_name ( )
328
+ } ;
329
+
319
330
// At any point two pools with the same name should
320
331
// not exists so returning error
321
332
if let Some ( pool) = Self :: lookup ( & args. name ) {
322
333
let pool_name = pool. base_bdev ( ) . name ( ) . to_string ( ) ;
323
- return if pool_name. as_str ( ) == parsed . get_name ( ) {
334
+ return if pool_name. as_str ( ) == pool_bdev_name {
324
335
Err ( LvsError :: Import {
325
336
source : BsError :: VolAlreadyExists { } ,
326
337
name : args. name . clone ( ) ,
@@ -353,7 +364,35 @@ impl Lvs {
353
364
Ok ( name) => Ok ( name) ,
354
365
} ?;
355
366
356
- let pool = Self :: import ( & args. name , & bdev) . await ?;
367
+ if let Some ( ref cname) = args. crypto_vbdev_name {
368
+ // Only if bdev doesn't exist. e.g. direct import path.
369
+ if UntypedBdev :: lookup_by_name ( cname) . is_none ( ) {
370
+ if let Some ( e) = args. enc_key {
371
+ match create_crypto_vbdev_on_base_bdev ( cname, & bdev, & e) {
372
+ Ok ( _) => { }
373
+ Err ( berr) => {
374
+ let _ = parsed. destroy ( ) . await . map_err ( |e| {
375
+ error ! (
376
+ "failed to delete base_bdev {bdev} after failed crypto vbdev creation. {e:?}"
377
+ ) ;
378
+ } ) ;
379
+ return Err ( LvsError :: PoolCreate {
380
+ source : BsError :: LvsCryptoVbdev {
381
+ source : match berr {
382
+ BdevError :: CreateBdevFailed { source, .. } => source,
383
+ _ => Errno :: EINVAL ,
384
+ } ,
385
+ } ,
386
+ name : args. name . clone ( ) ,
387
+ } ) ;
388
+ }
389
+ }
390
+ }
391
+ }
392
+ }
393
+
394
+ let bsdev_name = args. crypto_vbdev_name . as_ref ( ) . unwrap_or ( & bdev) ;
395
+ let pool = Self :: import ( & args. name , bsdev_name) . await ?;
357
396
// Try to destroy the pending snapshots without catching
358
397
// the error.
359
398
Lvol :: destroy_pending_discarded_snapshot ( ) . await ;
@@ -400,7 +439,11 @@ impl Lvs {
400
439
let bdev = args. disks [ 0 ] . clone ( ) ;
401
440
402
441
let pool_name = args. name . clone ( ) . into_cstring ( ) ;
403
- let bdev_name = bdev. into_cstring ( ) ;
442
+ let bdev_name = if let Some ( ref c) = args. crypto_vbdev_name {
443
+ c. clone ( ) . into_cstring ( )
444
+ } else {
445
+ bdev. into_cstring ( )
446
+ } ;
404
447
405
448
let cluster_size = if let Some ( cluster_size) = args. cluster_size {
406
449
if cluster_size % ROUND_TO_MB == 0 {
@@ -496,17 +539,31 @@ impl Lvs {
496
539
let disk = Self :: parse_disk ( args. disks . clone ( ) ) ?;
497
540
498
541
info ! (
499
- "Creating or importing lvs '{}' from '{}'..." ,
500
- args. name, disk
542
+ "Creating or importing {enc} lvs '{}' from '{}'..." ,
543
+ args. name,
544
+ disk,
545
+ enc = if args. crypto_vbdev_name. is_some( ) {
546
+ "encrypted"
547
+ } else {
548
+ "non-encrypted"
549
+ }
501
550
) ;
502
551
503
552
let bdev_ops = uri:: parse ( & disk) . map_err ( |e| LvsError :: InvalidBdev {
504
553
source : e,
505
554
name : args. name . clone ( ) ,
506
555
} ) ?;
507
556
557
+ // If we are requesting for an encrypted pool, then we should lookup existing pool(if any)
558
+ // by pool's bdev name as crypto bdev name.
559
+ let pool_bdev_name = if let Some ( c) = args. crypto_vbdev_name . as_ref ( ) {
560
+ c
561
+ } else {
562
+ & bdev_ops. get_name ( )
563
+ } ;
564
+
508
565
if let Some ( pool) = Self :: lookup ( & args. name ) {
509
- return if pool. base_bdev ( ) . name ( ) == bdev_ops . get_name ( ) {
566
+ return if pool. base_bdev ( ) . name ( ) == pool_bdev_name {
510
567
Err ( LvsError :: PoolCreate {
511
568
source : BsError :: VolAlreadyExists { } ,
512
569
name : args. name . clone ( ) ,
@@ -518,7 +575,6 @@ impl Lvs {
518
575
} )
519
576
} ;
520
577
}
521
-
522
578
// Create the underlying ndev.
523
579
let bdev_name = match bdev_ops. create ( ) . await {
524
580
Err ( e) => match e {
@@ -538,20 +594,55 @@ impl Lvs {
538
594
Ok ( name) => Ok ( name) ,
539
595
} ?;
540
596
597
+ // Create crypto bdev now if required.
598
+ if let Some ( ref cname) = args. crypto_vbdev_name {
599
+ if let Some ( ref e) = args. enc_key {
600
+ match create_crypto_vbdev_on_base_bdev ( cname, & bdev_name, e) {
601
+ Ok ( _) => { }
602
+ Err ( berr) => {
603
+ let _ = bdev_ops. destroy ( ) . await . map_err ( |e| {
604
+ error ! (
605
+ "failed to delete base_bdev {bdev_name} after failed crypto vbdev creation. {e:?}"
606
+ ) ;
607
+ } ) ;
608
+ return Err ( LvsError :: PoolCreate {
609
+ source : BsError :: LvsCryptoVbdev {
610
+ source : match berr {
611
+ BdevError :: CreateBdevFailed { source, .. } => source,
612
+ _ => Errno :: EINVAL ,
613
+ } ,
614
+ } ,
615
+ name : args. name . clone ( ) ,
616
+ } ) ;
617
+ }
618
+ }
619
+ }
620
+ }
621
+
541
622
match Self :: import_from_args ( args. clone ( ) ) . await {
542
623
Ok ( pool) => Ok ( pool) ,
543
624
// try to create the pool
544
625
Err ( LvsError :: Import {
545
626
source : BsError :: CannotImportLvs { } ,
546
627
..
547
628
} ) => {
629
+ let cbdev_name: Option < String > = args. crypto_vbdev_name . clone ( ) ;
548
630
match Self :: create_from_args_inner ( PoolArgs {
549
631
disks : vec ! [ bdev_name. clone( ) ] ,
550
632
..args
551
633
} )
552
634
. await
553
635
{
554
636
Err ( create) => {
637
+ // destroy crypto vbdev first.
638
+ if let Some ( c) = cbdev_name. as_ref ( ) {
639
+ let _ = destroy_crypto_vbdev ( c. clone ( ) ) . await . map_err ( |e| {
640
+ error ! (
641
+ "failed to delete crypto vbdev {c} after failed pool creation. {e}"
642
+ ) ;
643
+ } ) ;
644
+ }
645
+
555
646
let _ = bdev_ops. destroy ( ) . await . map_err ( |_e| {
556
647
// we failed to delete the base_bdev be loud about it
557
648
// there is not much we can do about it here, likely
@@ -664,7 +755,7 @@ impl Lvs {
664
755
// when destroying a pool unshare all volumes
665
756
self . unshare_all ( ) . await ;
666
757
667
- let base_bdev = self . base_bdev ( ) ;
758
+ let mut base_bdev = self . base_bdev ( ) ;
668
759
669
760
let evt = self . event ( EventAction :: Delete ) ;
670
761
@@ -677,16 +768,44 @@ impl Lvs {
677
768
name : pool. clone ( ) ,
678
769
} ) ?;
679
770
680
- info ! ( "{}: lvs destroyed successfully" , self_str) ;
771
+ info ! (
772
+ "{}: lvs destroyed successfully. base_bdev: {base_bdev:?}" ,
773
+ self_str
774
+ ) ;
681
775
682
776
evt. generate ( ) ;
683
777
684
- bdev_destroy ( & base_bdev. bdev_uri_original_str ( ) . unwrap ( ) )
685
- . await
686
- . map_err ( |e| LvsError :: Destroy {
778
+ // If the base_bdev is a crypto vbdev then we need to destroy both - the crypto vbdev and it's base.
779
+ if base_bdev. driver ( ) == "crypto" {
780
+ let cbdev = base_bdev. crypto_base_bdev ( ) ;
781
+
782
+ let _ = destroy_crypto_vbdev ( base_bdev. name ( ) . to_string ( ) )
783
+ . await
784
+ . map_err ( |e| {
785
+ error ! (
786
+ "failed to delete crypto vbdev {:?} after failed pool creation. {e}" ,
787
+ base_bdev. name( )
788
+ ) ;
789
+ } ) ;
790
+
791
+ // A None cbdev here is highly unlikely as the vbdev can't exist in thin air.
792
+ // If cbdev is somehow None anyway, then the following bdev_destroy will likely
793
+ // fail, and we can let it.
794
+ if let Some ( c) = cbdev {
795
+ base_bdev = Bdev :: new ( c) ;
796
+ }
797
+ }
798
+ trace ! (
799
+ "Deleting bdev {}, uri {:?}" ,
800
+ base_bdev. name( ) ,
801
+ base_bdev. bdev_uri_original_str( )
802
+ ) ;
803
+ if let Some ( u) = base_bdev. bdev_uri_original_str ( ) {
804
+ bdev_destroy ( & u) . await . map_err ( |e| LvsError :: Destroy {
687
805
source : e,
688
806
name : base_bdev. name ( ) . to_string ( ) ,
689
807
} ) ?;
808
+ }
690
809
691
810
if let Err ( error) = ptpl. destroy ( ) {
692
811
tracing:: error!(
0 commit comments