1 /* SPDX-License-Identifier: MIT */
2 /*
3 * Simple app that demonstrates how to setup an io_uring interface,
4 * submit and complete IO against it, and then tear it down.
5 *
6 * gcc -Wall -O2 -D_GNU_SOURCE -o io_uring-test io_uring-test.c -luring
7 */
8 #include <stdio.h>
9 #include <fcntl.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <unistd.h>
15 #include "liburing.h"
16
17 #define QD 4
18
main(int argc,char * argv[])19 int main(int argc, char *argv[])
20 {
21 struct io_uring ring;
22 int i, fd, ret, pending, done;
23 struct io_uring_sqe *sqe;
24 struct io_uring_cqe *cqe;
25 struct iovec *iovecs;
26 struct stat sb;
27 ssize_t fsize;
28 off_t offset;
29 void *buf;
30
31 if (argc < 2) {
32 printf("%s: file\n", argv[0]);
33 return 1;
34 }
35
36 ret = io_uring_queue_init(QD, &ring, 0);
37 if (ret < 0) {
38 fprintf(stderr, "queue_init: %s\n", strerror(-ret));
39 return 1;
40 }
41
42 fd = open(argv[1], O_RDONLY | O_DIRECT);
43 if (fd < 0) {
44 perror("open");
45 return 1;
46 }
47
48 if (fstat(fd, &sb) < 0) {
49 perror("fstat");
50 return 1;
51 }
52
53 fsize = 0;
54 iovecs = calloc(QD, sizeof(struct iovec));
55 for (i = 0; i < QD; i++) {
56 if (posix_memalign(&buf, 4096, 4096))
57 return 1;
58 iovecs[i].iov_base = buf;
59 iovecs[i].iov_len = 4096;
60 fsize += 4096;
61 }
62
63 offset = 0;
64 i = 0;
65 do {
66 sqe = io_uring_get_sqe(&ring);
67 if (!sqe)
68 break;
69 io_uring_prep_readv(sqe, fd, &iovecs[i], 1, offset);
70 offset += iovecs[i].iov_len;
71 i++;
72 if (offset > sb.st_size)
73 break;
74 } while (1);
75
76 ret = io_uring_submit(&ring);
77 if (ret < 0) {
78 fprintf(stderr, "io_uring_submit: %s\n", strerror(-ret));
79 return 1;
80 } else if (ret != i) {
81 fprintf(stderr, "io_uring_submit submitted less %d\n", ret);
82 return 1;
83 }
84
85 done = 0;
86 pending = ret;
87 fsize = 0;
88 for (i = 0; i < pending; i++) {
89 ret = io_uring_wait_cqe(&ring, &cqe);
90 if (ret < 0) {
91 fprintf(stderr, "io_uring_wait_cqe: %s\n", strerror(-ret));
92 return 1;
93 }
94
95 done++;
96 ret = 0;
97 if (cqe->res != 4096 && cqe->res + fsize != sb.st_size) {
98 fprintf(stderr, "ret=%d, wanted 4096\n", cqe->res);
99 ret = 1;
100 }
101 fsize += cqe->res;
102 io_uring_cqe_seen(&ring, cqe);
103 if (ret)
104 break;
105 }
106
107 printf("Submitted=%d, completed=%d, bytes=%lu\n", pending, done,
108 (unsigned long) fsize);
109 close(fd);
110 io_uring_queue_exit(&ring);
111 return 0;
112 }
113