Skip to content

Commit

Permalink
linux: use copy_file_range for uv_fs_copyfile when possible
Browse files Browse the repository at this point in the history
  • Loading branch information
CarterLi committed Jun 26, 2019
1 parent 5fc58eb commit 9ac78b7
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"files.associations": {
"syscall.h": "c"
}
}
31 changes: 31 additions & 0 deletions src/unix/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@
# include <sys/sendfile.h>
#endif

#if defined(__linux__)
# include <sys/syscall.h>
# include <sys/types.h>
#endif

#if defined(__APPLE__)
# include <sys/sysctl.h>
#elif defined(__linux__) && !defined(FICLONE)
Expand Down Expand Up @@ -736,6 +741,15 @@ static ssize_t uv__fs_sendfile_emul(uv_fs_t* req) {
return nsent;
}

#ifdef __NR_copy_file_range
static loff_t
uv__fs_copy_file_range(int fd_in, loff_t *off_in, int fd_out,
loff_t *off_out, size_t len, unsigned int flags)
{
return syscall(__NR_copy_file_range, fd_in, off_in,
fd_out, off_out, len, flags);
}
#endif

static ssize_t uv__fs_sendfile(uv_fs_t* req) {
int in_fd;
Expand All @@ -750,8 +764,25 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
ssize_t r;

off = req->off;

#ifdef __NR_copy_file_range
static int copy_file_range_support = 1;

if (copy_file_range_support) {
r = uv__fs_copy_file_range(in_fd, NULL, out_fd, &off, req->bufsml[0].len, 0);

if (r == -1 && errno == ENOSYS) {
errno = 0;
copy_file_range_support = 0;
} else {
goto ok;
}
}
#endif

r = sendfile(out_fd, in_fd, &off, req->bufsml[0].len);

ok:
/* sendfile() on SunOS returns EINVAL if the target fd is not a socket but
* it still writes out data. Fortunately, we can detect it by checking if
* the offset has been updated.
Expand Down

0 comments on commit 9ac78b7

Please sign in to comment.