Signed-off-by: Bijan Mottahedeh <bijan.mottahedeh@xxxxxxxxxx> --- .gitignore | 1 + test/Makefile | 2 + test/buffer-update.c | 165 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+) create mode 100644 test/buffer-update.c diff --git a/.gitignore b/.gitignore index 9d30cf7..b44560e 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ /test/b19062a56726-test /test/b5837bd5311d-test /test/buffer-register +/test/buffer-update /test/ce593a6c480a-test /test/close-opath /test/config.local diff --git a/test/Makefile b/test/Makefile index 4e1529d..79e3e00 100644 --- a/test/Makefile +++ b/test/Makefile @@ -30,6 +30,7 @@ test_targets += \ b19062a56726-test \ b5837bd5311d-test \ buffer-register \ + buffer-update \ ce593a6c480a-test \ close-opath \ connect \ @@ -154,6 +155,7 @@ test_srcs := \ b19062a56726-test.c \ b5837bd5311d-test.c \ buffer-register.c \ + buffer-update.c \ ce593a6c480a-test.c \ close-opath.c \ connect.c \ diff --git a/test/buffer-update.c b/test/buffer-update.c new file mode 100644 index 0000000..5f926aa --- /dev/null +++ b/test/buffer-update.c @@ -0,0 +1,165 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Description: run various buffer registration tests + * + */ +#include <errno.h> +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> + +#include "liburing.h" + +#define NBUFS 10 + +static int pagesize; + +static struct iovec *alloc_bufs(int nr_bufs) +{ + struct iovec *iovs; + void *buf; + int i; + + iovs = calloc(nr_bufs, sizeof(struct iovec)); + if (!iovs) { + perror("malloc"); + return NULL; + } + + for (i = 0; i < nr_bufs; i++) { + buf = malloc(pagesize); + if (!buf) { + perror("malloc"); + iovs = NULL; + break; + } + iovs[i].iov_base = buf; + iovs[i].iov_len = pagesize; + } + + return iovs; +} + +static void free_bufs(struct iovec *iovs, int nr_bufs) +{ + int i; + + for (i = 0; i < nr_bufs; i++) + free(iovs[i].iov_base); +} + +static int test_update_multiring(struct io_uring *r1, struct io_uring *r2, + struct io_uring *r3, int do_unreg) +{ + struct iovec *iovs, *newiovs; + + iovs = alloc_bufs(NBUFS); + newiovs = alloc_bufs(NBUFS); + + if (io_uring_register_buffers(r1, iovs, NBUFS) || + io_uring_register_buffers(r2, iovs, NBUFS) || + io_uring_register_buffers(r3, iovs, NBUFS)) { + fprintf(stderr, "%s: register buffers failed\n", __FUNCTION__); + goto err; + } + + if (io_uring_register_buffers_update(r1, 0, newiovs, NBUFS) != NBUFS || + io_uring_register_buffers_update(r2, 0, newiovs, NBUFS) != NBUFS || + io_uring_register_buffers_update(r3, 0, newiovs, NBUFS) != NBUFS) { + fprintf(stderr, "%s: update buffers failed\n", __FUNCTION__); + goto err; + } + + if (!do_unreg) + goto done; + + if (io_uring_unregister_buffers(r1) || + io_uring_unregister_buffers(r2) || + io_uring_unregister_buffers(r3)) { + fprintf(stderr, "%s: unregister buffers failed\n", + __FUNCTION__); + goto err; + } + +done: + free_bufs(iovs, NBUFS); + free_bufs(newiovs, NBUFS); + return 0; +err: + free_bufs(iovs, NBUFS); + free_bufs(newiovs, NBUFS); + return 1; +} + +static int test_sqe_update(struct io_uring *ring) +{ + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + struct iovec *iovs; + int ret; + + iovs = calloc(NBUFS, sizeof(struct iovec)); + + sqe = io_uring_get_sqe(ring); + io_uring_prep_buffers_update(sqe, iovs, NBUFS, 0); + ret = io_uring_submit(ring); + if (ret != 1) { + fprintf(stderr, "submit: %d\n", ret); + return 1; + } + + ret = io_uring_wait_cqe(ring, &cqe); + if (ret) { + fprintf(stderr, "wait: %d\n", ret); + return 1; + } + + ret = cqe->res; + io_uring_cqe_seen(ring, cqe); + if (ret == -EINVAL) { + fprintf(stdout, "IORING_OP_BUFFERSS_UPDATE not supported" \ + ", skipping\n"); + return 0; + } + return ret != NBUFS; +} + +int main(int argc, char *argv[]) +{ + struct io_uring r1, r2, r3; + int ret; + + if (argc > 1) + return 0; + + pagesize = getpagesize(); + + if (io_uring_queue_init(8, &r1, 0) || + io_uring_queue_init(8, &r2, 0) || + io_uring_queue_init(8, &r3, 0)) { + fprintf(stderr, "ring setup failed\n"); + return 1; + } + + ret = test_update_multiring(&r1, &r2, &r3, 1); + if (ret) { + fprintf(stderr, "test_update_multiring w/unreg\n"); + return ret; + } + + ret = test_update_multiring(&r1, &r2, &r3, 0); + if (ret) { + fprintf(stderr, "test_update_multiring wo/unreg\n"); + return ret; + } + + ret = test_sqe_update(&r1); + if (ret) { + fprintf(stderr, "test_sqe_update failed\n"); + return ret; + } + + return 0; +} -- 1.8.3.1