From ba65dd4b59985155daa550c6d62ad9a46895f4c0 Mon Sep 17 00:00:00 2001 From: John Baublitz Date: Tue, 21 Jan 2025 11:45:41 -0500 Subject: [PATCH] Increase token slot area for V2 pools --- src/bin/utils/predict_usage.rs | 3 +- src/engine/mod.rs | 1 + .../strat_engine/backstore/backstore/v2.rs | 11 ++-- .../strat_engine/backstore/blockdev/v1.rs | 4 +- src/engine/strat_engine/crypt/consts.rs | 3 +- src/engine/strat_engine/crypt/handle/v1.rs | 30 ++++++---- src/engine/strat_engine/crypt/handle/v2.rs | 59 ++++++++----------- src/engine/strat_engine/crypt/mod.rs | 4 +- src/engine/strat_engine/crypt/shared.rs | 17 +++--- src/engine/strat_engine/engine.rs | 4 +- src/engine/strat_engine/mod.rs | 1 + src/engine/strat_engine/pool/inspection.rs | 10 ++-- 12 files changed, 81 insertions(+), 66 deletions(-) diff --git a/src/bin/utils/predict_usage.rs b/src/bin/utils/predict_usage.rs index 268452757b..62b0aad0f2 100644 --- a/src/bin/utils/predict_usage.rs +++ b/src/bin/utils/predict_usage.rs @@ -15,6 +15,7 @@ use devicemapper::{Bytes, Sectors}; use stratisd::engine::{ crypt_metadata_size, integrity_meta_space, ThinPoolSizeParams, ValidatedIntegritySpec, BDA, + DEFAULT_CRYPT_METADATA_SIZE_V2, }; // 2^FS_SIZE_START_POWER is the logical size of the smallest Stratis @@ -195,7 +196,7 @@ fn predict_pool_metadata_usage( }) .collect::, _>>()?; - let crypt_metadata_size = crypt_metadata_size(); + let crypt_metadata_size = crypt_metadata_size(DEFAULT_CRYPT_METADATA_SIZE_V2); let crypt_metadata_size_sectors = crypt_metadata_size.sectors(); // verify that crypt metadata size is divisible by sector size assert_eq!(crypt_metadata_size_sectors.bytes(), crypt_metadata_size); diff --git a/src/engine/mod.rs b/src/engine/mod.rs index df0a86c2fc..a2d1cc7dd9 100644 --- a/src/engine/mod.rs +++ b/src/engine/mod.rs @@ -16,6 +16,7 @@ pub use self::{ crypt_metadata_size, get_dm, get_dm_init, integrity_meta_space, register_clevis_token, set_up_crypt_logging, unshare_mount_namespace, StaticHeader, StaticHeaderResult, StratEngine, StratKeyActions, ThinPoolSizeParams, BDA, CLEVIS_TANG_TRUST_URL, + DEFAULT_CRYPT_METADATA_SIZE_V2, }, structures::{AllLockReadGuard, ExclusiveGuard, SharedGuard, Table}, types::{ diff --git a/src/engine/strat_engine/backstore/backstore/v2.rs b/src/engine/strat_engine/backstore/backstore/v2.rs index ed10235457..81a05e4808 100644 --- a/src/engine/strat_engine/backstore/backstore/v2.rs +++ b/src/engine/strat_engine/backstore/backstore/v2.rs @@ -23,7 +23,7 @@ use crate::{ blockdevmgr::BlockDevMgr, cache_tier::CacheTier, data_tier::DataTier, devices::UnownedDevices, shared::BlockSizeSummary, }, - crypt::{crypt_metadata_size, handle::v2::CryptHandle}, + crypt::{crypt_metadata_size, handle::v2::CryptHandle, DEFAULT_CRYPT_METADATA_SIZE_V2}, dm::{get_dm, list_of_backstore_devices, remove_optional_devices, DEVICEMAPPER_PATH}, metadata::{MDADataSize, BDA}, names::{format_backstore_ids, CacheRole}, @@ -455,7 +455,7 @@ impl Backstore { crypt_meta_allocs: Vec::new(), }; - let size = crypt_metadata_size().sectors(); + let size = crypt_metadata_size(DEFAULT_CRYPT_METADATA_SIZE_V2).sectors(); if !backstore.meta_alloc_cache(&[size])? { return Err(StratisError::Msg(format!( "Failed to satisfy request in backstore for {size}" @@ -1202,7 +1202,7 @@ mod tests { assert_eq!( backstore.data_tier.allocated(), match (&backstore.origin, &backstore.cache) { - (None, None) => crypt_metadata_size().sectors(), + (None, None) => crypt_metadata_size(DEFAULT_CRYPT_METADATA_SIZE_V2).sectors(), (&None, Some(cache)) => cache.size(), (Some(linear), &None) => linear.size(), _ => panic!("impossible; see first assertion"), @@ -1500,7 +1500,10 @@ mod tests { // Allocate space from the backstore so that the cap device is made. backstore - .alloc(pool_uuid, &[2u64 * crypt_metadata_size().sectors()]) + .alloc( + pool_uuid, + &[2u64 * crypt_metadata_size(DEFAULT_CRYPT_METADATA_SIZE_V2).sectors()], + ) .unwrap() .unwrap(); diff --git a/src/engine/strat_engine/backstore/blockdev/v1.rs b/src/engine/strat_engine/backstore/blockdev/v1.rs index dd628fca0f..c521497030 100644 --- a/src/engine/strat_engine/backstore/blockdev/v1.rs +++ b/src/engine/strat_engine/backstore/blockdev/v1.rs @@ -26,7 +26,7 @@ use crate::{ devices::BlockSizes, range_alloc::{PerDevSegments, RangeAllocator}, }, - crypt::handle::v1::CryptHandle, + crypt::{handle::v1::CryptHandle, DEFAULT_CRYPT_METADATA_SIZE_V1}, device::blkdev_size, metadata::{ disown_device, static_header, BlockdevSize, MDADataSize, MetadataLocation, @@ -302,7 +302,7 @@ impl StratBlockDev { pub fn scan_blkdev_size(physical_path: &Path, is_encrypted: bool) -> StratisResult { Ok(blkdev_size(&File::open(physical_path)?)?.sectors() - if is_encrypted { - crypt_metadata_size().sectors() + crypt_metadata_size(DEFAULT_CRYPT_METADATA_SIZE_V1).sectors() } else { Sectors(0) }) diff --git a/src/engine/strat_engine/crypt/consts.rs b/src/engine/strat_engine/crypt/consts.rs index d4f953fa1e..ff3287366a 100644 --- a/src/engine/strat_engine/crypt/consts.rs +++ b/src/engine/strat_engine/crypt/consts.rs @@ -32,7 +32,8 @@ pub const LUKS2_SECTOR_SIZE: Bytes = Bytes(4096); /// tang server does not need to be verified. pub const CLEVIS_TANG_TRUST_URL: &str = "stratis:tang:trust_url"; -pub const DEFAULT_CRYPT_METADATA_SIZE: Bytes = Bytes(16 * IEC::Ki as u128); +pub const DEFAULT_CRYPT_METADATA_SIZE_V1: Bytes = Bytes(16 * IEC::Ki as u128); +pub const DEFAULT_CRYPT_METADATA_SIZE_V2: Bytes = Bytes(64 * IEC::Ki as u128); pub const DEFAULT_CRYPT_KEYSLOTS_SIZE: Bytes = Bytes(16352 * IEC::Ki as u128); pub const CLEVIS_TOKEN_NAME: &str = "clevis\0"; diff --git a/src/engine/strat_engine/crypt/handle/v1.rs b/src/engine/strat_engine/crypt/handle/v1.rs index 7e2625fd21..05662b5bfe 100644 --- a/src/engine/strat_engine/crypt/handle/v1.rs +++ b/src/engine/strat_engine/crypt/handle/v1.rs @@ -34,11 +34,11 @@ use crate::{ cmd::{clevis_decrypt, clevis_luks_bind, clevis_luks_regen, clevis_luks_unbind}, crypt::{ consts::{ - CLEVIS_LUKS_TOKEN_ID, DEFAULT_CRYPT_KEYSLOTS_SIZE, DEFAULT_CRYPT_METADATA_SIZE, - LUKS2_TOKEN_ID, STRATIS_MEK_SIZE, STRATIS_TOKEN_DEVNAME_KEY, - STRATIS_TOKEN_DEV_UUID_KEY, STRATIS_TOKEN_ID, STRATIS_TOKEN_POOLNAME_KEY, - STRATIS_TOKEN_POOL_UUID_KEY, STRATIS_TOKEN_TYPE, TOKEN_KEYSLOTS_KEY, - TOKEN_TYPE_KEY, + CLEVIS_LUKS_TOKEN_ID, DEFAULT_CRYPT_KEYSLOTS_SIZE, + DEFAULT_CRYPT_METADATA_SIZE_V1, LUKS2_TOKEN_ID, STRATIS_MEK_SIZE, + STRATIS_TOKEN_DEVNAME_KEY, STRATIS_TOKEN_DEV_UUID_KEY, STRATIS_TOKEN_ID, + STRATIS_TOKEN_POOLNAME_KEY, STRATIS_TOKEN_POOL_UUID_KEY, STRATIS_TOKEN_TYPE, + TOKEN_KEYSLOTS_KEY, TOKEN_TYPE_KEY, }, shared::{ acquire_crypt_device, activate, activate_by_token, add_keyring_keyslot, @@ -573,7 +573,7 @@ impl CryptHandle { physical_path.display() ); device.settings_handle().set_metadata_size( - MetadataSize::try_from(convert_int!(*DEFAULT_CRYPT_METADATA_SIZE, u128, u64)?)?, + MetadataSize::try_from(convert_int!(*DEFAULT_CRYPT_METADATA_SIZE_V1, u128, u64)?)?, KeyslotsSize::try_from(convert_int!(*DEFAULT_CRYPT_KEYSLOTS_SIZE, u128, u64)?)?, )?; Self::initialize_with_err(&mut device, physical_path, pool_uuid, dev_uuid, &pool_name, encryption_info, luks2_params.as_ref()) @@ -663,7 +663,11 @@ impl CryptHandle { .context_handle() .load::<()>(Some(EncryptionFormat::Luks2), None) { - return Err(wipe_fallback(physical_path, StratisError::from(e))); + return Err(wipe_fallback( + physical_path, + DEFAULT_CRYPT_METADATA_SIZE_V1, + StratisError::from(e), + )); } device.keyslot_handle().destroy(keyslot)?; @@ -695,7 +699,11 @@ impl CryptHandle { .context_handle() .load::<()>(Some(EncryptionFormat::Luks2), None) { - return Err(wipe_fallback(physical_path, StratisError::from(e))); + return Err(wipe_fallback( + physical_path, + DEFAULT_CRYPT_METADATA_SIZE_V1, + StratisError::from(e), + )); } Ok(()) @@ -1143,8 +1151,8 @@ mod tests { strat_engine::{ crypt::{ consts::{ - CLEVIS_LUKS_TOKEN_ID, DEFAULT_CRYPT_KEYSLOTS_SIZE, DEFAULT_CRYPT_METADATA_SIZE, - LUKS2_TOKEN_ID, STRATIS_MEK_SIZE, + CLEVIS_LUKS_TOKEN_ID, DEFAULT_CRYPT_KEYSLOTS_SIZE, + DEFAULT_CRYPT_METADATA_SIZE_V1, LUKS2_TOKEN_ID, STRATIS_MEK_SIZE, }, shared::acquire_crypt_device, }, @@ -1421,7 +1429,7 @@ mod tests { ) .unwrap(); let (metadata, keyslot) = context.settings_handle().get_metadata_size().unwrap(); - assert_eq!(DEFAULT_CRYPT_METADATA_SIZE, Bytes::from(*metadata)); + assert_eq!(DEFAULT_CRYPT_METADATA_SIZE_V1, Bytes::from(*metadata)); assert_eq!(DEFAULT_CRYPT_KEYSLOTS_SIZE, Bytes::from(*keyslot)); } diff --git a/src/engine/strat_engine/crypt/handle/v2.rs b/src/engine/strat_engine/crypt/handle/v2.rs index d514de406e..9a43b7bcf5 100644 --- a/src/engine/strat_engine/crypt/handle/v2.rs +++ b/src/engine/strat_engine/crypt/handle/v2.rs @@ -33,8 +33,8 @@ use crate::{ cmd::{clevis_decrypt, clevis_luks_bind, clevis_luks_regen, clevis_luks_unbind}, crypt::{ consts::{ - CLEVIS_LUKS_TOKEN_ID, DEFAULT_CRYPT_KEYSLOTS_SIZE, DEFAULT_CRYPT_METADATA_SIZE, - LUKS2_TOKEN_ID, STRATIS_MEK_SIZE, + CLEVIS_LUKS_TOKEN_ID, DEFAULT_CRYPT_KEYSLOTS_SIZE, + DEFAULT_CRYPT_METADATA_SIZE_V2, LUKS2_TOKEN_ID, STRATIS_MEK_SIZE, }, shared::{ acquire_crypt_device, activate, activate_by_token, add_keyring_keyslot, @@ -276,7 +276,7 @@ impl CryptHandle { physical_path.display() ); device.settings_handle().set_metadata_size( - MetadataSize::try_from(convert_int!(*DEFAULT_CRYPT_METADATA_SIZE, u128, u64)?)?, + MetadataSize::try_from(convert_int!(*DEFAULT_CRYPT_METADATA_SIZE_V2, u128, u64)?)?, KeyslotsSize::try_from(convert_int!(*DEFAULT_CRYPT_KEYSLOTS_SIZE, u128, u64)?)?, )?; Self::initialize_with_err(&mut device, physical_path, pool_uuid, encryption_info, luks2_params.as_ref()) @@ -366,7 +366,11 @@ impl CryptHandle { .context_handle() .load::<()>(Some(EncryptionFormat::Luks2), None) { - return Err(wipe_fallback(physical_path, StratisError::from(e))); + return Err(wipe_fallback( + physical_path, + DEFAULT_CRYPT_METADATA_SIZE_V2, + StratisError::from(e), + )); } device.keyslot_handle().destroy(keyslot)?; @@ -398,7 +402,11 @@ impl CryptHandle { .context_handle() .load::<()>(Some(EncryptionFormat::Luks2), None) { - return Err(wipe_fallback(physical_path, StratisError::from(e))); + return Err(wipe_fallback( + physical_path, + DEFAULT_CRYPT_METADATA_SIZE_V2, + StratisError::from(e), + )); } Ok(()) @@ -414,6 +422,12 @@ impl CryptHandle { let mut luks2_params_ref: Option> = luks2_params.map(|lp| lp.try_into()).transpose()?; + let (_, keyslots) = device.settings_handle().get_metadata_size()?; + device.settings_handle().set_metadata_size( + MetadataSize::try_from(convert_int!(*DEFAULT_CRYPT_METADATA_SIZE_V2, u128, u64)?)?, + keyslots, + )?; + log_on_failure!( device.context_handle().format::>( EncryptionFormat::Luks2, @@ -780,17 +794,14 @@ mod tests { }; use devicemapper::{Bytes, Sectors, IEC}; - use libcryptsetup_rs::{ - consts::vals::{CryptStatusInfo, EncryptionFormat}, - CryptInit, Either, - }; + use libcryptsetup_rs::consts::vals::CryptStatusInfo; use crate::engine::{ strat_engine::{ crypt::{ consts::{ - CLEVIS_LUKS_TOKEN_ID, DEFAULT_CRYPT_KEYSLOTS_SIZE, DEFAULT_CRYPT_METADATA_SIZE, - LUKS2_TOKEN_ID, STRATIS_MEK_SIZE, + CLEVIS_LUKS_TOKEN_ID, DEFAULT_CRYPT_KEYSLOTS_SIZE, + DEFAULT_CRYPT_METADATA_SIZE_V2, LUKS2_TOKEN_ID, }, shared::acquire_crypt_device, }, @@ -977,28 +988,6 @@ mod tests { ); } - #[test] - fn loop_test_crypt_metadata_defaults() { - fn test_defaults(paths: &[&Path]) { - let mut context = CryptInit::init(paths[0]).unwrap(); - context - .context_handle() - .format::<()>( - EncryptionFormat::Luks2, - ("aes", "xts-plain64"), - None, - Either::Right(STRATIS_MEK_SIZE), - None, - ) - .unwrap(); - let (metadata, keyslot) = context.settings_handle().get_metadata_size().unwrap(); - assert_eq!(DEFAULT_CRYPT_METADATA_SIZE, Bytes::from(*metadata)); - assert_eq!(DEFAULT_CRYPT_KEYSLOTS_SIZE, Bytes::from(*keyslot)); - } - - loopbacked::test_with_spec(&loopbacked::DeviceLimits::Exactly(1, None), test_defaults); - } - #[test] // Test passing an unusual, larger sector size for cryptsetup. 4096 should // be no smaller than the physical sector size of the loop device, and @@ -1114,6 +1103,10 @@ mod tests { .unwrap(); let mut device = acquire_crypt_device(handle.luks2_device_path()).unwrap(); + let (metadata, keyslot) = device.settings_handle().get_metadata_size().unwrap(); + assert_eq!(DEFAULT_CRYPT_METADATA_SIZE_V2, Bytes::from(*metadata)); + assert_eq!(DEFAULT_CRYPT_KEYSLOTS_SIZE, Bytes::from(*keyslot)); + assert!(device.token_handle().json_get(CLEVIS_LUKS_TOKEN_ID).is_ok()); assert!(device.token_handle().json_get(LUKS2_TOKEN_ID).is_err()); } diff --git a/src/engine/strat_engine/crypt/mod.rs b/src/engine/strat_engine/crypt/mod.rs index cf08bb5752..a5d70bc26c 100644 --- a/src/engine/strat_engine/crypt/mod.rs +++ b/src/engine/strat_engine/crypt/mod.rs @@ -10,7 +10,9 @@ pub mod handle; mod shared; pub use self::{ - consts::CLEVIS_TANG_TRUST_URL, + consts::{ + CLEVIS_TANG_TRUST_URL, DEFAULT_CRYPT_METADATA_SIZE_V1, DEFAULT_CRYPT_METADATA_SIZE_V2, + }, shared::{ back_up_luks_header, crypt_metadata_size, register_clevis_token, restore_luks_header, set_up_crypt_logging, diff --git a/src/engine/strat_engine/crypt/shared.rs b/src/engine/strat_engine/crypt/shared.rs index ef65070f2f..405d265893 100644 --- a/src/engine/strat_engine/crypt/shared.rs +++ b/src/engine/strat_engine/crypt/shared.rs @@ -35,9 +35,8 @@ use crate::{ cmd::clevis_decrypt, crypt::consts::{ CLEVIS_LUKS_TOKEN_ID, CLEVIS_RECURSION_LIMIT, CLEVIS_TANG_TRUST_URL, - CLEVIS_TOKEN_NAME, DEFAULT_CRYPT_KEYSLOTS_SIZE, DEFAULT_CRYPT_METADATA_SIZE, - LUKS2_SECTOR_SIZE, LUKS2_TOKEN_ID, LUKS2_TOKEN_TYPE, TOKEN_KEYSLOTS_KEY, - TOKEN_TYPE_KEY, + CLEVIS_TOKEN_NAME, DEFAULT_CRYPT_KEYSLOTS_SIZE, LUKS2_SECTOR_SIZE, LUKS2_TOKEN_ID, + LUKS2_TOKEN_TYPE, TOKEN_KEYSLOTS_KEY, TOKEN_TYPE_KEY, }, dm::get_dm, keys, @@ -623,7 +622,11 @@ fn ceiling_sector_size_alignment(bytes: Bytes) -> Bytes { /// Fallback method for wiping a crypt device where a handle to the encrypted device /// cannot be acquired. -pub fn wipe_fallback(path: &Path, causal_error: StratisError) -> StratisError { +pub fn wipe_fallback( + path: &Path, + metadata_size: Bytes, + causal_error: StratisError, +) -> StratisError { let mut file = match OpenOptions::new().write(true).open(path) { Ok(f) => f, Err(e) => { @@ -633,7 +636,7 @@ pub fn wipe_fallback(path: &Path, causal_error: StratisError) -> StratisError { } } }; - let size = match convert_int!(*crypt_metadata_size(), u128, usize) { + let size = match convert_int!(*metadata_size, u128, usize) { Ok(s) => s, Err(e) => { return StratisError::NoActionRollbackError { @@ -771,8 +774,8 @@ pub fn key_desc_from_metadata(device: &mut CryptDevice) -> Option { } // Bytes occupied by crypt metadata -pub fn crypt_metadata_size() -> Bytes { - 2u64 * DEFAULT_CRYPT_METADATA_SIZE + ceiling_sector_size_alignment(DEFAULT_CRYPT_KEYSLOTS_SIZE) +pub fn crypt_metadata_size(metadata_size: Bytes) -> Bytes { + 2u64 * metadata_size + ceiling_sector_size_alignment(DEFAULT_CRYPT_KEYSLOTS_SIZE) } /// Back up the LUKS2 header to a temporary file. diff --git a/src/engine/strat_engine/engine.rs b/src/engine/strat_engine/engine.rs index 1de9e4184f..43d3925641 100644 --- a/src/engine/strat_engine/engine.rs +++ b/src/engine/strat_engine/engine.rs @@ -900,7 +900,7 @@ mod test { engine::Pool, strat_engine::{ cmd, - crypt::crypt_metadata_size, + crypt::{crypt_metadata_size, DEFAULT_CRYPT_METADATA_SIZE_V1}, ns::unshare_mount_namespace, tests::{crypt, loopbacked, real, FailDevice}, }, @@ -1107,7 +1107,7 @@ mod test { } fail_device - .start_failing(*crypt_metadata_size().sectors()) + .start_failing(*crypt_metadata_size(DEFAULT_CRYPT_METADATA_SIZE_V1).sectors()) .unwrap(); assert_matches!(catch_unwind(move || operation(&mut pool)), Err(_)); diff --git a/src/engine/strat_engine/mod.rs b/src/engine/strat_engine/mod.rs index 37fd872abf..a983a5620e 100644 --- a/src/engine/strat_engine/mod.rs +++ b/src/engine/strat_engine/mod.rs @@ -32,6 +32,7 @@ pub use self::{ backstore::integrity_meta_space, crypt::{ crypt_metadata_size, register_clevis_token, set_up_crypt_logging, CLEVIS_TANG_TRUST_URL, + DEFAULT_CRYPT_METADATA_SIZE_V2, }, dm::{get_dm, get_dm_init}, engine::StratEngine, diff --git a/src/engine/strat_engine/pool/inspection.rs b/src/engine/strat_engine/pool/inspection.rs index 0cbe203d34..6119e813a3 100644 --- a/src/engine/strat_engine/pool/inspection.rs +++ b/src/engine/strat_engine/pool/inspection.rs @@ -11,14 +11,16 @@ use devicemapper::Sectors; use crate::{ engine::{ - strat_engine::serde_structs::PoolSave, + strat_engine::{ + crypt::{crypt_metadata_size, DEFAULT_CRYPT_METADATA_SIZE_V2}, + serde_structs::PoolSave, + }, types::{DevUuid, IntegrityTagSpec, ValidatedIntegritySpec}, }, stratis::{StratisError, StratisResult}, }; const SIZE_OF_CRYPT_METADATA_SECTORS: Sectors = Sectors(32768); -const SIZE_OF_STRATIS_METADATA_SECTORS: Sectors = Sectors(8192); // Encodes the use for each extent. trait Use: Copy + Eq + PartialEq + fmt::Display {} @@ -233,7 +235,7 @@ impl DataDevice { Sectors(0), ( DataDeviceUse::StratisMetadata, - SIZE_OF_STRATIS_METADATA_SECTORS, + crypt_metadata_size(DEFAULT_CRYPT_METADATA_SIZE_V2).sectors(), ), ); DataDevice { extents } @@ -346,7 +348,7 @@ impl CacheDevice { Sectors(0), ( CacheDeviceUse::StratisMetadata, - SIZE_OF_STRATIS_METADATA_SECTORS, + crypt_metadata_size(DEFAULT_CRYPT_METADATA_SIZE_V2).sectors(), ), ); CacheDevice { extents }