static void cleanup(void) { free(ptr_addr); SAFE_MUNMAP(file1, st.st_size); SAFE_MUNMAP(file2, st.st_size - pagesize); SAFE_MUNMAP(file3, st.st_size); SAFE_MUNMAP(shared_anon, MAP_SIZE); }
static void do_child(void) { int fd, offset; char buf[FS_BLOCKSIZE]; char *addr = NULL; /* * We have changed SIGBUS' handler in parent process by calling * tst_sig(FORK, DEF_HANDLER, NULL), so here just restore it. */ if (signal(SIGBUS, SIG_DFL) == SIG_ERR) tst_brkm(TBROK | TERRNO, NULL, "signal(SIGBUS) failed"); memset(buf, 'a', FS_BLOCKSIZE); fd = SAFE_OPEN(NULL, "testfilec", O_RDWR); SAFE_PWRITE(NULL, 1, fd, buf, FS_BLOCKSIZE, 0); /* * In case mremap() may fail because that memory area can not be * expanded at current virtual address(MREMAP_MAYMOVE is not set), * we first do a mmap(page_size * 2) operation to reserve some * free address space. */ addr = SAFE_MMAP(NULL, NULL, page_size * 2, PROT_WRITE | PROT_READ, MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, -1, 0); SAFE_MUNMAP(NULL, addr, page_size * 2); addr = SAFE_MMAP(NULL, addr, FS_BLOCKSIZE, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0); addr[0] = 'a'; SAFE_FTRUNCATE(NULL, fd, page_size * 2); addr = mremap(addr, FS_BLOCKSIZE, 2 * page_size, 0); if (addr == MAP_FAILED) tst_brkm(TBROK | TERRNO, NULL, "mremap failed unexpectedly"); /* * Let parent process consume FS free blocks as many as possible, then * there'll be no free blocks allocated for this new file mmaping for * offset starting at 1024, 2048, or 3072. If this above kernel bug * has been fixed, usually child process will killed by SIGBUS signal, * if not, the data 'A', 'B', 'C' will be silently discarded later when * kernel writepage is called, that means data corruption. */ TST_SAFE_CHECKPOINT_WAKE(NULL, 0); TST_SAFE_CHECKPOINT_WAIT(NULL, 0); for (offset = FS_BLOCKSIZE; offset < page_size; offset += FS_BLOCKSIZE) addr[offset] = 'a'; SAFE_MUNMAP(NULL, addr, 2 * page_size); SAFE_CLOSE(NULL, fd); exit(TFAIL); }
static void test_advice_willneed(void) { int i; char *src; char *dst[100]; int page_fault_num_1; int page_fault_num_2; /* allocate source memory (1GB only) */ src = SAFE_MMAP(NULL, 1 * GB_SZ, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); /* allocate destination memory (array) */ for (i = 0; i < dst_max; ++i) dst[i] = SAFE_MMAP(NULL, 1 * GB_SZ, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); /* memmove source to each destination memories (for SWAP-OUT) */ for (i = 0; i < dst_max; ++i) memmove(dst[i], src, 1 * GB_SZ); tst_res(TINFO, "PageFault(no madvice): %d", get_page_fault_num()); /* Do madvice() to dst[0] */ TEST(madvise(dst[0], pg_sz, MADV_WILLNEED)); if (TEST_RETURN == -1) tst_brk(TBROK | TERRNO, "madvise failed"); page_fault_num_1 = get_page_fault_num(); tst_res(TINFO, "PageFault(madvice / no mem access): %d", page_fault_num_1); *dst[0] = 'a'; page_fault_num_2 = get_page_fault_num(); tst_res(TINFO, "PageFault(madvice / mem access): %d", page_fault_num_2); if (page_fault_num_1 != page_fault_num_2) tst_res(TFAIL, "Bug has been reproduced"); else tst_res(TPASS, "Regression test pass"); SAFE_MUNMAP(src, 1 * GB_SZ); for (i = 0; i < dst_max; ++i) SAFE_MUNMAP(dst[i], 1 * GB_SZ); }
int main(int argc, char *argv[]) { int lc; void *p; tst_parse_opts(argc, argv, NULL, NULL); setup(); for (lc = 0; TEST_LOOPING(lc); lc++) { p = SAFE_MMAP(cleanup, NULL, ALLOC_SIZE, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0); TEST(mprotect(p, ALLOC_SIZE, PROT_NONE)); if (TEST_RETURN == -1) tst_brkm(TBROK | TTERRNO, cleanup, "mprotect failed"); TEST(madvise(p, ALLOC_SIZE, MADV_WILLNEED)); SAFE_MUNMAP(cleanup, p, ALLOC_SIZE); if (TEST_RETURN == 0) continue; if (TEST_ERRNO == EBADF) tst_brkm(TCONF, cleanup, "CONFIG_SWAP=n"); else tst_brkm(TBROK | TTERRNO, cleanup, "madvise failed"); } tst_resm(TPASS, "issue has not been reproduced"); cleanup(); tst_exit(); }
static void setup(void) { struct sigaction sigptr; page_sz = getpagesize(); /* * Used as hint for mmap thread, so it doesn't interfere * with other potential (temporary) mappings from libc */ distant_area = SAFE_MMAP(0, DISTANT_MMAP_SIZE, PROT_WRITE | PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); SAFE_MUNMAP(distant_area, (size_t)DISTANT_MMAP_SIZE); distant_area += DISTANT_MMAP_SIZE / 2; if (tst_parse_float(str_exec_time, &exec_time, 0, FLT_MAX)) { tst_brk(TBROK, "Invalid number for exec_time '%s'", str_exec_time); } sigptr.sa_sigaction = sig_handler; sigemptyset(&sigptr.sa_mask); sigptr.sa_flags = SA_SIGINFO | SA_NODEFER; SAFE_SIGACTION(SIGSEGV, &sigptr, NULL); tst_set_timeout((int)(exec_time * 3600)); }
static void setup(void) { int i, fd; fd = SAFE_OPEN(TEST_FILE, O_RDWR | O_CREAT, 0664); pagesize = getpagesize(); /* Writing 16 pages of random data into this file */ for (i = 0; i < (pagesize / 2); i++) SAFE_WRITE(1, fd, STR, sizeof(STR) - 1); SAFE_FSTAT(fd, &st); file1 = SAFE_MMAP(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); file2 = SAFE_MMAP(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); SAFE_MUNMAP(file2 + st.st_size - pagesize, pagesize); nonalign = file1 + 100; ptr_addr = SAFE_MALLOC(st.st_size); tmp_addr = (void*)LTP_ALIGN((long)ptr_addr, pagesize); SAFE_CLOSE(fd); tcases_filter(); }
static void queue_destroy(struct queue *q, int is_worker) { if (is_worker) sem_destroy(&q->sem); SAFE_MUNMAP(q, sizeof(*q)); }
static void setup(void) { int i, fd; fd = SAFE_OPEN(TEST_FILE, O_RDWR | O_CREAT, 0664); pagesize = getpagesize(); /* Writing 16 pages of random data into this file */ for (i = 0; i < (pagesize / 2); i++) SAFE_WRITE(1, fd, STR, sizeof(STR) - 1); SAFE_FSTAT(fd, &st); file1 = SAFE_MMAP(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); file2 = SAFE_MMAP(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); file3 = SAFE_MMAP(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); shared_anon = SAFE_MMAP(0, MAP_SIZE, PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0); nonalign = file1 + 100; ptr_addr = SAFE_MALLOC(st.st_size); tmp_addr = (void*)LTP_ALIGN((long)ptr_addr, pagesize); /* unmap as last step to avoid subsequent mmap(s) pick same address */ SAFE_MUNMAP(file2 + st.st_size - pagesize, pagesize); SAFE_CLOSE(fd); tcases_filter(); }
void cleanup(void) { #ifndef UCLINUX SAFE_MUNMAP(NULL, bad_addr, 1); #endif SAFE_CLOSE(NULL, fileHandle); tst_rmdir(); }
static void cleanup(void) { TEST_CLEANUP; if (addr != MAP_FAILED) { SAFE_MUNMAP(NULL, addr, sizeof(buf)); SAFE_CLOSE(NULL, fd); } tst_rmdir(); }
static void verify_futex_wait(void) { int res; void *buf; size_t pagesize = getpagesize(); buf = SAFE_MMAP(NULL, NULL, pagesize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); res = futex_wait(buf, 1, &to, 0); if (res == -1 && errno == EWOULDBLOCK) tst_resm(TPASS | TERRNO, "futex_wait() returned %i", res); else tst_resm(TFAIL | TERRNO, "futex_wait() returned %i", res); SAFE_MUNMAP(NULL, buf, pagesize); }
static void testfunc_protexec(void) { int page_sz; int (*func)(void); sig_caught = 0; page_sz = getpagesize(); func = SAFE_MMAP(cleanup, 0, page_sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); memcpy(func, exec_func, page_sz); /* Change the protection to PROT_EXEC. */ TEST(mprotect(func, page_sz, PROT_EXEC)); if (TEST_RETURN == -1) { tst_resm(TFAIL | TTERRNO, "mprotect failed"); } else { if (sigsetjmp(env, 1) == 0) (*func)(); switch (sig_caught) { case SIGSEGV: tst_resm(TFAIL, "test PROT_EXEC for mprotect failed"); break; case 0: tst_resm(TPASS, "test PROT_EXEC for mprotect success"); break; default: tst_brkm(TBROK, cleanup, "received an unexpected signal: %d", sig_caught); } } SAFE_MUNMAP(cleanup, func, page_sz); }
static void testfunc_protnone(void) { char *addr; int page_sz; sig_caught = 0; page_sz = getpagesize(); addr = SAFE_MMAP(cleanup, 0, page_sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); /* Change the protection to PROT_NONE. */ TEST(mprotect(addr, page_sz, PROT_NONE)); if (TEST_RETURN == -1) { tst_resm(TFAIL | TTERRNO, "mprotect failed"); } else { if (sigsetjmp(env, 1) == 0) addr[0] = 1; switch (sig_caught) { case SIGSEGV: tst_resm(TPASS, "test PROT_NONE for mprotect success"); break; case 0: tst_resm(TFAIL, "test PROT_NONE for mprotect failed"); break; default: tst_brkm(TBROK, cleanup, "received an unexpected signal: %d", sig_caught); } } SAFE_MUNMAP(cleanup, addr, page_sz); }
void *map_write_unmap(void *ptr) { int *fd = ptr; void *tmp; int i, j; for (i = 0; i < num_iter; i++) { map_address = SAFE_MMAP(distant_area, (size_t) file_size, PROT_WRITE | PROT_READ, MAP_SHARED, *fd, 0); tst_atomic_inc(&mapcnt); for (j = 0; j < file_size; j++) map_address[j] = 'b'; tmp = (void *)map_address; tst_atomic_inc(&unmapcnt); SAFE_MUNMAP(tmp, file_size); map_count++; } return NULL; }
int main(int argc, char **argv) { int c, i; int file_size; int num_iter; double exec_time; int fd; void *status; pthread_t thid[2]; long chld_args[3]; extern char *optarg; struct sigaction sigptr; int ret; /* set up the default values */ file_size = 1024; num_iter = 1000; exec_time = 24; while ((c = getopt(argc, argv, "hvl:s:x:")) != -1) { switch (c) { case 'h': usage(argv[0]); break; case 'l': if ((num_iter = atoi(optarg)) == 0) OPT_MISSING(argv[0], optopt); else if (num_iter < 0) printf ("WARNING: bad argument. Using default %d\n", (num_iter = 1000)); break; case 's': if ((file_size = atoi(optarg)) == 0) OPT_MISSING(argv[0], optopt); else if (file_size < 0) printf ("WARNING: bad argument. Using default %d\n", (file_size = 1024)); break; case 'v': verbose_print = 1; break; case 'x': exec_time = atof(optarg); if (exec_time == 0) OPT_MISSING(argv[0], optopt); else if (exec_time < 0) printf ("WARNING: bad argument. Using default %.0f\n", (exec_time = 24)); break; default: usage(argv[0]); break; } } /* We don't want other mmap calls to map into same area as is * used for test (mmap_address). The test expects read to return * test pattern or read must fail with SIGSEGV. Find an area * that we can use, which is unlikely to be chosen for other * mmap calls. */ distant_area = mmap(0, DISTANT_MMAP_SIZE, PROT_WRITE | PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); if (distant_area == (void *)-1) tst_brkm(TBROK | TERRNO, NULL, "distant_area: mmap()"); SAFE_MUNMAP(NULL, distant_area, (size_t)DISTANT_MMAP_SIZE); distant_area += DISTANT_MMAP_SIZE / 2; if (verbose_print) tst_resm(TINFO, "Input parameters are: File size: %d; " "Scheduled to run: %lf hours; " "Number of mmap/write/read: %d", file_size, exec_time, num_iter); alarm(exec_time * 3600); /* Do not mask SIGSEGV, as we are interested in handling it. */ sigptr.sa_sigaction = sig_handler; sigfillset(&sigptr.sa_mask); sigdelset(&sigptr.sa_mask, SIGSEGV); sigptr.sa_flags = SA_SIGINFO | SA_NODEFER; for (i = 0; sig_info[i].signum != -1; i++) { if (sigaction(sig_info[i].signum, &sigptr, NULL) == -1) { perror("man(): sigaction()"); fprintf(stderr, "could not set handler for %s, errno = %d\n", sig_info[i].signame, errno); exit(-1); } } tst_tmpdir(); for (;;) { if ((fd = mkfile(file_size)) == -1) tst_brkm(TBROK, NULL, "main(): mkfile(): Failed to create temp file"); if (verbose_print) tst_resm(TINFO, "Tmp file created"); chld_args[0] = fd; chld_args[1] = file_size; chld_args[2] = num_iter; if ((ret = pthread_create(&thid[0], NULL, map_write_unmap, chld_args))) tst_brkm(TBROK, NULL, "main(): pthread_create(): %s", strerror(ret)); tst_resm(TINFO, "created writing thread[%lu]", thid[0]); if ((ret = pthread_create(&thid[1], NULL, read_mem, chld_args))) tst_brkm(TBROK, NULL, "main(): pthread_create(): %s", strerror(ret)); tst_resm(TINFO, "created reading thread[%lu]", thid[1]); for (i = 0; i < 2; i++) { if ((ret = pthread_join(thid[i], &status))) tst_brkm(TBROK, NULL, "main(): pthread_join(): %s", strerror(ret)); if (status) tst_brkm(TFAIL, NULL, "thread [%lu] - process exited " "with %ld", thid[i], (long)status); } close(fd); } tst_rmdir(); exit(0); }
static void child(void) { size_t i; char *ptr; unsigned int usage, old_limit, old_memsw_limit; int status, pid, retries = 0; SAFE_MKDIR(cgroup_path, 0777); SAFE_FILE_PRINTF(tasks_path, "%i", getpid()); ptr = SAFE_MMAP(NULL, PAGES * page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); for (i = 0; i < PAGES * page_size; i++) ptr[i] = 'a'; if (madvise(ptr, PAGES * page_size, MADV_FREE)) { if (errno == EINVAL) tst_brk(TCONF | TERRNO, "MADV_FREE is not supported"); tst_brk(TBROK | TERRNO, "MADV_FREE failed"); } if (ptr[page_size] != 'a') tst_res(TFAIL, "MADV_FREE pages were freed immediatelly"); else tst_res(TPASS, "MADV_FREE pages were not freed immediatelly"); ptr[TOUCHED_PAGE1 * page_size] = 'b'; ptr[TOUCHED_PAGE2 * page_size] = 'b'; usage = 8 * 1024 * 1024; tst_res(TINFO, "Setting memory limits to %u %u", usage, 2 * usage); SAFE_FILE_SCANF(limit_in_bytes_path, "%u", &old_limit); if (swap_accounting_enabled) SAFE_FILE_SCANF(memsw_limit_in_bytes_path, "%u", &old_memsw_limit); SAFE_FILE_PRINTF(limit_in_bytes_path, "%u", usage); if (swap_accounting_enabled) SAFE_FILE_PRINTF(memsw_limit_in_bytes_path, "%u", 2 * usage); do { sleep_between_faults++; pid = SAFE_FORK(); if (!pid) memory_pressure_child(); tst_res(TINFO, "Memory hungry child %i started, try %i", pid, retries); SAFE_WAIT(&status); } while (retries++ < 10 && count_freed(ptr) == 0); char map[PAGES+1]; unsigned int freed = 0; unsigned int corrupted = 0; for (i = 0; i < PAGES; i++) { char exp_val; if (ptr[i * page_size]) { exp_val = 'a'; map[i] = 'p'; } else { exp_val = 0; map[i] = '_'; freed++; } if (i != TOUCHED_PAGE1 && i != TOUCHED_PAGE2) { if (check_page(ptr + i * page_size, exp_val)) { map[i] = '?'; corrupted++; } } else { if (check_page_baaa(ptr + i * page_size)) { map[i] = '?'; corrupted++; } } } map[PAGES] = '\0'; tst_res(TINFO, "Memory map: %s", map); if (freed) tst_res(TPASS, "Pages MADV_FREE were freed on low memory"); else tst_res(TFAIL, "No MADV_FREE page was freed on low memory"); if (corrupted) tst_res(TFAIL, "Found corrupted page"); else tst_res(TPASS, "All pages have expected content"); if (swap_accounting_enabled) SAFE_FILE_PRINTF(memsw_limit_in_bytes_path, "%u", old_memsw_limit); SAFE_FILE_PRINTF(limit_in_bytes_path, "%u", old_limit); SAFE_MUNMAP(ptr, PAGES); exit(0); }
/* 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; }
int main(int ac, char **av) { int lc; char *msg; int bytes_to_write, fd, num_bytes; pid_t pid; if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL) tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); setup(); for (lc = 0; TEST_LOOPING(lc); lc++) { tst_count = 0; fd = SAFE_OPEN(cleanup, file1, O_RDWR | O_CREAT, 0777); num_bytes = getpagesize(); do { if (num_bytes > strlen(buf)) bytes_to_write = strlen(buf); else bytes_to_write = num_bytes; num_bytes -= SAFE_WRITE(cleanup, 1, fd, buf, bytes_to_write); } while (0 < num_bytes); /* mmap the PAGESIZE bytes as read only. */ addr = SAFE_MMAP(cleanup, 0, sizeof(buf), PROT_READ, MAP_SHARED, fd, 0); if ((pid = FORK_OR_VFORK()) == -1) tst_brkm(TBROK | TERRNO, cleanup, "fork #1 failed"); if (pid == 0) { memcpy(addr, buf, strlen(buf)); exit(255); } if (waitpid(pid, &status, 0) == -1) tst_brkm(TBROK | TERRNO, cleanup, "waitpid failed"); if (!WIFEXITED(status)) tst_brkm(TBROK, cleanup, "child exited abnormally " "with status: %d", status); switch (status) { case 255: tst_brkm(TBROK, cleanup, "memcpy did not generate SIGSEGV"); case 0: tst_resm(TPASS, "got SIGSEGV as expected"); break; default: tst_brkm(TBROK, cleanup, "got unexpected signal: %d", status); break; } /* Change the protection to WRITE. */ TEST(mprotect(addr, sizeof(buf), PROT_WRITE)); if (TEST_RETURN != -1) { if (STD_FUNCTIONAL_TEST) { if ((pid = FORK_OR_VFORK()) == -1) tst_brkm(TBROK | TERRNO, cleanup, "fork #2 failed"); if (pid == 0) { memcpy(addr, buf, strlen(buf)); exit(0); } if (waitpid(pid, &status, 0) == -1) tst_brkm(TBROK | TERRNO, cleanup, "waitpid failed"); if (WIFEXITED(status) && WEXITSTATUS(status) == 0) tst_resm(TPASS, "didn't get SIGSEGV"); else tst_brkm(TBROK, cleanup, "child exited abnormally"); } else tst_resm(TPASS, "call succeeded"); } else { tst_resm(TFAIL | TERRNO, "mprotect failed"); continue; } SAFE_MUNMAP(cleanup, addr, sizeof(buf)); addr = MAP_FAILED; SAFE_CLOSE(cleanup, fd); SAFE_UNLINK(cleanup, file1); } cleanup(); tst_exit(); }
static void test_overcommit(void) { void *addr = NULL, *shmaddr = NULL; if (opt_shmid) { shmid = SAFE_SHMGET(key, (length / 2 * hugepagesize), SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W); } else { fd = SAFE_OPEN(TEST_FILE, O_CREAT | O_RDWR, 0755); addr = SAFE_MMAP(ADDR, (length / 2 * hugepagesize), PROTECTION, FLAGS, fd, 0); } if (opt_sysfs) { tst_res(TINFO, "check sysfs before allocation."); if (checksys(path_sys_sz_huge, "HugePages_Total", length / 2)) return; if (checksys(path_sys_sz_free, "HugePages_Free", length / 2)) return; if (checksys(path_sys_sz_surp, "HugePages_Surp", length / 2 - size)) return; if (checksys(path_sys_sz_resv, "HugePages_Rsvd", length / 2)) return; } else { tst_res(TINFO, "check /proc/meminfo before allocation."); if (checkproc(SAFE_READ_MEMINFO("HugePages_Total:"), "HugePages_Total", length / 2)) return; if (checkproc(SAFE_READ_MEMINFO("HugePages_Free:"), "HugePages_Free", length / 2)) return; if (checkproc(SAFE_READ_MEMINFO("HugePages_Surp:"), "HugePages_Surp", length / 2 - size)) return; if (checkproc(SAFE_READ_MEMINFO("HugePages_Rsvd:"), "HugePages_Rsvd", length / 2)) return; } if (opt_shmid) { tst_res(TINFO, "shmid: 0x%x", shmid); shmaddr = SAFE_SHMAT(shmid, ADDR, SHMAT_FLAGS); check_wr_bytes(shmaddr); } else { check_wr_bytes(addr); } if (opt_sysfs) { tst_res(TINFO, "check sysfs."); if (checksys(path_sys_sz_huge, "HugePages_Total", length / 2)) return; if (checksys(path_sys_sz_free, "HugePages_Free", 0)) return; if (checksys(path_sys_sz_surp, "HugePages_Surp", length / 2 - size)) return; if (checksys(path_sys_sz_resv, "HugePages_Rsvd", 0)) return; } else { tst_res(TINFO, "check /proc/meminfo."); if (checkproc(SAFE_READ_MEMINFO("HugePages_Total:"), "HugePages_Total", length / 2)) return; if (checkproc(SAFE_READ_MEMINFO("HugePages_Free:"), "HugePages_Free", 0)) return; if (checkproc(SAFE_READ_MEMINFO("HugePages_Surp:"), "HugePages_Surp", length / 2 - size)) return; if (checkproc(SAFE_READ_MEMINFO("HugePages_Rsvd:"), "HugePages_Rsvd", 0)) return; } if (opt_shmid) { SAFE_SHMDT(shmaddr); SAFE_SHMCTL(shmid, IPC_RMID, NULL); } else { SAFE_MUNMAP(addr, (length / 2 * hugepagesize)); SAFE_CLOSE(fd); SAFE_UNLINK(TEST_FILE); } tst_res(TPASS, "hugepages overcommit test pass"); }
/* 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); }
static void cleanup(void) { SAFE_MUNMAP(sfile, st.st_size); SAFE_MUNMAP(amem, st.st_size); SAFE_UMOUNT(TMP_DIR); }
int main(int ac, char **av) { int lc; char *addr; int fd, pid; char *buf = "abcdefghijklmnopqrstuvwxyz"; tst_parse_opts(ac, av, NULL, NULL); setup(); for (lc = 0; TEST_LOOPING(lc); lc++) { tst_count = 0; if ((fd = open(file1, O_RDWR | O_CREAT, 0777)) < 0) tst_brkm(TBROK, cleanup, "open failed"); SAFE_WRITE(cleanup, 1, fd, buf, strlen(buf)); /* * mmap the PAGESIZE bytes as read only. */ addr = mmap(0, strlen(buf), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (addr == MAP_FAILED) tst_brkm(TBROK, cleanup, "mmap failed"); /* * Try to change the protection to WRITE. */ TEST(mprotect(addr, strlen(buf), PROT_READ)); if (TEST_RETURN != -1) { if ((pid = FORK_OR_VFORK()) == -1) { tst_brkm(TBROK, cleanup, "fork failed"); } if (pid == 0) { memcpy(addr, buf, strlen(buf)); tst_resm(TINFO, "memcpy() did " "not generate SIGSEGV"); exit(1); } waitpid(pid, &status, 0); if (WEXITSTATUS(status) != 0) { tst_resm(TFAIL, "child returned " "unexpected status"); } else { tst_resm(TPASS, "SIGSEGV generated " "as expected"); } } else { tst_resm(TFAIL, "mprotect failed " "unexpectedly, errno: %d", errno); } /* clean up things in case we are looping */ SAFE_MUNMAP(cleanup, addr, strlen(buf)); SAFE_CLOSE(cleanup, fd); SAFE_UNLINK(cleanup, file1); } cleanup(); tst_exit(); }