Skip to content

Commit

Permalink
unix: better handling of unsupported F_FULLFSYNC
Browse files Browse the repository at this point in the history
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: libuv#2135
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: Santiago Gimeno <[email protected]>
Reviewed-By: Joran Dirk Greef <[email protected]>
  • Loading branch information
pwnall authored and santigimeno committed Jan 15, 2019
1 parent 1698be7 commit 6fc797c
Showing 1 changed file with 1 addition and 1 deletion.
2 changes: 1 addition & 1 deletion src/unix/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 6fc797c

Please sign in to comment.