diff --git a/src/service.rs b/src/service.rs index 5ec1fcf..e6eac1d 100644 --- a/src/service.rs +++ b/src/service.rs @@ -114,19 +114,57 @@ async fn get_pool_free_total_bytes( .into_tonic_result()? .into_tonic_result()? .into_inner(); - // TODO: do we need to add on TotalPhysicalSize - AllocatedSize? - let total_data: u128 = metadata + + let total_data_allocated: u128 = metadata .flex_devs .thin_data_dev .iter() .map(|region| Bytes::from(region.length).0) .sum(); + // Stratis won't allocate any more than 50GiB from a pool at first, so we + // need to combine the data device size with the amount of space that hasn't + // been allocated at all. Additionally, data sizes are always a multiple of + // the data block size, so round this down to match. + const BYTES_PER_DATA_BLOCK: u128 = 2 * 1024 * 512; + let total_unallocated = (total.0 + - metadata + .backstore + .data_tier + .blockdev + .allocs + .iter() + .flatten() + .map(|a| Bytes::from(a.length).0) + .sum::() + - metadata + .backstore + .data_tier + .blockdev + .devs + .iter() + .flat_map(|d| &d.integrity_meta_allocs) + .map(|r| Bytes::from(r.length).0) + .sum::() + // 8Ki sectors (4MiB) metadata at the very front. + - (8 * 1024 * 512)) + / BYTES_PER_DATA_BLOCK + * BYTES_PER_DATA_BLOCK; + + let total_data = total_data_allocated + total_unallocated; + let spare = u128::from(device_class.spare_gb) * u128::from(BYTES_PER_GIB); let free = total_data.saturating_sub(reserved).saturating_sub(spare); - debug!(reserved, spare, free, total_data, total = total.0); + debug!( + reserved, + spare, + free, + total_data_allocated, + total_unallocated, + total = total.0, + ); Ok((Bytes(free), total)) } diff --git a/src/stratis/dbus.rs b/src/stratis/dbus.rs index 2dabb02..86746da 100644 --- a/src/stratis/dbus.rs +++ b/src/stratis/dbus.rs @@ -231,7 +231,7 @@ trait ManagerV0 { const MIN_VERSION: Version = Version { major: 3, - minor: 7, + minor: 8, patch: 0, }; @@ -283,7 +283,7 @@ impl PoolMetadataJson { #[proxy( default_service = "org.storage.stratis3", - interface = "org.storage.stratis3.pool.r7" + interface = "org.storage.stratis3.pool.r8" )] pub trait Pool { fn create_filesystems( @@ -310,7 +310,7 @@ pub trait Pool { #[proxy( default_service = "org.storage.stratis3", - interface = "org.storage.stratis3.filesystem.r7" + interface = "org.storage.stratis3.filesystem.r8" )] pub trait Filesystem { #[zbus(property)] diff --git a/src/stratis/metadata.rs b/src/stratis/metadata.rs index 0809c79..2ac9dc7 100644 --- a/src/stratis/metadata.rs +++ b/src/stratis/metadata.rs @@ -7,7 +7,7 @@ pub struct Sectors(pub u64); #[derive(Debug, Clone)] #[allow(dead_code)] pub struct DeviceRegion { - pub start_offs: Sectors, + pub start: Sectors, pub length: Sectors, } @@ -16,11 +16,45 @@ impl<'de> Deserialize<'de> for DeviceRegion { where D: de::Deserializer<'de>, { - let (start_offs, length) = <(Sectors, Sectors)>::deserialize(deserializer)?; - Ok(DeviceRegion { start_offs, length }) + let (start, length) = <(Sectors, Sectors)>::deserialize(deserializer)?; + Ok(DeviceRegion { start, length }) } } +#[derive(Debug, Deserialize, Clone)] +#[allow(dead_code)] +pub struct Alloc { + pub parent: String, + pub start: Sectors, + pub length: Sectors, +} + +#[derive(Debug, Deserialize, Clone)] +#[allow(dead_code)] +pub struct Dev { + pub uuid: String, + pub integrity_meta_allocs: Vec, +} + +#[derive(Debug, Deserialize, Clone)] +#[allow(dead_code)] +pub struct Blockdev { + pub allocs: Vec>, + pub devs: Vec, +} + +#[derive(Debug, Deserialize, Clone)] +#[allow(dead_code)] +pub struct DataTier { + pub blockdev: Blockdev, +} + +#[derive(Debug, Deserialize, Clone)] +#[allow(dead_code)] +pub struct Backstore { + pub data_tier: DataTier, +} + #[derive(Debug, Deserialize, Clone)] #[allow(dead_code)] pub struct FlexDevs { @@ -32,5 +66,10 @@ pub struct FlexDevs { #[derive(Debug, Deserialize, Clone)] pub struct PoolMetadata { + pub backstore: Backstore, pub flex_devs: FlexDevs, } + +impl PoolMetadata { + pub const VERSION: u64 = 2; +} diff --git a/src/stratis/object_cache.rs b/src/stratis/object_cache.rs index 48df1ca..5bce5ba 100644 --- a/src/stratis/object_cache.rs +++ b/src/stratis/object_cache.rs @@ -15,6 +15,8 @@ use tokio_util::sync::{CancellationToken, DropGuard}; use tracing::{debug, info, warn}; use zbus::{proxy::Defaults, zvariant}; +use crate::stratis::metadata::PoolMetadata; + use super::dbus::{FilesystemProxy, PoolProxy, check_stratisd_version}; #[derive(MultiIndexMap, Debug, Clone)] @@ -159,7 +161,16 @@ impl ObjectCache { use futures_util::StreamExt; info!(?props, "add pool"); + let name: String = get_prop(&path, props, "Name")?.try_into()?; + + let mver: u64 = get_prop(&path, props, "MetadataVersion")?.try_into()?; + if mver != PoolMetadata::VERSION { + return Err(zbus::Error::Failure(format!( + "unsupported metadata version: {path} ({name}): {mver}" + ))); + } + let proxy = PoolProxy::new(&self.conn, path.clone().into_owned().to_owned()) .await? .to_owned();