• 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 			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, &reg, 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