8264744: (fs) Use file cloning in Linux version of Files::copy method

Reviewed-by: alanb
This commit is contained in:
Brian Burkhalter 2022-09-06 18:10:58 +00:00
parent 85d4b49151
commit da596182a4
4 changed files with 76 additions and 16 deletions

View File

@ -161,6 +161,8 @@ class LinuxFileSystem extends UnixFileSystem {
// -- native methods --
private static native void init();
/**
* Copies data between file descriptors {@code src} and {@code dst} using
* a platform-specific function or system call possibly having kernel
@ -179,4 +181,9 @@ class LinuxFileSystem extends UnixFileSystem {
private static native int directCopy0(int dst, int src,
long addressToPollForCancel)
throws UnixException;
static {
jdk.internal.loader.BootLoader.loadLibrary("nio");
init();
}
}

View File

@ -35,9 +35,14 @@
#include <sys/sendfile.h>
#include <fcntl.h>
#include <dlfcn.h>
#include "sun_nio_fs_LinuxFileSystem.h"
typedef ssize_t copy_file_range_func(int, loff_t*, int, loff_t*, size_t,
unsigned int);
static copy_file_range_func* my_copy_file_range_func = NULL;
#define RESTARTABLE(_cmd, _result) do { \
do { \
_result = _cmd; \
@ -52,6 +57,14 @@ static void throwUnixException(JNIEnv* env, int errnum) {
}
}
JNIEXPORT void JNICALL
Java_sun_nio_fs_LinuxFileSystem_init
(JNIEnv* env, jclass this)
{
my_copy_file_range_func =
(copy_file_range_func*) dlsym(RTLD_DEFAULT, "copy_file_range");
}
// Copy all bytes from src to dst, within the kernel if possible,
// and return zero, otherwise return the appropriate status code.
//
@ -72,7 +85,33 @@ Java_sun_nio_fs_LinuxFileSystem_directCopy0
const size_t count = cancel != NULL ?
1048576 : // 1 MB to give cancellation a chance
0x7ffff000; // maximum number of bytes that sendfile() can transfer
ssize_t bytes_sent;
if (my_copy_file_range_func != NULL) {
do {
RESTARTABLE(my_copy_file_range_func(src, NULL, dst, NULL, count, 0),
bytes_sent);
if (bytes_sent < 0) {
switch (errno) {
case EINVAL:
case ENOSYS:
case EXDEV:
// ignore and try sendfile()
break;
default:
JNU_ThrowIOExceptionWithLastError(env, "Copy failed");
return IOS_THROWN;
}
}
if (cancel != NULL && *cancel != 0) {
throwUnixException(env, ECANCELED);
return IOS_THROWN;
}
} while (bytes_sent > 0);
if (bytes_sent == 0)
return 0;
}
do {
RESTARTABLE(sendfile64(dst, src, NULL, count), bytes_sent);

View File

@ -71,6 +71,13 @@ class BsdFileSystem extends UnixFileSystem {
return SupportedFileFileAttributeViewsHolder.supportedFileAttributeViews;
}
@Override
protected int directCopy(int dst, int src, long addressToPollForCancel)
throws UnixException
{
return directCopy0(dst, src, addressToPollForCancel);
}
@Override
void copyNonPosixAttributes(int ofd, int nfd) {
UnixUserDefinedFileAttributeView.copyExtendedAttributes(ofd, nfd);
@ -102,22 +109,11 @@ class BsdFileSystem extends UnixFileSystem {
return entries;
}
@Override
FileStore getFileStore(UnixMountEntry entry) throws IOException {
return new BsdFileStore(this, entry);
}
// --- file copying ---
@Override
int directCopy(int dst, int src, long addressToPollForCancel)
throws UnixException
{
return directCopy0(dst, src, addressToPollForCancel);
}
// -- native methods --
private static native int directCopy0(int dst, int src,

View File

@ -22,7 +22,7 @@
*/
/* @test
* @bug 4313887 6838333 6917021 7006126 6950237 8006645 8201407 8267820
* @bug 4313887 6838333 6917021 7006126 6950237 8006645 8201407 8264744 8267820
* @summary Unit test for java.nio.file.Files copy and move methods (use -Dseed=X to set PRNG seed)
* @library .. /test/lib
* @build jdk.test.lib.Platform jdk.test.lib.RandomFactory
@ -59,15 +59,33 @@ public class CopyAndMove {
testCopyFileToFile(dir1, dir1, TestUtil.supportsLinks(dir1));
testMove(dir1, dir1, TestUtil.supportsLinks(dir1));
// Different directories. Use test.dir if possible as it might be
// a different volume/file system and so improve test coverage.
// Use test.dir to define second directory if possible as it might
// be a different volume/file system and so improve test coverage.
String testDir = System.getProperty("test.dir", ".");
Path dir2 = TestUtil.createTemporaryDirectory(testDir);
FileStore fileStore2 = getFileStore(dir2);
printDirInfo("dir2", dir2, fileStore2);
// If different type (format) from dir1, re-do same directory tests
if (!fileStore1.type().equals(fileStore2.type())) {
try {
testPosixAttributes =
fileStore2.supportsFileAttributeView("posix");
testCopyFileToFile(dir2, dir2, TestUtil.supportsLinks(dir2));
testMove(dir2, dir2, TestUtil.supportsLinks(dir2));
} finally {
TestUtil.removeAll(dir2);
}
}
// Different directories.
try {
// Recreate dir2 if it was removed above
if (notExists(dir2)) {
dir2 = TestUtil.createTemporaryDirectory(testDir);
}
boolean testSymbolicLinks =
TestUtil.supportsLinks(dir1) && TestUtil.supportsLinks(dir2);
FileStore fileStore2 = getFileStore(dir2);
printDirInfo("dir2", dir2, fileStore2);
testPosixAttributes = fileStore1.supportsFileAttributeView("posix") &&
fileStore2.supportsFileAttributeView("posix");
testCopyFileToFile(dir1, dir2, testSymbolicLinks);