diff options
author | Alex Auvolat <alex@adnab.me> | 2023-09-07 14:42:20 +0200 |
---|---|---|
committer | Alex Auvolat <alex@adnab.me> | 2023-09-07 14:42:20 +0200 |
commit | 2f112ac6827d24f5e8c87915a31a86ec721ebf9e (patch) | |
tree | afc3823169dec570ac55fd292a7b5dc96fbbf8cc | |
parent | 6a067e30ee51d3ea9874e3ce18670c39edfd665b (diff) | |
download | garage-2f112ac6827d24f5e8c87915a31a86ec721ebf9e.tar.gz garage-2f112ac6827d24f5e8c87915a31a86ec721ebf9e.zip |
correct free data space accounting for multiple data dirs on same fs
-rw-r--r-- | src/rpc/system.rs | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/src/rpc/system.rs b/src/rpc/system.rs index c5751d5d..cf480549 100644 --- a/src/rpc/system.rs +++ b/src/rpc/system.rs @@ -911,12 +911,30 @@ impl NodeStatus { self.data_disk_avail = match data_dir { DataDirEnum::Single(dir) => mount_avail(dir), DataDirEnum::Multiple(dirs) => { - dirs.iter() - .map(|d| mount_avail(&d.path)) - .fold(Some((0, 0)), |acc, cur| match (acc, cur) { - (Some((x, y)), Some((a, b))) => Some((x + a, y + b)), - _ => None, + // 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()) + })) + } } }; |