Source file src/internal/poll/copy_file_range_freebsd.go

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

View as plain text