diff options
author | David Sterba <dsterba@suse.com> | 2016-11-02 14:54:10 +0100 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2016-12-14 15:06:34 +0100 |
commit | ba23855cdc8961bbaef1fcad4854d494cdb3afd3 (patch) | |
tree | 4e49d4418d7b07066025eda008fcb9a5905d3c41 | |
parent | f6f9cd0cb76f52febd4f6579a4fb176c4d501068 (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.c | 34 |
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, |