Btrfs provides a copy-on-write clone ioctl so let's try to use it instead
of copying files block by block.  The ioctl is executed unconditionally if
it's available and we fall back to block copying if it fails, similarly to
cp --reflink=auto.

Signed-off-by: Oskari Saarenmaa <o...@ohmu.fi>
---
 configure.ac                  |  5 +++++
 src/storage/storage_backend.c | 11 +++++++++++
 2 files changed, 16 insertions(+)

diff --git a/configure.ac b/configure.ac
index 553015a..acae92e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1984,6 +1984,11 @@ fi
 AM_CONDITIONAL([WITH_STORAGE], [test "$with_storage" = "yes"])
 
 dnl
+dnl check for headers for filesystem specific operations
+dnl
+AC_CHECK_HEADERS([linux/btrfs.h])
+
+dnl
 dnl check for (ESX)
 dnl
 
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index b7edf85..40bfb73 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -38,6 +38,9 @@
 # include <sys/ioctl.h>
 # include <linux/fs.h>
 #endif
+#ifdef HAVE_LINUX_BTRFS_H
+# include <linux/btrfs.h>
+#endif
 
 #if WITH_SELINUX
 # include <selinux/selinux.h>
@@ -149,6 +152,13 @@ virStorageBackendCopyToFD(virStorageVolDefPtr vol,
         goto cleanup;
     }
 
+#ifdef HAVE_LINUX_BTRFS_H
+    /* try to perform a btrfs CoW clone */
+    if (ioctl(fd, BTRFS_IOC_CLONE, inputfd) == 0) {
+        goto done;
+    }
+#endif
+
 #ifdef __linux__
     if (ioctl(fd, BLKBSZGET, &wbytes) < 0) {
         wbytes = 0;
@@ -210,6 +220,7 @@ virStorageBackendCopyToFD(virStorageVolDefPtr vol,
         } while ((amtleft -= interval) > 0);
     }
 
+done:
     if (fdatasync(fd) < 0) {
         ret = -errno;
         virReportSystemError(errno, _("cannot sync data to file '%s'"),
-- 
1.8.3.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to