aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/liburing/test/read-mshot-empty.c
diff options
context:
space:
mode:
authorthegeorg <thegeorg@yandex-team.com>2024-06-09 11:55:21 +0300
committerthegeorg <thegeorg@yandex-team.com>2024-06-09 12:07:55 +0300
commitafd4899380eea1c70e2a68714b5da1c9919ccdbd (patch)
treecd5120708784139bc6a0f8881da1ed8389a065b3 /contrib/libs/liburing/test/read-mshot-empty.c
parenta83bd2dd3c21e38c6c0807ec5e679497ab567f24 (diff)
downloadydb-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.c154
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;
+}