Subject: kern/1358: getfsstat() reports incorrect free values for union mounts
To: None <gnats-bugs@NetBSD.ORG>
From: None <abs@mono.city.ac.uk>
List: netbsd-bugs
Date: 08/14/1995 19:46:35
>Number: 1358
>Category: kern
>Synopsis: getfsstat() reports incorrect free values for union mounts
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Mon Aug 14 15:20:01 1995
>Last-Modified:
>Originator: David Brownlee
>Organization:
Monochrome
>Release: Aug 14th 1995
>Environment:
sparc, 1.0A, current
System: NetBSD proton.city.ac.uk 1.0A NetBSD 1.0A (PROTON) #1: monoadm@proton.city.ac.uk:/mono/u1/NetBSD/src/sys/arch/sun3/compile/PROTON sparc
>Description:
getfsstat() reports the sum of both layers for disk sizes (total,
used, + avail). (see example here)
(proton src/lib)34># df /usr /mono/u4 /usr/src
Filesystem 1K-blocks Used Avail Capacity Mounted on
/dev/sd0g 116279 84846 19805 81% /usr
mfs-u4:/mono/u4 268782 172734 82608 68% /mono/u4
<below>:/mono/u4/netbsd/src 385061 257580 102413 72% /usr/src
This implies I have ~100M free in /usr/src, when in fact I have less
than 20M (as /usr is the top layer).
The values for df have to be made up as a union mount can't report
the 'Used' value correctly - that would be the total blocks in
the upper layer, plus all the blocks from the files that are in the
lower layer but not in the upper... arrg.., but the 'Avail' value
should definitely just be what space is available in the upper
layer.
>How-To-Repeat:
Use union mounts & think you have more free space than you have!
>Fix:
The below patch fixes getfsstat() to report free space (& nodes) on
union mounts correctly. (Plus a patch for mount_union.8 too...)
It also sets the number of blocks to be the total number of blocks
in the upper layer, plus the used blocks in the lower layer.
This makes the most sense to the user (I think :), but has the
side effect that if changes are made to the lower level then the
appatent _size_ of the union filesystem changes. Maybe this might be
a problem? :) If this is not wanted then just remove the two '-='
lines from the patch.
abs
The output from a kernel with the patch installed is:
(proton sys/mono)3># df /usr /mono/u4 /usr/src
Filesystem 1K-blocks Used Avail Capacity Mounted on
/dev/sd0g 116279 84412 20239 81% /usr
mfs-u4:/mono/u4 268782 172747 82595 68% /mono/u4
<below>:/mono/u4/netbsd/src 353194 321327 20239 94% /usr/src
*** sys/miscfs/union/union_vfsops.c.orig Mon Aug 14 19:13:34 1995
--- sys/miscfs/union/union_vfsops.c Mon Aug 14 19:19:34 1995
***************
*** 461,471 ****
sbp->f_bfree = sbp->f_bfree * lbsize / mstat.f_bsize;
sbp->f_bavail = sbp->f_bavail * lbsize / mstat.f_bsize;
}
sbp->f_blocks += mstat.f_blocks;
! sbp->f_bfree += mstat.f_bfree;
! sbp->f_bavail += mstat.f_bavail;
sbp->f_files += mstat.f_files;
! sbp->f_ffree += mstat.f_ffree;
if (sbp != &mp->mnt_stat) {
bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
--- 461,473 ----
sbp->f_bfree = sbp->f_bfree * lbsize / mstat.f_bsize;
sbp->f_bavail = sbp->f_bavail * lbsize / mstat.f_bsize;
}
+ sbp->f_blocks -= mstat.f_bfree;
sbp->f_blocks += mstat.f_blocks;
! sbp->f_bfree = mstat.f_bfree;
! sbp->f_bavail = mstat.f_bavail;
! sbp->f_files -= mstat.f_ffree;
sbp->f_files += mstat.f_files;
! sbp->f_ffree = mstat.f_ffree;
if (sbp != &mp->mnt_stat) {
bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
*** /usr/src/sbin/mount_union/mount_union.8.orig Tue May 30 13:35:46 1995
--- /usr/src/sbin/mount_union/mount_union.8 Mon Aug 14 19:42:35 1995
***************
*** 146,151 ****
--- 146,156 ----
.Xr mount 8
which only applies the union operation to the mount point itself,
and then only for lookups.
+ .Pp
+ The amount of free space in a union mounted filesystem is equal to the
+ amount of free space in the upper layer. The size of a union mounted
+ filesystem is equal to the size of the upper layer plus the space
+ used in the lower layer.
.Sh EXAMPLES
The commands
.Bd -literal -offset indent
>Audit-Trail:
>Unformatted: