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 ce5ebf7..37ea845 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 c84c6aa..9b0c23b 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 bd100ee..254483c 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 1bff917..28946c6 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);