Skip to content

Commit 79da7c8

Browse files
mayastor-borsabhilashshetty04
andcommitted
Merge #1922
1922: fix: encrypted pool expansion workflow r=abhilashshetty04 a=abhilashshetty04 We were rescanning base bdev of the Pool. Base bdev for the encrypted pool is crypto bdev which cant be resized. Now, we get the Aio bdev backing the crypto bdev. crypto bdev gets notified via event when aio is resized after which it adjusts the blockcnt. Co-authored-by: Abhilash Shetty <[email protected]>
2 parents 7fe36ec + dbe2a4d commit 79da7c8

File tree

2 files changed

+77
-30
lines changed

2 files changed

+77
-30
lines changed

io-engine/src/lvs/lvs_error.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,10 +271,14 @@ pub enum LvsError {
271271
source: BsError,
272272
name: String,
273273
},
274-
#[snafu(display("Failed to extend pool bdev: {name}"))]
274+
#[snafu(display("Pool Bdev not extended: {name}"))]
275275
BdevNotExtended {
276276
name: String,
277277
},
278+
#[snafu(display("Failed to resize crypto bdev: {name}"))]
279+
CryptoBdevNotResized {
280+
name: String,
281+
},
278282
}
279283

280284
/// Map CoreError to errno code.
@@ -285,7 +289,7 @@ impl ToErrno for LvsError {
285289
Self::PoolCreate { source, .. } => source.to_errno(),
286290
Self::Export { source, .. } => source.to_errno(),
287291
Self::Destroy { .. } => Errno::ENXIO,
288-
Self::Grow { .. } => Errno::ENXIO,
292+
Self::Grow { source, .. } => source.to_errno(),
289293
Self::PoolNotFound { source, .. } => source.to_errno(),
290294
Self::InvalidBdev { .. } => Errno::ENXIO,
291295
Self::Invalid { source, .. } => source.to_errno(),
@@ -313,6 +317,7 @@ impl ToErrno for LvsError {
313317
Self::MaxExpansionParse { .. } => Errno::EINVAL,
314318
Self::BdevRescanFailed { source, .. } => source.to_errno(),
315319
Self::BdevNotExtended { .. } => Errno::EOPNOTSUPP,
320+
Self::CryptoBdevNotResized { .. } => Errno::EBUSY,
316321
}
317322
}
318323
}

io-engine/src/lvs/lvs_store.rs

Lines changed: 70 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
use core::f64;
22
use std::{convert::TryFrom, fmt::Debug, os::raw::c_void, pin::Pin, ptr::NonNull, str::FromStr};
33

4+
use crate::sleep::mayastor_sleep;
45
use byte_unit::Byte;
56
use events_api::event::EventAction;
67
use futures::channel::oneshot;
78
use nix::errno::Errno;
89
use pin_utils::core_reexport::fmt::Formatter;
910

1011
use spdk_rs::libspdk::{
11-
bdev_aio_rescan, spdk_bdev_update_bs_blockcnt, spdk_blob_store, spdk_bs_free_cluster_count,
12-
spdk_bs_get_cluster_size, spdk_bs_get_max_growable_size, spdk_bs_get_md_len,
13-
spdk_bs_get_page_size, spdk_bs_get_used_md, spdk_bs_total_data_cluster_count, spdk_lvol,
14-
spdk_lvol_opts, spdk_lvol_opts_init, spdk_lvol_store, spdk_lvs_grow_live,
15-
vbdev_get_lvol_store_by_name, vbdev_get_lvol_store_by_uuid, vbdev_get_lvs_bdev_by_lvs,
16-
vbdev_lvol_create_with_opts, vbdev_lvs_create, vbdev_lvs_create_with_uuid, vbdev_lvs_destruct,
17-
vbdev_lvs_import, vbdev_lvs_unload, LVOL_CLEAR_WITH_NONE, LVOL_CLEAR_WITH_UNMAP,
18-
LVS_CLEAR_WITH_NONE,
12+
bdev_aio_rescan, bdev_uring_rescan, spdk_bdev_update_bs_blockcnt, spdk_blob_store,
13+
spdk_bs_free_cluster_count, spdk_bs_get_cluster_size, spdk_bs_get_max_growable_size,
14+
spdk_bs_get_md_len, spdk_bs_get_page_size, spdk_bs_get_used_md,
15+
spdk_bs_total_data_cluster_count, spdk_lvol, spdk_lvol_opts, spdk_lvol_opts_init,
16+
spdk_lvol_store, spdk_lvs_grow_live, vbdev_get_lvol_store_by_name,
17+
vbdev_get_lvol_store_by_uuid, vbdev_get_lvs_bdev_by_lvs, vbdev_lvol_create_with_opts,
18+
vbdev_lvs_create, vbdev_lvs_create_with_uuid, vbdev_lvs_destruct, vbdev_lvs_import,
19+
vbdev_lvs_unload, LVOL_CLEAR_WITH_NONE, LVOL_CLEAR_WITH_UNMAP, LVS_CLEAR_WITH_NONE,
1920
};
2021
use url::Url;
2122

@@ -442,7 +443,7 @@ impl Lvs {
442443
Byte::from_str(&param).map_err(|error| LvsError::MaxExpansionParse {
443444
msg: format!("Failed to parse max_expansion {param} as bytes: {error}"),
444445
})?;
445-
expand_bytes.as_u64() as f64 / capacity as f64
446+
(expand_bytes.as_u64() as f64 / capacity as f64).ceil()
446447
} else {
447448
return Err(LvsError::MaxExpansionParse {
448449
msg: format!("Max expansion factor {param} does not end with x or B"),
@@ -879,32 +880,48 @@ impl Lvs {
879880
#[tracing::instrument(level = "debug", err)]
880881
pub async fn grow(&self) -> Result<(), LvsError> {
881882
info!("{self:?}: growing lvs...");
883+
let lvs_name = self.name();
882884

883-
let cname = self.base_bdev().name().into_cstring();
884-
let uri_str = &self.base_bdev().bdev_uri_str().unwrap_or_default();
885-
let url = Url::parse(uri_str).map_err(|source| LvsError::InvalidBdev {
885+
let disk_bdev = self
886+
.base_bdev()
887+
.crypto_base_bdev()
888+
.map(Bdev::new)
889+
.unwrap_or_else(|| self.base_bdev());
890+
891+
let uri_str = disk_bdev.bdev_uri_str().unwrap_or_default();
892+
let url = Url::parse(&uri_str).map_err(|source| LvsError::InvalidBdev {
886893
source: BdevError::UriParseFailed {
887894
source,
888895
uri: uri_str.to_string(),
889896
},
890-
name: self.name().to_string(),
897+
name: lvs_name.to_string(),
891898
})?;
892-
if url.scheme() != "malloc" {
893-
info!(
894-
"Attempting to rescan bdev {:?} part of lvs {:?}, uri {:?}",
895-
self.base_bdev().name(),
896-
self.name(),
897-
self.base_bdev().bdev_uri_str().unwrap_or_default()
898-
);
899899

900-
let errno = unsafe { bdev_aio_rescan(cname.as_ptr() as *mut std::os::raw::c_char) };
900+
let bdev = disk_bdev.name().into_cstring();
901+
info!("Attempting to rescan bdev: {uri_str} part of lvs {lvs_name}");
901902

902-
if errno != 0 {
903-
return Err(LvsError::BdevRescanFailed {
904-
source: BsError::from_i32(errno),
905-
name: self.base_bdev().name().to_string(),
906-
});
907-
}
903+
// Performs a rescan only for uring or aio devices, this is a no-op for other device types.
904+
let errno = match url.scheme() {
905+
"uring" => unsafe { bdev_uring_rescan(bdev.as_ptr().cast()) },
906+
"aio" => unsafe { bdev_aio_rescan(bdev.as_ptr().cast()) },
907+
_ => 0,
908+
};
909+
910+
if errno != 0 {
911+
return Err(LvsError::BdevRescanFailed {
912+
source: BsError::from_i32(errno),
913+
name: self.base_bdev().name().to_string(),
914+
});
915+
}
916+
917+
if self.encrypted() && !self.crypto_vbdev_resized().await {
918+
error!(
919+
"crypto bdev {} has not resized",
920+
self.base_bdev().name().to_string()
921+
);
922+
return Err(LvsError::CryptoBdevNotResized {
923+
name: self.base_bdev().name().to_string(),
924+
});
908925
}
909926

910927
let capacity_before_grow = self.capacity();
@@ -925,7 +942,7 @@ impl Lvs {
925942
.expect("callback gone while growing lvs")
926943
.to_result(|e| LvsError::Grow {
927944
source: BsError::from_i32(e),
928-
name: self.name().to_string(),
945+
name: lvs_name.to_string(),
929946
})?;
930947

931948
if self.capacity() == capacity_before_grow {
@@ -939,6 +956,31 @@ impl Lvs {
939956
Ok(())
940957
}
941958

959+
/// When the underlying AIO bdev is resized, crypto bdev receives SPDK_BDEV_EVENT_RESIZE
960+
/// event. The crypto bdev then adjusts its block count accordingly. To ensure that this resize
961+
/// operation completes before proceeding, we wait briefly for the crypto bdev to update.
962+
/// This delay gives the crypto bdev time to process the resize event asynchronously.
963+
async fn crypto_vbdev_resized(&self) -> bool {
964+
for _i in 1..=30 {
965+
let base_bdev = self.base_bdev();
966+
let disk_bdev = base_bdev
967+
.crypto_base_bdev()
968+
.map(Bdev::new)
969+
.unwrap_or_else(|| self.base_bdev());
970+
let disk_bdev_size = disk_bdev.num_blocks() * disk_bdev.block_len() as u64;
971+
let crypto_bdev_size = base_bdev.num_blocks() * base_bdev.block_len() as u64;
972+
if crypto_bdev_size == disk_bdev_size {
973+
return true;
974+
} else {
975+
let rx = mayastor_sleep(std::time::Duration::from_millis(100));
976+
if rx.await.is_err() {
977+
error!("failed to wait for mayastor_sleep");
978+
}
979+
}
980+
}
981+
false
982+
}
983+
942984
/// return an iterator for enumerating all snapshots that reside on the pool
943985
pub fn snapshots(&self) -> Option<impl Iterator<Item = LvolSnapshotDescriptor>> {
944986
if let Some(bdev) = UntypedBdev::bdev_first() {

0 commit comments

Comments
 (0)