From c1c55ee1aa071ff566dc486ba274969ada2c7e18 Mon Sep 17 00:00:00 2001 From: Joran Dirk Greef Date: Fri, 4 Nov 2016 16:14:04 +0200 Subject: [PATCH] darwin: fix fsync and fdatasync Apple's fsync and fdatasync explicitly do NOT flush the drive write cache to the drive platters. This is in contrast to Linux's fsync and fdatasync which do, according to recent man pages. F_FULLFSYNC is Apple's equivalent for flushing buffered data to permanent storage. PR-URL: https://github.com/libuv/libuv/pull/1124 Refs: https://github.com/nodejs/node/issues/9439 Reviewed-By: Ben Noordhuis Reviewed-By: Colin Ihrig Reviewed-By: Santiago Gimeno --- src/unix/fs.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/unix/fs.c b/src/unix/fs.c index 3d478b79..ba64cbbf 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c @@ -129,8 +129,23 @@ static ssize_t uv__fs_fdatasync(uv_fs_t* req) { #if defined(__linux__) || defined(__sun) || defined(__NetBSD__) return fdatasync(req->file); -#elif defined(__APPLE__) && defined(SYS_fdatasync) - return syscall(SYS_fdatasync, req->file); +#elif defined(__APPLE__) + /* Apple's fdatasync and fsync explicitly do NOT flush the drive write cache + * to the drive platters. This is in contrast to Linux's fdatasync and fsync + * which do, according to recent man pages. F_FULLFSYNC is Apple's equivalent + * for flushing buffered data to permanent storage. + */ + return fcntl(req->file, F_FULLFSYNC); +#else + return fsync(req->file); +#endif +} + + +static ssize_t uv__fs_fsync(uv_fs_t* req) { +#if defined(__APPLE__) + /* See the comment in uv__fs_fdatasync. */ + return fcntl(req->file, F_FULLFSYNC); #else return fsync(req->file); #endif @@ -945,7 +960,7 @@ static void uv__fs_work(struct uv__work* w) { X(FCHOWN, fchown(req->file, req->uid, req->gid)); X(FDATASYNC, uv__fs_fdatasync(req)); X(FSTAT, uv__fs_fstat(req->file, &req->statbuf)); - X(FSYNC, fsync(req->file)); + X(FSYNC, uv__fs_fsync(req)); X(FTRUNCATE, ftruncate(req->file, req->off)); X(FUTIME, uv__fs_futime(req)); X(LSTAT, uv__fs_lstat(req->path, &req->statbuf));