aboutsummaryrefslogtreecommitdiff
path: root/src/rpc
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2023-09-07 14:42:20 +0200
committerAlex Auvolat <alex@adnab.me>2023-09-07 14:42:20 +0200
commit2f112ac6827d24f5e8c87915a31a86ec721ebf9e (patch)
treeafc3823169dec570ac55fd292a7b5dc96fbbf8cc /src/rpc
parent6a067e30ee51d3ea9874e3ce18670c39edfd665b (diff)
downloadgarage-2f112ac6827d24f5e8c87915a31a86ec721ebf9e.tar.gz
garage-2f112ac6827d24f5e8c87915a31a86ec721ebf9e.zip
correct free data space accounting for multiple data dirs on same fs
Diffstat (limited to 'src/rpc')
-rw-r--r--src/rpc/system.rs28
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())
+ }))
+ }
}
};