summaryrefslogtreecommitdiff
path: root/uring.c
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2020-06-22 15:17:36 +0200
committerDavid Härdeman <david@hardeman.nu>2020-06-22 15:17:36 +0200
commitfcd154280c21746db7d994ed1be77f20f91c90c0 (patch)
tree78796c8560c004ad4c4d81747a6d7546be4ca039 /uring.c
parenta7fd6536f76144d7e2d18caa71f4abe516299b91 (diff)
Add basic splice support to server-proxy (untested)
Diffstat (limited to 'uring.c')
-rw-r--r--uring.c55
1 files changed, 55 insertions, 0 deletions
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 <liburing.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
+#include <unistd.h>
#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 {
@@ -519,6 +525,22 @@ uring_accept(struct uring_task *task, struct saddr *saddr, utask_cb_t cb)
}
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)
{
struct io_uring_sqe *sqe;
@@ -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