--- old/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java 2016-11-16 10:28:18.418497902 -0800 +++ new/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java 2016-11-16 10:28:18.362497901 -0800 @@ -49,6 +49,12 @@ import jdk.internal.ref.Cleaner; import sun.security.action.GetPropertyAction; +import java.nio.file.FileStore; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.FileSystemException; + public class FileChannelImpl extends FileChannel { @@ -85,24 +91,55 @@ // Positional-read is not interruptible private volatile boolean uninterruptible; + //directIO + private volatile boolean direct; + + //IO alignment for DirectIO + private volatile int alignment = -1; + private FileChannelImpl(FileDescriptor fd, String path, boolean readable, - boolean writable, Object parent) + boolean writable, boolean direct, Object parent) { this.fd = fd; this.readable = readable; this.writable = writable; this.parent = parent; this.path = path; + this.direct = direct; + if (direct) + setDirectIO(); this.nd = new FileDispatcherImpl(); } + private void setDirectIO() + { + if (alignment == -1) { + Path fp = Paths.get(path); + try { + setDirect0(fd); + FileStore fs = Files.getFileStore(fp); + this.alignment = fs.getBlockSize(); + } catch (IOException e) { + this.alignment = -1; + throw new UnsupportedOperationException("Error setting up DirectIO"); + } + } + } + // Used by FileInputStream.getChannel(), FileOutputStream.getChannel // and RandomAccessFile.getChannel() public static FileChannel open(FileDescriptor fd, String path, boolean readable, boolean writable, Object parent) { - return new FileChannelImpl(fd, path, readable, writable, parent); + return new FileChannelImpl(fd, path, readable, writable, false, parent); + } + + public static FileChannel open(FileDescriptor fd, String path, + boolean readable, boolean writable, + boolean direct, Object parent) + { + return new FileChannelImpl(fd, path, readable, writable, direct, parent); } private void ensureOpen() throws IOException { @@ -150,6 +187,9 @@ } public int read(ByteBuffer dst) throws IOException { + if (direct && ((dst.remaining() % alignment != 0) || + (position() % alignment != 0))) + throw new IllegalArgumentException("IO size or position is not aligned"); ensureOpen(); if (!readable) throw new NonReadableChannelException(); @@ -162,7 +202,7 @@ if (!isOpen()) return 0; do { - n = IOUtil.read(fd, dst, -1, nd); + n = IOUtil.read(fd, dst, -1, direct, alignment, nd); } while ((n == IOStatus.INTERRUPTED) && isOpen()); return IOStatus.normalize(n); } finally { @@ -178,6 +218,10 @@ { if ((offset < 0) || (length < 0) || (offset > dsts.length - length)) throw new IndexOutOfBoundsException(); + + if (direct && (position() % alignment != 0)) + throw new IllegalArgumentException("Position is not aligned"); + ensureOpen(); if (!readable) throw new NonReadableChannelException(); @@ -190,7 +234,7 @@ if (!isOpen()) return 0; do { - n = IOUtil.read(fd, dsts, offset, length, nd); + n = IOUtil.read(fd, dsts, offset, length, direct, alignment, nd); } while ((n == IOStatus.INTERRUPTED) && isOpen()); return IOStatus.normalize(n); } finally { @@ -202,9 +246,13 @@ } public int write(ByteBuffer src) throws IOException { + ensureOpen(); if (!writable) throw new NonWritableChannelException(); + if (direct && ((src.remaining() % alignment != 0) || + (position() % alignment != 0))) + throw new IllegalArgumentException("IO size or position is not aligned"); synchronized (positionLock) { int n = 0; int ti = -1; @@ -214,7 +262,7 @@ if (!isOpen()) return 0; do { - n = IOUtil.write(fd, src, -1, nd); + n = IOUtil.write(fd, src, -1, direct, alignment, nd); } while ((n == IOStatus.INTERRUPTED) && isOpen()); return IOStatus.normalize(n); } finally { @@ -233,6 +281,10 @@ ensureOpen(); if (!writable) throw new NonWritableChannelException(); + + if (direct && (position() % alignment != 0)) + throw new IllegalArgumentException("Position is not aligned"); + synchronized (positionLock) { long n = 0; int ti = -1; @@ -242,7 +294,7 @@ if (!isOpen()) return 0; do { - n = IOUtil.write(fd, srcs, offset, length, nd); + n = IOUtil.write(fd, srcs, offset, length, direct, alignment, nd); } while ((n == IOStatus.INTERRUPTED) && isOpen()); return IOStatus.normalize(n); } finally { @@ -725,6 +777,10 @@ throw new IllegalArgumentException("Negative position"); if (!readable) throw new NonReadableChannelException(); + if (direct && ((dst.remaining() % alignment != 0) || + (position % alignment != 0))) + throw new IllegalArgumentException("IO size or position is not aligned"); + ensureOpen(); if (nd.needsPositionLock()) { synchronized (positionLock) { @@ -747,7 +803,7 @@ if (!isOpen()) return -1; do { - n = IOUtil.read(fd, dst, position, nd); + n = IOUtil.read(fd, dst, position, direct, alignment, nd); } while ((n == IOStatus.INTERRUPTED) && isOpen()); return IOStatus.normalize(n); } finally { @@ -764,6 +820,10 @@ throw new IllegalArgumentException("Negative position"); if (!writable) throw new NonWritableChannelException(); + if (direct && ((src.remaining() % alignment != 0) || + (position % alignment != 0))) + throw new IllegalArgumentException("IO size or position is not aligned"); + ensureOpen(); if (nd.needsPositionLock()) { synchronized (positionLock) { @@ -784,7 +844,7 @@ if (!isOpen()) return -1; do { - n = IOUtil.write(fd, src, position, nd); + n = IOUtil.write(fd, src, position, direct, alignment, nd); } while ((n == IOStatus.INTERRUPTED) && isOpen()); return IOStatus.normalize(n); } finally { @@ -1228,6 +1288,8 @@ // Caches fieldIDs private static native long initIDs(); + private native int setDirect0(FileDescriptor fd) throws IOException; + static { IOUtil.load(); allocationGranularity = initIDs();