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 }