fix: use fragmented block size for space calculation
We currently calculate the size of a datastore using `statfs64`, which returns the number of blocks in the fs and the two block sizes: fragemented block size(f_frsize) and block size (f_bsize). To calculate eg the total space in a datastore we use total_blocks * f_bsize, which is not always correct. `f_frsize` is the minimum unit of allocation on the filesystem (in bytes) and in 99% of the cases equal to `f_bsize`, but in some cases it differs. For example some filesystems allow smaller blocks for small files, in case f_frsize < f_bsize. In that case, f_frsize * total_blocks returns (mostly) the correct result (ceph also did some weird stuff, which is now being fixed though [0][1]). `statvfs` also documents this as the recommended way ('fsblkcnt_t f_blocks; /* Size of fs in f_frsize units */')[2]. This patch aligns the the behavior with the libc utilities (also used by `df`) [3]. Motivation: [4] (Forum post) [0]: https://tracker.ceph.com/issues/3793 [1]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=92a49fb0f79f3300e6e50ddf56238e70678e4202 [2]: https://www.man7.org/linux/man-pages/man3/statvfs.3.html [3]: https://git.savannah.gnu.org/cgit/gnulib.git/tree/lib/fsusage.c#n147 [4]: https://forum.proxmox.com/threads/pbs-3-1-2-wrong-datastore-information-sshfs.139875/#post-626959 Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
This commit is contained in:
parent
55f4d532c7
commit
78bf05a458
@ -121,12 +121,16 @@ pub fn fs_info<P: ?Sized + nix::NixPath>(path: &P) -> nix::Result<FileSystemInfo
|
||||
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;
|
||||
let block_size = if stat.f_frsize == 0 {
|
||||
stat.f_bsize as u64
|
||||
} else {
|
||||
stat.f_frsize as u64
|
||||
};
|
||||
|
||||
Ok(FileSystemInformation {
|
||||
total: stat.f_blocks * bsize,
|
||||
used: (stat.f_blocks - stat.f_bfree) * bsize,
|
||||
available: stat.f_bavail * bsize,
|
||||
total: stat.f_blocks * block_size,
|
||||
used: (stat.f_blocks - stat.f_bfree) * block_size,
|
||||
available: stat.f_bavail * block_size,
|
||||
total_inodes: stat.f_files,
|
||||
free_inodes: stat.f_ffree,
|
||||
fs_type: stat.f_type,
|
||||
|
Loading…
Reference in New Issue
Block a user