Skip to content

Commit

Permalink
Make CompressionAlgorithm strongly typed
Browse files Browse the repository at this point in the history
  • Loading branch information
smklein committed Aug 28, 2024
1 parent 0a63161 commit c9f170e
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 18 deletions.
89 changes: 87 additions & 2 deletions common/src/disk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,91 @@ impl DatasetName {
}
}

#[derive(
Copy,
Clone,
Debug,
Deserialize,
Serialize,
JsonSchema,
PartialEq,
Eq,
Hash,
PartialOrd,
Ord,
)]
pub struct GzipLevel(u8);

// Fastest compression level
const GZIP_LEVEL_MIN: u8 = 1;

// Best compression ratio
const GZIP_LEVEL_MAX: u8 = 9;

impl GzipLevel {
pub const fn new<const N: u8>() -> Self {
assert!(N >= GZIP_LEVEL_MIN, "Compression level too small");
assert!(N <= GZIP_LEVEL_MAX, "Compression level too large");
Self(N)
}
}

#[derive(
Copy,
Clone,
Debug,
Default,
Deserialize,
Serialize,
JsonSchema,
PartialEq,
Eq,
Hash,
PartialOrd,
Ord,
)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum CompressionAlgorithm {
// Selects a default compression algorithm. This is dependent on both the
// zpool and OS version.
On,

// Disables compression.
#[default]
Off,

// Selects the default Gzip compression level.
//
// According to the ZFS docs, this is "gzip-6", but that's a default value,
// which may change with OS updates.
Gzip,

GzipN {
level: GzipLevel,
},
Lz4,
Lzjb,
Zle,
}

impl fmt::Display for CompressionAlgorithm {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use CompressionAlgorithm::*;
let s = match self {
On => "on",
Off => "off",
Gzip => "gzip",
GzipN { level } => {
return write!(f, "gzip-{}", level.0);
}
Lz4 => "lz4",
Lzjb => "lzjb",
Zle => "zle",
};
write!(f, "{}", s)
}
}

/// Configuration information necessary to request a single dataset
#[derive(
Clone,
Expand All @@ -155,8 +240,8 @@ pub struct DatasetConfig {
/// The dataset's name
pub name: DatasetName,

/// The compression mode to be supplied, if any
pub compression: Option<String>,
/// The compression mode to be used by the dataset
pub compression: CompressionAlgorithm,

/// The upper bound on the amount of storage used by this dataset
pub quota: Option<usize>,
Expand Down
7 changes: 4 additions & 3 deletions illumos-utils/src/zfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use crate::{execute, PFEXEC};
use camino::{Utf8Path, Utf8PathBuf};
use omicron_common::disk::CompressionAlgorithm;
use omicron_common::disk::DiskIdentity;
use std::fmt;

Expand Down Expand Up @@ -204,7 +205,7 @@ pub struct EncryptionDetails {
pub struct SizeDetails {
pub quota: Option<usize>,
pub reservation: Option<usize>,
pub compression: Option<String>,
pub compression: CompressionAlgorithm,
}

#[cfg_attr(any(test, feature = "testing"), mockall::automock, allow(dead_code))]
Expand Down Expand Up @@ -403,15 +404,15 @@ impl Zfs {
mountpoint: &Mountpoint,
quota: Option<usize>,
reservation: Option<usize>,
compression: Option<String>,
compression: CompressionAlgorithm,
) -> Result<(), EnsureFilesystemError> {
let quota = quota
.map(|q| q.to_string())
.unwrap_or_else(|| String::from("none"));
let reservation = reservation
.map(|r| r.to_string())
.unwrap_or_else(|| String::from("none"));
let compression = compression.unwrap_or_else(|| String::from("off"));
let compression = compression.to_string();

if let Err(err) = Self::set_value(name, "quota", &quota) {
return Err(EnsureFilesystemError {
Expand Down
13 changes: 7 additions & 6 deletions sled-agent/src/backing_fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use camino::Utf8PathBuf;
use illumos_utils::zfs::{
EnsureFilesystemError, GetValueError, Mountpoint, SizeDetails, Zfs,
};
use omicron_common::disk::CompressionAlgorithm;
use std::io;

#[derive(Debug, thiserror::Error)]
Expand All @@ -50,7 +51,7 @@ struct BackingFs<'a> {
// Optional quota, in _bytes_
quota: Option<usize>,
// Optional compression mode
compression: Option<&'static str>,
compression: CompressionAlgorithm,
// Linked service
service: Option<&'static str>,
// Subdirectories to ensure
Expand All @@ -63,7 +64,7 @@ impl<'a> BackingFs<'a> {
name,
mountpoint: "legacy",
quota: None,
compression: None,
compression: CompressionAlgorithm::Off,
service: None,
subdirs: None,
}
Expand All @@ -79,8 +80,8 @@ impl<'a> BackingFs<'a> {
self
}

const fn compression(mut self, compression: &'static str) -> Self {
self.compression = Some(compression);
const fn compression(mut self, compression: CompressionAlgorithm) -> Self {
self.compression = compression;
self
}

Expand All @@ -101,7 +102,7 @@ const BACKING_FMD_SUBDIRS: [&'static str; 3] = ["rsrc", "ckpt", "xprt"];
const BACKING_FMD_SERVICE: &'static str = "svc:/system/fmd:default";
const BACKING_FMD_QUOTA: usize = 500 * (1 << 20); // 500 MiB

const BACKING_COMPRESSION: &'static str = "on";
const BACKING_COMPRESSION: CompressionAlgorithm = CompressionAlgorithm::On;

const BACKINGFS_COUNT: usize = 1;
static BACKINGFS: [BackingFs; BACKINGFS_COUNT] =
Expand Down Expand Up @@ -138,7 +139,7 @@ pub(crate) fn ensure_backing_fs(
let size_details = Some(SizeDetails {
quota: bfs.quota,
reservation: None,
compression: bfs.compression.map(|s| s.to_string()),
compression: bfs.compression,
});

Zfs::ensure_filesystem(
Expand Down
22 changes: 15 additions & 7 deletions sled-storage/src/dataset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ use illumos_utils::zfs::{
use illumos_utils::zpool::ZpoolName;
use key_manager::StorageKeyRequester;
use omicron_common::api::internal::shared::DatasetKind;
use omicron_common::disk::{DatasetName, DiskIdentity, DiskVariant};
use omicron_common::disk::{
CompressionAlgorithm, DatasetName, DiskIdentity, DiskVariant, GzipLevel,
};
use rand::distributions::{Alphanumeric, DistString};
use slog::{debug, info, Logger};
use std::process::Stdio;
Expand Down Expand Up @@ -43,7 +45,8 @@ cfg_if! {
// tuned as needed.
pub const DUMP_DATASET_QUOTA: usize = 100 * (1 << 30);
// passed to zfs create -o compression=
pub const DUMP_DATASET_COMPRESSION: &'static str = "gzip-9";
pub const DUMP_DATASET_COMPRESSION: CompressionAlgorithm =
CompressionAlgorithm::GzipN { level: GzipLevel::new::<9>() };

// U.2 datasets live under the encrypted dataset and inherit encryption
pub const ZONE_DATASET: &'static str = "crypt/zone";
Expand Down Expand Up @@ -100,12 +103,17 @@ struct ExpectedDataset {
// Identifies if the dataset should be deleted on boot
wipe: bool,
// Optional compression mode
compression: Option<&'static str>,
compression: CompressionAlgorithm,
}

impl ExpectedDataset {
const fn new(name: &'static str) -> Self {
ExpectedDataset { name, quota: None, wipe: false, compression: None }
ExpectedDataset {
name,
quota: None,
wipe: false,
compression: CompressionAlgorithm::Off,
}
}

const fn quota(mut self, quota: usize) -> Self {
Expand All @@ -118,8 +126,8 @@ impl ExpectedDataset {
self
}

const fn compression(mut self, compression: &'static str) -> Self {
self.compression = Some(compression);
const fn compression(mut self, compression: CompressionAlgorithm) -> Self {
self.compression = compression;
self
}
}
Expand Down Expand Up @@ -291,7 +299,7 @@ pub(crate) async fn ensure_zpool_has_datasets(
let size_details = Some(SizeDetails {
quota: dataset.quota,
reservation: None,
compression: dataset.compression.map(|s| s.to_string()),
compression: dataset.compression,
});
Zfs::ensure_filesystem(
name,
Expand Down

0 comments on commit c9f170e

Please sign in to comment.