3636
3737static 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)
110109return 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
122153static 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 */
155186static 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,
162193long read_bytes_start ;
163194unsigned char * p , tmp ;
164195off_t offset = 0 ;
196+ unsigned long cached_prev = 0 , cached_cur = 0 ;
165197
166198fd = 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 );
201233int 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
205237do {
206238usleep (SHORT_SLEEP_US );
207239
208240cached_prev = cached_cur ;
209- cached_cur = get_cached_size ( );
241+ cached_cur = get_file_cached_bytes ( fname , fsize );
210242
211243if (cached_cur <= cached_prev )
212244break ;
@@ -216,7 +248,7 @@ static int read_testfile(struct tcase *tc, int do_readahead,
216248
217249tst_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 */
222254offset = SAFE_LSEEK (fd , 0 , SEEK_CUR );
@@ -240,7 +272,7 @@ static int read_testfile(struct tcase *tc, int do_readahead,
240272tst_brk (TBROK , "This line should not be reached" );
241273
242274if (!do_readahead )
243- * cached = get_cached_size ( );
275+ * cached = get_file_cached_bytes ( fname , fsize );
244276
245277SAFE_MUNMAP (p , fsize );
246278
@@ -257,7 +289,7 @@ static void test_readahead(unsigned int n)
257289{
258290unsigned long read_bytes , read_bytes_ra ;
259291long long usec , usec_ra ;
260- unsigned long cached_high , cached_low , cached , cached_ra ;
292+ unsigned long cached , cached_ra ;
261293int ret ;
262294struct tcase * tc = & tcases [n ];
263295
@@ -270,26 +302,20 @@ static void test_readahead(unsigned int n)
270302
271303create_testfile (tc -> use_overlay );
272304
273- /* find out how much can cache hold if we read whole file */
274305read_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 */
277310sync ();
278311drop_caches ();
279- cached_low = get_cached_size ();
280- cached_max = MAX (cached_max , cached_high - cached_low );
281-
282312tst_res (TINFO , "read_testfile(0)" );
283313read_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
290317sync ();
291318drop_caches ();
292- cached_low = get_cached_size ();
293319tst_res (TINFO , "read_testfile(1)" );
294320ret = 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)
319345return ;
320346}
321347
322- if (cached_ra > cached_low )
323- cached_ra = cached_ra - cached_low ;
324- else
325- cached_ra = 0 ;
326-
327348tst_res (TINFO , "read_testfile(0) took: %lli usec" , usec );
328349tst_res (TINFO , "read_testfile(1) took: %lli usec" , usec_ra );
329350if (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 )
353374tst_res (TPASS , "using cache as expected" );
354375else if (!cached_ra )
355376tst_res (TFAIL , "readahead failed to use any cache" );
@@ -416,7 +437,6 @@ static void setup(void)
416437tst_brk (TCONF , "Requires " PROC_IO_FNAME );
417438
418439has_file (DROP_CACHES_FNAME , 1 );
419- has_file (MEMINFO_FNAME , 1 );
420440
421441/* check if readahead is supported */
422442tst_syscall (__NR_readahead , 0 , 0 , 0 );
0 commit comments