]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
cp: support btrfs' copy-on-write file clone operation
authorGiuseppe Scrivano <gscrivano@gnu.org>
Sat, 25 Jul 2009 14:35:27 +0000 (16:35 +0200)
committerJim Meyering <meyering@redhat.com>
Wed, 29 Jul 2009 10:15:50 +0000 (12:15 +0200)
* src/copy.c [HAVE_SYS_IOCTL_H]: Include <sys/ioctl.h>.
(BTRFS_IOCTL_MAGIC, BTRFS_IOC_CLONE): Define.
(clone_file): New function.
(copy_reg): Use the btrfs clone operation if possible.

src/copy.c

index 4c8c432fc3396d047940eae34f83f726e7cef6c1..bbed336b1e418d8f9ac99c62edbb109d2be23a30 100644 (file)
 # include "verror.h"
 #endif
 
+#if HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+
 #ifndef HAVE_FCHOWN
 # define HAVE_FCHOWN false
 # define fchown(fd, uid, gid) (-1)
@@ -114,6 +118,23 @@ static bool owner_failure_ok (struct cp_options const *x);
 static char const *top_level_src_name;
 static char const *top_level_dst_name;
 
+/* Perform the O(1) btrfs clone operation, if possible.
+   Upon success, return 0.  Otherwise, return -1 and set errno.  */
+static inline int
+clone_file (int dest_fd, int src_fd)
+{
+#ifdef __linux__
+# undef BTRFS_IOCTL_MAGIC
+# define BTRFS_IOCTL_MAGIC 0x94
+# undef BTRFS_IOC_CLONE
+# define BTRFS_IOC_CLONE _IOW (BTRFS_IOCTL_MAGIC, 9, int)
+  return ioctl (dest_fd, BTRFS_IOC_CLONE, src_fd);
+#else
+  errno = ENOTSUP;
+  return -1;
+#endif
+}
+
 /* FIXME: describe */
 /* FIXME: rewrite this to use a hash table so we avoid the quadratic
    performance hit that's probably noticeable only on trees deeper
@@ -589,6 +610,13 @@ copy_reg (char const *src_name, char const *dst_name,
       goto close_src_and_dst_desc;
     }
 
+  /* If --sparse=auto is in effect, attempt a btrfs clone operation.
+     If the operation is not supported or it fails then copy the file
+     in the usual way.  */
+  bool copied = (x->sparse_mode == SPARSE_AUTO
+                 && clone_file (dest_desc, source_desc) == 0);
+
+  if (!copied)
   {
     typedef uintptr_t word;
     off_t n_read_total = 0;