--- old/src/java.base/unix/native/libnio/ch/FileChannelImpl.c 2018-08-20 11:53:46.387452425 +0100 +++ new/src/java.base/unix/native/libnio/ch/FileChannelImpl.c 2018-08-20 11:53:46.099451567 +0100 @@ -47,6 +47,7 @@ #include "nio_util.h" #include "sun_nio_ch_FileChannelImpl.h" #include "java_lang_Integer.h" +#include static jfieldID chan_fd; /* jobject 'fd' in sun.nio.ch.FileChannelImpl */ @@ -72,7 +73,7 @@ JNIEXPORT jlong JNICALL Java_sun_nio_ch_FileChannelImpl_map0(JNIEnv *env, jobject this, - jint prot, jlong off, jlong len) + jint prot, jlong off, jlong len, jboolean map_sync) { void *mapAddress = 0; jobject fdo = (*env)->GetObjectField(env, this, chan_fd); @@ -80,6 +81,9 @@ int protections = 0; int flags = 0; + // should never be called with map_sync and prot == PRIVATE + assert((prot != sun_nio_ch_FileChannelImpl_MAP_PV) ||! map_sync); + if (prot == sun_nio_ch_FileChannelImpl_MAP_RO) { protections = PROT_READ; flags = MAP_SHARED; @@ -91,6 +95,33 @@ flags = MAP_PRIVATE; } + // if MAP_SYNC and MAP_SHARED_VALIDATE are not defined then it is + // best to define them here. This ensures the code compiles on old + // OS releases which do not provide the relevant headers. If run + // on the same machine then it will work if the kernel contains + // the necessary support otherwise mmap should fail with an + // invalid argument error + +#ifndef MAP_SYNC +#define MAP_SYNC 0x80000 +#endif +#ifndef MAP_SHARED_VALIDATE +#define MAP_SHARED_VALIDATE 0x03 +#endif + + if (map_sync) { + // ensure + // 1) this is Linux on AArch64 or x86_64 + // 2) the mmap APIs are available/ at compile time +#if !defined(LINUX) || ! (defined(aarch64) || (defined(amd64) && defined(_LP64))) + // TODO - implement for solaris/AIX/BSD/WINDOWS and for 32 bit + JNU_ThrowIOException(env, "map with persistent mode is not implemented"); + return IOS_THROWN; +#else + flags |= MAP_SYNC | MAP_SHARED_VALIDATE; +#endif + } + mapAddress = mmap64( 0, /* Let OS decide location */ len, /* Number of bytes to map */ @@ -100,6 +131,11 @@ off); /* Offset into file */ if (mapAddress == MAP_FAILED) { + if (map_sync && errno == ENOTSUP) { + JNU_ThrowIOExceptionWithLastError(env, "map with persistent mode is not supported"); + return IOS_THROWN; + } + if (errno == ENOMEM) { JNU_ThrowOutOfMemoryError(env, "Map failed"); return IOS_THROWN;