aboutsummaryrefslogtreecommitdiff
path: root/src/internal
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2021-02-14 17:14:41 -0800
committerIan Lance Taylor <iant@golang.org>2021-02-16 00:46:04 +0000
commit30641e36aa5b547eee48565caa3078b0a2e7c185 (patch)
treec085c8c6f8f46883cc0877fcf400b4b910fb3e84 /src/internal
parent33d72fd4122a4b7e31e738d5d9283093966ec14a (diff)
downloadgo-30641e36aa5b547eee48565caa3078b0a2e7c185.tar.gz
go-30641e36aa5b547eee48565caa3078b0a2e7c185.zip
internal/poll: if copy_file_range returns 0, assume it failed
On current Linux kernels copy_file_range does not correctly handle files in certain special file systems, such as /proc. For those file systems it fails to copy any data and returns zero. This breaks Go's io.Copy for those files. Fix the problem by assuming that if copy_file_range returns 0 the first time it is called on a file, that that file is not supported. In that case fall back to just using read. This will force an extra system call when using io.Copy to copy a zero-sized normal file, but at least it will work correctly. For #36817 Fixes #44272 Change-Id: I02e81872cb70fda0ce5485e2ea712f219132e614 Reviewed-on: https://go-review.googlesource.com/c/go/+/291989 Trust: Ian Lance Taylor <iant@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org>
Diffstat (limited to 'src/internal')
-rw-r--r--src/internal/poll/copy_file_range_linux.go10
1 files changed, 9 insertions, 1 deletions
diff --git a/src/internal/poll/copy_file_range_linux.go b/src/internal/poll/copy_file_range_linux.go
index fc34aef4cb..01b242a4ea 100644
--- a/src/internal/poll/copy_file_range_linux.go
+++ b/src/internal/poll/copy_file_range_linux.go
@@ -112,7 +112,15 @@ func CopyFileRange(dst, src *FD, remain int64) (written int64, handled bool, err
return 0, false, nil
case nil:
if n == 0 {
- // src is at EOF, which means we are done.
+ // If we did not read any bytes at all,
+ // then this file may be in a file system
+ // where copy_file_range silently fails.
+ // https://lore.kernel.org/linux-fsdevel/20210126233840.GG4626@dread.disaster.area/T/#m05753578c7f7882f6e9ffe01f981bc223edef2b0
+ if written == 0 {
+ return 0, false, nil
+ }
+ // Otherwise src is at EOF, which means
+ // we are done.
return written, true, nil
}
remain -= n