Commit c96d308a authored by Aaron Jacobs's avatar Aaron Jacobs

Set f_frsize, fixing free space calculation by `df` on OS X.

parent 81a0bd26
...@@ -564,7 +564,35 @@ func (c *Connection) kernelResponseForOp( ...@@ -564,7 +564,35 @@ func (c *Connection) kernelResponseForOp(
out.St.Bavail = o.BlocksAvailable out.St.Bavail = o.BlocksAvailable
out.St.Files = o.Inodes out.St.Files = o.Inodes
out.St.Ffree = o.InodesFree out.St.Ffree = o.InodesFree
// The posix spec for sys/statvfs.h defines the following fields, among
// others:
//
// f_bsize File system block size.
// f_frsize Fundamental file system block size.
// f_blocks Total number of blocks on file system in units of f_frsize.
//
// It appears as though f_bsize was the only thing supported by most unixes
// originally, but then f_frsize was added when new sorts of file systems
// came about. Quoth The Linux Programming Interface by Michael Kerrisk
// (https://goo.gl/5LZMxQ):
//
// For most Linux file systems, the values of f_bsize and f_frsize are
// the same. However, some file systems support the notion of block
// fragments, which can be used to allocate a smaller unit of storage
// at the end of the file if if a full block is not required. This
// avoids the waste of space that would otherwise occur if a full block
// was allocated. On such file systems, f_frsize is the size of a
// fragment, and f_bsize is the size of a whole block. (The notion of
// fragments in UNIX file systems first appeared in the early 1980s
// with the 4.2BSD Fast File System.)
//
// Confusingly, it appears as though osxfuse surfaces f_bsize as f_iosize
// (of advisory use only), and f_frsize as f_bsize (which affects free
// space display in the Finder). In any case, we don't care to let the user
// distinguish, so set both to the same value.
out.St.Bsize = o.BlockSize out.St.Bsize = o.BlockSize
out.St.Frsize = o.BlockSize
case *initOp: case *initOp:
out := (*fusekernel.InitOut)(m.Grow(unsafe.Sizeof(fusekernel.InitOut{}))) out := (*fusekernel.InitOut)(m.Grow(unsafe.Sizeof(fusekernel.InitOut{})))
......
...@@ -38,16 +38,31 @@ import ( ...@@ -38,16 +38,31 @@ import (
// convert_fuse_statfs to convert the response in a straightforward // convert_fuse_statfs to convert the response in a straightforward
// manner. // manner.
// //
// Note that this op is particularly important on OS X: if you don't implement // This op is particularly important on OS X: if you don't implement it, the
// it, the file system will not successfully mount. If you don't model a sane // file system will not successfully mount. If you don't model a sane amount of
// amount of free space, the Finder will refuse to copy files into the file // free space, the Finder will refuse to copy files into the file system.
// system.
type StatFSOp struct { type StatFSOp struct {
// The size of the file system's blocks, and how many there are in total. // The size of the file system's blocks. This may be used, in combination
// with the block counts below, by callers of statfs(2) to infer the file
// system's capacity and space availability.
//
// TODO(jacobsa): Document the range of values accepted on OS X and Linux.
// Cite sources in Linux if possible.
//
// On OS X this also affects statfs::f_iosize, which is documented as the
// "optimal transfer block size". It does not appear to cause osxfuse to
// change the size of data in WriteFile ops, though.
//
// This interface does not distinguish between blocks and block fragments.
BlockSize uint32 BlockSize uint32
Blocks uint64
// The number of blocks free, and how many are available to non-root users. // The total number of blocks in the file system, the number of unused
// blocks, and the count of the latter that are available for use by non-root
// users.
//
// For each category, the corresponding number of bytes is derived by
// multiplying by BlockSize.
Blocks uint64
BlocksFree uint64 BlocksFree uint64
BlocksAvailable uint64 BlocksAvailable uint64
......
...@@ -203,7 +203,7 @@ func (t *StatFSTest) Syscall_NonZeroValues() { ...@@ -203,7 +203,7 @@ func (t *StatFSTest) Syscall_NonZeroValues() {
err = syscall.Statfs(t.Dir, &stat) err = syscall.Statfs(t.Dir, &stat)
AssertEq(nil, err) AssertEq(nil, err)
ExpectEq(4096, stat.Bsize) // OS X seems to always make this 4096. ExpectEq(canned.BlockSize, stat.Bsize)
ExpectEq(canned.BlockSize, stat.Iosize) ExpectEq(canned.BlockSize, stat.Iosize)
ExpectEq(canned.Blocks, stat.Blocks) ExpectEq(canned.Blocks, stat.Blocks)
ExpectEq(canned.BlocksFree, stat.Bfree) ExpectEq(canned.BlocksFree, stat.Bfree)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment