Set f_frsize, fixing free space calculation by `df` on OS X.
parent
81a0bd26c3
commit
c96d308a7a
|
@ -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 (
|
||||||
// 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() {
|
||||||
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)
|
||||||
|
|
Loading…
Reference in New Issue