Skip to content

Commit 5aa4a4f

Browse files
committed
readahead02: detect cache stats via mincore per testfile
Stop sampling global “Cached” from /proc/meminfo and instead measure how many bytes of the current test file are resident via mincore(). This lets the test report per-file cache usage, removes the MEMINFO dependency, and makes the readahead wait loop watch the actual file cache growth. Because the mincore values are already in bytes we no longer juggle cached_high/cached_low deltas nor scale by 1024. The cache-capacity gate now compares cached_max directly against testfile_size, and the user- visible kB prints are derived from the byte counters. Signed-off-by: Li Wang <liwang@redhat.com> Reviewed-by: Jan Stancek <jstancek@redhat.com> Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
1 parent 613cba4 commit 5aa4a4f

File tree

1 file changed

+53
-33
lines changed

1 file changed

+53
-33
lines changed

testcases/kernel/syscalls/readahead/readahead02.c

Lines changed: 53 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636

3737
static char testfile[PATH_MAX] = "testfile";
3838
#define DROP_CACHES_FNAME "/proc/sys/vm/drop_caches"
39-
#define MEMINFO_FNAME "/proc/meminfo"
4039
#define PROC_IO_FNAME "/proc/self/io"
4140
#define DEFAULT_FILESIZE (64 * 1024 * 1024)
4241
#define INITIAL_SHORT_SLEEP_US 10000
@@ -110,13 +109,45 @@ static unsigned long get_bytes_read(void)
110109
return ret;
111110
}
112111

113-
static unsigned long get_cached_size(void)
112+
static unsigned long get_file_cached_bytes(const char *path, size_t length)
114113
{
115-
unsigned long ret;
114+
size_t pagecnt, resident = 0;
115+
size_t map_len;
116+
unsigned char *vec;
117+
void *addr;
118+
int fd;
119+
size_t i;
116120

117-
SAFE_FILE_LINES_SCANF(MEMINFO_FNAME, "Cached: %lu", &ret);
121+
if (!length)
122+
return 0;
118123

119-
return ret;
124+
fd = SAFE_OPEN(path, O_RDONLY);
125+
126+
pagecnt = LTP_ALIGN(length, pagesize) / pagesize;
127+
map_len = pagecnt * pagesize;
128+
129+
addr = SAFE_MMAP(NULL, map_len, PROT_NONE, MAP_SHARED, fd, 0);
130+
vec = SAFE_MALLOC(pagecnt);
131+
132+
if (mincore(addr, map_len, vec) == -1)
133+
tst_brk(TBROK | TERRNO, "mincore");
134+
135+
for (i = 0; i < pagecnt; i++) {
136+
size_t chunk = pagesize;
137+
size_t tail = length % pagesize;
138+
139+
if (i == pagecnt - 1 && tail)
140+
chunk = tail;
141+
142+
if (vec[i] & 1)
143+
resident += chunk;
144+
}
145+
146+
free(vec);
147+
SAFE_MUNMAP(addr, map_len);
148+
SAFE_CLOSE(fd);
149+
150+
return resident;
120151
}
121152

122153
static void create_testfile(int use_overlay)
@@ -150,7 +181,7 @@ static void create_testfile(int use_overlay)
150181
* @fsize: how many bytes to read/mmap
151182
* @read_bytes: returns difference of bytes read, parsed from /proc/<pid>/io
152183
* @usec: returns how many microsecond it took to go over fsize bytes
153-
* @cached: returns cached kB from /proc/meminfo
184+
* @cached: returns cached bytes for @fname via mincore()
154185
*/
155186
static int read_testfile(struct tcase *tc, int do_readahead,
156187
const char *fname, size_t fsize,
@@ -162,6 +193,7 @@ static int read_testfile(struct tcase *tc, int do_readahead,
162193
long read_bytes_start;
163194
unsigned char *p, tmp;
164195
off_t offset = 0;
196+
unsigned long cached_prev = 0, cached_cur = 0;
165197

166198
fd = SAFE_OPEN(fname, O_RDONLY);
167199

@@ -197,16 +229,16 @@ static int read_testfile(struct tcase *tc, int do_readahead,
197229
* long a cache is increasing which will gives us high
198230
* chance of waiting for the readahead to happen.
199231
*/
200-
unsigned long cached_prev, cached_cur = get_cached_size();
232+
cached_cur = get_file_cached_bytes(fname, fsize);
201233
int retries = readahead_length / (5 * SHORT_SLEEP_US);
202234

203-
tst_res(TDEBUG, "Readahead cached %lu", cached_cur);
235+
tst_res(TDEBUG, "Per-file cached: %lu kB", cached_cur / 1024);
204236

205237
do {
206238
usleep(SHORT_SLEEP_US);
207239

208240
cached_prev = cached_cur;
209-
cached_cur = get_cached_size();
241+
cached_cur = get_file_cached_bytes(fname, fsize);
210242

211243
if (cached_cur <= cached_prev)
212244
break;
@@ -216,7 +248,7 @@ static int read_testfile(struct tcase *tc, int do_readahead,
216248

217249
tst_res(TINFO, "readahead calls made: %zu", i);
218250

219-
*cached = get_cached_size();
251+
*cached = get_file_cached_bytes(fname, fsize);
220252

221253
/* offset of file shouldn't change after readahead */
222254
offset = SAFE_LSEEK(fd, 0, SEEK_CUR);
@@ -240,7 +272,7 @@ static int read_testfile(struct tcase *tc, int do_readahead,
240272
tst_brk(TBROK, "This line should not be reached");
241273

242274
if (!do_readahead)
243-
*cached = get_cached_size();
275+
*cached = get_file_cached_bytes(fname, fsize);
244276

245277
SAFE_MUNMAP(p, fsize);
246278

@@ -257,7 +289,7 @@ static void test_readahead(unsigned int n)
257289
{
258290
unsigned long read_bytes, read_bytes_ra;
259291
long long usec, usec_ra;
260-
unsigned long cached_high, cached_low, cached, cached_ra;
292+
unsigned long cached, cached_ra;
261293
int ret;
262294
struct tcase *tc = &tcases[n];
263295

@@ -270,26 +302,20 @@ static void test_readahead(unsigned int n)
270302

271303
create_testfile(tc->use_overlay);
272304

273-
/* find out how much can cache hold if we read whole file */
274305
read_testfile(tc, 0, testfile, testfile_size, &read_bytes, &usec,
275306
&cached);
276-
cached_high = get_cached_size();
307+
cached_max = MAX(cached_max, cached);
308+
309+
/* ensure the measured baseline run starts from cold cache */
277310
sync();
278311
drop_caches();
279-
cached_low = get_cached_size();
280-
cached_max = MAX(cached_max, cached_high - cached_low);
281-
282312
tst_res(TINFO, "read_testfile(0)");
283313
read_testfile(tc, 0, testfile, testfile_size, &read_bytes, &usec,
284314
&cached);
285-
if (cached > cached_low)
286-
cached = cached - cached_low;
287-
else
288-
cached = 0;
315+
cached_max = MAX(cached_max, cached);
289316

290317
sync();
291318
drop_caches();
292-
cached_low = get_cached_size();
293319
tst_res(TINFO, "read_testfile(1)");
294320
ret = read_testfile(tc, 1, testfile, testfile_size, &read_bytes_ra,
295321
&usec_ra, &cached_ra);
@@ -319,11 +345,6 @@ static void test_readahead(unsigned int n)
319345
return;
320346
}
321347

322-
if (cached_ra > cached_low)
323-
cached_ra = cached_ra - cached_low;
324-
else
325-
cached_ra = 0;
326-
327348
tst_res(TINFO, "read_testfile(0) took: %lli usec", usec);
328349
tst_res(TINFO, "read_testfile(1) took: %lli usec", usec_ra);
329350
if (has_file(PROC_IO_FNAME, 0)) {
@@ -340,16 +361,16 @@ static void test_readahead(unsigned int n)
340361
" unable to determine read bytes during test");
341362
}
342363

343-
tst_res(TINFO, "cache can hold at least: %ld kB", cached_max);
344-
tst_res(TINFO, "read_testfile(0) used cache: %ld kB", cached);
345-
tst_res(TINFO, "read_testfile(1) used cache: %ld kB", cached_ra);
364+
tst_res(TINFO, "cache can hold at least: %ld kB", cached_max / 1024);
365+
tst_res(TINFO, "read_testfile(0) used cache: %ld kB", cached / 1024);
366+
tst_res(TINFO, "read_testfile(1) used cache: %ld kB", cached_ra / 1024);
346367

347-
if (cached_max * 1024 >= testfile_size) {
368+
if (cached_max >= testfile_size) {
348369
/*
349370
* if cache can hold ~testfile_size then cache increase
350371
* for readahead should be at least testfile_size/2
351372
*/
352-
if (cached_ra * 1024 > testfile_size / 2)
373+
if (cached_ra > testfile_size / 2)
353374
tst_res(TPASS, "using cache as expected");
354375
else if (!cached_ra)
355376
tst_res(TFAIL, "readahead failed to use any cache");
@@ -416,7 +437,6 @@ static void setup(void)
416437
tst_brk(TCONF, "Requires " PROC_IO_FNAME);
417438

418439
has_file(DROP_CACHES_FNAME, 1);
419-
has_file(MEMINFO_FNAME, 1);
420440

421441
/* check if readahead is supported */
422442
tst_syscall(__NR_readahead, 0, 0, 0);

0 commit comments

Comments
 (0)