diff options
author | thegeorg <thegeorg@yandex-team.com> | 2024-06-09 11:55:21 +0300 |
---|---|---|
committer | thegeorg <thegeorg@yandex-team.com> | 2024-06-09 12:07:55 +0300 |
commit | afd4899380eea1c70e2a68714b5da1c9919ccdbd (patch) | |
tree | cd5120708784139bc6a0f8881da1ed8389a065b3 /contrib/libs/liburing/test/ringbuf-status.c | |
parent | a83bd2dd3c21e38c6c0807ec5e679497ab567f24 (diff) | |
download | ydb-afd4899380eea1c70e2a68714b5da1c9919ccdbd.tar.gz |
Update contrib/libs/liburing to 2.6
3b51a9fb14de805208d11f1c077c78bb5d487e0f
Diffstat (limited to 'contrib/libs/liburing/test/ringbuf-status.c')
-rw-r--r-- | contrib/libs/liburing/test/ringbuf-status.c | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/contrib/libs/liburing/test/ringbuf-status.c b/contrib/libs/liburing/test/ringbuf-status.c new file mode 100644 index 0000000000..d4a56c7473 --- /dev/null +++ b/contrib/libs/liburing/test/ringbuf-status.c @@ -0,0 +1,243 @@ +#include "../config-host.h" +/* SPDX-License-Identifier: MIT */ +/* + * Description: test reading provided ring buf head + * + */ +#include <errno.h> +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> + +#include "liburing.h" +#include "helpers.h" + +#define BUF_SIZE 32 +#define NR_BUFS 8 +#define FSIZE (BUF_SIZE * NR_BUFS) + +#define BR_MASK (NR_BUFS - 1) +#define BGID 1 + +static int no_buf_ring; +static int no_buf_ring_status; + +static int test_max(void) +{ + struct io_uring_buf_ring *br; + struct io_uring ring; + int nr_bufs = 32768; + int ret, i; + char *buf; + + ret = io_uring_queue_init(1, &ring, 0); + if (ret) { + fprintf(stderr, "ring setup failed: %d\n", ret); + return 1; + } + + if (posix_memalign((void **) &buf, 4096, FSIZE)) + return 1; + + br = io_uring_setup_buf_ring(&ring, nr_bufs, BGID, 0, &ret); + if (!br) { + fprintf(stderr, "Buffer ring register failed %d\n", ret); + return 1; + } + + ret = io_uring_buf_ring_available(&ring, br, BGID); + if (ret) { + fprintf(stderr, "Bad available count %d\n", ret); + return 1; + } + + for (i = 0; i < nr_bufs / 2; i++) + io_uring_buf_ring_add(br, buf, BUF_SIZE, i + 1, nr_bufs - 1, i); + io_uring_buf_ring_advance(br, nr_bufs / 2); + + ret = io_uring_buf_ring_available(&ring, br, BGID); + if (ret != nr_bufs / 2) { + fprintf(stderr, "Bad half full available count %d\n", ret); + return 1; + } + + for (i = 0; i < nr_bufs / 2; i++) + io_uring_buf_ring_add(br, buf, BUF_SIZE, i + 1, nr_bufs - 1, i); + io_uring_buf_ring_advance(br, nr_bufs / 2); + + ret = io_uring_buf_ring_available(&ring, br, BGID); + if (ret != nr_bufs) { + fprintf(stderr, "Bad half full available count %d\n", ret); + return 1; + } + + free(buf); + io_uring_queue_exit(&ring); + return T_EXIT_PASS; +} + +static int test(int invalid) +{ + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + struct io_uring ring; + struct io_uring_buf_ring *br; + int ret, i, fds[2]; + uint16_t head; + char *buf; + void *ptr; + char output[16]; + + memset(output, 0x55, sizeof(output)); + + ret = io_uring_queue_init(NR_BUFS, &ring, 0); + if (ret) { + fprintf(stderr, "ring setup failed: %d\n", ret); + return 1; + } + + if (pipe(fds) < 0) { + perror("pipe"); + return T_EXIT_FAIL; + } + + if (posix_memalign((void **) &buf, 4096, FSIZE)) + return 1; + + br = io_uring_setup_buf_ring(&ring, NR_BUFS, BGID, 0, &ret); + if (!br) { + if (ret == -EINVAL) { + no_buf_ring = 1; + return 0; + } + fprintf(stderr, "Buffer ring register failed %d\n", ret); + return 1; + } + + ptr = buf; + for (i = 0; i < NR_BUFS; i++) { + io_uring_buf_ring_add(br, ptr, BUF_SIZE, i + 1, BR_MASK, i); + ptr += BUF_SIZE; + } + io_uring_buf_ring_advance(br, NR_BUFS); + + /* head should be zero at this point */ + head = 1; + if (!invalid) + ret = io_uring_buf_ring_head(&ring, BGID, &head); + else + ret = io_uring_buf_ring_head(&ring, BGID + 10, &head); + if (ret) { + if (ret == -EINVAL) { + no_buf_ring_status = 1; + return T_EXIT_SKIP; + } + if (invalid && ret == -ENOENT) + return T_EXIT_PASS; + fprintf(stderr, "buf_ring_head: %d\n", ret); + return T_EXIT_FAIL; + } + if (invalid) { + fprintf(stderr, "lookup of bad group id succeeded\n"); + return T_EXIT_FAIL; + } + if (head != 0) { + fprintf(stderr, "bad head %d\n", head); + return T_EXIT_FAIL; + } + + ret = io_uring_buf_ring_available(&ring, br, BGID); + if (ret != NR_BUFS) { + fprintf(stderr, "ring available %d\n", ret); + return T_EXIT_FAIL; + } + + sqe = io_uring_get_sqe(&ring); + io_uring_prep_read(sqe, fds[0], NULL, BUF_SIZE, i * BUF_SIZE); + sqe->buf_group = BGID; + sqe->flags |= IOSQE_BUFFER_SELECT; + sqe->user_data = 1; + + ret = io_uring_submit(&ring); + if (ret != 1) { + fprintf(stderr, "submit: %d\n", ret); + return T_EXIT_FAIL; + } + + /* head should still be zero at this point, no buffers consumed */ + head = 1; + ret = io_uring_buf_ring_head(&ring, BGID, &head); + if (head != 0) { + fprintf(stderr, "bad head after submit %d\n", head); + return T_EXIT_FAIL; + } + + ret = write(fds[1], output, sizeof(output)); + if (ret != sizeof(output)) { + fprintf(stderr, "pipe buffer write %d\n", ret); + return T_EXIT_FAIL; + } + + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "wait cqe failed %d\n", ret); + return T_EXIT_FAIL; + } + if (cqe->res != sizeof(output)) { + fprintf(stderr, "cqe res %d\n", cqe->res); + return T_EXIT_FAIL; + } + if (!(cqe->flags & IORING_CQE_F_BUFFER)) { + fprintf(stderr, "no buffer selected\n"); + return T_EXIT_FAIL; + } + io_uring_cqe_seen(&ring, cqe); + + /* head should now be one, we consumed a buffer */ + ret = io_uring_buf_ring_head(&ring, BGID, &head); + if (head != 1) { + fprintf(stderr, "bad head after cqe %d\n", head); + return T_EXIT_FAIL; + } + + ret = io_uring_buf_ring_available(&ring, br, BGID); + if (ret != NR_BUFS - 1) { + fprintf(stderr, "ring available %d\n", ret); + return T_EXIT_FAIL; + } + + close(fds[0]); + close(fds[1]); + free(buf); + io_uring_queue_exit(&ring); + return T_EXIT_PASS; +} + +int main(int argc, char *argv[]) +{ + int ret; + + ret = test(0); + if (ret == T_EXIT_FAIL) { + fprintf(stderr, "test 0 failed\n"); + return T_EXIT_FAIL; + } + if (no_buf_ring || no_buf_ring_status) + return T_EXIT_SKIP; + + ret = test(1); + if (ret == T_EXIT_FAIL) { + fprintf(stderr, "test 1 failed\n"); + return T_EXIT_FAIL; + } + + ret = test_max(); + if (ret == T_EXIT_FAIL) { + fprintf(stderr, "test_max failed\n"); + return T_EXIT_FAIL; + } + + return T_EXIT_PASS; +} |