fuse_statfs: scale with long double to avoid integer overflow

The branch-aggregation code computed
  blocks * f_frsize / min_frsize
as u64 arithmetic. With large filesystems the intermediate product
blocks * f_frsize overflows 64 bits long before the division can
bring the result back into range, producing garbage bavail/bfree
values reported to userspace.

Compute the scale factor once in long double and multiply each
count by it, so the only narrowing happens in the final cast back
to fsblkcnt_t.
This commit is contained in:
Antonio S. Musumeci
2026-04-18 13:47:23 -05:00
committed by trapexit
parent 4288a60c5d
commit ef9c7ad5df
+7 -3
View File
@@ -41,9 +41,13 @@ _normalize_statvfs(struct statvfs *fsstat_,
const unsigned long min_frsize_,
const unsigned long min_namemax_)
{
fsstat_->f_blocks = (fsblkcnt_t)((fsstat_->f_blocks * fsstat_->f_frsize) / min_frsize_);
fsstat_->f_bfree = (fsblkcnt_t)((fsstat_->f_bfree * fsstat_->f_frsize) / min_frsize_);
fsstat_->f_bavail = (fsblkcnt_t)((fsstat_->f_bavail * fsstat_->f_frsize) / min_frsize_);
long double scale;
scale = (((long double)fsstat_->f_frsize) / ((long double)min_frsize_));
fsstat_->f_blocks = (fsblkcnt_t)(fsstat_->f_blocks * scale);
fsstat_->f_bfree = (fsblkcnt_t)(fsstat_->f_bfree * scale);
fsstat_->f_bavail = (fsblkcnt_t)(fsstat_->f_bavail * scale);
fsstat_->f_bsize = min_bsize_;
fsstat_->f_frsize = min_frsize_;
fsstat_->f_namemax = min_namemax_;