1 /* SPDX-License-Identifier: MIT */
2 /*
3 * Description: test IOU_PBUF_RING_MMAP with a ring setup with a ring
4 * setup without mmap'ing sq/cq arrays
5 *
6 */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <fcntl.h>
11 #include <string.h>
12 #include <sys/mman.h>
13
14 #include "liburing.h"
15 #include "helpers.h"
16
17 static int bgid = 5;
18 static int bid = 89;
19
main(int argc,char * argv[])20 int main(int argc, char *argv[])
21 {
22 struct io_uring_buf_ring *br;
23 struct io_uring_sqe *sqe;
24 struct io_uring_cqe *cqe;
25 struct io_uring ring;
26 size_t ring_size;
27 int ret, ring_mask, fds[2];
28 struct io_uring_buf_reg reg = {
29 .ring_entries = 1,
30 .bgid = bgid,
31 .flags = IOU_PBUF_RING_MMAP,
32 };
33 struct io_uring_params p = { };
34 void *ring_mem;
35 char buf[32];
36 off_t off;
37
38 if (argc > 1)
39 return T_EXIT_SKIP;
40
41 if (posix_memalign(&ring_mem, 16384, 16384))
42 return T_EXIT_FAIL;
43
44 memset(ring_mem, 0, 16384);
45
46 p.flags = IORING_SETUP_NO_MMAP;
47 ret = io_uring_queue_init_mem(1, &ring, &p, ring_mem, 16384);
48 if (ret < 0) {
49 if (ret == -EINVAL || ret == -ENOMEM) {
50 free(ring_mem);
51 return T_EXIT_SKIP;
52 }
53 fprintf(stderr, "queue init failed %d\n", ret);
54 return T_EXIT_FAIL;
55 }
56
57 if (pipe(fds) < 0) {
58 perror("pipe");
59 return T_EXIT_FAIL;
60 }
61
62 ring_size = sizeof(struct io_uring_buf);
63 ring_mask = io_uring_buf_ring_mask(1);
64
65 ret = io_uring_register_buf_ring(&ring, ®, 0);
66 if (ret) {
67 if (ret == -EINVAL) {
68 free(ring_mem);
69 return T_EXIT_SKIP;
70 }
71 fprintf(stderr, "reg buf ring: %d\n", ret);
72 return T_EXIT_FAIL;
73 }
74
75 off = IORING_OFF_PBUF_RING |
76 (unsigned long long) bgid << IORING_OFF_PBUF_SHIFT;
77 br = mmap(NULL, ring_size, PROT_READ | PROT_WRITE,
78 MAP_SHARED | MAP_POPULATE, ring.ring_fd, off);
79 if (br == MAP_FAILED) {
80 if (errno == ENOMEM) {
81 free(ring_mem);
82 return T_EXIT_SKIP;
83 }
84 perror("mmap");
85 return T_EXIT_FAIL;
86 }
87
88 io_uring_buf_ring_add(br, buf, sizeof(buf), bid, ring_mask, 0);
89 io_uring_buf_ring_advance(br, 1);
90
91 sqe = io_uring_get_sqe(&ring);
92 io_uring_prep_read(sqe, fds[0], NULL, 0, 0);
93 sqe->flags |= IOSQE_BUFFER_SELECT;
94 sqe->buf_group = bgid;
95
96 io_uring_submit(&ring);
97
98 ret = write(fds[1], "Hello", 5);
99 if (ret < 0) {
100 perror("write");
101 return T_EXIT_FAIL;
102 } else if (ret != 5) {
103 fprintf(stderr, "short write %d\n", ret);
104 return T_EXIT_FAIL;
105 }
106
107 ret = io_uring_wait_cqe(&ring, &cqe);
108 if (ret) {
109 fprintf(stderr, "wait %d\n", ret);
110 return T_EXIT_FAIL;
111 }
112 if (cqe->res < 0) {
113 fprintf(stderr, "cqe res %d\n", cqe->res);
114 return T_EXIT_FAIL;
115 }
116 if (!(cqe->flags & IORING_CQE_F_BUFFER)) {
117 fprintf(stderr, "buffer not selected in cqe\n");
118 return T_EXIT_FAIL;
119 }
120 if ((cqe->flags >> IORING_CQE_BUFFER_SHIFT) != bid) {
121 fprintf(stderr, "wrong buffer id returned\n");
122 return T_EXIT_FAIL;
123 }
124
125 io_uring_cqe_seen(&ring, cqe);
126
127 io_uring_queue_exit(&ring);
128 free(ring_mem);
129 return T_EXIT_PASS;
130 }
131