123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- #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;
- free(buf);
- 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;
- free(buf);
- return T_EXIT_SKIP;
- }
- if (invalid && ret == -ENOENT) {
- free(buf);
- 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;
- }
|