Subject: bug#6331: [sshfs] df reports wrong disk space usage on solaris

From: Miklos Szeredi <[email-masked]>
Date: Wed, 02 Jun 2010 12:40:12 +0200

[bug-coreutils@... added to CC]

On Tue, 01 Jun 2010, Sandon Van Ness wrote:
> > NFS:
> >
> > root@sabayonx86-64: 01:27 PM :~# stat -f /osol
> >   File: "/osol"
> >     ID: 0        Namelen: 255     Type: nfs
> > Block size: 32768      Fundamental block size: 32768
> > Blocks: Total: 532021184  Free: 109079823  Available: 109079823
> > Inodes: Total: 6987112837 Free: 6981108616
> >
> > SSHFS:
> > root@sabayonx86-64: 01:27 PM :~# stat -f /sshfs
> >   File: "/sshfs"
> >     ID: 0        Namelen: 255     Type: UNKNOWN (0x65735546)
> > Block size: 131072     Fundamental block size: 131072
> > Blocks: Total: 34049356570 Free: 6980647748 Available: 6980647748
> > Inodes: Total: 6986651970 Free: 6980647748
> >   
> Also here is the stats on the solaris box itself vs ssshfs:
> 
> opensolaris:
> 
> 
> root@opensolaris: 06:38 PM :/usr/local/etc#  stat -f /data
>   File: "/data"
>     ID: 1690006  Namelen: 255     Type: zfs
> Block size: 131072     Fundamental block size: 512
> Blocks: Total: 34049348764 Free: 6056839257 Available: 6056839257
> Inodes: Total: 6064436485 Free: 6056839257
> 
> sshfs:
> root@sabayonx86-64: 06:35 PM :~# stat -f /sshfs/
>   File: "/sshfs/"
>     ID: 0        Namelen: 255     Type: UNKNOWN (0x65735546)
> Block size: 131072     Fundamental block size: 131072
> Blocks: Total: 34049348764 Free: 6056839257 Available: 6056839257
> Inodes: Total: 6064436485 Free: 6056839257
> 
> I noticed the block counts are equal but the block size is 131072 on
> sshfs and 512 on the solaris machine.
> 

I looked more deeply into this issue and it appears that "df" and
"stat" on linux both use the statfs libc function which doesn't have
f_frsize.

To verify this, try doing 

  strace -o /tmp/strace stat -f /sshfs

You should get a line like this in the strace output:

statfs("/sshfs/", {f_type=0x65735546, ..., f_frsize=512}) = 0

Notice that the real statfs syscall does have an f_frsize field, but
for some historical reason it is not exported in the library API.

Options to fix this behavior would be:

 1) fix df and stat in coreutils to use statvfs
 2) make sshfs set f_bsize to f_frsize
 3) make sshfs set f_frsize to f_bsize and recalculate stats
 4) change both f_frsize and f_bsize to a common value and
    recalculate stats (this is what NFS appears to be doing)

There is some difficulty with 1) as the libc implementation of statvfs
has problems:

 "Do not use statvfs on systems with GNU libc on Linux, because that function
  stats all preceding entries in /proc/mounts, and that makes df hang if even
  one of the corresponding file systems is hard-mounted, but not available.
  statvfs in GNU libc on Hurd, BeOS, Haiku operates differently: it only makes
  a system call."

This might have been fixed in libc since, so it's possible that
coreutils developers are willing to using statvfs on linux.

Another option would be to use the direct statfs (and statfs64)
syscall interface on linux, bypassing the unnecessary cruft that libc
put there.  But this adds some complexity.

Thanks,
Miklos