1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-only
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker * Copyright (C) 2012 Linux Test Project, Inc.
4*49cdfc7eSAndroid Build Coastguard Worker */
5*49cdfc7eSAndroid Build Coastguard Worker
6*49cdfc7eSAndroid Build Coastguard Worker /*
7*49cdfc7eSAndroid Build Coastguard Worker * functional test for readahead() syscall
8*49cdfc7eSAndroid Build Coastguard Worker *
9*49cdfc7eSAndroid Build Coastguard Worker * This test is measuring effects of readahead syscall.
10*49cdfc7eSAndroid Build Coastguard Worker * It mmaps/reads a test file with and without prior call to readahead.
11*49cdfc7eSAndroid Build Coastguard Worker *
12*49cdfc7eSAndroid Build Coastguard Worker * The overlay part of the test is regression for:
13*49cdfc7eSAndroid Build Coastguard Worker * b833a3660394
14*49cdfc7eSAndroid Build Coastguard Worker * ("ovl: add ovl_fadvise()")
15*49cdfc7eSAndroid Build Coastguard Worker * Introduced by:
16*49cdfc7eSAndroid Build Coastguard Worker * 5b910bd615ba
17*49cdfc7eSAndroid Build Coastguard Worker * ("ovl: fix GPF in swapfile_activate of file from overlayfs over xfs")
18*49cdfc7eSAndroid Build Coastguard Worker */
19*49cdfc7eSAndroid Build Coastguard Worker #define _GNU_SOURCE
20*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
21*49cdfc7eSAndroid Build Coastguard Worker #include <sys/syscall.h>
22*49cdfc7eSAndroid Build Coastguard Worker #include <sys/mman.h>
23*49cdfc7eSAndroid Build Coastguard Worker #include <sys/mount.h>
24*49cdfc7eSAndroid Build Coastguard Worker #include <sys/stat.h>
25*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
26*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
27*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
28*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
29*49cdfc7eSAndroid Build Coastguard Worker #include <stdint.h>
30*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
31*49cdfc7eSAndroid Build Coastguard Worker #include <fcntl.h>
32*49cdfc7eSAndroid Build Coastguard Worker #include "config.h"
33*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
34*49cdfc7eSAndroid Build Coastguard Worker #include "tst_timer.h"
35*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/syscalls.h"
36*49cdfc7eSAndroid Build Coastguard Worker
37*49cdfc7eSAndroid Build Coastguard Worker static char testfile[PATH_MAX] = "testfile";
38*49cdfc7eSAndroid Build Coastguard Worker #define DROP_CACHES_FNAME "/proc/sys/vm/drop_caches"
39*49cdfc7eSAndroid Build Coastguard Worker #define MEMINFO_FNAME "/proc/meminfo"
40*49cdfc7eSAndroid Build Coastguard Worker #define PROC_IO_FNAME "/proc/self/io"
41*49cdfc7eSAndroid Build Coastguard Worker #define DEFAULT_FILESIZE (64 * 1024 * 1024)
42*49cdfc7eSAndroid Build Coastguard Worker
43*49cdfc7eSAndroid Build Coastguard Worker static size_t testfile_size = DEFAULT_FILESIZE;
44*49cdfc7eSAndroid Build Coastguard Worker static char *opt_fsizestr;
45*49cdfc7eSAndroid Build Coastguard Worker static int pagesize;
46*49cdfc7eSAndroid Build Coastguard Worker static unsigned long cached_max;
47*49cdfc7eSAndroid Build Coastguard Worker static int ovl_mounted;
48*49cdfc7eSAndroid Build Coastguard Worker static int readahead_length = 4096;
49*49cdfc7eSAndroid Build Coastguard Worker static char sys_bdi_ra_path[PATH_MAX];
50*49cdfc7eSAndroid Build Coastguard Worker static int orig_bdi_limit;
51*49cdfc7eSAndroid Build Coastguard Worker
52*49cdfc7eSAndroid Build Coastguard Worker static const char mntpoint[] = OVL_BASE_MNTPOINT;
53*49cdfc7eSAndroid Build Coastguard Worker
libc_readahead(int fd,off_t offset,size_t len)54*49cdfc7eSAndroid Build Coastguard Worker static int libc_readahead(int fd, off_t offset, size_t len)
55*49cdfc7eSAndroid Build Coastguard Worker {
56*49cdfc7eSAndroid Build Coastguard Worker return readahead(fd, offset, len);
57*49cdfc7eSAndroid Build Coastguard Worker }
58*49cdfc7eSAndroid Build Coastguard Worker
fadvise_willneed(int fd,off_t offset,size_t len)59*49cdfc7eSAndroid Build Coastguard Worker static int fadvise_willneed(int fd, off_t offset, size_t len)
60*49cdfc7eSAndroid Build Coastguard Worker {
61*49cdfc7eSAndroid Build Coastguard Worker /* Should have the same effect as readahead() syscall */
62*49cdfc7eSAndroid Build Coastguard Worker errno = posix_fadvise(fd, offset, len, POSIX_FADV_WILLNEED);
63*49cdfc7eSAndroid Build Coastguard Worker /* posix_fadvise returns error number (not in errno) */
64*49cdfc7eSAndroid Build Coastguard Worker return errno ? -1 : 0;
65*49cdfc7eSAndroid Build Coastguard Worker }
66*49cdfc7eSAndroid Build Coastguard Worker
67*49cdfc7eSAndroid Build Coastguard Worker static struct tcase {
68*49cdfc7eSAndroid Build Coastguard Worker const char *tname;
69*49cdfc7eSAndroid Build Coastguard Worker int use_overlay;
70*49cdfc7eSAndroid Build Coastguard Worker int use_fadvise;
71*49cdfc7eSAndroid Build Coastguard Worker /* Use either readahead() syscall or POSIX_FADV_WILLNEED */
72*49cdfc7eSAndroid Build Coastguard Worker int (*readahead)(int fd, off_t offset, size_t len);
73*49cdfc7eSAndroid Build Coastguard Worker } tcases[] = {
74*49cdfc7eSAndroid Build Coastguard Worker { "readahead on file", 0, 0, libc_readahead },
75*49cdfc7eSAndroid Build Coastguard Worker { "readahead on overlayfs file", 1, 0, libc_readahead },
76*49cdfc7eSAndroid Build Coastguard Worker { "POSIX_FADV_WILLNEED on file", 0, 1, fadvise_willneed },
77*49cdfc7eSAndroid Build Coastguard Worker { "POSIX_FADV_WILLNEED on overlayfs file", 1, 1, fadvise_willneed },
78*49cdfc7eSAndroid Build Coastguard Worker };
79*49cdfc7eSAndroid Build Coastguard Worker
80*49cdfc7eSAndroid Build Coastguard Worker static int readahead_supported = 1;
81*49cdfc7eSAndroid Build Coastguard Worker static int fadvise_supported = 1;
82*49cdfc7eSAndroid Build Coastguard Worker
has_file(const char * fname,int required)83*49cdfc7eSAndroid Build Coastguard Worker static int has_file(const char *fname, int required)
84*49cdfc7eSAndroid Build Coastguard Worker {
85*49cdfc7eSAndroid Build Coastguard Worker struct stat buf;
86*49cdfc7eSAndroid Build Coastguard Worker
87*49cdfc7eSAndroid Build Coastguard Worker if (stat(fname, &buf) == -1) {
88*49cdfc7eSAndroid Build Coastguard Worker if (errno != ENOENT)
89*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK | TERRNO, "stat %s", fname);
90*49cdfc7eSAndroid Build Coastguard Worker if (required)
91*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TCONF, "%s not available", fname);
92*49cdfc7eSAndroid Build Coastguard Worker return 0;
93*49cdfc7eSAndroid Build Coastguard Worker }
94*49cdfc7eSAndroid Build Coastguard Worker return 1;
95*49cdfc7eSAndroid Build Coastguard Worker }
96*49cdfc7eSAndroid Build Coastguard Worker
drop_caches(void)97*49cdfc7eSAndroid Build Coastguard Worker static void drop_caches(void)
98*49cdfc7eSAndroid Build Coastguard Worker {
99*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_PRINTF(DROP_CACHES_FNAME, "1");
100*49cdfc7eSAndroid Build Coastguard Worker }
101*49cdfc7eSAndroid Build Coastguard Worker
get_bytes_read(void)102*49cdfc7eSAndroid Build Coastguard Worker static unsigned long get_bytes_read(void)
103*49cdfc7eSAndroid Build Coastguard Worker {
104*49cdfc7eSAndroid Build Coastguard Worker unsigned long ret;
105*49cdfc7eSAndroid Build Coastguard Worker
106*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_LINES_SCANF(PROC_IO_FNAME, "read_bytes: %lu", &ret);
107*49cdfc7eSAndroid Build Coastguard Worker
108*49cdfc7eSAndroid Build Coastguard Worker return ret;
109*49cdfc7eSAndroid Build Coastguard Worker }
110*49cdfc7eSAndroid Build Coastguard Worker
get_cached_size(void)111*49cdfc7eSAndroid Build Coastguard Worker static unsigned long get_cached_size(void)
112*49cdfc7eSAndroid Build Coastguard Worker {
113*49cdfc7eSAndroid Build Coastguard Worker unsigned long ret;
114*49cdfc7eSAndroid Build Coastguard Worker
115*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_LINES_SCANF(MEMINFO_FNAME, "Cached: %lu", &ret);
116*49cdfc7eSAndroid Build Coastguard Worker
117*49cdfc7eSAndroid Build Coastguard Worker return ret;
118*49cdfc7eSAndroid Build Coastguard Worker }
119*49cdfc7eSAndroid Build Coastguard Worker
create_testfile(int use_overlay)120*49cdfc7eSAndroid Build Coastguard Worker static void create_testfile(int use_overlay)
121*49cdfc7eSAndroid Build Coastguard Worker {
122*49cdfc7eSAndroid Build Coastguard Worker int fd;
123*49cdfc7eSAndroid Build Coastguard Worker char *tmp;
124*49cdfc7eSAndroid Build Coastguard Worker size_t i;
125*49cdfc7eSAndroid Build Coastguard Worker
126*49cdfc7eSAndroid Build Coastguard Worker sprintf(testfile, "%s/testfile",
127*49cdfc7eSAndroid Build Coastguard Worker use_overlay ? OVL_MNT : OVL_BASE_MNTPOINT);
128*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "creating test file of size: %zu", testfile_size);
129*49cdfc7eSAndroid Build Coastguard Worker tmp = SAFE_MALLOC(pagesize);
130*49cdfc7eSAndroid Build Coastguard Worker
131*49cdfc7eSAndroid Build Coastguard Worker /* round to page size */
132*49cdfc7eSAndroid Build Coastguard Worker testfile_size = testfile_size & ~((long)pagesize - 1);
133*49cdfc7eSAndroid Build Coastguard Worker
134*49cdfc7eSAndroid Build Coastguard Worker fd = SAFE_CREAT(testfile, 0644);
135*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < testfile_size; i += pagesize)
136*49cdfc7eSAndroid Build Coastguard Worker SAFE_WRITE(SAFE_WRITE_ALL, fd, tmp, pagesize);
137*49cdfc7eSAndroid Build Coastguard Worker SAFE_FSYNC(fd);
138*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fd);
139*49cdfc7eSAndroid Build Coastguard Worker free(tmp);
140*49cdfc7eSAndroid Build Coastguard Worker }
141*49cdfc7eSAndroid Build Coastguard Worker
142*49cdfc7eSAndroid Build Coastguard Worker /* read_testfile - mmap testfile and read every page.
143*49cdfc7eSAndroid Build Coastguard Worker * This functions measures how many I/O and time it takes to fully
144*49cdfc7eSAndroid Build Coastguard Worker * read contents of test file.
145*49cdfc7eSAndroid Build Coastguard Worker *
146*49cdfc7eSAndroid Build Coastguard Worker * @do_readahead: call readahead prior to reading file content?
147*49cdfc7eSAndroid Build Coastguard Worker * @fname: name of file to test
148*49cdfc7eSAndroid Build Coastguard Worker * @fsize: how many bytes to read/mmap
149*49cdfc7eSAndroid Build Coastguard Worker * @read_bytes: returns difference of bytes read, parsed from /proc/<pid>/io
150*49cdfc7eSAndroid Build Coastguard Worker * @usec: returns how many microsecond it took to go over fsize bytes
151*49cdfc7eSAndroid Build Coastguard Worker * @cached: returns cached kB from /proc/meminfo
152*49cdfc7eSAndroid Build Coastguard Worker */
read_testfile(struct tcase * tc,int do_readahead,const char * fname,size_t fsize,unsigned long * read_bytes,long long * usec,unsigned long * cached)153*49cdfc7eSAndroid Build Coastguard Worker static int read_testfile(struct tcase *tc, int do_readahead,
154*49cdfc7eSAndroid Build Coastguard Worker const char *fname, size_t fsize,
155*49cdfc7eSAndroid Build Coastguard Worker unsigned long *read_bytes, long long *usec,
156*49cdfc7eSAndroid Build Coastguard Worker unsigned long *cached)
157*49cdfc7eSAndroid Build Coastguard Worker {
158*49cdfc7eSAndroid Build Coastguard Worker int fd;
159*49cdfc7eSAndroid Build Coastguard Worker size_t i = 0;
160*49cdfc7eSAndroid Build Coastguard Worker long read_bytes_start;
161*49cdfc7eSAndroid Build Coastguard Worker unsigned char *p, tmp;
162*49cdfc7eSAndroid Build Coastguard Worker off_t offset = 0;
163*49cdfc7eSAndroid Build Coastguard Worker
164*49cdfc7eSAndroid Build Coastguard Worker fd = SAFE_OPEN(fname, O_RDONLY);
165*49cdfc7eSAndroid Build Coastguard Worker
166*49cdfc7eSAndroid Build Coastguard Worker if (do_readahead) {
167*49cdfc7eSAndroid Build Coastguard Worker do {
168*49cdfc7eSAndroid Build Coastguard Worker TEST(tc->readahead(fd, offset, fsize - offset));
169*49cdfc7eSAndroid Build Coastguard Worker if (TST_RET != 0) {
170*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fd);
171*49cdfc7eSAndroid Build Coastguard Worker return TST_ERR;
172*49cdfc7eSAndroid Build Coastguard Worker }
173*49cdfc7eSAndroid Build Coastguard Worker
174*49cdfc7eSAndroid Build Coastguard Worker i++;
175*49cdfc7eSAndroid Build Coastguard Worker offset += readahead_length;
176*49cdfc7eSAndroid Build Coastguard Worker } while ((size_t)offset < fsize);
177*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "readahead calls made: %zu", i);
178*49cdfc7eSAndroid Build Coastguard Worker *cached = get_cached_size();
179*49cdfc7eSAndroid Build Coastguard Worker
180*49cdfc7eSAndroid Build Coastguard Worker /* offset of file shouldn't change after readahead */
181*49cdfc7eSAndroid Build Coastguard Worker offset = SAFE_LSEEK(fd, 0, SEEK_CUR);
182*49cdfc7eSAndroid Build Coastguard Worker if (offset == 0)
183*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS, "offset is still at 0 as expected");
184*49cdfc7eSAndroid Build Coastguard Worker else
185*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL, "offset has changed to: %lu", offset);
186*49cdfc7eSAndroid Build Coastguard Worker }
187*49cdfc7eSAndroid Build Coastguard Worker
188*49cdfc7eSAndroid Build Coastguard Worker tst_timer_start(CLOCK_MONOTONIC);
189*49cdfc7eSAndroid Build Coastguard Worker read_bytes_start = get_bytes_read();
190*49cdfc7eSAndroid Build Coastguard Worker
191*49cdfc7eSAndroid Build Coastguard Worker p = SAFE_MMAP(NULL, fsize, PROT_READ, MAP_SHARED | MAP_POPULATE, fd, 0);
192*49cdfc7eSAndroid Build Coastguard Worker
193*49cdfc7eSAndroid Build Coastguard Worker /* for old kernels, where MAP_POPULATE doesn't work, touch each page */
194*49cdfc7eSAndroid Build Coastguard Worker tmp = 0;
195*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < fsize; i += pagesize)
196*49cdfc7eSAndroid Build Coastguard Worker tmp = tmp ^ p[i];
197*49cdfc7eSAndroid Build Coastguard Worker /* prevent gcc from optimizing out loop above */
198*49cdfc7eSAndroid Build Coastguard Worker if (tmp != 0)
199*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "This line should not be reached");
200*49cdfc7eSAndroid Build Coastguard Worker
201*49cdfc7eSAndroid Build Coastguard Worker if (!do_readahead)
202*49cdfc7eSAndroid Build Coastguard Worker *cached = get_cached_size();
203*49cdfc7eSAndroid Build Coastguard Worker
204*49cdfc7eSAndroid Build Coastguard Worker SAFE_MUNMAP(p, fsize);
205*49cdfc7eSAndroid Build Coastguard Worker
206*49cdfc7eSAndroid Build Coastguard Worker *read_bytes = get_bytes_read() - read_bytes_start;
207*49cdfc7eSAndroid Build Coastguard Worker
208*49cdfc7eSAndroid Build Coastguard Worker tst_timer_stop();
209*49cdfc7eSAndroid Build Coastguard Worker *usec = tst_timer_elapsed_us();
210*49cdfc7eSAndroid Build Coastguard Worker
211*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fd);
212*49cdfc7eSAndroid Build Coastguard Worker return 0;
213*49cdfc7eSAndroid Build Coastguard Worker }
214*49cdfc7eSAndroid Build Coastguard Worker
test_readahead(unsigned int n)215*49cdfc7eSAndroid Build Coastguard Worker static void test_readahead(unsigned int n)
216*49cdfc7eSAndroid Build Coastguard Worker {
217*49cdfc7eSAndroid Build Coastguard Worker unsigned long read_bytes, read_bytes_ra;
218*49cdfc7eSAndroid Build Coastguard Worker long long usec, usec_ra;
219*49cdfc7eSAndroid Build Coastguard Worker unsigned long cached_high, cached_low, cached, cached_ra;
220*49cdfc7eSAndroid Build Coastguard Worker int ret;
221*49cdfc7eSAndroid Build Coastguard Worker struct tcase *tc = &tcases[n];
222*49cdfc7eSAndroid Build Coastguard Worker
223*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "Test #%d: %s", n, tc->tname);
224*49cdfc7eSAndroid Build Coastguard Worker
225*49cdfc7eSAndroid Build Coastguard Worker if (tc->use_overlay && !ovl_mounted) {
226*49cdfc7eSAndroid Build Coastguard Worker tst_res(TCONF, "overlayfs is not configured in this kernel");
227*49cdfc7eSAndroid Build Coastguard Worker return;
228*49cdfc7eSAndroid Build Coastguard Worker }
229*49cdfc7eSAndroid Build Coastguard Worker
230*49cdfc7eSAndroid Build Coastguard Worker create_testfile(tc->use_overlay);
231*49cdfc7eSAndroid Build Coastguard Worker
232*49cdfc7eSAndroid Build Coastguard Worker /* find out how much can cache hold if we read whole file */
233*49cdfc7eSAndroid Build Coastguard Worker read_testfile(tc, 0, testfile, testfile_size, &read_bytes, &usec,
234*49cdfc7eSAndroid Build Coastguard Worker &cached);
235*49cdfc7eSAndroid Build Coastguard Worker cached_high = get_cached_size();
236*49cdfc7eSAndroid Build Coastguard Worker sync();
237*49cdfc7eSAndroid Build Coastguard Worker drop_caches();
238*49cdfc7eSAndroid Build Coastguard Worker cached_low = get_cached_size();
239*49cdfc7eSAndroid Build Coastguard Worker cached_max = MAX(cached_max, cached_high - cached_low);
240*49cdfc7eSAndroid Build Coastguard Worker
241*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "read_testfile(0)");
242*49cdfc7eSAndroid Build Coastguard Worker read_testfile(tc, 0, testfile, testfile_size, &read_bytes, &usec,
243*49cdfc7eSAndroid Build Coastguard Worker &cached);
244*49cdfc7eSAndroid Build Coastguard Worker if (cached > cached_low)
245*49cdfc7eSAndroid Build Coastguard Worker cached = cached - cached_low;
246*49cdfc7eSAndroid Build Coastguard Worker else
247*49cdfc7eSAndroid Build Coastguard Worker cached = 0;
248*49cdfc7eSAndroid Build Coastguard Worker
249*49cdfc7eSAndroid Build Coastguard Worker sync();
250*49cdfc7eSAndroid Build Coastguard Worker drop_caches();
251*49cdfc7eSAndroid Build Coastguard Worker cached_low = get_cached_size();
252*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "read_testfile(1)");
253*49cdfc7eSAndroid Build Coastguard Worker ret = read_testfile(tc, 1, testfile, testfile_size, &read_bytes_ra,
254*49cdfc7eSAndroid Build Coastguard Worker &usec_ra, &cached_ra);
255*49cdfc7eSAndroid Build Coastguard Worker
256*49cdfc7eSAndroid Build Coastguard Worker if (ret == EINVAL) {
257*49cdfc7eSAndroid Build Coastguard Worker if (tc->use_fadvise &&
258*49cdfc7eSAndroid Build Coastguard Worker (!tc->use_overlay || !fadvise_supported)) {
259*49cdfc7eSAndroid Build Coastguard Worker fadvise_supported = 0;
260*49cdfc7eSAndroid Build Coastguard Worker tst_res(TCONF, "CONFIG_ADVISE_SYSCALLS not configured "
261*49cdfc7eSAndroid Build Coastguard Worker "in kernel?");
262*49cdfc7eSAndroid Build Coastguard Worker return;
263*49cdfc7eSAndroid Build Coastguard Worker }
264*49cdfc7eSAndroid Build Coastguard Worker
265*49cdfc7eSAndroid Build Coastguard Worker if (!tc->use_overlay || !readahead_supported) {
266*49cdfc7eSAndroid Build Coastguard Worker readahead_supported = 0;
267*49cdfc7eSAndroid Build Coastguard Worker tst_res(TCONF, "readahead not supported on %s",
268*49cdfc7eSAndroid Build Coastguard Worker tst_device->fs_type);
269*49cdfc7eSAndroid Build Coastguard Worker return;
270*49cdfc7eSAndroid Build Coastguard Worker }
271*49cdfc7eSAndroid Build Coastguard Worker }
272*49cdfc7eSAndroid Build Coastguard Worker
273*49cdfc7eSAndroid Build Coastguard Worker if (ret) {
274*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL | TTERRNO, "%s failed on %s",
275*49cdfc7eSAndroid Build Coastguard Worker tc->use_fadvise ? "fadvise" : "readahead",
276*49cdfc7eSAndroid Build Coastguard Worker tc->use_overlay ? "overlayfs" :
277*49cdfc7eSAndroid Build Coastguard Worker tst_device->fs_type);
278*49cdfc7eSAndroid Build Coastguard Worker return;
279*49cdfc7eSAndroid Build Coastguard Worker }
280*49cdfc7eSAndroid Build Coastguard Worker
281*49cdfc7eSAndroid Build Coastguard Worker if (cached_ra > cached_low)
282*49cdfc7eSAndroid Build Coastguard Worker cached_ra = cached_ra - cached_low;
283*49cdfc7eSAndroid Build Coastguard Worker else
284*49cdfc7eSAndroid Build Coastguard Worker cached_ra = 0;
285*49cdfc7eSAndroid Build Coastguard Worker
286*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "read_testfile(0) took: %lli usec", usec);
287*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "read_testfile(1) took: %lli usec", usec_ra);
288*49cdfc7eSAndroid Build Coastguard Worker if (has_file(PROC_IO_FNAME, 0)) {
289*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "read_testfile(0) read: %ld bytes", read_bytes);
290*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "read_testfile(1) read: %ld bytes",
291*49cdfc7eSAndroid Build Coastguard Worker read_bytes_ra);
292*49cdfc7eSAndroid Build Coastguard Worker /* actual number of read bytes depends on total RAM */
293*49cdfc7eSAndroid Build Coastguard Worker if (read_bytes_ra < read_bytes)
294*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS, "readahead saved some I/O");
295*49cdfc7eSAndroid Build Coastguard Worker else
296*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL, "readahead failed to save any I/O");
297*49cdfc7eSAndroid Build Coastguard Worker } else {
298*49cdfc7eSAndroid Build Coastguard Worker tst_res(TCONF, "Your system doesn't have /proc/self/io,"
299*49cdfc7eSAndroid Build Coastguard Worker " unable to determine read bytes during test");
300*49cdfc7eSAndroid Build Coastguard Worker }
301*49cdfc7eSAndroid Build Coastguard Worker
302*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "cache can hold at least: %ld kB", cached_max);
303*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "read_testfile(0) used cache: %ld kB", cached);
304*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "read_testfile(1) used cache: %ld kB", cached_ra);
305*49cdfc7eSAndroid Build Coastguard Worker
306*49cdfc7eSAndroid Build Coastguard Worker if (cached_max * 1024 >= testfile_size) {
307*49cdfc7eSAndroid Build Coastguard Worker /*
308*49cdfc7eSAndroid Build Coastguard Worker * if cache can hold ~testfile_size then cache increase
309*49cdfc7eSAndroid Build Coastguard Worker * for readahead should be at least testfile_size/2
310*49cdfc7eSAndroid Build Coastguard Worker */
311*49cdfc7eSAndroid Build Coastguard Worker if (cached_ra * 1024 > testfile_size / 2)
312*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS, "using cache as expected");
313*49cdfc7eSAndroid Build Coastguard Worker else if (!cached_ra)
314*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL, "readahead failed to use any cache");
315*49cdfc7eSAndroid Build Coastguard Worker else
316*49cdfc7eSAndroid Build Coastguard Worker tst_res(TWARN, "using less cache than expected");
317*49cdfc7eSAndroid Build Coastguard Worker } else {
318*49cdfc7eSAndroid Build Coastguard Worker tst_res(TCONF, "Page cache on your system is too small "
319*49cdfc7eSAndroid Build Coastguard Worker "to hold whole testfile.");
320*49cdfc7eSAndroid Build Coastguard Worker }
321*49cdfc7eSAndroid Build Coastguard Worker
322*49cdfc7eSAndroid Build Coastguard Worker /*
323*49cdfc7eSAndroid Build Coastguard Worker * The time consuming of readahead quite depending on the platform IO
324*49cdfc7eSAndroid Build Coastguard Worker * speed, sometime test timeout when the default max_runtime is used up.
325*49cdfc7eSAndroid Build Coastguard Worker *
326*49cdfc7eSAndroid Build Coastguard Worker * readahead02.c:221: TINFO: Test #2: POSIX_FADV_WILLNEED on file
327*49cdfc7eSAndroid Build Coastguard Worker * readahead02.c:285: TINFO: read_testfile(0) took: 26317623 usec
328*49cdfc7eSAndroid Build Coastguard Worker * readahead02.c:286: TINFO: read_testfile(1) took: 26101484 usec
329*49cdfc7eSAndroid Build Coastguard Worker *
330*49cdfc7eSAndroid Build Coastguard Worker * Here raise the maximum runtime dynamically.
331*49cdfc7eSAndroid Build Coastguard Worker */
332*49cdfc7eSAndroid Build Coastguard Worker if ((tc+1)->readahead)
333*49cdfc7eSAndroid Build Coastguard Worker tst_set_max_runtime(test.max_runtime + (usec + usec_ra) / 1000000);
334*49cdfc7eSAndroid Build Coastguard Worker }
335*49cdfc7eSAndroid Build Coastguard Worker
336*49cdfc7eSAndroid Build Coastguard Worker
337*49cdfc7eSAndroid Build Coastguard Worker /*
338*49cdfc7eSAndroid Build Coastguard Worker * We try raising bdi readahead limit as much as we can. We write
339*49cdfc7eSAndroid Build Coastguard Worker * and read back "read_ahead_kb" sysfs value, starting with filesize.
340*49cdfc7eSAndroid Build Coastguard Worker * If that fails, we try again with lower value.
341*49cdfc7eSAndroid Build Coastguard Worker * readahead_length used in the test is then set to MIN(bdi limit, 2M),
342*49cdfc7eSAndroid Build Coastguard Worker * to respect kernels prior to commit 600e19afc5f8a6c.
343*49cdfc7eSAndroid Build Coastguard Worker */
setup_readahead_length(void)344*49cdfc7eSAndroid Build Coastguard Worker static void setup_readahead_length(void)
345*49cdfc7eSAndroid Build Coastguard Worker {
346*49cdfc7eSAndroid Build Coastguard Worker struct stat sbuf;
347*49cdfc7eSAndroid Build Coastguard Worker char tmp[PATH_MAX], *backing_dev;
348*49cdfc7eSAndroid Build Coastguard Worker int ra_new_limit, ra_limit;
349*49cdfc7eSAndroid Build Coastguard Worker
350*49cdfc7eSAndroid Build Coastguard Worker /* Find out backing device name */
351*49cdfc7eSAndroid Build Coastguard Worker SAFE_LSTAT(tst_device->dev, &sbuf);
352*49cdfc7eSAndroid Build Coastguard Worker if (S_ISLNK(sbuf.st_mode))
353*49cdfc7eSAndroid Build Coastguard Worker SAFE_READLINK(tst_device->dev, tmp, PATH_MAX);
354*49cdfc7eSAndroid Build Coastguard Worker else
355*49cdfc7eSAndroid Build Coastguard Worker strcpy(tmp, tst_device->dev);
356*49cdfc7eSAndroid Build Coastguard Worker
357*49cdfc7eSAndroid Build Coastguard Worker backing_dev = basename(tmp);
358*49cdfc7eSAndroid Build Coastguard Worker sprintf(sys_bdi_ra_path, "/sys/class/block/%s/bdi/read_ahead_kb",
359*49cdfc7eSAndroid Build Coastguard Worker backing_dev);
360*49cdfc7eSAndroid Build Coastguard Worker if (access(sys_bdi_ra_path, F_OK))
361*49cdfc7eSAndroid Build Coastguard Worker return;
362*49cdfc7eSAndroid Build Coastguard Worker
363*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_SCANF(sys_bdi_ra_path, "%d", &orig_bdi_limit);
364*49cdfc7eSAndroid Build Coastguard Worker
365*49cdfc7eSAndroid Build Coastguard Worker /* raise bdi limit as much as kernel allows */
366*49cdfc7eSAndroid Build Coastguard Worker ra_new_limit = testfile_size / 1024;
367*49cdfc7eSAndroid Build Coastguard Worker while (ra_new_limit > pagesize / 1024) {
368*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_PRINTF(sys_bdi_ra_path, "%d", ra_new_limit);
369*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_SCANF(sys_bdi_ra_path, "%d", &ra_limit);
370*49cdfc7eSAndroid Build Coastguard Worker
371*49cdfc7eSAndroid Build Coastguard Worker if (ra_limit == ra_new_limit) {
372*49cdfc7eSAndroid Build Coastguard Worker readahead_length = MIN(ra_new_limit * 1024,
373*49cdfc7eSAndroid Build Coastguard Worker 2 * 1024 * 1024);
374*49cdfc7eSAndroid Build Coastguard Worker break;
375*49cdfc7eSAndroid Build Coastguard Worker }
376*49cdfc7eSAndroid Build Coastguard Worker ra_new_limit = ra_new_limit / 2;
377*49cdfc7eSAndroid Build Coastguard Worker }
378*49cdfc7eSAndroid Build Coastguard Worker }
379*49cdfc7eSAndroid Build Coastguard Worker
setup(void)380*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
381*49cdfc7eSAndroid Build Coastguard Worker {
382*49cdfc7eSAndroid Build Coastguard Worker if (opt_fsizestr) {
383*49cdfc7eSAndroid Build Coastguard Worker testfile_size = SAFE_STRTOL(opt_fsizestr, 1, INT_MAX);
384*49cdfc7eSAndroid Build Coastguard Worker tst_set_max_runtime(1 + testfile_size / (DEFAULT_FILESIZE/32));
385*49cdfc7eSAndroid Build Coastguard Worker }
386*49cdfc7eSAndroid Build Coastguard Worker
387*49cdfc7eSAndroid Build Coastguard Worker if (access(PROC_IO_FNAME, F_OK))
388*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TCONF, "Requires " PROC_IO_FNAME);
389*49cdfc7eSAndroid Build Coastguard Worker
390*49cdfc7eSAndroid Build Coastguard Worker has_file(DROP_CACHES_FNAME, 1);
391*49cdfc7eSAndroid Build Coastguard Worker has_file(MEMINFO_FNAME, 1);
392*49cdfc7eSAndroid Build Coastguard Worker
393*49cdfc7eSAndroid Build Coastguard Worker /* check if readahead is supported */
394*49cdfc7eSAndroid Build Coastguard Worker tst_syscall(__NR_readahead, 0, 0, 0);
395*49cdfc7eSAndroid Build Coastguard Worker
396*49cdfc7eSAndroid Build Coastguard Worker pagesize = getpagesize();
397*49cdfc7eSAndroid Build Coastguard Worker
398*49cdfc7eSAndroid Build Coastguard Worker setup_readahead_length();
399*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "readahead length: %d", readahead_length);
400*49cdfc7eSAndroid Build Coastguard Worker
401*49cdfc7eSAndroid Build Coastguard Worker ovl_mounted = TST_MOUNT_OVERLAY();
402*49cdfc7eSAndroid Build Coastguard Worker }
403*49cdfc7eSAndroid Build Coastguard Worker
cleanup(void)404*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
405*49cdfc7eSAndroid Build Coastguard Worker {
406*49cdfc7eSAndroid Build Coastguard Worker if (ovl_mounted)
407*49cdfc7eSAndroid Build Coastguard Worker SAFE_UMOUNT(OVL_MNT);
408*49cdfc7eSAndroid Build Coastguard Worker
409*49cdfc7eSAndroid Build Coastguard Worker if (orig_bdi_limit)
410*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_PRINTF(sys_bdi_ra_path, "%d", orig_bdi_limit);
411*49cdfc7eSAndroid Build Coastguard Worker }
412*49cdfc7eSAndroid Build Coastguard Worker
413*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
414*49cdfc7eSAndroid Build Coastguard Worker .needs_root = 1,
415*49cdfc7eSAndroid Build Coastguard Worker .mount_device = 1,
416*49cdfc7eSAndroid Build Coastguard Worker .mntpoint = mntpoint,
417*49cdfc7eSAndroid Build Coastguard Worker .setup = setup,
418*49cdfc7eSAndroid Build Coastguard Worker .cleanup = cleanup,
419*49cdfc7eSAndroid Build Coastguard Worker .options = (struct tst_option[]) {
420*49cdfc7eSAndroid Build Coastguard Worker {"s:", &opt_fsizestr, "Testfile size (default 64MB)"},
421*49cdfc7eSAndroid Build Coastguard Worker {}
422*49cdfc7eSAndroid Build Coastguard Worker },
423*49cdfc7eSAndroid Build Coastguard Worker .test = test_readahead,
424*49cdfc7eSAndroid Build Coastguard Worker .tcnt = ARRAY_SIZE(tcases),
425*49cdfc7eSAndroid Build Coastguard Worker .max_runtime = 30,
426*49cdfc7eSAndroid Build Coastguard Worker .tags = (const struct tst_tag[]) {
427*49cdfc7eSAndroid Build Coastguard Worker {"linux-git", "b833a3660394"},
428*49cdfc7eSAndroid Build Coastguard Worker {"linux-git", "5b910bd615ba"},
429*49cdfc7eSAndroid Build Coastguard Worker {}
430*49cdfc7eSAndroid Build Coastguard Worker }
431*49cdfc7eSAndroid Build Coastguard Worker };
432