copy_file_range_freebsd.mx raw

   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