--- old/make/mapfiles/libjava/mapfile-vers 2016-09-29 14:26:25.631927314 -0700 +++ new/make/mapfiles/libjava/mapfile-vers 2016-09-29 14:26:25.479927312 -0700 @@ -77,6 +77,7 @@ Java_java_io_FileDescriptor_initIDs; Java_java_io_FileDescriptor_sync; Java_java_io_FileDescriptor_getAppend; + Java_java_io_FileDescriptor_getDirect; Java_java_io_FileInputStream_available; Java_java_io_FileInputStream_close0; Java_java_io_FileInputStream_initIDs; --- old/make/mapfiles/libnio/mapfile-linux 2016-09-29 14:26:25.915927316 -0700 +++ new/make/mapfiles/libnio/mapfile-linux 2016-09-29 14:26:25.797927315 -0700 @@ -70,11 +70,17 @@ Java_sun_nio_ch_FileDispatcherImpl_pwrite0; Java_sun_nio_ch_FileDispatcherImpl_read0; Java_sun_nio_ch_FileDispatcherImpl_readv0; + Java_sun_nio_ch_FileDispatcherImpl_preadDirect0; + Java_sun_nio_ch_FileDispatcherImpl_pwriteDirect0; + Java_sun_nio_ch_FileDispatcherImpl_readDirect0; + Java_sun_nio_ch_FileDispatcherImpl_readvDirect0; Java_sun_nio_ch_FileDispatcherImpl_release0; Java_sun_nio_ch_FileDispatcherImpl_size0; Java_sun_nio_ch_FileDispatcherImpl_truncate0; Java_sun_nio_ch_FileDispatcherImpl_write0; Java_sun_nio_ch_FileDispatcherImpl_writev0; + Java_sun_nio_ch_FileDispatcherImpl_writeDirect0; + Java_sun_nio_ch_FileDispatcherImpl_writevDirect0; Java_sun_nio_ch_FileKey_init; Java_sun_nio_ch_FileKey_initIDs; Java_sun_nio_ch_InheritedChannel_close0; --- old/src/java.base/share/classes/jdk/internal/misc/JavaIOFileDescriptorAccess.java 2016-09-29 14:26:26.165927319 -0700 +++ new/src/java.base/share/classes/jdk/internal/misc/JavaIOFileDescriptorAccess.java 2016-09-29 14:26:26.050927318 -0700 @@ -35,6 +35,8 @@ public int get(FileDescriptor fd); public void setAppend(FileDescriptor obj, boolean append); public boolean getAppend(FileDescriptor obj); + public void setDirect(FileDescriptor obj, boolean direct); + public boolean getDirect(FileDescriptor obj); // Only valid on Windows public void setHandle(FileDescriptor obj, long handle); --- old/src/java.base/share/classes/sun/nio/ch/IOUtil.java 2016-09-29 14:26:26.410927321 -0700 +++ new/src/java.base/share/classes/sun/nio/ch/IOUtil.java 2016-09-29 14:26:26.295927320 -0700 @@ -29,6 +29,11 @@ import java.io.IOException; import java.nio.ByteBuffer; +import jdk.internal.misc.JavaIOFileDescriptorAccess; +import jdk.internal.misc.JavaNioAccess; +import jdk.internal.misc.SharedSecrets; +import jdk.internal.ref.Cleaner; +import sun.security.action.GetPropertyAction; /** * File-descriptor based I/O utilities that are shared by NIO classes. @@ -41,6 +46,9 @@ */ static final int IOV_MAX; + private static final JavaIOFileDescriptorAccess fdAccess = + SharedSecrets.getJavaIOFileDescriptorAccess(); + private IOUtil() { } // No instantiation static int write(FileDescriptor fd, ByteBuffer src, long position, @@ -86,11 +94,19 @@ if (rem == 0) return 0; if (position != -1) { - written = nd.pwrite(fd, - ((DirectBuffer)bb).address() + pos, - rem, position); + if (fdAccess.getDirect(fd)) + written = nd.pwriteDirect(fd, + ((DirectBuffer)bb).address() + pos, + rem, position); + else + written = nd.pwrite(fd, + ((DirectBuffer)bb).address() + pos, + rem, position); } else { - written = nd.write(fd, ((DirectBuffer)bb).address() + pos, rem); + if (fdAccess.getDirect(fd)) + written = nd.writeDirect(fd, ((DirectBuffer)bb).address() + pos, rem); + else + written = nd.write(fd, ((DirectBuffer)bb).address() + pos, rem); } if (written > 0) bb.position(pos + written); @@ -145,7 +161,11 @@ if (iov_len == 0) return 0L; - long bytesWritten = nd.writev(fd, vec.address, iov_len); + long bytesWritten; + if (fdAccess.getDirect(fd)) + bytesWritten = nd.writevDirect(fd, vec.address, iov_len); + else + bytesWritten = nd.writev(fd, vec.address, iov_len); // Notify the buffers how many bytes were taken long left = bytesWritten; @@ -217,10 +237,17 @@ return 0; int n = 0; if (position != -1) { - n = nd.pread(fd, ((DirectBuffer)bb).address() + pos, - rem, position); + if (fdAccess.getDirect(fd)) + n = nd.preadDirect(fd, ((DirectBuffer)bb).address() + pos, + rem, position); + else + n = nd.pread(fd, ((DirectBuffer)bb).address() + pos, + rem, position); } else { - n = nd.read(fd, ((DirectBuffer)bb).address() + pos, rem); + if (fdAccess.getDirect(fd)) + n = nd.readDirect(fd, ((DirectBuffer)bb).address() + pos, rem); + else + n = nd.read(fd, ((DirectBuffer)bb).address() + pos, rem); } if (n > 0) bb.position(pos + n); @@ -274,8 +301,11 @@ } if (iov_len == 0) return 0L; - - long bytesRead = nd.readv(fd, vec.address, iov_len); + long bytesRead; + if (fdAccess.getDirect(fd)) + bytesRead = nd.readvDirect(fd, vec.address, iov_len); + else + bytesRead = nd.readv(fd, vec.address, iov_len); // Notify the buffers how many bytes were read long left = bytesRead; --- old/src/java.base/share/classes/sun/nio/ch/NativeDispatcher.java 2016-09-29 14:26:26.651927323 -0700 +++ new/src/java.base/share/classes/sun/nio/ch/NativeDispatcher.java 2016-09-29 14:26:26.545927322 -0700 @@ -38,6 +38,12 @@ abstract int read(FileDescriptor fd, long address, int len) throws IOException; + int readDirect(FileDescriptor fd, long address, int len) + throws IOException + { + throw new IOException("Operation Unsupported"); + } + /** * Returns {@code true} if pread/pwrite needs to be synchronized with * position sensitive methods. @@ -52,21 +58,51 @@ throw new IOException("Operation Unsupported"); } + int preadDirect(FileDescriptor fd, long address, int len, long position) + throws IOException + { + throw new IOException("Operation Unsupported"); + } + abstract long readv(FileDescriptor fd, long address, int len) throws IOException; + long readvDirect(FileDescriptor fd, long address, int len) + throws IOException + { + throw new IOException("Operation Unsupported"); + } + abstract int write(FileDescriptor fd, long address, int len) throws IOException; + int writeDirect(FileDescriptor fd, long address, int len) + throws IOException + { + throw new IOException("Operation Unsupported"); + } + int pwrite(FileDescriptor fd, long address, int len, long position) throws IOException { throw new IOException("Operation Unsupported"); } + int pwriteDirect(FileDescriptor fd, long address, int len, long position) + throws IOException + { + throw new IOException("Operation Unsupported"); + } + abstract long writev(FileDescriptor fd, long address, int len) throws IOException; + long writevDirect(FileDescriptor fd, long address, int len) + throws IOException + { + throw new IOException("Operation Unsupported"); + } + abstract void close(FileDescriptor fd) throws IOException; // Prepare the given fd for closing by duping it to a known internal fd --- old/src/java.base/share/classes/sun/nio/fs/ExtendedOptions.java 2016-09-29 14:26:26.919927326 -0700 +++ new/src/java.base/share/classes/sun/nio/fs/ExtendedOptions.java 2016-09-29 14:26:26.795927325 -0700 @@ -137,6 +137,8 @@ public static final InternalOption FILE_TREE = new InternalOption<>(); + public static final InternalOption DIRECT = new InternalOption<>(); + public static final InternalOption SENSITIVITY_HIGH = new InternalOption<>(); public static final InternalOption SENSITIVITY_MEDIUM = new InternalOption<>(); public static final InternalOption SENSITIVITY_LOW = new InternalOption<>(); --- old/src/java.base/unix/classes/java/io/FileDescriptor.java 2016-09-29 14:26:27.176927328 -0700 +++ new/src/java.base/unix/classes/java/io/FileDescriptor.java 2016-09-29 14:26:27.053927327 -0700 @@ -59,6 +59,11 @@ private boolean append; /** + * true, if file is opened with O_DIRECT flag; + */ + private boolean direct; + + /** * Constructs an (invalid) FileDescriptor * object. */ @@ -69,6 +74,7 @@ private FileDescriptor(int fd) { this.fd = fd; this.append = getAppend(fd); + this.direct = getDirect(fd); } /** @@ -165,6 +171,14 @@ return obj.append; } + public void setDirect(FileDescriptor obj, boolean direct) { + obj.direct = direct; + } + + public boolean getDirect(FileDescriptor obj) { + return obj.direct; + } + public void setHandle(FileDescriptor obj, long handle) { throw new UnsupportedOperationException(); } @@ -181,6 +195,11 @@ */ private static native boolean getAppend(int fd); + /** + * Returns true, if the file was opened with O_DIRECT flag. + */ + private native boolean getDirect(int fd); + /* * Package private methods to track referents. * If multiple streams point to the same FileDescriptor, we cycle --- old/src/java.base/unix/classes/sun/nio/ch/FileDispatcherImpl.java 2016-09-29 14:26:27.416927331 -0700 +++ new/src/java.base/unix/classes/sun/nio/ch/FileDispatcherImpl.java 2016-09-29 14:26:27.310927330 -0700 @@ -30,6 +30,8 @@ class FileDispatcherImpl extends FileDispatcher { + private int pageSize = -1; + static { IOUtil.load(); init(); @@ -52,6 +54,20 @@ return readv0(fd, address, len); } + int readDirect(FileDescriptor fd, long address, int len) throws IOException { + return readDirect0(fd, address, len); + } + + int preadDirect(FileDescriptor fd, long address, int len, long position) + throws IOException + { + return preadDirect0(fd, address, len, position); + } + + long readvDirect(FileDescriptor fd, long address, int len) throws IOException { + return readvDirect0(fd, address, len); + } + int write(FileDescriptor fd, long address, int len) throws IOException { return write0(fd, address, len); } @@ -68,6 +84,22 @@ return writev0(fd, address, len); } + int writeDirect(FileDescriptor fd, long address, int len) throws IOException { + return writeDirect0(fd, address, len); + } + + int pwriteDirect(FileDescriptor fd, long address, int len, long position) + throws IOException + { + return pwriteDirect0(fd, address, len, position); + } + + long writevDirect(FileDescriptor fd, long address, int len) + throws IOException + { + return writevDirect0(fd, address, len); + } + int force(FileDescriptor fd, boolean metaData) throws IOException { return force0(fd, metaData); } @@ -123,6 +155,15 @@ static native long readv0(FileDescriptor fd, long address, int len) throws IOException; + static native int readDirect0(FileDescriptor fd, long address, int len) + throws IOException; + + static native int preadDirect0(FileDescriptor fd, long address, int len, + long position) throws IOException; + + static native long readvDirect0(FileDescriptor fd, long address, int len) + throws IOException; + static native int write0(FileDescriptor fd, long address, int len) throws IOException; @@ -132,6 +173,15 @@ static native long writev0(FileDescriptor fd, long address, int len) throws IOException; + static native int writeDirect0(FileDescriptor fd, long address, int len) + throws IOException; + + static native int pwriteDirect0(FileDescriptor fd, long address, int len, + long position) throws IOException; + + static native long writevDirect0(FileDescriptor fd, long address, int len) + throws IOException; + static native int force0(FileDescriptor fd, boolean metaData) throws IOException; @@ -153,5 +203,4 @@ static native void closeIntFD(int fd) throws IOException; static native void init(); - } --- old/src/java.base/unix/classes/sun/nio/fs/UnixChannelFactory.java 2016-09-29 14:26:27.658927333 -0700 +++ new/src/java.base/unix/classes/sun/nio/fs/UnixChannelFactory.java 2016-09-29 14:26:27.552927332 -0700 @@ -64,6 +64,7 @@ boolean deleteOnClose; boolean sync; boolean dsync; + boolean direct; static Flags toFlags(Set options) { Flags flags = new Flags(); @@ -88,6 +89,12 @@ flags.noFollowLinks = true; continue; } + + if (ExtendedOptions.DIRECT.matches(option)) { + flags.direct = true; + continue; + } + if (option == null) throw new NullPointerException(); throw new UnsupportedOperationException(option + " not supported"); @@ -236,6 +243,9 @@ if (flags.sync) oflags |= O_SYNC; + if (flags.direct) + oflags |= O_DIRECT; + // permission check before we open the file SecurityManager sm = System.getSecurityManager(); if (sm != null) { @@ -289,6 +299,7 @@ FileDescriptor fdObj = new FileDescriptor(); fdAccess.set(fdObj, fd); fdAccess.setAppend(fdObj, flags.append); + fdAccess.setDirect(fdObj, flags.direct); return fdObj; } } --- old/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template 2016-09-29 14:26:27.902927335 -0700 +++ new/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template 2016-09-29 14:26:27.795927334 -0700 @@ -27,6 +27,8 @@ @@END_COPYRIGHT@@ +#define _GNU_SOURCE + #include #include #include @@ -55,6 +57,7 @@ static final int PREFIX_O_EXCL = O_EXCL; static final int PREFIX_O_TRUNC = O_TRUNC; static final int PREFIX_O_SYNC = O_SYNC; + static final int PREFIX_O_DIRECT = O_DIRECT; #ifndef O_DSYNC // At least FreeBSD doesn't define O_DSYNC --- old/src/java.base/unix/native/include/jvm_md.h 2016-09-29 14:26:28.145927338 -0700 +++ new/src/java.base/unix/native/include/jvm_md.h 2016-09-29 14:26:28.039927337 -0700 @@ -75,6 +75,7 @@ #define JVM_O_O_APPEND O_APPEND #define JVM_O_EXCL O_EXCL #define JVM_O_CREAT O_CREAT +#define JVM_O_DIRECT O_DIRECT /* Signals */ --- old/src/java.base/unix/native/libjava/FileDescriptor_md.c 2016-09-29 14:26:28.386927340 -0700 +++ new/src/java.base/unix/native/libjava/FileDescriptor_md.c 2016-09-29 14:26:28.281927339 -0700 @@ -70,3 +70,9 @@ int flags = fcntl(fd, F_GETFL); return ((flags & O_APPEND) == 0) ? JNI_FALSE : JNI_TRUE; } + +JNIEXPORT jboolean JNICALL +Java_java_io_FileDescriptor_getDirect(JNIEnv *env, jclass fdClass, jint fd) { + int flags = fcntl(fd, F_GETFL); + return ((flags & O_DIRECT) == 0) ? JNI_FALSE : JNI_TRUE; +} --- old/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c 2016-09-29 14:26:28.724927343 -0700 +++ new/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c 2016-09-29 14:26:28.524927341 -0700 @@ -34,6 +34,8 @@ #include #include #include +#include +#include #if defined(__linux__) #include #include @@ -58,7 +60,7 @@ static int preCloseFD = -1; /* File descriptor to which we dup other fd's before closing them for real */ - +static int pageSize = -1; JNIEXPORT void JNICALL Java_sun_nio_ch_FileDispatcherImpl_init(JNIEnv *env, jclass cl) @@ -70,6 +72,75 @@ } preCloseFD = sp[0]; close(sp[1]); + + pageSize = getpagesize(); +} + +jint readDirect(JNIEnv *env, jclass clazz, jint fd, jlong offset, jint len, void *buf, jint pageSize) +{ + int gap = 0; + int newLen = -1; + long newStartLocation = -1; + void *bytes = NULL; + int nread = -1; + + newStartLocation = offset; + if ((newStartLocation % pageSize) != 0) { + newStartLocation = offset / pageSize * pageSize; + gap = offset - newStartLocation; + } + + lseek(fd, newStartLocation, SEEK_SET); + + newLen = len; + if ((newLen % pageSize) != 0) { + newLen = (len / pageSize + 1) * pageSize; + } + + if ((newLen - gap) < len) { + newLen = newLen + pageSize; + } + + posix_memalign(&bytes, pageSize, newLen); + + nread = read(fd, bytes, newLen); + + if (nread > gap) { + if ((nread - gap) >= len) { + memcpy(buf, bytes+gap, len); + nread = len; + } else { + memcpy(buf, bytes+gap, (nread-gap)); + nread = nread - gap; + } + } else if (nread == -1) { + JNU_ThrowIOExceptionWithLastError(env, "Read error"); + } else { /*EOF*/ + nread = 0; + } + + free(bytes); + + return nread; +} + +jint writeDirect(JNIEnv *env, jclass clazz, jint fd, jlong offset, jint len, void *buf, jint pageSize) +{ + void *bytes = NULL; + int nwrite = -1; + posix_memalign(&bytes, pageSize, len); + memcpy(bytes, buf, len); + + lseek(fd, offset, SEEK_SET); + + nwrite = write(fd, bytes, len); + if (nwrite == -1) { + JNU_ThrowIOExceptionWithLastError(env, "Write error"); + } + + free(bytes); + + return nwrite; } JNIEXPORT jint JNICALL @@ -83,6 +154,23 @@ } JNIEXPORT jint JNICALL +Java_sun_nio_ch_FileDispatcherImpl_readDirect0(JNIEnv *env, jclass clazz, + jobject fdo, jlong address, jint len) +{ + jint fd = fdval(env, fdo); + void *buf = (void *)jlong_to_ptr(address); + long currentLocation = lseek(fd, 0, SEEK_CUR); + + if (currentLocation % pageSize == 0 && len % pageSize == 0 && address % pageSize == 0) { + return convertReturnVal(env, read(fd, buf, len), JNI_TRUE); + } + + int nread = readDirect(env, clazz, fd, currentLocation, len, buf, pageSize); + lseek(fd, (currentLocation + nread), SEEK_SET); + return convertReturnVal(env, nread, JNI_TRUE); +} + +JNIEXPORT jint JNICALL Java_sun_nio_ch_FileDispatcherImpl_pread0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len, jlong offset) { @@ -92,15 +180,111 @@ return convertReturnVal(env, pread64(fd, buf, len, offset), JNI_TRUE); } +JNIEXPORT jint JNICALL +Java_sun_nio_ch_FileDispatcherImpl_preadDirect0(JNIEnv *env, jclass clazz, jobject fdo, + jlong address, jint len, jlong offset) +{ + jint fd = fdval(env, fdo); + void *buf = (void *)jlong_to_ptr(address); + + long currentLocation = lseek(fd, 0, SEEK_CUR); + + if (offset % pageSize == 0 && len % pageSize == 0 && address % pageSize == 0) { + return convertReturnVal(env, pread64(fd, buf, len, offset), JNI_TRUE); + } + + int nread = readDirect(env, clazz, fd, offset, len, buf, pageSize); + lseek(fd, currentLocation, SEEK_SET); + return convertReturnVal(env, nread, JNI_TRUE); +} + JNIEXPORT jlong JNICALL Java_sun_nio_ch_FileDispatcherImpl_readv0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len) { jint fd = fdval(env, fdo); struct iovec *iov = (struct iovec *)jlong_to_ptr(address); + return convertLongReturnVal(env, readv(fd, iov, len), JNI_TRUE); } +JNIEXPORT jlong JNICALL +Java_sun_nio_ch_FileDispatcherImpl_readvDirect0(JNIEnv *env, jclass clazz, + jobject fdo, jlong address, jint len) +{ + int i; + int totalLen = 0; + int newLen = 0; + int gap = 0; + int nread = 0; + int result = 0; + void *bytes = NULL; + long currentLocation = -1; + long newStartLocation = -1; + + jint fd = fdval(env, fdo); + struct iovec *iov = (struct iovec *)jlong_to_ptr(address); + + currentLocation = lseek(fd, 0, SEEK_CUR); + newStartLocation = currentLocation; + if ((newStartLocation % pageSize) != 0) { + newStartLocation = currentLocation / pageSize * pageSize; + gap = currentLocation - newStartLocation; + } + + lseek(fd, newStartLocation, SEEK_SET); + + for (i = 0; i < len; i++) { + totalLen += iov[i].iov_len; + } + + newLen = totalLen; + if ((newLen % pageSize) != 0) { + newLen = (totalLen / pageSize + 1) * pageSize; + } + + if ((newLen - gap) < totalLen) { + newLen += pageSize; + } + + posix_memalign(&bytes, pageSize, newLen); + nread = read(fd, bytes, newLen); + + if (nread > gap) { + if ((nread - gap) >= totalLen) { + nread = totalLen; + } else { + nread -= gap; + } + } else if (nread == -1) { + JNU_ThrowIOExceptionWithLastError(env, "Read error"); + } else { /*EOF*/ + nread = 0; + } + + i = 0; + int tempLen; + while (nread > 0) { + tempLen = iov[i].iov_len; + if (nread >= tempLen) { + memcpy(iov[i].iov_base, (bytes + gap + result), tempLen); + result += tempLen; + nread -= tempLen; + } else { + memcpy(iov[i].iov_base, (bytes + gap + result), nread); + result += nread; + nread = 0; + } + i++; + } + + free(bytes); + + lseek(fd, (currentLocation + result), SEEK_SET); + + return convertLongReturnVal(env, result, JNI_TRUE); +} + JNIEXPORT jint JNICALL Java_sun_nio_ch_FileDispatcherImpl_write0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len) @@ -112,6 +296,31 @@ } JNIEXPORT jint JNICALL +Java_sun_nio_ch_FileDispatcherImpl_writeDirect0(JNIEnv *env, jclass clazz, + jobject fdo, jlong address, jint len) +{ + jint fd = fdval(env, fdo); + void *buf = (void *)jlong_to_ptr(address); + + long currentLocation = lseek(fd, 0, SEEK_CUR); + + if ((len % pageSize != 0) || (currentLocation % pageSize != 0)) { + JNU_ThrowByNameWithMessageAndLastError(env, "java/io/IOException", + "In DirectIO mode, the IO size and currentLocation must be aligned with kernel page size"); + } + + if (address % pageSize == 0) { + return convertReturnVal(env, write(fd, buf, len), JNI_FALSE); + } + + int nwrite = writeDirect(env, clazz, fd, currentLocation, len, buf, pageSize); + + lseek(fd, (currentLocation + nwrite), SEEK_SET); + + return convertReturnVal(env, nwrite, JNI_FALSE); +} + +JNIEXPORT jint JNICALL Java_sun_nio_ch_FileDispatcherImpl_pwrite0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len, jlong offset) { @@ -121,15 +330,85 @@ return convertReturnVal(env, pwrite64(fd, buf, len, offset), JNI_FALSE); } +JNIEXPORT jint JNICALL +Java_sun_nio_ch_FileDispatcherImpl_pwriteDirect0(JNIEnv *env, jclass clazz, jobject fdo, + jlong address, jint len, jlong offset) +{ + jint fd = fdval(env, fdo); + void *buf = (void *)jlong_to_ptr(address); + + if ((len % pageSize != 0) || (offset % pageSize != 0)) { + JNU_ThrowByNameWithMessageAndLastError(env, "java/io/IOException", + "In DirectIO mode, the IO size and offset must be aligned with kernel page size"); + } + + if (address % pageSize == 0) { + return convertReturnVal(env, pwrite64(fd, buf, len, offset), JNI_FALSE); + } + + long currentLocation = lseek(fd, 0, SEEK_CUR); + + int nwrite = writeDirect(env, clazz, fd, offset, len, buf, pageSize); + + lseek(fd, currentLocation, SEEK_SET); + + return convertReturnVal(env, nwrite, JNI_FALSE); +} + JNIEXPORT jlong JNICALL Java_sun_nio_ch_FileDispatcherImpl_writev0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len) { jint fd = fdval(env, fdo); struct iovec *iov = (struct iovec *)jlong_to_ptr(address); + return convertLongReturnVal(env, writev(fd, iov, len), JNI_FALSE); } +JNIEXPORT jlong JNICALL +Java_sun_nio_ch_FileDispatcherImpl_writevDirect0(JNIEnv *env, jclass clazz, + jobject fdo, jlong address, jint len) +{ + int i; + int totalLen = 0; + int currentLocation = -1; + int nwrite = 0; + int result = 0; + void *bytes = NULL; + + jint fd = fdval(env, fdo); + struct iovec *iov = (struct iovec *)jlong_to_ptr(address); + + for (i = 0; i < len; i++) { + totalLen += iov[i].iov_len; + } + + currentLocation = lseek(fd, 0, SEEK_CUR); + + if ((totalLen % pageSize != 0) || (currentLocation % pageSize != 0)) { + JNU_ThrowByNameWithMessageAndLastError(env, "java/io/IOException", + "In DirectIO mode, the IO size and offset must be aligned with kernel page size"); + } + + posix_memalign(&bytes, pageSize, totalLen); + + int tempLen; + for (i = 0; i < len; i++) { + tempLen = iov[i].iov_len; + memcpy((bytes + result), iov[i].iov_base, tempLen); + result += tempLen; + } + nwrite = write(fd, bytes, totalLen); + if (nwrite == -1) { + JNU_ThrowIOExceptionWithLastError(env, "Write error"); + } + + free(bytes); + + return convertLongReturnVal(env, nwrite, JNI_FALSE); + +} + static jlong handle(JNIEnv *env, jlong rv, char *msg) { --- old/src/jdk.unsupported/share/classes/com/sun/nio/file/ExtendedOpenOption.java 2016-09-29 14:26:29.004927346 -0700 +++ new/src/jdk.unsupported/share/classes/com/sun/nio/file/ExtendedOpenOption.java 2016-09-29 14:26:28.880927344 -0700 @@ -47,7 +47,12 @@ /** * Prevent operations on the file that request delete access. */ - NOSHARE_DELETE(ExtendedOptions.NOSHARE_DELETE); + NOSHARE_DELETE(ExtendedOptions.NOSHARE_DELETE), + + /** + * DirectIO. + */ + DIRECT(ExtendedOptions.DIRECT); ExtendedOpenOption(ExtendedOptions.InternalOption option) { option.register(this);