summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-01-17 18:11:45 +0100
committerLennart Poettering <lennart@poettering.net>2015-01-19 20:24:09 +0100
commit1c7dd82563ff2e71a067aea20d2acb2d0553644b (patch)
treef26693719aeea09d4ab0f94e503bf82de96fa241
parent1e20b41187ff7d27477b5322690e447753c66ace (diff)
qcow2: when dissecting qcow2, use btrfs clone ioctls for reflinking blocks to target
-rw-r--r--Makefile.am1
-rw-r--r--src/import/qcow2-util.c6
-rw-r--r--src/shared/btrfs-util.c20
-rw-r--r--src/shared/btrfs-util.h1
4 files changed, 28 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am
index ce5ebf7c48..37ea845ed4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5285,6 +5285,7 @@ test_qcow2_CFLAGS = \
test_qcow2_LDADD = \
libsystemd-internal.la \
+ libsystemd-label.la \
libsystemd-shared.la \
$(ZLIB_LIBS)
endif
diff --git a/src/import/qcow2-util.c b/src/import/qcow2-util.c
index c84c6aa0d7..9b0c23bb14 100644
--- a/src/import/qcow2-util.c
+++ b/src/import/qcow2-util.c
@@ -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)
diff --git a/src/shared/btrfs-util.c b/src/shared/btrfs-util.c
index bd100eef0b..254483c31a 100644
--- a/src/shared/btrfs-util.c
+++ b/src/shared/btrfs-util.c
@@ -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;
diff --git a/src/shared/btrfs-util.h b/src/shared/btrfs-util.h
index 1bff9171d7..28946c60c9 100644
--- a/src/shared/btrfs-util.h
+++ b/src/shared/btrfs-util.h
@@ -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);