diff --git a/src/bin/proxmox-backup-proxy.rs b/src/bin/proxmox-backup-proxy.rs index 8a3b684f..17ce0e71 100644 --- a/src/bin/proxmox-backup-proxy.rs +++ b/src/bin/proxmox-backup-proxy.rs @@ -710,10 +710,9 @@ async fn generate_host_stats(save: bool) { }); } - fn gather_disk_stats(disk_manager: Arc, path: &Path, rrd_prefix: &str, save: bool) { - match disk_usage(path) { + match proxmox_backup::tools::disks::disk_usage(path) { Ok((total, used, _avail)) => { let rrd_key = format!("{}/total", rrd_prefix); rrd_update_gauge(&rrd_key, total as f64, save); @@ -725,84 +724,45 @@ fn gather_disk_stats(disk_manager: Arc, path: &Path, rrd_prefix: &st } } - match disk_manager.mount_info() { - Ok(mountinfo) => { - if let Some((fs_type, device, source)) = find_mounted_device(mountinfo, path) { - let mut device_stat = None; - match fs_type.as_str() { - "zfs" => { - if let Some(pool) = source { - match zfs_pool_stats(&pool) { - Ok(stat) => device_stat = stat, - Err(err) => eprintln!("zfs_pool_stats({:?}) failed - {}", pool, err), - } - } - } - _ => { - if let Ok(disk) = disk_manager.clone().disk_by_dev_num(device.into_dev_t()) { - match disk.read_stat() { - Ok(stat) => device_stat = stat, - Err(err) => eprintln!("disk.read_stat {:?} failed - {}", path, err), - } + match disk_manager.find_mounted_device(path) { + Ok(None) => {}, + Ok(Some((fs_type, device, source))) => { + let mut device_stat = None; + match fs_type.as_str() { + "zfs" => { + if let Some(pool) = source { + match zfs_pool_stats(&pool) { + Ok(stat) => device_stat = stat, + Err(err) => eprintln!("zfs_pool_stats({:?}) failed - {}", pool, err), } } } - if let Some(stat) = device_stat { - let rrd_key = format!("{}/read_ios", rrd_prefix); - rrd_update_derive(&rrd_key, stat.read_ios as f64, save); - let rrd_key = format!("{}/read_bytes", rrd_prefix); - rrd_update_derive(&rrd_key, (stat.read_sectors*512) as f64, save); - - let rrd_key = format!("{}/write_ios", rrd_prefix); - rrd_update_derive(&rrd_key, stat.write_ios as f64, save); - let rrd_key = format!("{}/write_bytes", rrd_prefix); - rrd_update_derive(&rrd_key, (stat.write_sectors*512) as f64, save); - - let rrd_key = format!("{}/io_ticks", rrd_prefix); - rrd_update_derive(&rrd_key, (stat.io_ticks as f64)/1000.0, save); + _ => { + if let Ok(disk) = disk_manager.clone().disk_by_dev_num(device.into_dev_t()) { + match disk.read_stat() { + Ok(stat) => device_stat = stat, + Err(err) => eprintln!("disk.read_stat {:?} failed - {}", path, err), + } + } } } + if let Some(stat) = device_stat { + let rrd_key = format!("{}/read_ios", rrd_prefix); + rrd_update_derive(&rrd_key, stat.read_ios as f64, save); + let rrd_key = format!("{}/read_bytes", rrd_prefix); + rrd_update_derive(&rrd_key, (stat.read_sectors*512) as f64, save); + + let rrd_key = format!("{}/write_ios", rrd_prefix); + rrd_update_derive(&rrd_key, stat.write_ios as f64, save); + let rrd_key = format!("{}/write_bytes", rrd_prefix); + rrd_update_derive(&rrd_key, (stat.write_sectors*512) as f64, save); + + let rrd_key = format!("{}/io_ticks", rrd_prefix); + rrd_update_derive(&rrd_key, (stat.io_ticks as f64)/1000.0, save); + } } Err(err) => { - eprintln!("disk_manager mount_info() failed - {}", err); + eprintln!("find_mounted_device failed - {}", err); } } } - -// Returns (total, used, avail) -fn disk_usage(path: &std::path::Path) -> Result<(u64, u64, u64), Error> { - - let mut stat: libc::statfs64 = unsafe { std::mem::zeroed() }; - - use nix::NixPath; - - let res = path.with_nix_path(|cstr| unsafe { libc::statfs64(cstr.as_ptr(), &mut stat) })?; - nix::errno::Errno::result(res)?; - - let bsize = stat.f_bsize as u64; - - Ok((stat.f_blocks*bsize, (stat.f_blocks-stat.f_bfree)*bsize, stat.f_bavail*bsize)) -} - -// Returns (fs_type, device, mount_source) -pub fn find_mounted_device( - mountinfo: &MountInfo, - path: &std::path::Path, -) -> Option<(String, Device, Option)> { - - let mut result = None; - let mut match_len = 0; - - let root_path = std::path::Path::new("/"); - for (_id, entry) in mountinfo { - if entry.root == root_path && path.starts_with(&entry.mount_point) { - let len = entry.mount_point.as_path().as_os_str().len(); - if len > match_len { - match_len = len; - result = Some((entry.fs_type.clone(), entry.device, entry.mount_source.clone())); - } - } - } - - result -} diff --git a/src/tools/disks.rs b/src/tools/disks.rs index f82f9f7c..c8f7cbbf 100644 --- a/src/tools/disks.rs +++ b/src/tools/disks.rs @@ -13,7 +13,7 @@ use libc::dev_t; use once_cell::sync::OnceCell; use proxmox::sys::error::io_err_other; -use proxmox::sys::linux::procfs::MountInfo; +use proxmox::sys::linux::procfs::{MountInfo, mountinfo::Device}; use proxmox::{io_bail, io_format_err}; pub mod zfs; @@ -135,6 +135,28 @@ impl DiskManage { }) } + /// Information about file system type and unsed device for a path + /// + /// Returns tuple (fs_type, device, mount_source) + pub fn find_mounted_device( + &self, + path: &std::path::Path, + ) -> Result)>, Error> { + + let stat = nix::sys::stat::stat(path)?; + let device = Device::from_dev_t(stat.st_dev); + + let root_path = std::path::Path::new("/"); + + for (_id, entry) in self.mount_info()? { + if entry.root == root_path && entry.device == device { + return Ok(Some((entry.fs_type.clone(), entry.device, entry.mount_source.clone()))); + } + } + + Ok(None) + } + /// Check whether a specific device node is mounted. /// /// Note that this tries to `stat` the sources of all mount points without caching the result @@ -450,6 +472,21 @@ impl Disk { } } +/// Returns disk usage information (total, used, avail) +pub fn disk_usage(path: &std::path::Path) -> Result<(u64, u64, u64), Error> { + + let mut stat: libc::statfs64 = unsafe { std::mem::zeroed() }; + + use nix::NixPath; + + let res = path.with_nix_path(|cstr| unsafe { libc::statfs64(cstr.as_ptr(), &mut stat) })?; + nix::errno::Errno::result(res)?; + + let bsize = stat.f_bsize as u64; + + Ok((stat.f_blocks*bsize, (stat.f_blocks-stat.f_bfree)*bsize, stat.f_bavail*bsize)) +} + /// This is just a rough estimate for a "type" of disk. pub enum DiskType { /// We know nothing.