Skip to content

Commit

Permalink
Allocate space for dm-integrity
Browse files Browse the repository at this point in the history
  • Loading branch information
jbaublitz committed Apr 18, 2024
1 parent 7d75941 commit bfe55f3
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 38 deletions.
11 changes: 6 additions & 5 deletions src/engine/strat_engine/backstore/blockdev/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::{
engine::{
strat_engine::{
backstore::{devices::BlockSizes, range_alloc::PerDevSegments},
metadata::{BDAExtendedSize, BlockdevSize, MDADataSize, BDA},
metadata::{BlockdevSize, MDADataSize, BDA},
},
types::{DevUuid, StratSigblockVersion},
},
Expand Down Expand Up @@ -71,12 +71,13 @@ pub trait InternalBlockDev {
fn available(&self) -> Sectors;

// ALL SIZE METHODS (except size(), which is in BlockDev impl.)
/// The number of Sectors on this device used by Stratis for metadata
fn metadata_size(&self) -> BDAExtendedSize;
/// The number of Sectors on this device used by Stratis and potentially other devicemapper
/// layers for metadata
fn metadata_size(&self) -> Sectors;

/// The maximum size of variable length metadata that can be accommodated.
/// The maximum size of variable length Stratis metadata that can be accommodated.
/// self.max_metadata_size() < self.metadata_size()
fn max_metadata_size(&self) -> MDADataSize;
fn max_stratis_metadata_size(&self) -> MDADataSize;

/// Whether or not the blockdev is in use by upper layers. It is if the
/// sum of the blocks used exceeds the Stratis metadata size.
Expand Down
16 changes: 8 additions & 8 deletions src/engine/strat_engine/backstore/blockdev/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ use crate::{
crypt::handle::v1::CryptHandle,
device::blkdev_size,
metadata::{
disown_device, static_header, BDAExtendedSize, BlockdevSize, MDADataSize,
MetadataLocation, StaticHeader, BDA,
disown_device, static_header, BlockdevSize, MDADataSize, MetadataLocation,
StaticHeader, BDA,
},
serde_structs::{BaseBlockDevSave, Recordable},
types::BDAResult,
Expand Down Expand Up @@ -197,8 +197,8 @@ impl StratBlockDev {
}

/// The maximum size of variable length metadata that can be accommodated.
/// self.max_metadata_size() < self.metadata_size()
pub fn max_metadata_size(&self) -> MDADataSize {
/// self.max_stratis_metadata_size() > self.metadata_size()
pub fn max_stratis_metadata_size(&self) -> MDADataSize {
self.bda.max_data_size()
}

Expand Down Expand Up @@ -360,16 +360,16 @@ impl InternalBlockDev for StratBlockDev {
self.used.available()
}

fn metadata_size(&self) -> BDAExtendedSize {
self.bda.extended_size()
fn metadata_size(&self) -> Sectors {
self.bda.extended_size().sectors()
}

fn max_metadata_size(&self) -> MDADataSize {
fn max_stratis_metadata_size(&self) -> MDADataSize {
self.bda.max_data_size()
}

fn in_use(&self) -> bool {
self.used.used() > self.metadata_size().sectors()
self.used.used() > self.metadata_size()
}

fn alloc(&mut self, size: Sectors) -> PerDevSegments {
Expand Down
42 changes: 25 additions & 17 deletions src/engine/strat_engine/backstore/blockdev/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use std::{
use chrono::{DateTime, Utc};
use serde_json::Value;

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

use crate::{
engine::{
Expand All @@ -26,8 +26,8 @@ use crate::{
},
device::blkdev_size,
metadata::{
disown_device, static_header, BDAExtendedSize, BlockdevSize, MDADataSize,
MetadataLocation, StaticHeader, BDA,
disown_device, static_header, BlockdevSize, MDADataSize, MetadataLocation,
StaticHeader, BDA,
},
serde_structs::{BaseBlockDevSave, Recordable},
types::BDAResult,
Expand All @@ -40,6 +40,17 @@ use crate::{
stratis::{StratisError, StratisResult},
};

/// 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
/// size, once the integrity metadata size is calculated, the remaining data size is now smaller
/// than the metadata region could support for integrity.
pub fn integrity_meta_space(total_space: Sectors) -> Sectors {
Bytes(4096).sectors()
+ Bytes::from(64 * IEC::Mi).sectors()
+ Bytes::from((*total_space * 32u64 + 4095) & !4096).sectors()
}

#[derive(Debug)]
pub struct StratBlockDev {
dev: Device,
Expand Down Expand Up @@ -163,16 +174,12 @@ impl StratBlockDev {
Ok(blkdev_size(&File::open(physical_path)?)?.sectors())
}

/// Allocate room for metadata from the front of the device.
#[allow(dead_code)]
fn alloc_meta_front(&mut self, size: Sectors) -> PerDevSegments {
self.used.alloc_front(size)
}

/// Allocate room for metadata from the back of the device.
#[allow(dead_code)]
fn alloc_meta_back(&mut self, size: Sectors) -> PerDevSegments {
self.used.alloc_back(size)
/// Allocate room for integrity metadata from the back of the device.
pub fn alloc_int_meta_back(&mut self, size: Sectors) {
let segs = self.used.alloc_back(size);
for (start, len) in segs.iter() {
self.integrity_meta_allocs.push((*start, *len));
}
}

/// Set the newly detected size of a block device.
Expand Down Expand Up @@ -230,16 +237,17 @@ impl InternalBlockDev for StratBlockDev {
self.used.available()
}

fn metadata_size(&self) -> BDAExtendedSize {
self.bda.extended_size()
fn metadata_size(&self) -> Sectors {
self.bda.extended_size().sectors()
+ self.integrity_meta_allocs.iter().map(|(_, len)| *len).sum()
}

fn max_metadata_size(&self) -> MDADataSize {
fn max_stratis_metadata_size(&self) -> MDADataSize {
self.bda.max_data_size()
}

fn in_use(&self) -> bool {
self.used.used() > self.metadata_size().sectors()
self.used.used() > self.metadata_size()
}

fn alloc(&mut self, size: Sectors) -> PerDevSegments {
Expand Down
7 changes: 2 additions & 5 deletions src/engine/strat_engine/backstore/blockdevmgr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ where
let candidates = self
.block_devs
.iter_mut()
.filter(|b| b.max_metadata_size().bytes() >= data_size);
.filter(|b| b.max_stratis_metadata_size().bytes() >= data_size);

debug!(
"Writing {} of pool level metadata to devices in pool",
Expand Down Expand Up @@ -416,10 +416,7 @@ where
/// The number of sectors given over to Stratis metadata
/// self.allocated_size() - self.metadata_size() >= self.avail_space()
pub fn metadata_size(&self) -> Sectors {
self.block_devs
.iter()
.map(|bd| bd.metadata_size().sectors())
.sum()
self.block_devs.iter().map(|bd| bd.metadata_size()).sum()
}

pub fn grow(&mut self, dev: DevUuid) -> StratisResult<bool> {
Expand Down
36 changes: 34 additions & 2 deletions src/engine/strat_engine/backstore/data_tier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ use crate::{
stratis::StratisResult,
};

use super::blockdev::v2::integrity_meta_space;

/// Handles the lowest level, base layer of this tier.
#[derive(Debug)]
pub struct DataTier<B> {
Expand Down Expand Up @@ -101,7 +103,15 @@ impl DataTier<v2::StratBlockDev> {
/// Initially 0 segments are allocated.
///
/// WARNING: metadata changing event
pub fn new(block_mgr: BlockDevMgr<v2::StratBlockDev>) -> DataTier<v2::StratBlockDev> {
pub fn new(mut block_mgr: BlockDevMgr<v2::StratBlockDev>) -> DataTier<v2::StratBlockDev> {
for (_, bd) in block_mgr.blockdevs_mut() {
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(),
))
}
DataTier {
block_mgr,
segments: AllocatedAbove { inner: vec![] },
Expand All @@ -116,7 +126,29 @@ impl DataTier<v2::StratBlockDev> {
pool_uuid: PoolUuid,
devices: UnownedDevices,
) -> StratisResult<Vec<DevUuid>> {
self.block_mgr.add(pool_uuid, devices)
let uuids = self.block_mgr.add(pool_uuid, devices)?;
let bds = self
.block_mgr
.blockdevs_mut()
.into_iter()
.filter_map(|(uuid, bd)| {
if uuids.contains(&uuid) {
Some(bd)
} else {
None
}
})
.collect::<Vec<_>>();
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(),
));
}
Ok(uuids)
}

/// Lookup an immutable blockdev by its Stratis UUID.
Expand Down
2 changes: 1 addition & 1 deletion src/engine/strat_engine/metadata/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ mod static_header;

pub use self::{
bda::BDA,
sizes::{BDAExtendedSize, BlockdevSize, MDADataSize},
sizes::{BlockdevSize, MDADataSize},
static_header::{
device_identifiers, disown_device, static_header, MetadataLocation, StaticHeader,
StaticHeaderResult, StratisIdentifiers,
Expand Down

0 comments on commit bfe55f3

Please sign in to comment.