Skip to content

Commit f4ee295

Browse files
committed
feat(encryption): request encrypted pool crypto vbdev
Given encryption related args available from create pool request, this creates a crypto vbdev based on the incoming parameters, and then requests the lvolstore creation on that crypto vbdev. Signed-off-by: Diwakar Sharma <diwakar.sharma@datacore.com>
1 parent bd2e431 commit f4ee295

File tree

3 files changed

+123
-15
lines changed

3 files changed

+123
-15
lines changed

io-engine/src/bin/io-engine-client/v1/pool_cli.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ pub fn subcommands() -> Command {
130130
.short('e')
131131
.long("xts-key")
132132
.help("encryption key2 required for AES_XTS")
133-
.required_if_eq("cipher", "AES_XTS"),
133+
.required_if_eq("cipher", "AES_XTS")
134+
.required(false),
134135
);
135136

136137
let destroy = Command::new("destroy")

io-engine/src/lvs/lvs_store.rs

+120-13
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ use url::Url;
2020
use super::{BsError, ImportErrorReason, Lvol, LvsError, LvsIter, PropName, PropValue};
2121

2222
use crate::{
23-
bdev::{uri, PtplFileOps},
23+
bdev::{
24+
crypto::{create_crypto_vbdev_on_base_bdev, destroy_crypto_vbdev},
25+
uri, PtplFileOps,
26+
},
2427
bdev_api::{bdev_destroy, BdevError},
2528
core::{
2629
logical_volume::LogicalVolume, snapshot::LvolSnapshotOps, Bdev, IoType, NvmfShareProps,
@@ -310,11 +313,19 @@ impl Lvs {
310313
name: args.name.clone(),
311314
})?;
312315

316+
// If we are requesting for an encypted pool, then we should match existing pool(if any)
317+
// by pool's bdev name as crypto bdev name.
318+
let pool_bdev_name = if let Some(c) = args.crypto_vbdev_name.as_ref() {
319+
c
320+
} else {
321+
&parsed.get_name()
322+
};
323+
313324
// At any point two pools with the same name should
314325
// not exists so returning error
315326
if let Some(pool) = Self::lookup(&args.name) {
316327
let pool_name = pool.base_bdev().name().to_string();
317-
return if pool_name.as_str() == parsed.get_name() {
328+
return if pool_name.as_str() == pool_bdev_name {
318329
Err(LvsError::Import {
319330
source: BsError::VolAlreadyExists {},
320331
name: args.name.clone(),
@@ -347,7 +358,30 @@ impl Lvs {
347358
Ok(name) => Ok(name),
348359
}?;
349360

350-
let pool = Self::import(&args.name, &bdev).await?;
361+
if let Some(ref cname) = args.crypto_vbdev_name {
362+
// Only if bdev doesn't exist. e.g. direct import path.
363+
if UntypedBdev::lookup_by_name(cname).is_none() {
364+
if let Some(e) = args.enc_key {
365+
match create_crypto_vbdev_on_base_bdev(cname, &bdev, &e) {
366+
Ok(_) => {}
367+
Err(_) => {
368+
let _ = parsed.destroy().await.map_err(|_e| {
369+
error!(
370+
"failed to delete base_bdev {bdev} after failed crypto vbdev creation"
371+
);
372+
});
373+
return Err(LvsError::PoolCreate {
374+
source: BsError::LvsCryptoVbdev {},
375+
name: args.name.clone(),
376+
});
377+
}
378+
}
379+
}
380+
}
381+
}
382+
383+
let bsdev_name = args.crypto_vbdev_name.as_ref().unwrap_or(&bdev);
384+
let pool = Self::import(&args.name, bsdev_name).await?;
351385
// Try to destroy the pending snapshots without catching
352386
// the error.
353387
Lvol::destroy_pending_discarded_snapshot().await;
@@ -394,7 +428,11 @@ impl Lvs {
394428
let bdev = args.disks[0].clone();
395429

396430
let pool_name = args.name.clone().into_cstring();
397-
let bdev_name = bdev.into_cstring();
431+
let bdev_name = if let Some(ref c) = args.crypto_vbdev_name {
432+
c.clone().into_cstring()
433+
} else {
434+
bdev.into_cstring()
435+
};
398436

399437
let cluster_size = if let Some(cluster_size) = args.cluster_size {
400438
if cluster_size % ROUND_TO_MB == 0 {
@@ -490,17 +528,31 @@ impl Lvs {
490528
let disk = Self::parse_disk(args.disks.clone())?;
491529

492530
info!(
493-
"Creating or importing lvs '{}' from '{}'...",
494-
args.name, disk
531+
"Creating or importing {enc} lvs '{}' from '{}'...",
532+
args.name,
533+
disk,
534+
enc = if args.crypto_vbdev_name.is_some() {
535+
"encrypted"
536+
} else {
537+
"non-encrypted"
538+
}
495539
);
496540

497541
let bdev_ops = uri::parse(&disk).map_err(|e| LvsError::InvalidBdev {
498542
source: e,
499543
name: args.name.clone(),
500544
})?;
501545

546+
// If we are requesting for an encypted pool, then we should lookup existing pool(if any)
547+
// by pool's bdev name as crypto bdev name.
548+
let pool_bdev_name = if let Some(c) = args.crypto_vbdev_name.as_ref() {
549+
c
550+
} else {
551+
&bdev_ops.get_name()
552+
};
553+
502554
if let Some(pool) = Self::lookup(&args.name) {
503-
return if pool.base_bdev().name() == bdev_ops.get_name() {
555+
return if pool.base_bdev().name() == pool_bdev_name {
504556
Err(LvsError::PoolCreate {
505557
source: BsError::VolAlreadyExists {},
506558
name: args.name.clone(),
@@ -512,7 +564,6 @@ impl Lvs {
512564
})
513565
};
514566
}
515-
516567
// Create the underlying ndev.
517568
let bdev_name = match bdev_ops.create().await {
518569
Err(e) => match e {
@@ -532,20 +583,50 @@ impl Lvs {
532583
Ok(name) => Ok(name),
533584
}?;
534585

586+
// Create crypto bdev now if required.
587+
if let Some(ref cname) = args.crypto_vbdev_name {
588+
if let Some(ref e) = args.enc_key {
589+
match create_crypto_vbdev_on_base_bdev(cname, &bdev_name, e) {
590+
Ok(_) => {}
591+
Err(_) => {
592+
let _ = bdev_ops.destroy().await.map_err(|_e| {
593+
error!(
594+
"failed to delete base_bdev {bdev_name} after failed crypto vbdev creation"
595+
);
596+
});
597+
return Err(LvsError::PoolCreate {
598+
source: BsError::LvsCryptoVbdev {},
599+
name: args.name.clone(),
600+
});
601+
}
602+
}
603+
}
604+
}
605+
535606
match Self::import_from_args(args.clone()).await {
536607
Ok(pool) => Ok(pool),
537608
// try to create the pool
538609
Err(LvsError::Import {
539610
source: BsError::CannotImportLvs {},
540611
..
541612
}) => {
613+
let cbdev_name: Option<String> = args.crypto_vbdev_name.clone();
542614
match Self::create_from_args_inner(PoolArgs {
543615
disks: vec![bdev_name.clone()],
544616
..args
545617
})
546618
.await
547619
{
548620
Err(create) => {
621+
// destroy crypto vbdev first.
622+
if let Some(c) = cbdev_name.as_ref() {
623+
let _ = destroy_crypto_vbdev(c.clone()).await.map_err(|_e| {
624+
error!(
625+
"failed to delete crypto vbdev {c} after failed pool creation"
626+
);
627+
});
628+
}
629+
549630
let _ = bdev_ops.destroy().await.map_err(|_e| {
550631
// we failed to delete the base_bdev be loud about it
551632
// there is not much we can do about it here, likely
@@ -658,7 +739,7 @@ impl Lvs {
658739
// when destroying a pool unshare all volumes
659740
self.unshare_all().await;
660741

661-
let base_bdev = self.base_bdev();
742+
let mut base_bdev = self.base_bdev();
662743

663744
let evt = self.event(EventAction::Delete);
664745

@@ -671,16 +752,42 @@ impl Lvs {
671752
name: pool.clone(),
672753
})?;
673754

674-
info!("{}: lvs destroyed successfully", self_str);
755+
info!(
756+
"{}: lvs destroyed successfully. base_bdev: {base_bdev:?}",
757+
self_str
758+
);
675759

676760
evt.generate();
677761

678-
bdev_destroy(&base_bdev.bdev_uri_original_str().unwrap())
679-
.await
680-
.map_err(|e| LvsError::Destroy {
762+
// If the base_bdev is a crypto vbdev then we need to destroy both - the crypto vbdev and it's base.
763+
if base_bdev.driver() == "crypto" {
764+
let cbdev = base_bdev.crypto_base_bdev();
765+
766+
let _ = destroy_crypto_vbdev(base_bdev.name().to_string())
767+
.await
768+
.map_err(|e| LvsError::Destroy {
769+
source: e,
770+
name: self_str.clone(),
771+
});
772+
773+
// A None cbdev here is highly unlikely as the vbdev can't exist in thin air.
774+
// If cbdev is somehow None anyway, then the following bdev_destroy will likely
775+
// fail, and we can let it.
776+
if let Some(c) = cbdev {
777+
base_bdev = Bdev::new(c);
778+
}
779+
}
780+
trace!(
781+
"Deleting bdev {}, uri {:?}",
782+
base_bdev.name(),
783+
base_bdev.bdev_uri_original_str()
784+
);
785+
if let Some(u) = base_bdev.bdev_uri_original_str() {
786+
bdev_destroy(&u).await.map_err(|e| LvsError::Destroy {
681787
source: e,
682788
name: base_bdev.name().to_string(),
683789
})?;
790+
}
684791

685792
if let Err(error) = ptpl.destroy() {
686793
tracing::error!(

io-engine/src/subsys/config/pool.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ struct Pool {
159159
#[serde(skip_serializing)]
160160
replicas: Option<Vec<Replica>>,
161161
backend: PoolBackend,
162-
/// Is the pool enrypted.
162+
/// Is the pool encrypted.
163163
encrypted: bool,
164164
}
165165

0 commit comments

Comments
 (0)