unix,win: add UV_FS_COPYFILE_FICLONE_FORCE support
UV_FS_COPYFILE_FICLONE_FORCE attempts to use copy-on-write semantics in uv_fs_copyfile(). If CoW is not available, an error is returned. Refs: https://github.com/libuv/libuv/pull/1465 Refs: https://github.com/libuv/libuv/pull/1491 PR-URL: https://github.com/libuv/libuv/pull/1768 Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
This commit is contained in:
parent
36671bf32c
commit
3ae88200d6
@ -252,6 +252,9 @@ API
|
|||||||
- `UV_FS_COPYFILE_FICLONE`: If present, `uv_fs_copyfile()` will attempt to
|
- `UV_FS_COPYFILE_FICLONE`: If present, `uv_fs_copyfile()` will attempt to
|
||||||
create a copy-on-write reflink. If the underlying platform does not
|
create a copy-on-write reflink. If the underlying platform does not
|
||||||
support copy-on-write, then a fallback copy mechanism is used.
|
support copy-on-write, then a fallback copy mechanism is used.
|
||||||
|
- `UV_FS_COPYFILE_FICLONE_FORCE`: If present, `uv_fs_copyfile()` will
|
||||||
|
attempt to create a copy-on-write reflink. If the underlying platform does
|
||||||
|
not support copy-on-write, then an error is returned.
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
If the destination path is created, but an error occurs while copying
|
If the destination path is created, but an error occurs while copying
|
||||||
@ -261,7 +264,8 @@ API
|
|||||||
|
|
||||||
.. versionadded:: 1.14.0
|
.. versionadded:: 1.14.0
|
||||||
|
|
||||||
.. versionchanged:: 1.20.0 `UV_FS_COPYFILE_FICLONE` is supported.
|
.. versionchanged:: 1.20.0 `UV_FS_COPYFILE_FICLONE` and
|
||||||
|
`UV_FS_COPYFILE_FICLONE_FORCE` are supported.
|
||||||
|
|
||||||
.. c:function:: int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd, uv_file in_fd, int64_t in_offset, size_t length, uv_fs_cb cb)
|
.. c:function:: int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd, uv_file in_fd, int64_t in_offset, size_t length, uv_fs_cb cb)
|
||||||
|
|
||||||
|
|||||||
@ -1196,6 +1196,12 @@ UV_EXTERN int uv_fs_write(uv_loop_t* loop,
|
|||||||
*/
|
*/
|
||||||
#define UV_FS_COPYFILE_FICLONE 0x0002
|
#define UV_FS_COPYFILE_FICLONE 0x0002
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This flag can be used with uv_fs_copyfile() to attempt to create a reflink.
|
||||||
|
* If copy-on-write is not supported, an error is returned.
|
||||||
|
*/
|
||||||
|
#define UV_FS_COPYFILE_FICLONE_FORCE 0x0004
|
||||||
|
|
||||||
UV_EXTERN int uv_fs_copyfile(uv_loop_t* loop,
|
UV_EXTERN int uv_fs_copyfile(uv_loop_t* loop,
|
||||||
uv_fs_t* req,
|
uv_fs_t* req,
|
||||||
const char* path,
|
const char* path,
|
||||||
|
|||||||
@ -797,6 +797,15 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
|
|||||||
if (req->flags & UV_FS_COPYFILE_FICLONE)
|
if (req->flags & UV_FS_COPYFILE_FICLONE)
|
||||||
flags |= COPYFILE_CLONE;
|
flags |= COPYFILE_CLONE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
|
||||||
|
#ifdef COPYFILE_CLONE_FORCE
|
||||||
|
flags |= COPYFILE_CLONE_FORCE;
|
||||||
|
#else
|
||||||
|
return UV_ENOSYS;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
return copyfile(req->path, req->new_path, NULL, flags);
|
return copyfile(req->path, req->new_path, NULL, flags);
|
||||||
#else
|
#else
|
||||||
uv_fs_t fs_req;
|
uv_fs_t fs_req;
|
||||||
@ -850,11 +859,14 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FICLONE
|
#ifdef FICLONE
|
||||||
if (req->flags & UV_FS_COPYFILE_FICLONE) {
|
if (req->flags & UV_FS_COPYFILE_FICLONE ||
|
||||||
|
req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
|
||||||
if (ioctl(dstfd, FICLONE, srcfd) == -1) {
|
if (ioctl(dstfd, FICLONE, srcfd) == -1) {
|
||||||
/* If an error occurred that the sendfile fallback also won't handle,
|
/* If an error occurred that the sendfile fallback also won't handle, or
|
||||||
then exit. Otherwise, fall through to try using sendfile(). */
|
this is a force clone then exit. Otherwise, fall through to try using
|
||||||
if (errno != ENOTTY && errno != EOPNOTSUPP && errno != EXDEV) {
|
sendfile(). */
|
||||||
|
if ((errno != ENOTTY && errno != EOPNOTSUPP && errno != EXDEV) ||
|
||||||
|
req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
|
||||||
err = -errno;
|
err = -errno;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -862,6 +874,11 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
|
||||||
|
err = UV_ENOSYS;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bytes_to_send = statsbuf.st_size;
|
bytes_to_send = statsbuf.st_size;
|
||||||
@ -1526,8 +1543,11 @@ int uv_fs_copyfile(uv_loop_t* loop,
|
|||||||
uv_fs_cb cb) {
|
uv_fs_cb cb) {
|
||||||
INIT(COPYFILE);
|
INIT(COPYFILE);
|
||||||
|
|
||||||
if (flags & ~(UV_FS_COPYFILE_EXCL | UV_FS_COPYFILE_FICLONE))
|
if (flags & ~(UV_FS_COPYFILE_EXCL |
|
||||||
|
UV_FS_COPYFILE_FICLONE |
|
||||||
|
UV_FS_COPYFILE_FICLONE_FORCE)) {
|
||||||
return UV_EINVAL;
|
return UV_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
PATH2;
|
PATH2;
|
||||||
req->flags = flags;
|
req->flags = flags;
|
||||||
|
|||||||
11
src/win/fs.c
11
src/win/fs.c
@ -1390,6 +1390,12 @@ static void fs__copyfile(uv_fs_t* req) {
|
|||||||
int overwrite;
|
int overwrite;
|
||||||
|
|
||||||
flags = req->fs.info.file_flags;
|
flags = req->fs.info.file_flags;
|
||||||
|
|
||||||
|
if (flags & UV_FS_COPYFILE_FICLONE_FORCE) {
|
||||||
|
SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
overwrite = flags & UV_FS_COPYFILE_EXCL;
|
overwrite = flags & UV_FS_COPYFILE_EXCL;
|
||||||
|
|
||||||
if (CopyFileW(req->file.pathw, req->fs.info.new_pathw, overwrite) == 0) {
|
if (CopyFileW(req->file.pathw, req->fs.info.new_pathw, overwrite) == 0) {
|
||||||
@ -2334,8 +2340,11 @@ int uv_fs_copyfile(uv_loop_t* loop,
|
|||||||
|
|
||||||
INIT(UV_FS_COPYFILE);
|
INIT(UV_FS_COPYFILE);
|
||||||
|
|
||||||
if (flags & ~(UV_FS_COPYFILE_EXCL | UV_FS_COPYFILE_FICLONE))
|
if (flags & ~(UV_FS_COPYFILE_EXCL |
|
||||||
|
UV_FS_COPYFILE_FICLONE |
|
||||||
|
UV_FS_COPYFILE_FICLONE_FORCE)) {
|
||||||
return UV_EINVAL;
|
return UV_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
err = fs__capture_path(req, path, new_path, cb != NULL);
|
err = fs__capture_path(req, path, new_path, cb != NULL);
|
||||||
|
|
||||||
|
|||||||
@ -175,6 +175,15 @@ TEST_IMPL(fs_copyfile) {
|
|||||||
ASSERT(r == 0);
|
ASSERT(r == 0);
|
||||||
handle_result(&req);
|
handle_result(&req);
|
||||||
|
|
||||||
|
/* Copies file using UV_FS_COPYFILE_FICLONE_FORCE. */
|
||||||
|
unlink(dst);
|
||||||
|
r = uv_fs_copyfile(NULL, &req, fixture, dst, UV_FS_COPYFILE_FICLONE_FORCE,
|
||||||
|
NULL);
|
||||||
|
ASSERT(r == 0 || r == UV_ENOSYS || r == UV_ENOTSUP || r == UV_ENOTTY);
|
||||||
|
|
||||||
|
if (r == 0)
|
||||||
|
handle_result(&req);
|
||||||
|
|
||||||
unlink(dst); /* Cleanup */
|
unlink(dst); /* Cleanup */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user