Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 38 additions & 4 deletions src/core/utils/sys/storage.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
//! System utilities related to devices/peripherals

//!
//! Discovery reads sysfs under `/sys/dev/block/` and stats the device through
//! `MetadataExt`, neither of which exists outside the unix family. Non-unix
//! targets get arms that report nothing found, so callers need no condition of
//! their own.

use std::path::Path;
#[cfg(unix)]
use std::{
ffi::OsStr,
fs,
fs::{FileType, read_to_string},
path::{Path, PathBuf},
path::PathBuf,
};

#[cfg(unix)]
use itertools::Itertools;
#[cfg(unix)]
use libc::dev_t;

use crate::Result;
#[cfg(unix)]
use crate::{
Result,
result::FlatOk,
utils::{result::LogDebugErr, string::SplitInfallible},
};
Expand Down Expand Up @@ -53,6 +63,7 @@ pub struct Queue {
}

/// Get properties of a MultiDevice (md) storage system
#[cfg(unix)]
#[must_use]
pub fn md_discover(path: &Path) -> MultiDevice {
let dev_id = dev_from_path(path)
Expand Down Expand Up @@ -97,7 +108,16 @@ pub fn md_discover(path: &Path) -> MultiDevice {
}
}

/// Get properties of a MultiDevice (md) storage system.
///
/// Reports no raid on a target without sysfs, which is what the unix arm also
/// returns for a path that is not on one.
#[cfg(not(unix))]
#[must_use]
pub fn md_discover(_path: &Path) -> MultiDevice { MultiDevice::default() }

/// Get properties of a MultiQueue within a MultiDevice.
#[cfg(unix)]
#[must_use]
fn mq_discover(path: &Path) -> MultiQueue {
let mq_path = path.join("mq/");
Expand Down Expand Up @@ -129,6 +149,7 @@ fn mq_discover(path: &Path) -> MultiQueue {
}

/// Get properties of a Queue within a MultiQueue.
#[cfg(unix)]
fn queue_discover(dir: &Path) -> Queue {
let queue_id = dir.file_name();

Expand Down Expand Up @@ -161,6 +182,7 @@ fn queue_discover(dir: &Path) -> Queue {
}

/// Get the name of the block device on which Path is mounted.
#[cfg(unix)]
pub fn name_from_path(path: &Path) -> Result<String> {
use std::io::{Error, ErrorKind::NotFound};

Expand All @@ -177,9 +199,20 @@ pub fn name_from_path(path: &Path) -> Result<String> {
.map(Into::into)
}

/// Get the name of the block device on which Path is mounted.
///
/// Naming the device requires sysfs, so this reports the target cannot do it.
/// The unix arm already returns an error when the name is not there to be read.
#[cfg(not(unix))]
pub fn name_from_path(_path: &Path) -> Result<String> {
use std::io::{Error, ErrorKind::Unsupported};

Err(Error::new(Unsupported, "Block device discovery requires sysfs.").into())
}

/// Get the (major, minor) of the block device on which Path is mounted.
#[cfg(unix)]
fn dev_from_path(path: &Path) -> Result<(dev_t, dev_t)> {
#[cfg(target_family = "unix")]
use std::os::unix::fs::MetadataExt;

let stat = fs::metadata(path)?;
Expand Down Expand Up @@ -210,6 +243,7 @@ fn dev_from_path(path: &Path) -> Result<(dev_t, dev_t)> {
Ok((major, minor))
}

#[cfg(unix)]
fn block_path((major, minor): (dev_t, dev_t)) -> PathBuf {
format!("/sys/dev/block/{major}:{minor}/").into()
}