From fcd154280c21746db7d994ed1be77f20f91c90c0 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Mon, 22 Jun 2020 15:17:36 +0200 Subject: Add basic splice support to server-proxy (untested) --- uring.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'uring.c') diff --git a/uring.c b/uring.c index 31dfe26..3437d7e 100644 --- a/uring.c +++ b/uring.c @@ -1,9 +1,11 @@ +#define _GNU_SOURCE #include #include #include #include #include #include +#include #include "main.h" #include "uring.h" @@ -12,6 +14,10 @@ struct uring_ev { struct io_uring uring; struct io_uring_params uring_params; struct uring_task task; + + /* for testing if the kernel supports splice */ + int pipe[2]; + int tfd; }; enum cqe_type { @@ -518,6 +524,22 @@ uring_accept(struct uring_task *task, struct saddr *saddr, utask_cb_t cb) io_uring_sqe_set_data(sqe, task); } +void +uring_splice(struct uring_task *task, int fd_in, int fd_out, utask_cb_t cb) +{ + struct io_uring_sqe *sqe; + + assert_return(task && fd_in >= 0 && fd_out >= 0 && cb); + + debug(DBG_UR, "task %s (%p), fd_in %i, fd_out %i, refcount %u", + task->name, task, fd_in, fd_out, task->refcount); + + sqe = get_sqe(task); + task->cb = cb; + io_uring_prep_splice(sqe, fd_in, -1, fd_out, -1, 4096, SPLICE_F_MOVE); + io_uring_sqe_set_data(sqe, task); +} + void uring_poll(struct uring_task *task, short poll_mask, utask_cb_t cb) { @@ -592,6 +614,30 @@ uring_delete() uring_task_put(task); } +static void +uring_splice_test_cb(struct uring_task *task, int res) +{ + struct uring_ev *uring = container_of(task, struct uring_ev, task); + + assert_die(task && uring == cfg->uring, "splice test failed"); + + uring_close(task, uring->tfd); + uring_close(task, uring->pipe[PIPE_RD]); + uring_close(task, uring->pipe[PIPE_WR]); + + uring->tfd = -1; + uring->pipe[PIPE_RD] = -1; + uring->pipe[PIPE_WR] = -1; + + if (res >= 0) { + cfg->splice_supported = true; + debug(DBG_UR, "splice supported"); + } else if (res == -EINVAL) + debug(DBG_UR, "splice not supported"); + else + error("splice check failed: %i\n", res); +} + void uring_init() { @@ -611,6 +657,15 @@ uring_init() uring_task_init(&uring->task, "io_uring", &cfg->task, uring_free); cfg->uring = uring; + + /* splice check, a bit convoluted, but seems to be no simpler way */ + cfg->splice_supported = false; + if (pipe2(uring->pipe, O_CLOEXEC) < 0) + die("pipe2: %m"); + uring->tfd = open("/dev/null", O_RDONLY | O_CLOEXEC | O_NOCTTY); + if (uring->tfd < 0) + die("open(\"/dev/null\"): %m"); + uring_splice(&uring->task, uring->tfd, uring->pipe[PIPE_WR], uring_splice_test_cb); } static inline void -- cgit v1.2.3