Skip to content

Commit b5b3119

Browse files
author
Brian Burkhalter
committed
8266589: (fs) Improve performance of Files.copy() on macOS using copyfile(3)
Reviewed-by: alanb
1 parent 947d69d commit b5b3119

File tree

1 file changed

+40
-3
lines changed

1 file changed

+40
-3
lines changed

src/java.base/unix/native/libnio/fs/UnixCopyFile.c

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@
3232

3333
#if defined(__linux__)
3434
#include <sys/sendfile.h>
35+
#elif defined(_ALLBSD_SOURCE)
36+
#include <copyfile.h>
3537
#endif
36-
3738
#include "sun_nio_fs_UnixCopyFile.h"
3839

3940
#define RESTARTABLE(_cmd, _result) do { \
@@ -50,6 +51,23 @@ static void throwUnixException(JNIEnv* env, int errnum) {
5051
}
5152
}
5253

54+
#if defined(_ALLBSD_SOURCE)
55+
int fcopyfile_callback(int what, int stage, copyfile_state_t state,
56+
const char* src, const char* dst, void* cancel)
57+
{
58+
if (what == COPYFILE_COPY_DATA) {
59+
if (stage == COPYFILE_ERR
60+
|| (stage == COPYFILE_PROGRESS && *((int*)cancel) != 0)) {
61+
// errno will be set to ECANCELED if the operation is cancelled,
62+
// or to the appropriate error number if there is an error,
63+
// but in either case we need to quit.
64+
return COPYFILE_QUIT;
65+
}
66+
}
67+
return COPYFILE_CONTINUE;
68+
}
69+
#endif
70+
5371
/**
5472
* Transfer all bytes from src to dst within the kernel if possible (Linux),
5573
* otherwise via user-space buffers
@@ -62,10 +80,11 @@ Java_sun_nio_fs_UnixCopyFile_transfer
6280

6381
#if defined(__linux__)
6482
// Transfer within the kernel
65-
const size_t count = 1048576; // 1 MB to give cancellation a chance
83+
const size_t count = cancel != NULL ?
84+
1048576 : // 1 MB to give cancellation a chance
85+
0x7ffff000; // maximum number of bytes that sendfile() can transfer
6686
ssize_t bytes_sent;
6787
do {
68-
// sendfile() can transfer at most 0x7ffff000 bytes
6988
RESTARTABLE(sendfile64(dst, src, NULL, count), bytes_sent);
7089
if (bytes_sent == -1) {
7190
throwUnixException(env, errno);
@@ -76,6 +95,24 @@ Java_sun_nio_fs_UnixCopyFile_transfer
7695
return;
7796
}
7897
} while (bytes_sent > 0);
98+
#elif defined(_ALLBSD_SOURCE)
99+
copyfile_state_t state;
100+
if (cancel != NULL) {
101+
state = copyfile_state_alloc();
102+
copyfile_state_set(state, COPYFILE_STATE_STATUS_CB, fcopyfile_callback);
103+
copyfile_state_set(state, COPYFILE_STATE_STATUS_CTX, (void*)cancel);
104+
} else {
105+
state = NULL;
106+
}
107+
if (fcopyfile(src, dst, state, COPYFILE_DATA) < 0) {
108+
int errno_fcopyfile = errno;
109+
if (state != NULL)
110+
copyfile_state_free(state);
111+
throwUnixException(env, errno_fcopyfile);
112+
return;
113+
}
114+
if (state != NULL)
115+
copyfile_state_free(state);
79116
#else
80117
// Transfer via user-space buffers
81118
char buf[8192];

0 commit comments

Comments
 (0)