/* read_testfile - mmap testfile and read every page. * This functions measures how many I/O and time it takes to fully * read contents of test file. * * @do_readahead: call readahead prior to reading file content? * @fname: name of file to test * @fsize: how many bytes to read/mmap * @read_bytes: returns difference of bytes read, parsed from /proc/<pid>/io * @usec: returns how many microsecond it took to go over fsize bytes * @cached: returns cached kB from /proc/meminfo */ static void read_testfile(int do_readahead, const char *fname, size_t fsize, unsigned long *read_bytes, long *usec, unsigned long *cached) { int fd; size_t i = 0; long read_bytes_start; unsigned char *p, tmp; unsigned long time_start_usec, time_end_usec; unsigned long cached_start, max_ra_estimate = 0; off_t offset = 0; struct timeval now; fd = SAFE_OPEN(cleanup, fname, O_RDONLY); if (do_readahead) { cached_start = get_cached_size(); do { TEST(readahead(fd, offset, fsize - offset)); if (TEST_RETURN != 0) { check_ret(0); break; } /* estimate max readahead size based on first call */ if (!max_ra_estimate) { *cached = get_cached_size(); if (*cached > cached_start) { max_ra_estimate = (1024 * (*cached - cached_start)); tst_resm(TINFO, "max ra estimate: %lu", max_ra_estimate); } max_ra_estimate = MAX(max_ra_estimate, MIN_SANE_READAHEAD); } i++; offset += max_ra_estimate; } while ((size_t)offset < fsize); tst_resm(TINFO, "readahead calls made: %zu", i); *cached = get_cached_size(); /* offset of file shouldn't change after readahead */ offset = lseek(fd, 0, SEEK_CUR); if (offset == (off_t) - 1) tst_brkm(TBROK | TERRNO, cleanup, "lseek failed"); if (offset == 0) tst_resm(TPASS, "offset is still at 0 as expected"); else tst_resm(TFAIL, "offset has changed to: %lu", offset); } if (gettimeofday(&now, NULL) == -1) tst_brkm(TBROK | TERRNO, cleanup, "gettimeofday failed"); time_start_usec = now.tv_sec * 1000000 + now.tv_usec; read_bytes_start = get_bytes_read(); p = mmap(NULL, fsize, PROT_READ, MAP_SHARED | MAP_POPULATE, fd, 0); if (p == MAP_FAILED) tst_brkm(TBROK | TERRNO, cleanup, "mmap failed"); /* for old kernels, where MAP_POPULATE doesn't work, touch each page */ tmp = 0; for (i = 0; i < fsize; i += pagesize) tmp = tmp ^ p[i]; /* prevent gcc from optimizing out loop above */ if (tmp != 0) tst_brkm(TBROK, NULL, "This line should not be reached"); if (!do_readahead) *cached = get_cached_size(); SAFE_MUNMAP(cleanup, p, fsize); *read_bytes = get_bytes_read() - read_bytes_start; if (gettimeofday(&now, NULL) == -1) tst_brkm(TBROK | TERRNO, cleanup, "gettimeofday failed"); time_end_usec = now.tv_sec * 1000000 + now.tv_usec; *usec = time_end_usec - time_start_usec; SAFE_CLOSE(cleanup, fd); }
/* read_testfile - mmap testfile and read every page. * This functions measures how many I/O and time it takes to fully * read contents of test file. * * @do_readahead: call readahead prior to reading file content? * @fname: name of file to test * @fsize: how many bytes to read/mmap * @read_bytes: returns difference of bytes read, parsed from /proc/<pid>/io * @usec: returns how many microsecond it took to go over fsize bytes * @cached: returns cached kB from /proc/meminfo */ static void read_testfile(int do_readahead, const char *fname, size_t fsize, unsigned long *read_bytes, long *usec, unsigned long *cached) { int fd; size_t i; long read_bytes_start; unsigned char *p, tmp; unsigned long time_start_usec, time_end_usec; off_t offset; struct timeval now; fd = open(fname, O_RDONLY); if (fd < 0) tst_brkm(TBROK | TERRNO, cleanup, "Failed to open %s", fname); if (do_readahead) { /* read ahead in chunks, 2MB is maximum since 3.15-rc1 */ for (i = 0; i < fsize; i += 2*1024*1024) { TEST(ltp_syscall(__NR_readahead, fd, (off64_t) i, 2*1024*1024)); if (TEST_RETURN != 0) break; } check_ret(0); *cached = get_cached_size(); /* offset of file shouldn't change after readahead */ offset = lseek(fd, 0, SEEK_CUR); if (offset == (off_t) - 1) tst_brkm(TBROK | TERRNO, cleanup, "lseek failed"); if (offset == 0) tst_resm(TPASS, "offset is still at 0 as expected"); else tst_resm(TFAIL, "offset has changed to: %lu", offset); } if (gettimeofday(&now, NULL) == -1) tst_brkm(TBROK | TERRNO, cleanup, "gettimeofday failed"); time_start_usec = now.tv_sec * 1000000 + now.tv_usec; read_bytes_start = get_bytes_read(); p = mmap(NULL, fsize, PROT_READ, MAP_SHARED | MAP_POPULATE, fd, 0); if (p == MAP_FAILED) tst_brkm(TBROK | TERRNO, cleanup, "mmap failed"); /* for old kernels, where MAP_POPULATE doesn't work, touch each page */ tmp = 0; for (i = 0; i < fsize; i += pagesize) tmp = tmp ^ p[i]; /* prevent gcc from optimizing out loop above */ if (tmp != 0) tst_brkm(TBROK, NULL, "This line should not be reached"); if (!do_readahead) *cached = get_cached_size(); if (munmap(p, fsize) == -1) tst_brkm(TBROK | TERRNO, cleanup, "munmap failed"); *read_bytes = get_bytes_read() - read_bytes_start; if (gettimeofday(&now, NULL) == -1) tst_brkm(TBROK | TERRNO, cleanup, "gettimeofday failed"); time_end_usec = now.tv_sec * 1000000 + now.tv_usec; *usec = time_end_usec - time_start_usec; if (close(fd) == -1) tst_brkm(TBROK | TERRNO, cleanup, "close failed"); }
/* read_testfile - mmap testfile and read every page. * This functions measures how many I/O and time it takes to fully * read contents of test file. * * @do_readahead: call readahead prior to reading file content? * @fname: name of file to test * @fsize: how many bytes to read/mmap * @read_bytes: returns difference of bytes read, parsed from /proc/<pid>/io * @usec: returns how many microsecond it took to go over fsize bytes * @cached: returns cached kB from /proc/meminfo */ static int read_testfile(struct tcase *tc, int do_readahead, const char *fname, size_t fsize, unsigned long *read_bytes, long long *usec, unsigned long *cached) { int fd; size_t i = 0; long read_bytes_start; unsigned char *p, tmp; off_t offset = 0; fd = SAFE_OPEN(fname, O_RDONLY); if (do_readahead) { do { TEST(tc->readahead(fd, offset, fsize - offset)); if (TST_RET != 0) { SAFE_CLOSE(fd); return TST_ERR; } i++; offset += readahead_length; } while ((size_t)offset < fsize); tst_res(TINFO, "readahead calls made: %zu", i); *cached = get_cached_size(); /* offset of file shouldn't change after readahead */ offset = SAFE_LSEEK(fd, 0, SEEK_CUR); if (offset == 0) tst_res(TPASS, "offset is still at 0 as expected"); else tst_res(TFAIL, "offset has changed to: %lu", offset); } tst_timer_start(CLOCK_MONOTONIC); read_bytes_start = get_bytes_read(); p = SAFE_MMAP(NULL, fsize, PROT_READ, MAP_SHARED | MAP_POPULATE, fd, 0); /* for old kernels, where MAP_POPULATE doesn't work, touch each page */ tmp = 0; for (i = 0; i < fsize; i += pagesize) tmp = tmp ^ p[i]; /* prevent gcc from optimizing out loop above */ if (tmp != 0) tst_brk(TBROK, "This line should not be reached"); if (!do_readahead) *cached = get_cached_size(); SAFE_MUNMAP(p, fsize); *read_bytes = get_bytes_read() - read_bytes_start; tst_timer_stop(); *usec = tst_timer_elapsed_us(); SAFE_CLOSE(fd); return 0; }