From 2adb0d7f3596302b4bbddd21f12d7e672bdfe57e Mon Sep 17 00:00:00 2001 From: John Baublitz Date: Thu, 9 Mar 2023 17:32:15 -0500 Subject: [PATCH] Placeholder LinearDev to be converted to CacheDev This commit adds a linear device in between the thin pool and linear device containing all of the data devices. This will later be used when the cryptsetup layer is moved on top of the cap device. This way, the backing device for the crypt device will never change. Changing the backing device for the dm-crypt device outside of cryptsetup could result in future problems. --- Cargo.lock | 43 ++++------- Cargo.toml | 3 +- .../strat_engine/backstore/backstore.rs | 72 ++++++++++++++++--- src/engine/types/keys.rs | 3 + 4 files changed, 81 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 04eb7bcacf4..7d0fab0e6b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -333,26 +333,28 @@ dependencies = [ [[package]] name = "devicemapper" -version = "0.32.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1da7c273a50833e1fbbff5b71b06fd1f3f00356b0fa1d392a21ee8b4aabb2a1e" +version = "0.33.1" +source = "git+https://github.com/jbaublitz/devicemapper-rs?branch=stratisd-metadata-rework#b6f6a703701390548f553b020b95256fcf1128c6" dependencies = [ "bitflags", "devicemapper-sys", + "env_logger", "lazy_static", - "nix 0.24.3", + "log", + "nix 0.26.2", + "rand", + "retry", "semver", "serde", ] [[package]] name = "devicemapper-sys" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d2aad5bae6bc8a217f8c398c5737122966cbd35f19dd223433606225ec48285" +version = "0.1.5" +source = "git+https://github.com/jbaublitz/devicemapper-rs?branch=stratisd-metadata-rework#b6f6a703701390548f553b020b95256fcf1128c6" dependencies = [ - "bindgen 0.59.2", - "nix 0.24.3", + "bindgen 0.63.0", + "nix 0.26.2", ] [[package]] @@ -799,15 +801,6 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg", -] - [[package]] name = "memoffset" version = "0.7.1" @@ -848,18 +841,6 @@ dependencies = [ "void", ] -[[package]] -name = "nix" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" -dependencies = [ - "bitflags", - "cfg-if 1.0.0", - "libc", - "memoffset 0.6.5", -] - [[package]] name = "nix" version = "0.26.2" @@ -869,7 +850,7 @@ dependencies = [ "bitflags", "cfg-if 1.0.0", "libc", - "memoffset 0.7.1", + "memoffset", "pin-utils", "static_assertions", ] diff --git a/Cargo.toml b/Cargo.toml index 40fc13263f3..e45392c2272 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -84,7 +84,8 @@ version = "2.3.0" optional = true [dependencies.devicemapper] -version = "0.32.3" +git = "https://github.com/jbaublitz/devicemapper-rs" +branch = "stratisd-metadata-rework" optional = true [dependencies.dbus] diff --git a/src/engine/strat_engine/backstore/backstore.rs b/src/engine/strat_engine/backstore/backstore.rs index 5823b25ba93..049e402ee92 100644 --- a/src/engine/strat_engine/backstore/backstore.rs +++ b/src/engine/strat_engine/backstore/backstore.rs @@ -10,7 +10,10 @@ use chrono::{DateTime, Utc}; use serde_json::Value; use tempfile::TempDir; -use devicemapper::{CacheDev, Device, DmDevice, LinearDev, Sectors}; +use devicemapper::{ + CacheDev, CacheDevTargetTable, CacheTargetParams, DevId, Device, DmDevice, DmFlags, DmOptions, + LinearDev, LinearDevTargetParams, LinearTargetParams, Sectors, TargetLine, TargetTable, +}; use crate::{ engine::{ @@ -52,6 +55,7 @@ fn make_cache( pool_uuid: PoolUuid, cache_tier: &CacheTier, origin: LinearDev, + cap: Option, new: bool, ) -> StratisResult { let (dm_name, dm_uuid) = format_backstore_ids(pool_uuid, CacheRole::MetaSub); @@ -80,6 +84,32 @@ fn make_cache( )?; let (dm_name, dm_uuid) = format_backstore_ids(pool_uuid, CacheRole::Cache); + if cap.is_some() { + let dm = get_dm(); + dm.device_suspend( + &DevId::Name(&dm_name), + DmOptions::default().set_flags(DmFlags::DM_SUSPEND), + )?; + let table = CacheDevTargetTable::new( + Sectors(0), + origin.size(), + CacheTargetParams::new( + meta.device(), + cache.device(), + origin.device(), + CACHE_BLOCK_SIZE, + vec!["writethrough".into()], + "default".to_owned(), + Vec::new(), + ), + ); + dm.table_load( + &DevId::Name(&dm_name), + &table.to_raw_table(), + DmOptions::default(), + )?; + dm.device_suspend(&DevId::Name(&dm_name), DmOptions::default())?; + }; Ok(CacheDev::setup( get_dm(), &dm_name, @@ -91,6 +121,18 @@ fn make_cache( )?) } +/// Set up the linear device on top of the data tier that can later be converted to a +/// cache device and serves as a placeholder for the device beneath encryption. +fn make_cap_linear_dev(pool_uuid: PoolUuid, origin: &LinearDev) -> Result { + let (dm_name, dm_uuid) = format_backstore_ids(pool_uuid, CacheRole::Cache); + let target = vec![TargetLine::new( + Sectors(0), + origin.size(), + LinearDevTargetParams::Linear(LinearTargetParams::new(origin.device(), Sectors(0))), + )]; + LinearDev::setup(get_dm(), &dm_name, Some(&dm_uuid), target).map_err(StratisError::from) +} + /// This structure can allocate additional space to the upper layer, but it /// cannot accept returned space. When it is extended to be able to accept /// returned space the allocation algorithm will have to be revised. @@ -105,6 +147,8 @@ pub struct Backstore { data_tier: DataTier, /// A linear DM device. linear: Option, + /// A placeholder device to be converted to cache. + cap_linear: Option, /// Index for managing allocation of cap device next: Sectors, } @@ -162,7 +206,7 @@ impl Backstore { } }; - let (cache_tier, cache, origin) = if !cachedevs.is_empty() { + let (cap_linear, cache_tier, cache, origin) = if !cachedevs.is_empty() { let block_mgr = BlockDevMgr::new(cachedevs, Some(last_update_time)); match backstore_save.cache_tier { Some(ref cache_tier_save) => { @@ -174,7 +218,8 @@ impl Backstore { } }; - let cache_device = match make_cache(pool_uuid, &cache_tier, origin, false) { + let cache_device = match make_cache(pool_uuid, &cache_tier, origin, None, false) + { Ok(cd) => cd, Err(e) => { return Err(( @@ -188,7 +233,7 @@ impl Backstore { )); } }; - (Some(cache_tier), Some(cache_device), None) + (None, Some(cache_tier), Some(cache_device), None) } None => { let err_msg = "Cachedevs exist, but cache metadata does not exist"; @@ -204,7 +249,11 @@ impl Backstore { } } } else { - (None, None, Some(origin)) + let cap_linear = match make_cap_linear_dev(pool_uuid, &origin) { + Ok(cap) => cap, + Err(e) => return Err((e, data_tier.block_mgr.into_bdas())), + }; + (Some(cap_linear), None, None, Some(origin)) }; Ok(Backstore { @@ -212,6 +261,7 @@ impl Backstore { cache_tier, linear: origin, cache, + cap_linear, next: backstore_save.cap.allocs[0].1, }) } @@ -245,6 +295,7 @@ impl Backstore { cache_tier: None, linear: None, cache: None, + cap_linear: None, next: Sectors(0), }) } @@ -287,8 +338,11 @@ impl Backstore { let linear = self.linear .take() .expect("some space has already been allocated from the backstore => (cache_tier.is_none() <=> self.linear.is_some())"); + let cap = self.cap_linear + .take() + .expect("some space has already been allocated from the backstore => (cache_tier.is_none() <=> self.cap_linear.is_some())"); - let cache = make_cache(pool_uuid, &cache_tier, linear, true)?; + let cache = make_cache(pool_uuid, &cache_tier, linear, Some(cap), true)?; self.cache = Some(cache); @@ -369,7 +423,7 @@ impl Backstore { /// device if it does not already exist. Return an error if DM /// operations fail. Use all segments currently allocated in the data tier. fn extend_cap_device(&mut self, pool_uuid: PoolUuid) -> StratisResult<()> { - let create = match (self.cache.as_mut(), self.linear.as_mut()) { + let create = match (self.cache.as_mut(), self.cap_linear.as_mut()) { (None, None) => true, (Some(cache), None) => { let table = self.data_tier.segments.map_to_dm(); @@ -390,7 +444,9 @@ impl Backstore { let table = self.data_tier.segments.map_to_dm(); let (dm_name, dm_uuid) = format_backstore_ids(pool_uuid, CacheRole::OriginSub); let origin = LinearDev::setup(get_dm(), &dm_name, Some(&dm_uuid), table)?; + let cap = make_cap_linear_dev(pool_uuid, &origin)?; self.linear = Some(origin); + self.cap_linear = Some(cap); } Ok(()) @@ -613,7 +669,7 @@ impl Backstore { self.cache .as_ref() .map(|d| d.device()) - .or_else(|| self.linear.as_ref().map(|d| d.device())) + .or_else(|| self.cap_linear.as_ref().map(|d| d.device())) } /// Lookup an immutable blockdev by its Stratis UUID. diff --git a/src/engine/types/keys.rs b/src/engine/types/keys.rs index 5d02bcbce8f..e47a849e4b8 100644 --- a/src/engine/types/keys.rs +++ b/src/engine/types/keys.rs @@ -142,7 +142,10 @@ impl fmt::Display for EncryptionInfo { // serves no obvious purpose to stringify it and then hash it. // Necessary Hash Property: \forall x_1, x_2 in EncryptionInfo, // if x_1 == x_2, then hash(x_1) == hash(x_2) obviously holds. +#[allow(unknown_lints)] +#[allow(renamed_and_removed_lints)] #[allow(clippy::derive_hash_xor_eq)] +#[allow(clippy::derived_hash_with_manual_eq)] impl Hash for EncryptionInfo { fn hash(&self, state: &mut H) { self.key_description().hash(state);