Skip to content

Commit

Permalink
DOSE-516 Mechanism to version on-disk format and upgrade (openzfs#69)
Browse files Browse the repository at this point in the history
  • Loading branch information
sdimitro authored Dec 16, 2021
1 parent d161175 commit 30bd1b0
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 0 deletions.
92 changes: 92 additions & 0 deletions cmd/zfs_object_agent/zettacache/src/features.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
use lazy_static::lazy_static;
use log::info;
use more_asserts::assert_lt;
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, fmt::Display};

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub enum FeatureType {
Upgradeable,
NonUpgradeable,
}

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub struct FeatureName(pub String);

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Feature {
name: FeatureName,
info: FeatureType,
}

lazy_static! {
pub static ref SUPPORTED_FEATURES: HashMap<FeatureName, FeatureType> = [ORIGIN.clone()]
.map(|feature| (feature.name, feature.info))
.into_iter()
.collect();
pub static ref ORIGIN: Feature = Feature {
name: FeatureName("com.delphix:origin".to_string()),
info: FeatureType::Upgradeable
};
}

#[derive(Debug)]
pub struct FeatureError {
non_upgradeable_features: Vec<FeatureName>,
unknown_features: Vec<FeatureName>,
}

impl Display for FeatureError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
assert_lt!(
0,
self.non_upgradeable_features.len() + self.unknown_features.len(),
);
f.write_fmt(format_args!(
"Missing Zettacache Features: {:?} - Unknown Features Encountered: {:?}",
self.non_upgradeable_features, self.unknown_features,
))
}
}

impl std::error::Error for FeatureError {}

pub fn check_features<'a, I>(feature_list: I) -> Result<(), FeatureError>
where
I: Iterator<Item = &'a FeatureName>,
{
let mut upgradeable_features = vec![];
let mut non_upgradeable_features = vec![];
let mut unknown_features = vec![];
let mut supported_features = SUPPORTED_FEATURES.clone();

for feature in feature_list {
match supported_features.contains_key(feature) {
true => {
supported_features.remove(feature);
}
false => {
unknown_features.push(feature.clone());
}
}
}
for (feature_name, feature_type) in supported_features {
match feature_type {
FeatureType::Upgradeable => upgradeable_features.push(feature_name),
FeatureType::NonUpgradeable => non_upgradeable_features.push(feature_name),
}
}

if !non_upgradeable_features.is_empty() || !unknown_features.is_empty() {
Err(FeatureError {
non_upgradeable_features,
unknown_features,
})
} else {
info!(
"enabling the following upgradeable features: {:?}",
upgradeable_features
);
Ok(())
}
}
1 change: 1 addition & 0 deletions cmd/zfs_object_agent/zettacache/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mod block_access;
mod block_allocator;
mod block_based_log;
mod extent_allocator;
mod features;
mod index;
mod size_histogram;
mod space_map;
Expand Down
2 changes: 2 additions & 0 deletions cmd/zfs_object_agent/zettacache/src/superblock.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::base_types::*;
use crate::block_access::*;
use crate::features::FeatureName;
use anyhow::anyhow;
use anyhow::Result;
use futures::stream::*;
Expand All @@ -26,6 +27,7 @@ pub struct PrimaryPhys {
pub checkpoint_capacity: Extent, // space available for checkpoints
pub checkpoint: Extent, // space used by latest checkpoint
pub num_disks: usize,
pub feature_flags: Vec<FeatureName>,
}

impl PrimaryPhys {
Expand Down
7 changes: 7 additions & 0 deletions cmd/zfs_object_agent/zettacache/src/zettacache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ use crate::block_based_log::*;
use crate::extent_allocator::ExtentAllocator;
use crate::extent_allocator::ExtentAllocatorBuilder;
use crate::extent_allocator::ExtentAllocatorPhys;
use crate::features::check_features;
use crate::features::SUPPORTED_FEATURES;
use crate::index::*;
use crate::size_histogram::SizeHistogramPhys;
use crate::superblock::PrimaryPhys;
Expand Down Expand Up @@ -545,6 +547,7 @@ impl ZettaCache {
checkpoint_capacity,
checkpoint: checkpoint_extent,
num_disks,
feature_flags: SUPPORTED_FEATURES.keys().cloned().collect(),
}
.write_all(DiskId(0), guid, block_access)
.await;
Expand All @@ -564,6 +567,9 @@ impl ZettaCache {
PrimaryPhys::read(&block_access).await.unwrap()
}
};
if let Err(feature_error) = check_features(primary.feature_flags.iter()) {
panic!("{}", feature_error)
};

let checkpoint = ZettaCheckpointPhys::read(&block_access, primary.checkpoint).await;

Expand Down Expand Up @@ -1731,6 +1737,7 @@ impl ZettaCacheState {

self.primary.checkpoint = checkpoint_extent;
self.primary.checkpoint_id = self.primary.checkpoint_id.next();
self.primary.feature_flags = SUPPORTED_FEATURES.keys().cloned().collect();
self.primary
.write_all(self.primary_disk, self.guid, &self.block_access)
.await;
Expand Down

0 comments on commit 30bd1b0

Please sign in to comment.