|Summary:||[fusefs]: statfs doesn't set f_iosize ("optimal transfer block size")|
|Product:||Base System||Reporter:||John Millikin <jmillikin>|
|Component:||kern||Assignee:||Alan Somers <asomers>|
|Status:||In Progress ---|
|Severity:||Affects Only Me||CC:||asomers, chris|
Description John Millikin 2021-02-11 01:21:11 UTC
The FUSE_STATFS response includes fields `bsize` and `frsize`, matching the Linux statfs fields of the same names: * f_bsize: optimal transfer block size * f_frsize: fragment size The FreeBSD `struct statfs' equivalent fields are: * f_bsize: filesystem fragment size * f_iosize: optimal transfer block size The fusefs driver function `fuse_vfsop_statfs()' copies the fragment size correctly, but doesn't copy the transfer block size. This causes `statfs()' calls on a FUSE filesystem to return an incorrect `(struct statfs*)->f_iosize' value of 65535, instead of whatever the filesystem server returned. Additionally, during testing, I noticed that the wrapper implementation of `statvfs()' doesn't propagate `(struct statfs*)->f_namemax' -- it calls `pathconf(path, _PC_NAME_MAX)' instead, which doesn't return correct values for FUSE filesystems.
Comment 1 Alan Somers 2021-02-11 02:07:05 UTC
I think you're right about f_iosize. But what is this about "the wrapper implementation of statvfs"? What wrapper are you talking about?
Comment 2 John Millikin 2021-02-11 02:25:26 UTC
In libc, the `lib/libc/gen/statvfs.c' file contains an implementation of `statvfs()' that wraps the `statfs()' syscall. This wrapper copies most of the fields, but does not copy the maximum name length -- for that, it uses: pcval = pathconf(path, _PC_NAME_MAX); if (pcval == -1) result->f_namemax = ~0UL; else result->f_namemax = (unsigned long)pcval;
Comment 3 Alan Somers 2021-02-11 02:51:11 UTC
(In reply to John Millikin from comment #2) Oh, I thought you were talking about something that wraps statvfs. I wouldn't call statvfs a wrapper; it's the standardized interface for getting information about a file system. statfs is the older, but non-portable version. And the reason that statvfs uses pathconf is because when it was written (2002) statfs didn't have an f_namemax field. f_namemax was only added in 2003 when statfs(2) was updated for 64-bit block counts.
Comment 4 Alan Somers 2021-02-12 03:42:01 UTC
John, could you please test the patch under review?
Comment 5 John Millikin 2021-02-12 11:09:06 UTC
(In reply to Alan Somers from comment #4) The special-casing of `f_iosize' based on `fsess_opt_datacache()' is confusing to me. Is it important that `(struct statfs*)->f_iosize' always be >= the buffer cache iosize? I would expect `statfs()' to report the IO size exactly as provided by the filesystem, without varying depending on presence of a kernel cache. Consider the case of a file opened with `FOPEN_DIRECT_IO' on a filesystem with a small write size (like a network fs limited by MTU). Trying to get the IO size with `statfs()' will return a much larger number than the filesystem daemon reported, and since the statfs vnop is handled by the mount it's not possible for a client to skip the cache check by using `fstatfs()' and `IO_DIRECT'.