...
Source file
src/internal/poll/copy_file_range_unix.go
1
2
3
4
5
6
7 package poll
8
9 import "internal/syscall/unix"
10
11
12
13 func CopyFileRange(dst, src *FD, remain int64) (written int64, handled bool, err error) {
14 if !supportCopyFileRange() {
15 return 0, false, nil
16 }
17
18 for remain > 0 {
19 max := remain
20 if max > maxCopyFileRangeRound {
21 max = maxCopyFileRangeRound
22 }
23 n, e := copyFileRange(dst, src, int(max))
24 if n > 0 {
25 remain -= n
26 written += n
27 }
28 handled, err = handleCopyFileRangeErr(e, n, written)
29 if n == 0 || !handled || err != nil {
30 return
31 }
32 }
33
34 return written, true, nil
35 }
36
37
38 func copyFileRange(dst, src *FD, max int) (written int64, err error) {
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58 if err := dst.writeLock(); err != nil {
59 return 0, err
60 }
61 defer dst.writeUnlock()
62 if err := src.readLock(); err != nil {
63 return 0, err
64 }
65 defer src.readUnlock()
66 return ignoringEINTR2(func() (int64, error) {
67 n, err := unix.CopyFileRange(src.Sysfd, nil, dst.Sysfd, nil, max, 0)
68 return int64(n), err
69 })
70 }
71
View as plain text