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: