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 return T_EXIT_SKIP;
51 fprintf(stderr, "queue init failed %d\n", ret);
52 return T_EXIT_FAIL;
53 }
54
55 if (pipe(fds) < 0) {
56 perror("pipe");
57 return T_EXIT_FAIL;
58 }
59
60 ring_size = sizeof(struct io_uring_buf);
61 ring_mask = io_uring_buf_ring_mask(1);
62
63 ret = io_uring_register_buf_ring(&ring, ®, 0);
64 if (ret) {
65 if (ret == -EINVAL)
66 return T_EXIT_SKIP;
67 fprintf(stderr, "reg buf ring: %d\n", ret);
68 return T_EXIT_FAIL;
69 }
70
71 off = IORING_OFF_PBUF_RING |
72 (unsigned long long) bgid << IORING_OFF_PBUF_SHIFT;
73 br = mmap(NULL, ring_size, PROT_READ | PROT_WRITE,
74 MAP_SHARED | MAP_POPULATE, ring.ring_fd, off);
75 if (br == MAP_FAILED) {
76 if (errno == ENOMEM)
77 return T_EXIT_SKIP;
78 perror("mmap");
79 return T_EXIT_FAIL;
80 }
81
82 io_uring_buf_ring_add(br, buf, sizeof(buf), bid, ring_mask, 0);
83 io_uring_buf_ring_advance(br, 1);
84
85 sqe = io_uring_get_sqe(&ring);
86 io_uring_prep_read(sqe, fds[0], NULL, 0, 0);
87 sqe->flags |= IOSQE_BUFFER_SELECT;
88 sqe->buf_group = bgid;
89
90 io_uring_submit(&ring);
91
92 ret = write(fds[1], "Hello", 5);
93 if (ret < 0) {
94 perror("write");
95 return T_EXIT_FAIL;
96 } else if (ret != 5) {
97 fprintf(stderr, "short write %d\n", ret);
98 return T_EXIT_FAIL;
99 }
100
101 ret = io_uring_wait_cqe(&ring, &cqe);
102 if (ret) {
103 fprintf(stderr, "wait %d\n", ret);
104 return T_EXIT_FAIL;
105 }
106 if (cqe->res < 0) {
107 fprintf(stderr, "cqe res %d\n", cqe->res);
108 return T_EXIT_FAIL;
109 }
110 if (!(cqe->flags & IORING_CQE_F_BUFFER)) {
111 fprintf(stderr, "buffer not selected in cqe\n");
112 return T_EXIT_FAIL;
113 }
114 if ((cqe->flags >> IORING_CQE_BUFFER_SHIFT) != bid) {
115 fprintf(stderr, "wrong buffer id returned\n");
116 return T_EXIT_FAIL;
117 }
118
119 io_uring_cqe_seen(&ring, cqe);
120
121 io_uring_queue_exit(&ring);
122 return T_EXIT_PASS;
123 }
124