8274548: (fc) FileChannel gathering write fails with IOException "Invalid argument" on macOS 11.6

Reviewed-by: alanb
This commit is contained in:
Brian Burkhalter 2021-10-12 15:25:53 +00:00
parent f623460668
commit 07b1f1c282
4 changed files with 172 additions and 4 deletions

View file

@ -44,6 +44,11 @@ public class IOUtil {
*/
static final int IOV_MAX;
/**
* Max total number of bytes that writev supports
*/
static final long WRITEV_MAX;
private IOUtil() { } // No instantiation
static int write(FileDescriptor fd, ByteBuffer src, long position,
@ -172,9 +177,10 @@ public class IOUtil {
Runnable handleReleasers = null;
try {
// Iterate over buffers to populate native iovec array.
long writevLen = 0L;
int count = offset + length;
int i = offset;
while (i < count && iov_len < IOV_MAX) {
while (i < count && iov_len < IOV_MAX && writevLen < WRITEV_MAX) {
ByteBuffer buf = bufs[i];
var h = acquireScope(buf, async);
if (h != null) {
@ -188,6 +194,10 @@ public class IOUtil {
Util.checkRemainingBufferSizeAligned(rem, alignment);
if (rem > 0) {
long headroom = WRITEV_MAX - writevLen;
if (headroom < rem)
rem = (int)headroom;
vec.setBuffer(iov_len, buf, pos, rem);
// allocate shadow buffer to ensure I/O is done with direct buffer
@ -197,10 +207,9 @@ public class IOUtil {
shadow = Util.getTemporaryAlignedDirectBuffer(rem, alignment);
else
shadow = Util.getTemporaryDirectBuffer(rem);
shadow.put(buf);
shadow.put(shadow.position(), buf, pos, rem);
shadow.flip();
vec.setShadow(iov_len, shadow);
buf.position(pos); // temporarily restore position in user buffer
buf = shadow;
pos = shadow.position();
}
@ -208,6 +217,7 @@ public class IOUtil {
vec.putBase(iov_len, bufferAddress(buf) + pos);
vec.putLen(iov_len, rem);
iov_len++;
writevLen += rem;
}
i++;
}
@ -580,6 +590,8 @@ public class IOUtil {
static native int iovMax();
static native long writevMax();
static native void initIDs();
/**
@ -593,6 +605,7 @@ public class IOUtil {
initIDs();
IOV_MAX = iovMax();
WRITEV_MAX = writevMax();
}
}