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