8140241: (fc) Data transfer from FileChannel to itself causes hang in case of overlap

Reviewed-by: alanb
This commit is contained in:
Brian Burkhalter 2021-08-12 15:27:09 +00:00
parent 93cab7d07d
commit 428d51694f
6 changed files with 167 additions and 7 deletions

View file

@ -585,6 +585,15 @@ public class FileChannelImpl
if (!((target instanceof FileChannelImpl) || isSelChImpl))
return IOStatus.UNSUPPORTED;
if (target == this) {
long posThis = position();
if (posThis - count + 1 <= position &&
position - count + 1 <= posThis &&
!nd.canTransferToFromOverlappedMap()) {
return IOStatus.UNSUPPORTED_CASE;
}
}
// Trusted target: Use a mapped buffer
long remaining = count;
while (remaining > 0L) {
@ -677,7 +686,7 @@ public class FileChannelImpl
return 0;
if ((sz - position) < count)
count = (int)(sz - position);
count = sz - position;
// Attempt a direct transfer, if the kernel supports it, limiting
// the number of bytes according to which platform
@ -704,6 +713,14 @@ public class FileChannelImpl
long pos = src.position();
long max = Math.min(count, src.size() - pos);
if (src == this) {
if (position() - max + 1 <= pos &&
pos - max + 1 <= position() &&
!nd.canTransferToFromOverlappedMap()) {
return IOStatus.UNSUPPORTED_CASE;
}
}
long remaining = max;
long p = pos;
while (remaining > 0L) {
@ -779,9 +796,12 @@ public class FileChannelImpl
throw new IllegalArgumentException();
if (position > size())
return 0;
if (src instanceof FileChannelImpl)
return transferFromFileChannel((FileChannelImpl)src,
position, count);
if (src instanceof FileChannelImpl fci) {
long n = transferFromFileChannel(fci, position, count);
if (n >= 0)
return n;
}
return transferFromArbitraryChannel(src, position, count);
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -67,5 +67,7 @@ abstract class FileDispatcher extends NativeDispatcher {
abstract boolean transferToDirectlyNeedsPositionLock();
abstract boolean canTransferToFromOverlappedMap();
abstract int setDirectIO(FileDescriptor fd, String path);
}