summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Sterba <dsterba@suse.com>2016-11-02 14:54:10 +0100
committerDavid Sterba <dsterba@suse.com>2016-12-14 15:06:34 +0100
commitba23855cdc8961bbaef1fcad4854d494cdb3afd3 (patch)
tree4e49d4418d7b07066025eda008fcb9a5905d3c41
parentf6f9cd0cb76f52febd4f6579a4fb176c4d501068 (diff)
btrfs-progs: send: use splice syscall instead of read/write to transfer buffer
We can utilize the splice syscall as the source descriptor is a pipe and avoid read/write through userspace. The original implementation is kept but shall be removed in the future. Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r--cmds-send.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/cmds-send.c b/cmds-send.c
index cae600e4..37b4e791 100644
--- a/cmds-send.c
+++ b/cmds-send.c
@@ -197,6 +197,7 @@ static int add_clone_source(struct btrfs_send *sctx, u64 root_id)
return 0;
}
+#if 0
static int write_buf(int fd, const char *buf, size_t size)
{
int ret;
@@ -224,7 +225,7 @@ out:
return ret;
}
-static void *dump_thread(void *arg)
+static void *dump_thread_copy(void *arg)
{
int ret;
struct btrfs_send *sctx = (struct btrfs_send*)arg;
@@ -255,6 +256,37 @@ out:
return ERR_PTR(ret);
}
+#endif
+
+static void* dump_thread(void *arg)
+{
+ int ret;
+ struct btrfs_send *sctx = (struct btrfs_send*)arg;
+
+ while (1) {
+ ssize_t sbytes;
+
+ /* Source is a pipe, output is either file or stdout */
+ sbytes = splice(sctx->send_fd, NULL, sctx->dump_fd,
+ NULL, SEND_BUFFER_SIZE, SPLICE_F_MORE);
+ if (sbytes < 0) {
+ ret = -errno;
+ error("failed to read stream from kernel: %s",
+ strerror(-ret));
+ goto out;
+ }
+ if (!sbytes) {
+ ret = 0;
+ goto out;
+ }
+ }
+
+out:
+ if (ret < 0)
+ exit(-ret);
+
+ return ERR_PTR(ret);
+}
static int do_send(struct btrfs_send *send, u64 parent_root_id,
int is_first_subvol, int is_last_subvol, const char *subvol,