1 /* SPDX-License-Identifier: MIT */
2 /*
3 * Description: IOPOLL with overflow test case
4 */
5 #include <errno.h>
6 #include <stdio.h>
7 #include <unistd.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <fcntl.h>
11 #include <sys/types.h>
12 #include <poll.h>
13 #include <sys/eventfd.h>
14 #include <sys/resource.h>
15 #include "helpers.h"
16 #include "liburing.h"
17 #include "../src/syscall.h"
18
19 #define FILE_SIZE (128 * 1024)
20 #define BS 4096
21 #define BUFFERS (FILE_SIZE / BS)
22
23 static struct iovec *vecs;
24
test(struct io_uring * ring,int fd)25 static int test(struct io_uring *ring, int fd)
26 {
27 struct io_uring_sqe *sqe;
28 int i, j, ret;
29 loff_t off;
30
31 off = FILE_SIZE - BS;
32 for (j = 0; j < 8; j++) {
33 for (i = 0; i < BUFFERS; i++) {
34 sqe = io_uring_get_sqe(ring);
35 io_uring_prep_read(sqe, fd, vecs[i].iov_base,
36 vecs[i].iov_len, off);
37 if (!off)
38 off = FILE_SIZE - BS;
39 else
40 off -= BS;
41 }
42 ret = io_uring_submit(ring);
43 if (ret != BUFFERS) {
44 fprintf(stderr, "submitted %d\n", ret);
45 return T_EXIT_FAIL;
46 }
47 }
48
49 sleep(1);
50
51 ret = __sys_io_uring_enter(ring->ring_fd, 0, BUFFERS * 8,
52 IORING_ENTER_GETEVENTS, NULL);
53
54 for (i = 0; i < BUFFERS * 8; i++) {
55 struct io_uring_cqe *cqe;
56
57 ret = io_uring_wait_cqe(ring, &cqe);
58 if (ret) {
59 fprintf(stderr, "wait=%d\n", ret);
60 return T_EXIT_FAIL;
61 }
62 io_uring_cqe_seen(ring, cqe);
63 }
64
65 return T_EXIT_PASS;
66 }
67
main(int argc,char * argv[])68 int main(int argc, char *argv[])
69 {
70 struct io_uring_params p = { };
71 struct io_uring ring;
72 char buf[256];
73 char *fname;
74 int ret, fd;
75
76 p.flags = IORING_SETUP_IOPOLL | IORING_SETUP_CQSIZE;
77 p.cq_entries = 64;
78 ret = t_create_ring_params(64, &ring, &p);
79 if (ret == T_SETUP_SKIP)
80 return 0;
81 if (ret != T_SETUP_OK) {
82 fprintf(stderr, "ring create failed: %d\n", ret);
83 return 1;
84 }
85
86 if (argc > 1) {
87 fname = argv[1];
88 } else {
89 srand((unsigned)time(NULL));
90 snprintf(buf, sizeof(buf), ".basic-rw-%u-%u",
91 (unsigned)rand(), (unsigned)getpid());
92 fname = buf;
93 t_create_file(fname, FILE_SIZE);
94 }
95
96 fd = open(fname, O_RDONLY | O_DIRECT);
97 if (fd < 0) {
98 if (errno == EINVAL || errno == EACCES || errno == EPERM) {
99 if (fname != argv[1])
100 unlink(fname);
101 return T_EXIT_SKIP;
102 }
103 perror("open");
104 goto err;
105 }
106
107 vecs = t_create_buffers(BUFFERS, BS);
108
109 ret = test(&ring, fd);
110
111 if (fname != argv[1])
112 unlink(fname);
113 return ret;
114 err:
115 if (fname != argv[1])
116 unlink(fname);
117 return T_EXIT_FAIL;
118 }
119