1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package poll
import (
"internal/syscall/unix"
"syscall"
)
func supportCopyFileRange() bool {
return unix.SupportCopyFileRange()
}
// For best performance, call copy_file_range() with the largest len value
// possible. It is interruptible on most file systems, so there is no penalty
// for using very large len values, even SSIZE_MAX.
const maxCopyFileRangeRound = 1<<31 - 1
func handleCopyFileRangeErr(err error, copied, written int64) (bool, error) {
switch err {
case syscall.ENOSYS:
// The copy_file_range(2) function first appeared in FreeBSD 13.0.
// Go supports FreeBSD >= 12, so the system call
// may not be present. We've detected the FreeBSD version with
// unix.SupportCopyFileRange() at the beginning of this function,
// but we still want to check for ENOSYS here to prevent some rare
// case like https://go.dev/issue/58592
//
// If we see ENOSYS, we have certainly not transferred
// any data, so we can tell the caller that we
// couldn't handle the transfer and let them fall
// back to more generic code.
return false, nil
case syscall.EFBIG, syscall.EINVAL, syscall.EIO:
// For EFBIG, the copy has exceeds the process's file size limit
// or the maximum file size for the filesystem dst resides on, in
// this case, we leave it to generic copy.
//
// For EINVAL, there could be a few reasons:
// 1. Either dst or src refers to a file object that
// is not a regular file, for instance, a pipe.
// 2. src and dst refer to the same file and byte ranges
// overlap.
// 3. The flags argument is not 0.
// Neither of these cases should be considered handled by
// copy_file_range(2) because there is no data transfer, so
// just fall back to generic copy.
return false, nil
}
return true, err
}
|