diff --git a/src/tools/disks.rs b/src/tools/disks.rs index 31cff5f8..fb299aad 100644 --- a/src/tools/disks.rs +++ b/src/tools/disks.rs @@ -16,6 +16,8 @@ use proxmox::sys::error::io_err_other; use proxmox::sys::linux::procfs::MountInfo; use proxmox::{io_bail, io_format_err}; +pub mod zfs; + bitflags! { /// Ways a device is being used. pub struct DiskUse: u32 { diff --git a/src/tools/disks/zfs.rs b/src/tools/disks/zfs.rs new file mode 100644 index 00000000..55936ab6 --- /dev/null +++ b/src/tools/disks/zfs.rs @@ -0,0 +1,47 @@ +use anyhow::{bail, Error}; + +use std::path::PathBuf; + +use super::*; + +pub fn zfs_pool_stats(pool: &OsStr) -> Result, Error> { + + let mut path = PathBuf::from("/proc/spl/kstat/zfs"); + path.push(pool); + path.push("io"); + + let text = match proxmox::tools::fs::file_read_optional_string(&path)? { + Some(text) => text, + None => { return Ok(None); } + }; + + let lines: Vec<&str> = text.lines().collect(); + + if lines.len() < 3 { + bail!("unable to parse {:?} - got less than 3 lines", path); + } + + // https://github.com/openzfs/zfs/blob/master/lib/libspl/include/sys/kstat.h#L578 + // nread nwritten reads writes wtime wlentime wupdate rtime rlentime rupdate wcnt rcnt + // Note: w -> wait (wtime -> wait time) + // Note: r -> run (rtime -> run time) + // All times are nanoseconds + let stat: Vec = lines[2].split_ascii_whitespace().map(|s| { + u64::from_str_radix(s, 10).unwrap_or(0) + }).collect(); + + let ticks = stat[4]/1_000_000; // convert to milisec + + let stat = BlockDevStat { + read_sectors: stat[0]>>9, + write_sectors: stat[1]>>9, + read_ios: stat[2], + write_ios: stat[3], + read_merges: 0, // there is no such info + write_merges: 0, // there is no such info + write_ticks: ticks, + read_ticks: ticks, + }; + + Ok(Some(stat)) +}