• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &reg, 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