blob: 0759446b22f9ef06e314f6ac8e8d55cbe5f04abc [file] [log] [blame]
Jens Axboee5024352020-02-11 20:34:12 -07001/* SPDX-License-Identifier: MIT */
Jens Axboeebba2422019-12-26 10:36:01 -07002/*
3 * Description: basic fadvise test
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/time.h>
13
14#include "liburing.h"
15
16#define FILE_SIZE (128 * 1024)
17#define LOOPS 100
Jens Axboe4aca25a2019-12-26 11:09:34 -070018#define MIN_LOOPS 10
Jens Axboeebba2422019-12-26 10:36:01 -070019
20static unsigned long long utime_since(const struct timeval *s,
21 const struct timeval *e)
22{
23 long long sec, usec;
24
25 sec = e->tv_sec - s->tv_sec;
26 usec = (e->tv_usec - s->tv_usec);
27 if (sec > 0 && usec < 0) {
28 sec--;
29 usec += 1000000;
30 }
31
32 sec *= 1000000;
33 return sec + usec;
34}
35
36static unsigned long long utime_since_now(struct timeval *tv)
37{
38 struct timeval end;
39
40 gettimeofday(&end, NULL);
41 return utime_since(tv, &end);
42}
43
44static int create_file(const char *file)
45{
46 ssize_t ret;
47 char *buf;
48 int fd;
49
50 buf = malloc(FILE_SIZE);
51 memset(buf, 0xaa, FILE_SIZE);
52
53 fd = open(file, O_WRONLY | O_CREAT, 0644);
54 if (fd < 0) {
55 perror("open file");
56 return 1;
57 }
58 ret = write(fd, buf, FILE_SIZE);
59 fsync(fd);
60 close(fd);
61 return ret != FILE_SIZE;
62}
63
64static int do_fadvise(struct io_uring *ring, int fd, off_t offset, off_t len,
65 int advice)
66{
67 struct io_uring_sqe *sqe;
68 struct io_uring_cqe *cqe;
69 int ret;
70
71 sqe = io_uring_get_sqe(ring);
72 if (!sqe) {
73 fprintf(stderr, "failed to get sqe\n");
74 return 1;
75 }
76
77 io_uring_prep_fadvise(sqe, fd, offset, len, advice);
78 sqe->user_data = advice;
79 ret = io_uring_submit_and_wait(ring, 1);
80 if (ret != 1) {
81 fprintf(stderr, "submit: %d\n", ret);
82 return 1;
83 }
84
85 ret = io_uring_wait_cqe(ring, &cqe);
86 if (ret) {
87 fprintf(stderr, "wait: %d\n", ret);
88 return 1;
89 }
90
91 ret = cqe->res;
Jens Axboee421b9e2019-12-26 11:37:54 -070092 if (ret == -EINVAL || ret == -EBADF) {
Jens Axboeebba2422019-12-26 10:36:01 -070093 fprintf(stdout, "Fadvise not supported, skipping\n");
Guillem Jover8bf676e2020-02-08 23:16:51 +010094 unlink(".fadvise.tmp");
Jens Axboeebba2422019-12-26 10:36:01 -070095 exit(0);
96 } else if (ret) {
97 fprintf(stderr, "cqe->res=%d\n", cqe->res);
98 }
99 io_uring_cqe_seen(ring, cqe);
100 return ret;
101}
102
103static long do_read(int fd, char *buf)
104{
105 struct timeval tv;
106 int ret;
107 long t;
108
109 ret = lseek(fd, 0, SEEK_SET);
110 if (ret) {
111 perror("lseek");
112 return -1;
113 }
114
115 gettimeofday(&tv, NULL);
116 ret = read(fd, buf, FILE_SIZE);
117 t = utime_since_now(&tv);
118 if (ret < 0) {
119 perror("read");
120 return -1;
121 } else if (ret != FILE_SIZE) {
122 fprintf(stderr, "short read1: %d\n", ret);
123 return -1;
124 }
125
126 return t;
127}
128
129static int test_fadvise(struct io_uring *ring, const char *filename)
130{
131 unsigned long cached_read, uncached_read, cached_read2;
132 int fd, ret;
133 char *buf;
134
135 fd = open(filename, O_RDONLY);
136 if (fd < 0) {
137 perror("open");
138 return 1;
139 }
140
141 buf = malloc(FILE_SIZE);
142
143 cached_read = do_read(fd, buf);
144 if (cached_read == -1)
145 return 1;
146
147 ret = do_fadvise(ring, fd, 0, FILE_SIZE, POSIX_FADV_DONTNEED);
148 if (ret)
149 return 1;
150
151 uncached_read = do_read(fd, buf);
152 if (uncached_read == -1)
153 return 1;
154
155 ret = do_fadvise(ring, fd, 0, FILE_SIZE, POSIX_FADV_DONTNEED);
156 if (ret)
157 return 1;
158
159 ret = do_fadvise(ring, fd, 0, FILE_SIZE, POSIX_FADV_WILLNEED);
160 if (ret)
161 return 1;
162
163 fsync(fd);
164
165 cached_read2 = do_read(fd, buf);
166 if (cached_read2 == -1)
167 return 1;
168
169 if (cached_read < uncached_read &&
170 cached_read2 < uncached_read)
171 return 0;
172
173 return 2;
174}
175
176int main(int argc, char *argv[])
177{
178 struct io_uring ring;
179 int ret, i, good, bad;
Jens Axboe5967ae52020-05-19 21:58:01 -0600180 char *fname;
Jens Axboeebba2422019-12-26 10:36:01 -0700181
Jens Axboe5967ae52020-05-19 21:58:01 -0600182 if (argc > 1) {
183 fname = argv[1];
184 } else {
185 fname = ".fadvise.tmp";
186 if (create_file(".fadvise.tmp")) {
187 fprintf(stderr, "file creation failed\n");
188 goto err;
189 }
Jens Axboeebba2422019-12-26 10:36:01 -0700190 }
191 if (io_uring_queue_init(8, &ring, 0)) {
192 fprintf(stderr, "ring creation failed\n");
193 goto err;
194 }
195
196 good = bad = 0;
197 for (i = 0; i < LOOPS; i++) {
Jens Axboe5967ae52020-05-19 21:58:01 -0600198 ret = test_fadvise(&ring, fname);
Jens Axboeebba2422019-12-26 10:36:01 -0700199 if (ret == 1) {
200 fprintf(stderr, "read_fadvise failed\n");
201 goto err;
202 } else if (!ret)
203 good++;
204 else if (ret == 2)
205 bad++;
Jens Axboe4aca25a2019-12-26 11:09:34 -0700206 if (i >= MIN_LOOPS && !bad)
207 break;
Jens Axboeebba2422019-12-26 10:36:01 -0700208 }
209 if (bad > good) {
210 fprintf(stderr, "Suspicious timings\n");
211 goto err;
212 }
213
Jens Axboe5967ae52020-05-19 21:58:01 -0600214 if (fname != argv[1])
215 unlink(fname);
Jens Axboeebba2422019-12-26 10:36:01 -0700216 io_uring_queue_exit(&ring);
217 return 0;
218err:
Jens Axboe5967ae52020-05-19 21:58:01 -0600219 if (fname != argv[1])
220 unlink(fname);
Jens Axboeebba2422019-12-26 10:36:01 -0700221 return 1;
222}