fs.go 1.4 KB

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