chiark / gitweb /
qcow2: when dissecting qcow2, use btrfs clone ioctls for reflinking blocks to target
authorLennart Poettering <lennart@poettering.net>
Sat, 17 Jan 2015 17:11:45 +0000 (18:11 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 19 Jan 2015 19:24:09 +0000 (20:24 +0100)
Makefile.am
src/import/qcow2-util.c
src/shared/btrfs-util.c
src/shared/btrfs-util.h

index ce5ebf7c4829aeeb2e00e1b3c3a77766be4fcc61..37ea845ed433bd6e92466a6f6d20ca4b30e8732a 100644 (file)
@@ -5285,6 +5285,7 @@ test_qcow2_CFLAGS = \
 
 test_qcow2_LDADD = \
        libsystemd-internal.la \
+       libsystemd-label.la \
        libsystemd-shared.la \
        $(ZLIB_LIBS)
 endif
index c84c6aa0d72b20948df62f4c1ec4a38cd1af0235..9b0c23bb1476148af0a5386a0367b2f692bcfb45 100644 (file)
@@ -24,6 +24,7 @@
 #include "util.h"
 #include "sparse-endian.h"
 #include "qcow2-util.h"
+#include "btrfs-util.h"
 
 #define QCOW2_MAGIC 0x514649fb
 
@@ -85,6 +86,11 @@ static int copy_cluster(
                 void *buffer) {
 
         ssize_t l;
+        int r;
+
+        r = btrfs_clone_range(sfd, soffset, dfd, doffset, cluster_size);
+        if (r >= 0)
+                return r;
 
         l = pread(sfd, buffer, cluster_size, soffset);
         if (l < 0)
index bd100eef0b435b710f7817883cbc0c2f841b2934..254483c31a3ce5649fc0d722456c448a5461d450 100644 (file)
@@ -275,6 +275,26 @@ int btrfs_reflink(int infd, int outfd) {
         return 0;
 }
 
+int btrfs_clone_range(int infd, uint64_t in_offset, int outfd, uint64_t out_offset, uint64_t sz) {
+        struct btrfs_ioctl_clone_range_args args = {
+                .src_fd = infd,
+                .src_offset = in_offset,
+                .src_length = sz,
+                .dest_offset = out_offset,
+        };
+        int r;
+
+        assert(infd >= 0);
+        assert(outfd >= 0);
+        assert(sz > 0);
+
+        r = ioctl(outfd, BTRFS_IOC_CLONE_RANGE, &args);
+        if (r < 0)
+                return -errno;
+
+        return 0;
+}
+
 int btrfs_get_block_device(const char *path, dev_t *dev) {
         struct btrfs_ioctl_fs_info_args fsi = {};
         _cleanup_close_ int fd = -1;
index 1bff9171d7e1b96e76455e81021d9abb1dea8d77..28946c60c9ceaa84ad00c0b93352a64c69172f23 100644 (file)
@@ -55,6 +55,7 @@ int btrfs_subvol_get_info_fd(int fd, BtrfsSubvolInfo *info);
 int btrfs_subvol_get_quota_fd(int fd, BtrfsQuotaInfo *quota);
 
 int btrfs_reflink(int infd, int outfd);
+int btrfs_clone_range(int infd, uint64_t in_offset, int ofd, uint64_t out_offset, uint64_t sz);
 
 int btrfs_get_block_device(const char *path, dev_t *dev);