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/read-mshot-empty.c | |
parent | a83bd2dd3c21e38c6c0807ec5e679497ab567f24 (diff) | |
download | ydb-afd4899380eea1c70e2a68714b5da1c9919ccdbd.tar.gz |
Update contrib/libs/liburing to 2.6
3b51a9fb14de805208d11f1c077c78bb5d487e0f
Diffstat (limited to 'contrib/libs/liburing/test/read-mshot-empty.c')
-rw-r--r-- | contrib/libs/liburing/test/read-mshot-empty.c | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/contrib/libs/liburing/test/read-mshot-empty.c b/contrib/libs/liburing/test/read-mshot-empty.c new file mode 100644 index 0000000000..2fc5a63184 --- /dev/null +++ b/contrib/libs/liburing/test/read-mshot-empty.c @@ -0,0 +1,154 @@ +#include "../config-host.h" +/* SPDX-License-Identifier: MIT */ +/* + * Description: test that multishot read correctly keeps reading until all + * data has been emptied. the original implementation failed + * to do so, if the available buffer size was less than what + * was available, hence requiring multiple reads to empty the + * file buffer. + */ +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <pthread.h> +#include <sys/time.h> + +#include "liburing.h" +#include "helpers.h" + +#define BGID 17 +#define NR_BUFS 4 +#define BR_MASK (NR_BUFS - 1) +#define BUF_SIZE 32 + +static int do_write(int fd, void *buf, int buf_size) +{ + int ret; + + ret = write(fd, buf, buf_size); + if (ret < 0) { + perror("write"); + return 0; + } else if (ret != buf_size) { + fprintf(stderr, "bad write size %d\n", ret); + return 0; + } + + return 1; +} + +static void *thread_fn(void *data) +{ + char w1[BUF_SIZE], w2[BUF_SIZE]; + int *fds = data; + + memset(w1, 0x11, BUF_SIZE); + memset(w2, 0x22, BUF_SIZE); + + if (!do_write(fds[1], w1, BUF_SIZE)) + return NULL; + if (!do_write(fds[1], w2, BUF_SIZE)) + return NULL; + + usleep(100000); + + if (!do_write(fds[1], w1, BUF_SIZE)) + return NULL; + if (!do_write(fds[1], w2, BUF_SIZE)) + return NULL; + + return NULL; +} + +int main(int argc, char *argv[]) +{ + struct io_uring_buf_ring *br; + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + struct io_uring ring; + pthread_t thread; + int i, ret, fds[2]; + void *buf, *tret; + + if (argc > 1) + return T_EXIT_SKIP; + + if (pipe(fds) < 0) { + perror("pipe"); + return T_EXIT_FAIL; + } + + ret = io_uring_queue_init(8, &ring, 0); + if (ret) { + fprintf(stderr, "queue_init: %d\n", ret); + return T_EXIT_FAIL; + } + + br = io_uring_setup_buf_ring(&ring, NR_BUFS, BGID, 0, &ret); + if (!br) { + if (ret == -EINVAL) + return T_EXIT_SKIP; + fprintf(stderr, "failed buffer ring %d\n", ret); + return T_EXIT_FAIL; + } + + buf = malloc(NR_BUFS * BUF_SIZE); + for (i = 0; i < NR_BUFS; i++) { + void *this_buf = buf + i * BUF_SIZE; + + io_uring_buf_ring_add(br, this_buf, BUF_SIZE, i, BR_MASK, i); + } + io_uring_buf_ring_advance(br, NR_BUFS); + + sqe = io_uring_get_sqe(&ring); + io_uring_prep_read_multishot(sqe, fds[0], 0, 0, BGID); + + ret = io_uring_submit(&ring); + if (ret != 1) { + fprintf(stderr, "bad submit %d\n", ret); + return T_EXIT_FAIL; + } + + /* + * read multishot not available would be ready as a cqe when + * submission returns, check and skip if not. + */ + ret = io_uring_peek_cqe(&ring, &cqe); + if (!ret) { + if (cqe->res == -EINVAL || cqe->res == -EBADF) + return T_EXIT_SKIP; + } + + pthread_create(&thread, NULL, thread_fn, fds); + + for (i = 0; i < 4; i++) { + int buf_index; + + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret) { + fprintf(stderr, "wait %d\n", ret); + break; + } + + if (cqe->res != BUF_SIZE) { + fprintf(stderr, "size %d\n", cqe->res); + return T_EXIT_FAIL; + } + if (!(cqe->flags & IORING_CQE_F_BUFFER)) { + fprintf(stderr, "buffer not set\n"); + return T_EXIT_FAIL; + } + if (!(cqe->flags & IORING_CQE_F_MORE)) { + fprintf(stderr, "more not set\n"); + return T_EXIT_FAIL; + } + buf_index = cqe->flags >> 16; + assert(buf_index >= 0 && buf_index <= NR_BUFS); + io_uring_cqe_seen(&ring, cqe); + } + + pthread_join(thread, &tret); + return T_EXIT_PASS; +} |