-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Back /var/fm/fmd with a dataset from the boot M.2
/var/fm/fmd is where the illumos fault management system records data. We want to preserve this data across system reboots and in real time rather than via periodic data copying, so that the information is available should the system panic shortly thereafter. Fixes: #4211
- Loading branch information
Showing
8 changed files
with
231 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
// This Source Code Form is subject to the terms of the Mozilla Public | ||
// License, v. 2.0. If a copy of the MPL was not distributed with this | ||
// file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
|
||
//! Operations for dealing with persistent backing mounts for OS data | ||
// On Oxide hardware, the root filesystem is backed by a ramdisk and | ||
// non-persistent. However, there are several things within the root filesystem | ||
// which are useful to preserve across reboots, and these are backed persistent | ||
// datasets on the boot disk. | ||
// | ||
// Each boot disk contains a dataset sled_hardware::disk::M2_BACKING_DATASET | ||
// and for each backing mount, a child dataset is created under there that | ||
// is configured with the desired mountpoint in the root filesystem. Since | ||
// there are multiple disks which can be used to boot, these datasets are also | ||
// marked with the "canmount=noauto" attribute so that they do not all try to | ||
// mount automatically and race -- only one could ever succeed. This allows us | ||
// to come along later an specifically mount the one that we want (the one from | ||
// the current boot disk) and also perform an overlay mount so that it succeeds | ||
// even if there is content from the ramdisk image or early boot services | ||
// present underneath. The overlay mount action is optionally bracketed with a | ||
// service stop/start. | ||
|
||
use camino::Utf8PathBuf; | ||
use illumos_utils::zfs::{ | ||
EnsureFilesystemError, GetValueError, Mountpoint, SizeDetails, Zfs, | ||
}; | ||
|
||
#[derive(Debug, thiserror::Error)] | ||
pub enum BackingFsError { | ||
#[error("Error administering service: {0}")] | ||
Adm(#[from] smf::AdmError), | ||
|
||
#[error("Error retrieving dataset property: {0}")] | ||
DatasetProperty(#[from] GetValueError), | ||
|
||
#[error("Error initializing dataset: {0}")] | ||
Mount(#[from] EnsureFilesystemError), | ||
} | ||
|
||
struct BackingFs { | ||
// Dataset name | ||
name: &'static str, | ||
// Mountpoint | ||
mountpoint: &'static str, | ||
// Optional quota, in _bytes_ | ||
quota: Option<usize>, | ||
// Optional compression mode | ||
compression: Option<&'static str>, | ||
// Linked service | ||
service: Option<&'static str>, | ||
} | ||
|
||
impl BackingFs { | ||
const fn new(name: &'static str) -> Self { | ||
Self { | ||
name, | ||
mountpoint: "legacy", | ||
quota: None, | ||
compression: None, | ||
service: None, | ||
} | ||
} | ||
|
||
const fn mountpoint(mut self, mountpoint: &'static str) -> Self { | ||
self.mountpoint = mountpoint; | ||
self | ||
} | ||
|
||
const fn quota(mut self, quota: usize) -> Self { | ||
self.quota = Some(quota); | ||
self | ||
} | ||
|
||
const fn compression(mut self, compression: &'static str) -> Self { | ||
self.compression = Some(compression); | ||
self | ||
} | ||
|
||
const fn service(mut self, service: &'static str) -> Self { | ||
self.service = Some(service); | ||
self | ||
} | ||
} | ||
|
||
const BACKING_FMD_DATASET: &'static str = "fmd"; | ||
const BACKING_FMD_MOUNTPOINT: &'static str = "/var/fm/fmd"; | ||
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 BACKINGFS_COUNT: usize = 1; | ||
static BACKINGFS: [BackingFs; BACKINGFS_COUNT] = | ||
[BackingFs::new(BACKING_FMD_DATASET) | ||
.mountpoint(BACKING_FMD_MOUNTPOINT) | ||
.quota(BACKING_FMD_QUOTA) | ||
.compression(BACKING_COMPRESSION) | ||
.service(BACKING_FMD_SERVICE)]; | ||
|
||
/// Ensure that the backing filesystems are mounted. | ||
/// If the underlying dataset for a backing fs does not exist on the specified | ||
/// boot disk then it will be created. | ||
pub(crate) fn ensure_backing_fs( | ||
log: &slog::Logger, | ||
boot_zpool_name: &illumos_utils::zpool::ZpoolName, | ||
) -> Result<(), BackingFsError> { | ||
let log = log.new(o!( | ||
"component" => "BackingFs", | ||
)); | ||
for bfs in BACKINGFS.iter() { | ||
info!(log, "Processing {}", bfs.name); | ||
|
||
let dataset = format!( | ||
"{}/{}/{}", | ||
boot_zpool_name, | ||
sled_hardware::disk::M2_BACKING_DATASET, | ||
bfs.name | ||
); | ||
let mountpoint = Mountpoint::Path(Utf8PathBuf::from(bfs.mountpoint)); | ||
|
||
info!(log, "Ensuring dataset {}", dataset); | ||
|
||
let size_details = Some(SizeDetails { | ||
quota: bfs.quota, | ||
compression: bfs.compression, | ||
}); | ||
|
||
Zfs::ensure_filesystem( | ||
&dataset, | ||
mountpoint.clone(), | ||
false, // zoned | ||
true, // do_format | ||
None, // encryption_details, | ||
size_details, | ||
Some(vec!["canmount=noauto".to_string()]), // options | ||
)?; | ||
|
||
if Zfs::get_value(&bfs.mountpoint, "mountpoint")? == bfs.mountpoint { | ||
info!(log, "{} is already mounted", bfs.mountpoint); | ||
return Ok(()); | ||
} | ||
|
||
if let Some(service) = bfs.service { | ||
info!(log, "Stopping service {}", service); | ||
smf::Adm::new() | ||
.disable() | ||
.temporary() | ||
.synchronous() | ||
.run(smf::AdmSelection::ByPattern(&[service]))?; | ||
} | ||
|
||
info!(log, "Mounting {} on {}", dataset, mountpoint); | ||
|
||
Zfs::mount_overlay_dataset(&dataset, &mountpoint)?; | ||
|
||
if let Some(service) = bfs.service { | ||
info!(log, "Starting service {}", service); | ||
smf::Adm::new() | ||
.enable() | ||
.synchronous() | ||
.run(smf::AdmSelection::ByPattern(&[service]))?; | ||
} | ||
} | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters