github.com/sym3tri/etcd@v0.2.1-0.20140422215517-a563d82f95d6/pkg/btrfs/btrfs_linux.go (about)

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