darwin: emulate fdatasync() with fcntl(F_FULLFSYNC)
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.
This commit is contained in:
parent
837edf4c0f
commit
23dc564f3b
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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__) \
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user