use std::path::{Path, PathBuf};
use itertools::Itertools;
use nix::{fcntl::readlink, sys::stat::stat};
#[cfg_attr(not(target_os = "linux"), allow(dead_code))]
#[derive(PartialEq, Clone, Copy, Debug)]
pub enum FsType {
Xfs,
Ext4,
Btrfs,
Tmpfs,
Others,
}
#[cfg_attr(not(target_os = "linux"), allow(unused_variables))]
pub fn detect_fs_type(path: impl AsRef<Path>) -> FsType {
#[cfg(target_os = "linux")]
{
use nix::sys::statfs::{statfs, BTRFS_SUPER_MAGIC, EXT4_SUPER_MAGIC, TMPFS_MAGIC, XFS_SUPER_MAGIC};
let fs_stat = statfs(path.as_ref()).unwrap();
match fs_stat.filesystem_type() {
XFS_SUPER_MAGIC => FsType::Xfs,
EXT4_SUPER_MAGIC => FsType::Ext4,
BTRFS_SUPER_MAGIC => FsType::Btrfs,
TMPFS_MAGIC => FsType::Tmpfs,
_ => FsType::Others,
}
}
#[cfg(not(target_os = "linux"))]
FsType::Others
}
pub fn file_stat_path(path: impl AsRef<Path>) -> PathBuf {
let st_dev = stat(path.as_ref()).unwrap().st_dev;
let major = unsafe { libc::major(st_dev) };
let minor = unsafe { libc::minor(st_dev) };
let dev = PathBuf::from("/dev/block").join(format!("{}:{}", major, minor));
let linkname = readlink(&dev).unwrap();
let devname = Path::new(linkname.as_os_str()).file_name().unwrap();
dev_stat_path(devname.to_str().unwrap())
}
pub fn dev_stat_path(devname: &str) -> PathBuf {
let classpath = Path::new("/sys/class/block").join(devname);
let devclass = readlink(&classpath).unwrap();
let devpath = Path::new(&devclass);
Path::new("/sys")
.join(devpath.strip_prefix("../..").unwrap())
.join("stat")
}
#[derive(Debug, Clone, Copy)]
pub struct IoStat {
pub read_ios: usize,
pub read_merges: usize,
pub read_sectors: usize,
pub read_ticks: usize,
pub write_ios: usize,
pub write_merges: usize,
pub write_sectors: usize,
pub write_ticks: usize,
pub in_flight: usize,
pub io_ticks: usize,
pub time_in_queue: usize,
pub discard_ios: usize,
pub discard_merges: usize,
pub discard_sectors: usize,
pub discard_ticks: usize,
pub flush_ios: usize,
pub flush_ticks: usize,
}
pub fn iostat(path: impl AsRef<Path>) -> IoStat {
let content = std::fs::read_to_string(path.as_ref()).unwrap();
let nums = content.split_ascii_whitespace().collect_vec();
let read_ios = nums[0].parse().unwrap();
let read_merges = nums[1].parse().unwrap();
let read_sectors = nums[2].parse().unwrap();
let read_ticks = nums[3].parse().unwrap();
let write_ios = nums[4].parse().unwrap();
let write_merges = nums[5].parse().unwrap();
let write_sectors = nums[6].parse().unwrap();
let write_ticks = nums[7].parse().unwrap();
let in_flight = nums[8].parse().unwrap();
let io_ticks = nums[9].parse().unwrap();
let time_in_queue = nums[10].parse().unwrap();
let discard_ios = nums[11].parse().unwrap();
let discard_merges = nums[12].parse().unwrap();
let discard_sectors = nums[13].parse().unwrap();
let discard_ticks = nums[14].parse().unwrap();
let flush_ios = nums[15].parse().unwrap();
let flush_ticks = nums[16].parse().unwrap();
IoStat {
read_ios,
read_merges,
read_sectors,
read_ticks,
write_ios,
write_merges,
write_sectors,
write_ticks,
in_flight,
io_ticks,
time_in_queue,
discard_ios,
discard_merges,
discard_sectors,
discard_ticks,
flush_ios,
flush_ticks,
}
}