Skip to content

Commit

Permalink
Record integrity parameters in metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
jbaublitz committed Nov 12, 2024
1 parent 677593e commit 59f77ae
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 36 deletions.
18 changes: 11 additions & 7 deletions src/engine/strat_engine/backstore/backstore/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ use either::Either;
use serde_json::Value;

use devicemapper::{
CacheDev, CacheDevTargetTable, CacheTargetParams, DevId, Device, DmDevice, DmFlags, DmOptions,
LinearDev, LinearDevTargetParams, LinearTargetParams, Sectors, TargetLine, TargetTable,
Bytes, CacheDev, CacheDevTargetTable, CacheTargetParams, DevId, Device, DmDevice, DmFlags,
DmOptions, LinearDev, LinearDevTargetParams, LinearTargetParams, Sectors, TargetLine,
TargetTable,
};

use crate::{
Expand Down Expand Up @@ -437,12 +438,15 @@ impl Backstore {
devices: UnownedDevices,
mda_data_size: MDADataSize,
encryption_info: Option<&EncryptionInfo>,
integrity_journal_size: Option<Sectors>,
integrity_tag_size: Option<Bytes>,
) -> StratisResult<Backstore> {
let data_tier = DataTier::<StratBlockDev>::new(BlockDevMgr::<StratBlockDev>::initialize(
pool_uuid,
devices,
mda_data_size,
)?);
let data_tier = DataTier::<StratBlockDev>::new(
BlockDevMgr::<StratBlockDev>::initialize(pool_uuid, devices, mda_data_size)?,
integrity_journal_size,
None,
integrity_tag_size,
);

let mut backstore = Backstore {
data_tier,
Expand Down
9 changes: 7 additions & 2 deletions src/engine/strat_engine/backstore/blockdev/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{fmt, path::Path};

use chrono::{DateTime, Utc};

use devicemapper::{Device, Sectors};
use devicemapper::{Bytes, Device, Sectors};

use crate::{
engine::{
Expand Down Expand Up @@ -104,7 +104,12 @@ pub trait InternalBlockDev {
/// an exclusive lock on the pool and therefore the thin pool cannot be
/// extended to use the larger or unencrypted block device size until the
/// transaction has been completed successfully.
fn grow(&mut self) -> StratisResult<bool>;
fn grow(
&mut self,
integrity_journal_size: Sectors,
integrity_block_size: Bytes,
integrity_tag_size: Bytes,
) -> StratisResult<bool>;

/// Load the pool-level metadata for the given block device.
fn load_state(&self) -> StratisResult<Option<(Vec<u8>, &DateTime<Utc>)>>;
Expand Down
4 changes: 2 additions & 2 deletions src/engine/strat_engine/backstore/blockdev/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use std::{
use chrono::{DateTime, Utc};
use serde_json::Value;

use devicemapper::{Device, Sectors};
use devicemapper::{Bytes, Device, Sectors};

use crate::{
engine::{
Expand Down Expand Up @@ -401,7 +401,7 @@ impl InternalBlockDev for StratBlockDev {
}
}

fn grow(&mut self) -> StratisResult<bool> {
fn grow(&mut self, _: Sectors, _: Bytes, _: Bytes) -> StratisResult<bool> {
/// Precondition: size > h.blkdev_size
fn needs_rollback(bd: &mut StratBlockDev, size: BlockdevSize) -> StratisResult<()> {
let mut f = OpenOptions::new()
Expand Down
38 changes: 26 additions & 12 deletions src/engine/strat_engine/backstore/blockdev/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use std::{
use chrono::{DateTime, Utc};
use serde_json::Value;

use devicemapper::{Bytes, Device, Sectors, IEC};
use devicemapper::{Bytes, Device, Sectors};

use crate::{
engine::{
Expand Down Expand Up @@ -43,14 +43,19 @@ use crate::{

/// Return the amount of space required for integrity for a device of the given size.
///
/// This is a slight overestimation for the sake of simplicity. Because it uses the whole disk
/// This default is a slight overestimation for the sake of simplicity. Because it uses the whole disk
/// size, once the integrity metadata size is calculated, the remaining data size is now smaller
/// than the metadata region could support for integrity.
/// The result is divisible by 8 sectors.
pub fn integrity_meta_space(total_space: Sectors) -> Sectors {
pub fn integrity_meta_space(
total_space: Sectors,
journal_size: Sectors,
block_size: Bytes,
tag_size: Bytes,
) -> Sectors {
Bytes(4096).sectors()
+ Bytes::from(64 * IEC::Mi).sectors()
+ Bytes::from((*total_space * 32u64 + 4095) & !4095).sectors()
+ journal_size
+ Bytes::from(((*total_space.bytes() / *block_size) * *tag_size + 4095) & !4095).sectors()
}

#[derive(Debug)]
Expand Down Expand Up @@ -269,7 +274,12 @@ impl InternalBlockDev for StratBlockDev {
}
}

fn grow(&mut self) -> StratisResult<bool> {
fn grow(
&mut self,
integrity_journal_size: Sectors,
integrity_block_size: Bytes,
integrity_tag_size: Bytes,
) -> StratisResult<bool> {
let size = BlockdevSize::new(Self::scan_blkdev_size(self.devnode())?);
let metadata_size = self.bda.dev_size();
match size.cmp(&metadata_size) {
Expand All @@ -296,12 +306,16 @@ impl InternalBlockDev for StratBlockDev {
self.bda.header = h;
self.used.increase_size(size.sectors());

let integrity_grow = integrity_meta_space(size.sectors())
- self
.integrity_meta_allocs
.iter()
.map(|(_, len)| *len)
.sum::<Sectors>();
let integrity_grow = integrity_meta_space(
size.sectors(),
integrity_journal_size,
integrity_block_size,
integrity_tag_size,
) - self
.integrity_meta_allocs
.iter()
.map(|(_, len)| *len)
.sum::<Sectors>();
self.alloc_int_meta_back(integrity_grow);

Ok(true)
Expand Down
14 changes: 12 additions & 2 deletions src/engine/strat_engine/backstore/blockdevmgr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,13 +467,23 @@ where
self.block_devs.iter().map(|bd| bd.metadata_size()).sum()
}

pub fn grow(&mut self, dev: DevUuid) -> StratisResult<bool> {
pub fn grow(
&mut self,
dev: DevUuid,
integrity_journal_size: Sectors,
integrity_block_size: Bytes,
integrity_tag_size: Bytes,
) -> StratisResult<bool> {
let bd = self
.block_devs
.iter_mut()
.find(|bd| bd.uuid() == dev)
.ok_or_else(|| StratisError::Msg(format!("Block device with UUID {dev} not found")))?;
bd.grow()
bd.grow(
integrity_journal_size,
integrity_block_size,
integrity_tag_size,
)
}

/// Tear down devicemapper devices for the block devices in this BlockDevMgr.
Expand Down
54 changes: 46 additions & 8 deletions src/engine/strat_engine/backstore/data_tier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#[cfg(test)]
use std::collections::HashSet;

use devicemapper::Sectors;
use devicemapper::{Bytes, Sectors, IEC};

use crate::{
engine::{
Expand All @@ -32,13 +32,23 @@ use crate::{
stratis::StratisResult,
};

const DEFAULT_INTEGRITY_JOURNAL_SIZE: Bytes = Bytes(128 * IEC::Mi as u128);
const DEFAULT_INTEGRITY_BLOCK_SIZE: Bytes = Bytes(4 * IEC::Ki as u128);
const DEFAULT_INTEGRITY_TAG_SIZE: Bytes = Bytes(64u128);

/// Handles the lowest level, base layer of this tier.
#[derive(Debug)]
pub struct DataTier<B> {
/// Manages the individual block devices
pub(super) block_mgr: BlockDevMgr<B>,
/// The list of segments granted by block_mgr and used by dm_device
pub(super) segments: AllocatedAbove,
/// Integrity journal size.
integrity_journal_size: Sectors,
/// Integrity tag size.
integrity_tag_size: Bytes,
/// Integrity block size.
integrity_block_size: Bytes,
}

impl DataTier<v1::StratBlockDev> {
Expand Down Expand Up @@ -105,16 +115,33 @@ impl DataTier<v2::StratBlockDev> {
/// Initially 0 segments are allocated.
///
/// WARNING: metadata changing event
pub fn new(mut block_mgr: BlockDevMgr<v2::StratBlockDev>) -> DataTier<v2::StratBlockDev> {
pub fn new(
mut block_mgr: BlockDevMgr<v2::StratBlockDev>,
integrity_journal_size: Option<Sectors>,
integrity_block_size: Option<Bytes>,
integrity_tag_size: Option<Bytes>,
) -> DataTier<v2::StratBlockDev> {
let integrity_journal_size =
integrity_journal_size.unwrap_or_else(|| DEFAULT_INTEGRITY_JOURNAL_SIZE.sectors());
let integrity_block_size = integrity_block_size.unwrap_or(DEFAULT_INTEGRITY_BLOCK_SIZE);
let integrity_tag_size = integrity_tag_size.unwrap_or(DEFAULT_INTEGRITY_TAG_SIZE);
for (_, bd) in block_mgr.blockdevs_mut() {
// NOTE: over-allocates integrity metadata slightly. Some of the
// total size of the device will not make use of the integrity
// metadata.
bd.alloc_int_meta_back(integrity_meta_space(bd.total_size().sectors()));
bd.alloc_int_meta_back(integrity_meta_space(
bd.total_size().sectors(),
integrity_journal_size,
integrity_block_size,
integrity_tag_size,
));
}
DataTier {
block_mgr,
segments: AllocatedAbove { inner: vec![] },
integrity_journal_size,
integrity_block_size,
integrity_tag_size,
}
}

Expand Down Expand Up @@ -142,10 +169,10 @@ impl DataTier<v2::StratBlockDev> {
assert_eq!(bds.len(), uuids.len());
for bd in bds {
bd.alloc_int_meta_back(integrity_meta_space(
// NOTE: Subtracting metadata size works here because the only metadata currently
// recorded in a newly created block device is the BDA. If this becomes untrue in
// the future, this code will no longer work.
bd.total_size().sectors() - bd.metadata_size(),
bd.total_size().sectors(),
self.integrity_journal_size,
self.integrity_block_size,
self.integrity_tag_size,
));
}
Ok(uuids)
Expand Down Expand Up @@ -207,6 +234,9 @@ where
Ok(DataTier {
block_mgr,
segments,
integrity_journal_size: data_tier_save.integrity_journal_size,
integrity_block_size: data_tier_save.integrity_block_size,
integrity_tag_size: data_tier_save.integrity_tag_size,
})
}

Expand Down Expand Up @@ -266,7 +296,12 @@ where
}

pub fn grow(&mut self, dev: DevUuid) -> StratisResult<bool> {
self.block_mgr.grow(dev)
self.block_mgr.grow(
dev,
self.integrity_journal_size,
self.integrity_block_size,
self.integrity_tag_size,
)
}

/// Return the partition of the block devs that are in use and those
Expand Down Expand Up @@ -301,6 +336,9 @@ where
allocs: vec![self.segments.record()],
devs: self.block_mgr.record(),
},
integrity_journal_size: self.integrity_journal_size,
integrity_block_size: self.integrity_block_size,
integrity_tag_size: self.integrity_tag_size,
}
}
}
Expand Down
10 changes: 8 additions & 2 deletions src/engine/strat_engine/pool/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,14 @@ impl StratPool {
// FIXME: Initializing with the minimum MDA size is not necessarily
// enough. If there are enough devices specified, more space will be
// required.
let mut backstore =
Backstore::initialize(pool_uuid, devices, MDADataSize::default(), encryption_info)?;
let mut backstore = Backstore::initialize(
pool_uuid,
devices,
MDADataSize::default(),
encryption_info,
None,
None,
)?;

let thinpool = ThinPool::<Backstore>::new(
pool_uuid,
Expand Down
5 changes: 4 additions & 1 deletion src/engine/strat_engine/serde_structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

use serde::{Serialize, Serializer};

use devicemapper::{Sectors, ThinDevId};
use devicemapper::{Bytes, Sectors, ThinDevId};

use crate::engine::types::{DevUuid, Features, FilesystemUuid};

Expand Down Expand Up @@ -117,6 +117,9 @@ pub struct BackstoreSave {
#[derive(Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct DataTierSave {
pub blockdev: BlockDevSave,
pub integrity_journal_size: Sectors,
pub integrity_block_size: Bytes,
pub integrity_tag_size: Bytes,
}

#[derive(Debug, Deserialize, Eq, PartialEq, Serialize)]
Expand Down

0 comments on commit 59f77ae

Please sign in to comment.