| // 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 |
| } |