reflink_copy_linux.go 961 B

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. // +build amd64
  2. package docker
  3. // FIXME: This could be easily rewritten in pure Go
  4. /*
  5. #include <sys/ioctl.h>
  6. #include <linux/fs.h>
  7. #include <errno.h>
  8. // See linux.git/fs/btrfs/ioctl.h
  9. #define BTRFS_IOCTL_MAGIC 0x94
  10. #define BTRFS_IOC_CLONE _IOW(BTRFS_IOCTL_MAGIC, 9, int)
  11. int
  12. btrfs_reflink(int fd_out, int fd_in)
  13. {
  14. int res;
  15. res = ioctl(fd_out, BTRFS_IOC_CLONE, fd_in);
  16. if (res < 0)
  17. return errno;
  18. return 0;
  19. }
  20. */
  21. import "C"
  22. import (
  23. "io"
  24. "os"
  25. "syscall"
  26. )
  27. // FIXME: Move this to btrfs package?
  28. func BtrfsReflink(fd_out, fd_in uintptr) error {
  29. res := C.btrfs_reflink(C.int(fd_out), C.int(fd_in))
  30. if res != 0 {
  31. return syscall.Errno(res)
  32. }
  33. return nil
  34. }
  35. func CopyFile(dstFile, srcFile *os.File) error {
  36. err := BtrfsReflink(dstFile.Fd(), srcFile.Fd())
  37. if err == nil {
  38. return nil
  39. }
  40. // Fall back to normal copy
  41. // FIXME: Check the return of Copy and compare with dstFile.Stat().Size
  42. _, err = io.Copy(dstFile, srcFile)
  43. return err
  44. }