diff options
author | Alex Auvolat <alex@adnab.me> | 2023-09-11 20:00:02 +0200 |
---|---|---|
committer | Alex Auvolat <alex@adnab.me> | 2023-09-11 20:00:02 +0200 |
commit | 51abbb02d8b77529c2e3db079d527d0f28c737bc (patch) | |
tree | 5dbc1611f968214ba103c73cd0cf2cc966696eef /src/rpc | |
parent | ad6b1cc0bed8a01ebeb2aacf995a69ced785b5a6 (diff) | |
parent | 2548a247f22a6404a2f447e9f9c47fe18e10f67a (diff) | |
download | garage-51abbb02d8b77529c2e3db079d527d0f28c737bc.tar.gz garage-51abbb02d8b77529c2e3db079d527d0f28c737bc.zip |
Merge branch 'main' into next
Diffstat (limited to 'src/rpc')
-rw-r--r-- | src/rpc/Cargo.toml | 2 | ||||
-rw-r--r-- | src/rpc/system.rs | 66 |
2 files changed, 31 insertions, 37 deletions
diff --git a/src/rpc/Cargo.toml b/src/rpc/Cargo.toml index f66478ce..8ccee46f 100644 --- a/src/rpc/Cargo.toml +++ b/src/rpc/Cargo.toml @@ -26,7 +26,7 @@ tracing = "0.1" rand = "0.8" itertools="0.10" sodiumoxide = { version = "0.2.5-0", package = "kuska-sodiumoxide" } -systemstat = "0.2.3" +nix = { version = "0.27", default-features = false, features = ["fs"] } async-trait = "0.1.7" serde = { version = "1.0", default-features = false, features = ["derive", "rc"] } diff --git a/src/rpc/system.rs b/src/rpc/system.rs index cf480549..b76e6d4a 100644 --- a/src/rpc/system.rs +++ b/src/rpc/system.rs @@ -896,46 +896,40 @@ impl NodeStatus { data_dir: &DataDirEnum, metrics: &SystemMetrics, ) { - use systemstat::{Platform, System}; - let mounts = System::new().mounts().unwrap_or_default(); - - let mount_avail = |path: &Path| { - mounts - .iter() - .filter(|x| path.starts_with(&x.fs_mounted_on)) - .max_by_key(|x| x.fs_mounted_on.len()) - .map(|x| (x.avail.as_u64(), x.total.as_u64())) + use nix::sys::statvfs::statvfs; + let mount_avail = |path: &Path| match statvfs(path) { + Ok(x) => { + let avail = x.blocks_available() * x.fragment_size(); + let total = x.blocks() * x.fragment_size(); + Some((x.filesystem_id(), avail, total)) + } + Err(_) => None, }; - self.meta_disk_avail = mount_avail(meta_dir); + self.meta_disk_avail = mount_avail(meta_dir).map(|(_, a, t)| (a, t)); self.data_disk_avail = match data_dir { - DataDirEnum::Single(dir) => mount_avail(dir), - DataDirEnum::Multiple(dirs) => { - // Take mounts corresponding to all specified data directories that - // can be used for writing data - let mounts = dirs - .iter() - .filter(|dir| dir.capacity.is_some()) - .map(|dir| { - mounts - .iter() - .filter(|mnt| dir.path.starts_with(&mnt.fs_mounted_on)) - .max_by_key(|mnt| mnt.fs_mounted_on.len()) - }) - .collect::<Vec<_>>(); - if mounts.iter().any(|x| x.is_none()) { - None // could not get info for at least one mount - } else { - // dedup mounts in case several data directories are on the same filesystem - let mut mounts = mounts.iter().map(|x| x.unwrap()).collect::<Vec<_>>(); - mounts.sort_by(|x, y| x.fs_mounted_on.cmp(&y.fs_mounted_on)); - mounts.dedup_by(|x, y| x.fs_mounted_on == y.fs_mounted_on); - // calculate sum of available and total space - Some(mounts.iter().fold((0, 0), |(x, y), mnt| { - (x + mnt.avail.as_u64(), y + mnt.total.as_u64()) - })) + DataDirEnum::Single(dir) => mount_avail(dir).map(|(_, a, t)| (a, t)), + DataDirEnum::Multiple(dirs) => (|| { + // TODO: more precise calculation that takes into account + // how data is going to be spread among partitions + let mut mounts = HashMap::new(); + for dir in dirs.iter() { + if dir.capacity.is_none() { + continue; + } + match mount_avail(&dir.path) { + Some((fsid, avail, total)) => { + mounts.insert(fsid, (avail, total)); + } + None => return None, + } } - } + Some( + mounts + .into_iter() + .fold((0, 0), |(x, y), (_, (a, b))| (x + a, y + b)), + ) + })(), }; if let Some((avail, total)) = self.meta_disk_avail { |