1 /* SPDX-License-Identifier: MIT */
2 /*
3 * Description: test a mem leak with IOPOLL
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 <sys/wait.h>
13 #include "helpers.h"
14 #include "liburing.h"
15
16 #define FILE_SIZE (128 * 1024)
17 #define BS 4096
18 #define BUFFERS (FILE_SIZE / BS)
19
do_iopoll(const char * fname)20 static int do_iopoll(const char *fname)
21 {
22 struct io_uring_sqe *sqe;
23 struct io_uring ring;
24 struct iovec *iov;
25 int fd;
26
27 fd = open(fname, O_RDONLY | O_DIRECT);
28 if (fd < 0) {
29 if (errno == EINVAL || errno == EPERM || errno == EACCES)
30 return T_EXIT_SKIP;
31 perror("open");
32 return T_EXIT_SKIP;
33 }
34
35 iov = t_create_buffers(1, 4096);
36
37 t_create_ring(2, &ring, IORING_SETUP_IOPOLL);
38
39 sqe = io_uring_get_sqe(&ring);
40 io_uring_prep_read(sqe, fd, iov->iov_base, iov->iov_len, 0);
41 io_uring_submit(&ring);
42
43 close(fd);
44 free(iov->iov_base);
45 free(iov);
46 return T_EXIT_PASS;
47 }
48
test(const char * fname)49 static int test(const char *fname)
50 {
51 if (fork()) {
52 int stat;
53
54 wait(&stat);
55 return WEXITSTATUS(stat);
56 } else {
57 int ret;
58
59 ret = do_iopoll(fname);
60 exit(ret);
61 }
62 }
63
main(int argc,char * argv[])64 int main(int argc, char *argv[])
65 {
66 char buf[256];
67 char *fname;
68 int i, ret;
69
70 if (argc > 1) {
71 fname = argv[1];
72 } else {
73 srand((unsigned)time(NULL));
74 snprintf(buf, sizeof(buf), ".iopoll-leak-%u-%u",
75 (unsigned)rand(), (unsigned)getpid());
76 fname = buf;
77 t_create_file(fname, FILE_SIZE);
78 }
79
80 for (i = 0; i < 16; i++) {
81 ret = test(fname);
82 if (ret == T_EXIT_SKIP || ret == T_EXIT_FAIL)
83 break;
84 }
85
86 if (fname != argv[1])
87 unlink(fname);
88 return ret;
89 }
90