-
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
disks: Begin skeletal new "disks" crate
The disks crate will support enumeration of various disks in time, but for now we're solely focusing on NVME and SCSI (really all libata managed devices) By keeping these distinct for enumeration we'll be able to tacke on composite and multipath devices without causing ourselves confusion down the road. Note, child partitions are deliberately ignored. Signed-off-by: Ikey Doherty <[email protected]>
- Loading branch information
Showing
5 changed files
with
140 additions
and
0 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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,8 @@ | ||
[package] | ||
name = "disks" | ||
version = "0.1.0" | ||
edition = "2021" | ||
description = "A library for working with disks and partitions" | ||
|
||
[dependencies] | ||
regex = "1" |
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,41 @@ | ||
// SPDX-FileCopyrightText: Copyright © 2025 Serpent OS Developers | ||
// | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
use std::{fs, path::PathBuf}; | ||
|
||
pub mod nvme; | ||
pub mod scsi; | ||
|
||
const SYSFS_DIR: &str = "/sys/class/block"; | ||
|
||
#[derive(Debug)] | ||
pub struct Disk { | ||
/// Partial-name, ie "sda" | ||
pub name: String, | ||
|
||
// Number of sectors (* 512 sector size for data size) | ||
pub sectors: u64, | ||
} | ||
|
||
impl Disk { | ||
fn from_sysfs_block_name(name: impl AsRef<str>) -> Self { | ||
let name = name.as_ref().to_owned(); | ||
let entry = PathBuf::from(SYSFS_DIR).join(&name); | ||
|
||
// Determine number of blocks | ||
let block_file = entry.join("size"); | ||
let sectors = fs::read_to_string(block_file) | ||
.ok() | ||
.and_then(|s| s.trim().parse::<u64>().ok()) | ||
.unwrap_or(0); | ||
|
||
Self { name, sectors } | ||
} | ||
|
||
/// Return usable size | ||
/// TODO: Grab the block size from the system. We know Linux is built on 512s though. | ||
pub fn size_in_bytes(&self) -> u64 { | ||
self.sectors * 512 | ||
} | ||
} |
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,50 @@ | ||
// SPDX-FileCopyrightText: Copyright © 2025 Serpent OS Developers | ||
// | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
//! NVME device enumeration and handling | ||
//! | ||
//! This module provides functionality to enumerate and handle NVME devices. | ||
use std::{fs, io}; | ||
|
||
use regex::Regex; | ||
|
||
use crate::{Disk, SYSFS_DIR}; | ||
|
||
pub fn enumerate() -> io::Result<Vec<Disk>> { | ||
// Filter for NVME block devices in format nvmeXnY where X and Y are digits | ||
// Exclude partitions (nvmeXnYpZ) and character devices | ||
let nvme_pattern = Regex::new(r"^nvme\d+n\d+$").unwrap(); | ||
|
||
let items = fs::read_dir(SYSFS_DIR)? | ||
.filter_map(Result::ok) | ||
.filter_map(|e| Some(e.file_name().to_str()?.to_owned())) | ||
.filter(|name| nvme_pattern.is_match(name)) | ||
.map(Disk::from_sysfs_block_name) | ||
.collect(); | ||
Ok(items) | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn test_enumerate() { | ||
let devices = enumerate().expect("failed to collect nvme disks"); | ||
eprintln!("nvme devices: {devices:?}"); | ||
for device in devices.iter() { | ||
let mut size = device.size_in_bytes() as f64; | ||
size /= 1024.0 * 1024.0 * 1024.0; | ||
// Cheeky emulation of `fdisk -l` output | ||
eprintln!( | ||
"Disk /dev/{}: {:.2} GiB, {} bytes, {} sectors", | ||
device.name, | ||
size, | ||
device.size_in_bytes(), | ||
device.sectors | ||
); | ||
} | ||
} | ||
} |
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,34 @@ | ||
// SPDX-FileCopyrightText: Copyright © 2025 Serpent OS Developers | ||
// | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
//! SCSI device enumeration and handling | ||
//! | ||
//! OK. Not quite true. Per modern conventions, all libata devices are also considered SCSI devices. | ||
//! This means all `/dev/sd*` devices. | ||
use std::{fs, io}; | ||
|
||
use crate::{Disk, SYSFS_DIR}; | ||
|
||
pub fn enumerate() -> io::Result<Vec<Disk>> { | ||
// Filtered list of SCSI devices whose paths begin with "sd" but not ending with a digit | ||
let items = fs::read_dir(SYSFS_DIR)? | ||
.filter_map(Result::ok) | ||
.filter_map(|e| Some(e.file_name().to_str()?.to_owned())) | ||
.filter(|e| e.starts_with("sd") && e[2..].chars().all(char::is_alphabetic)) | ||
.map(Disk::from_sysfs_block_name) | ||
.collect(); | ||
Ok(items) | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn test_enumerate() { | ||
let devices = enumerate().expect("Failed to enumerate SCSI devices"); | ||
eprintln!("scsi devices: {devices:?}"); | ||
} | ||
} |