github.com/ghodss/etcd@v0.3.1-0.20140417172404-cc329bfa55cb/pkg/btrfs/btrfs.go (about)

     1  package btrfs
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"runtime"
     7  	"syscall"
     8  	"unsafe"
     9  
    10  	"github.com/coreos/etcd/log"
    11  )
    12  
    13  const (
    14  	// from Linux/include/uapi/linux/magic.h
    15  	BTRFS_SUPER_MAGIC = 0x9123683E
    16  
    17  	// from Linux/include/uapi/linux/fs.h
    18  	FS_NOCOW_FL = 0x00800000
    19  	FS_IOC_GETFLAGS = 0x80086601
    20  	FS_IOC_SETFLAGS = 0x40086602
    21  )
    22  
    23  // IsBtrfs checks whether the file is in btrfs
    24  func IsBtrfs(path string) bool {
    25  	// btrfs is linux-only filesystem
    26  	// exit on other platforms
    27  	if runtime.GOOS != "linux" {
    28  		return false
    29  	}
    30  	var buf syscall.Statfs_t
    31  	if err := syscall.Statfs(path, &buf); err != nil {
    32  		log.Warnf("Failed to statfs: %v", err)
    33  		return false
    34  	}
    35  	log.Debugf("The type of path %v is %v", path, buf.Type)
    36  	if buf.Type != BTRFS_SUPER_MAGIC {
    37  		return false
    38  	}
    39  	log.Infof("The path %v is in btrfs", path)
    40  	return true
    41  }
    42  
    43  // SetNOCOWFile sets NOCOW flag for file
    44  func SetNOCOWFile(path string) error {
    45  	file, err := os.Open(path)
    46  	if err != nil {
    47  		return err
    48  	}
    49  	defer file.Close()
    50  
    51  	fileinfo, err := file.Stat()
    52  	if err != nil {
    53  		return err
    54  	}
    55  	if fileinfo.IsDir() {
    56  		return fmt.Errorf("skip directory")
    57  	}
    58  	if fileinfo.Size() != 0 {
    59  		return fmt.Errorf("skip nonempty file")
    60  	}
    61  
    62  	var attr int
    63  	if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, file.Fd(), FS_IOC_GETFLAGS, uintptr(unsafe.Pointer(&attr))); errno != 0 {
    64  		return errno
    65  	}
    66  	attr |= FS_NOCOW_FL
    67  	if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, file.Fd(), FS_IOC_SETFLAGS, uintptr(unsafe.Pointer(&attr))); errno != 0 {
    68  		return errno
    69  	}
    70  	log.Infof("Set NOCOW to path %v succeeded", path)
    71  	return nil
    72  }