unix: better handling of unsupported F_FULLFSYNC

Apple's released source code at https://opensource.apple.com/ shows at
least three different error codes being returned when a filesystem does
not support F_FULLFSYNC.

fcntl() is implemented in xnu-4903.221.2 in bsd/kern/kern_descrip.c,
where it delegates to fcntl_nocancel(). The documentation for
fcntl_nocancel() mentions error codes for some operations, but does not
include F_FULLFSYNC.  The F_FULLSYNC branch in fcntl_nocancel() calls
VNOP_IOCTL(_, F_FULLSYNC, NULL, 0, _), whose return value sets the error
code.

VNOP_IOCTL() is implemented in bsd/vfs/kpi_vfs.c and calls the ioctl
function in the vnode's operation vector. The filesystem-level function
names follow the pattern _vnop_ioctl() for all the instances in
opensource code -- {hfs,msdosfs,nfs,ntfs,smbfs,webdav,zfs}_vnop_ioctl().

hfs-407.30.1, msdosfs-229.200.3, and nfs in xnu-4903.221.2 handle
F_FULLFSYNC. ntfs-94.200.1 and smb-759.40.1 do not handle F_FULLFSYNC,
and the default branch returns ENOSUP. webdav-380.200.1 also does not
handle F_FULLFSYNC, but the default branch returns EINVAL. zfs-59 also
does not handle F_FULLSYNC, and its default branch returns ENOTTY.

From a different angle, Apple's ntfs-94.200.1 includes utility code that
uses fcntl(F_FULLFSYNC) and falls back to fsync() just like this patch
does, supporting the hypothesis that there is no good way to detect lack
of F_FULLFSYNC support.

PR-URL: https://github.com/libuv/libuv/pull/2135
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
Reviewed-By: Joran Dirk Greef <joran@ronomon.com>
This commit is contained in:
Victor Costan 2019-01-09 03:20:03 -08:00 committed by Santiago Gimeno
parent 1698be7205
commit 6fc797c3fe
No known key found for this signature in database
GPG Key ID: F28C3C8DA33C03BE

View File

@ -155,7 +155,7 @@ static ssize_t uv__fs_fsync(uv_fs_t* req) {
int r;
r = fcntl(req->file, F_FULLFSYNC);
if (r != 0 && errno == ENOTTY)
if (r != 0)
r = fsync(req->file);
return r;
#else