Skip to content
This repository has been archived by the owner on May 4, 2018. It is now read-only.

Commit

Permalink
darwin: emulate fdatasync() with fcntl(F_FULLFSYNC)
Browse files Browse the repository at this point in the history
OS X has no public API for fdatasync. And as pointed out in `man fsync(2)`:

  For applications that require tighter guarantees about the integrity of
  their data, Mac OS X provides the F_FULLFSYNC fcntl. The F_FULLFSYNC
  fcntl asks the drive to flush all buffered data to permanent storage.
  Applications, such as databases, that require a strict ordering of writes
  should use F_FULLFSYNC to ensure that their data is written in the order
  they expect.  Please see fcntl(2) for more detail.
  • Loading branch information
indutny authored and bnoordhuis committed Aug 11, 2012
1 parent 837edf4 commit 23dc564
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 1 deletion.
3 changes: 2 additions & 1 deletion include/uv-private/uv-unix.h
Expand Up @@ -267,7 +267,8 @@ struct uv__io_s {

#define UV_FS_PRIVATE_FIELDS \
struct stat statbuf; \
eio_req* eio;
uv_file file; \
eio_req* eio; \

#define UV_WORK_PRIVATE_FIELDS \
eio_req* eio;
Expand Down
40 changes: 40 additions & 0 deletions src/unix/fs.c
Expand Up @@ -72,6 +72,7 @@ static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req, uv_fs_type fs_type,
req->result = 0;
req->ptr = NULL;
req->path = path ? strdup(path) : NULL;
req->file = -1;
req->errorno = 0;
req->eio = NULL;

Expand Down Expand Up @@ -445,6 +446,20 @@ int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
}


#if defined(__APPLE__) && defined(F_FULLFSYNC)
ssize_t uv__fs_fdatasync(uv_file file) {
return fcntl(file, F_FULLFSYNC);
}


void uv__fs_fdatasync_work(eio_req* eio) {
uv_fs_t* req = eio->data;

eio->result = uv__fs_fdatasync(req->file);
}
#endif


int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
char* path = NULL;
#if defined(__FreeBSD__) \
Expand All @@ -453,6 +468,31 @@ int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
* do a full fsync instead.
*/
WRAP_EIO(UV_FS_FDATASYNC, eio_fdatasync, fsync, ARGS1(file))
#elif defined(__APPLE__) && defined(F_FULLFSYNC)
/* OSX >= 10.6 does have fdatasync, but better use fcntl anyway */
uv_fs_req_init(loop, req, UV_FS_FDATASYNC, path, cb);
req->file = file;

if (cb) {
/* async */
req->eio = eio_custom(uv__fs_fdatasync_work,
EIO_PRI_DEFAULT,
uv__fs_after,
req,
&loop->uv_eio_channel);
if (req->eio == NULL) {
uv__set_sys_error(loop, ENOMEM);
return -1;
}
} else {
/* sync */
req->result = uv__fs_fdatasync(file);
if (req->result) {
uv__set_sys_error(loop, errno);
}
return req->result;
}
return 0;
#else
WRAP_EIO(UV_FS_FDATASYNC, eio_fdatasync, fdatasync, ARGS1(file))
#endif
Expand Down

0 comments on commit 23dc564

Please sign in to comment.