A couple of tests for bid limits when allocating/freeing buffers with provide_buffers command. Signed-off-by: Gabriel Krisman Bertazi <krisman@xxxxxxx> --- test/Makefile | 1 + test/provide-buffers.c | 132 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 test/provide-buffers.c diff --git a/test/Makefile b/test/Makefile index f16cedc..60ca45f 100644 --- a/test/Makefile +++ b/test/Makefile @@ -138,6 +138,7 @@ test_srcs := \ poll-v-poll.c \ pollfree.c \ probe.c \ + provide-buffers.c \ read-before-exit.c \ read-write.c \ recv-msgall.c \ diff --git a/test/provide-buffers.c b/test/provide-buffers.c new file mode 100644 index 0000000..62fd8d8 --- /dev/null +++ b/test/provide-buffers.c @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Description: test BID checks for provide buffers command. + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <sys/mman.h> + +#include "liburing.h" +#include "helpers.h" + +/* BID id address space is 16 bits. */ +#define MAX_BID_NR (1<<16) + +int test_bid_space_limits() +{ + struct io_uring ring; + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + void * buf; + int buf_len; + int ret; + + ret = io_uring_queue_init(1, &ring, 0); + if (ret < 0) { + fprintf(stderr, "queue_init: %s\n", strerror(-ret)); + return 1; + } + + /* + * Individual buffer size (buf_len) is irrelevant for this + * test. As long as the full size can be mapped and io_uring + * likes it. sizeof(int) is always safe. + */ + buf_len = sizeof(int); + buf = mmap(NULL, MAX_BID_NR*buf_len, PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_ANON, -1, 0); + if (buf == MAP_FAILED) { + fprintf(stderr, "mmap failed\n"); + return 1; + } + + /* allocate/free the last tag possible for a given bid. */ + sqe = io_uring_get_sqe(&ring); + io_uring_prep_provide_buffers(sqe, buf, buf_len, 1, 0, USHRT_MAX); + io_uring_submit(&ring); + io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "wait_cqe %d\n", ret); + return 1; + } else if (cqe->res != 0) { + fprintf(stderr, "Failed to register buffer with tag USHRT_MAX. (res = %d)\n", + cqe->res); + return 1; + } + io_uring_cqe_seen(&ring, cqe); + + sqe = io_uring_get_sqe(&ring); + io_uring_prep_remove_buffers(sqe, 1, 0); + io_uring_submit(&ring); + io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "wait_cqe %d\n", ret); + return 1; + } else if (cqe->res != 1) { + fprintf(stderr, "Failed to remove buffer with tag USHRT_MAX. (res = %d)\n", + cqe->res); + return 1; + } + io_uring_cqe_seen(&ring, cqe); + + /* Wrapping the bid counter could be valid but is confusing, thus it is disabled. */ + sqe = io_uring_get_sqe(&ring); + io_uring_prep_provide_buffers(sqe, buf, buf_len, 2, 0, USHRT_MAX); + io_uring_submit(&ring); + io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "wait_cqe %d\n", ret); + return 1; + } else if (cqe->res == 0) { + fprintf(stderr, "Shouldn't have succeded to register the BID counter.\n"); + return 1; + } + io_uring_cqe_seen(&ring, cqe); + + /* Allocate and free the full address space */ + sqe = io_uring_get_sqe(&ring); + io_uring_prep_provide_buffers(sqe, buf, buf_len, MAX_BID_NR, 0, 0); + io_uring_submit(&ring); + io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "wait_cqe %d\n", ret); + return 1; + } else if (cqe->res != 0) { + fprintf(stderr, "Failed to register 65536 buffers. (res = %d)\n", + cqe->res); + return 1; + } + io_uring_cqe_seen(&ring, cqe); + + sqe = io_uring_get_sqe(&ring); + io_uring_prep_remove_buffers(sqe, MAX_BID_NR, 0); + io_uring_submit(&ring); + io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "wait_cqe %d\n", ret); + return 1; + } else if (cqe->res != MAX_BID_NR) { + fprintf(stderr, "Failed to remove 65536 buffers.\n"); + return 1; + } + io_uring_cqe_seen(&ring, cqe); + + io_uring_queue_exit(&ring); + + return 0; +} + +int main (int argc, char *argv[]) +{ + int ret; + + if (argc > 1) + return T_EXIT_SKIP; + + ret = test_bid_space_limits(); + if (ret) + return T_EXIT_FAIL; + return T_EXIT_PASS; +} -- 2.42.0