From 6fc797c3fe18d8df71b36ecf2184f085c0283251 Mon Sep 17 00:00:00 2001 From: Victor Costan Date: Wed, 9 Jan 2019 03:20:03 -0800 Subject: [PATCH] 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 Reviewed-By: Santiago Gimeno Reviewed-By: Joran Dirk Greef --- src/unix/fs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/unix/fs.c b/src/unix/fs.c index d22c70f0c29..a0bd70d04ca 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c @@ -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