github.com/ncw/rclone@v1.48.1-0.20190724201158-a35aa1360e3e/backend/local/preallocate_unix.go (about)

     1  //+build linux
     2  
     3  package local
     4  
     5  import (
     6  	"os"
     7  	"sync/atomic"
     8  
     9  	"github.com/ncw/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  // preAllocate the file for performance reasons
    22  func preAllocate(size int64, out *os.File) error {
    23  	if size <= 0 {
    24  		return nil
    25  	}
    26  	index := atomic.LoadInt32(&fallocFlagsIndex)
    27  again:
    28  	if index >= int32(len(fallocFlags)) {
    29  		return nil // Fallocate is disabled
    30  	}
    31  	flags := fallocFlags[index]
    32  	err := unix.Fallocate(int(out.Fd()), flags, 0, size)
    33  	if err == unix.ENOTSUP {
    34  		// Try the next flags combination
    35  		index++
    36  		atomic.StoreInt32(&fallocFlagsIndex, index)
    37  		fs.Debugf(nil, "preAllocate: got error on fallocate, trying combination %d/%d: %v", index, len(fallocFlags), err)
    38  		goto again
    39  
    40  	}
    41  	// FIXME could be doing something here
    42  	// if err == unix.ENOSPC {
    43  	// 	log.Printf("No space")
    44  	// }
    45  	return err
    46  }