github.com/10XDev/rclone@v1.52.3-0.20200626220027-16af9ab76b2a/lib/file/preallocate_unix.go (about)

     1  //+build linux
     2  
     3  package file
     4  
     5  import (
     6  	"os"
     7  	"sync/atomic"
     8  
     9  	"github.com/rclone/rclone/fs"
    10  	"golang.org/x/sys/unix"
    11  )
    12  
    13  var (
    14  	fallocFlags = [...]uint32{
    15  		unix.FALLOC_FL_KEEP_SIZE,                             // Default
    16  		unix.FALLOC_FL_KEEP_SIZE | unix.FALLOC_FL_PUNCH_HOLE, // for ZFS #3066
    17  	}
    18  	fallocFlagsIndex int32
    19  )
    20  
    21  // PreallocateImplemented is a constant indicating whether the
    22  // implementation of Preallocate actually does anything.
    23  const PreallocateImplemented = true
    24  
    25  // PreAllocate the file for performance reasons
    26  func PreAllocate(size int64, out *os.File) error {
    27  	if size <= 0 {
    28  		return nil
    29  	}
    30  	index := atomic.LoadInt32(&fallocFlagsIndex)
    31  again:
    32  	if index >= int32(len(fallocFlags)) {
    33  		return nil // Fallocate is disabled
    34  	}
    35  	flags := fallocFlags[index]
    36  	err := unix.Fallocate(int(out.Fd()), flags, 0, size)
    37  	if err == unix.ENOTSUP {
    38  		// Try the next flags combination
    39  		index++
    40  		atomic.StoreInt32(&fallocFlagsIndex, index)
    41  		fs.Debugf(nil, "preAllocate: got error on fallocate, trying combination %d/%d: %v", index, len(fallocFlags), err)
    42  		goto again
    43  
    44  	}
    45  	// FIXME could be doing something here
    46  	// if err == unix.ENOSPC {
    47  	// 	log.Printf("No space")
    48  	// }
    49  	return err
    50  }
    51  
    52  // SetSparseImplemented is a constant indicating whether the
    53  // implementation of SetSparse actually does anything.
    54  const SetSparseImplemented = false
    55  
    56  // SetSparse makes the file be a sparse file
    57  func SetSparse(out *os.File) error {
    58  	return nil
    59  }