static void assert_test_fn(void) { int cnt = 0; if (tst_test->test) cnt++; if (tst_test->test_all) cnt++; if (tst_test->sample) cnt++; if (!cnt) tst_brk(TBROK, "No test function speficied"); if (cnt != 1) tst_brk(TBROK, "You can define only one test function"); if (tst_test->test && !tst_test->tcnt) tst_brk(TBROK, "Number of tests (tcnt) must not be > 0"); if (!tst_test->test && tst_test->tcnt) tst_brk(TBROK, "You can define tcnt only for test()"); }
static int init_key(char *name, int cmd) { int n; int sec = 1; n = add_key("keyring", name, NULL, 0, KEY_SPEC_THREAD_KEYRING); if (n == -1) tst_brk(TBROK | TERRNO, "add_key() failed"); if (cmd == KEYCTL_REVOKE) { if (keyctl(cmd, n) == -1) { tst_brk(TBROK | TERRNO, "failed to revoke a key"); } } if (cmd == KEYCTL_SET_TIMEOUT) { if (keyctl(cmd, n, sec) == -1) { tst_brk(TBROK | TERRNO, "failed to set timeout for a key"); } sleep(sec + 1); } return n; }
static void setup(void) { int ret; SAFE_MKDIR(mntpoint, DIR_MODE); SAFE_MOUNT(tst_device->dev, mntpoint, tst_device->fs_type, 0, NULL); mount_flag = 1; sprintf(fname, "%s/tfile_%d", mntpoint, getpid()); fd = SAFE_OPEN(fname, O_RDWR | O_CREAT, 0700); ret = write(fd, fname, 1); if (ret == -1) { tst_brk(TBROK | TERRNO, "write(%d, %s, 1) failed", fd, fname); } /* close the file we have open */ SAFE_CLOSE(fd); fd_notify = myinotify_init(); if (fd_notify < 0) { if (errno == ENOSYS) tst_brk(TCONF, "inotify is not configured in this kernel."); else tst_brk(TBROK | TERRNO, "inotify_init failed"); } tst_umount(mntpoint); mount_flag = 0; }
static void caid_flags_setup(void) { int attr, ret; fd = SAFE_OPEN(TESTDIR_FLAGGED, O_RDONLY | O_DIRECTORY); ret = ioctl(fd, FS_IOC_GETFLAGS, &attr); if (ret < 0) { if (errno == ENOTTY) tst_brk(TCONF | TERRNO, "FS_IOC_GETFLAGS not supported"); /* ntfs3g fuse fs returns wrong errno for unimplemented ioctls */ if (!strcmp(tst_device->fs_type, "ntfs")) { tst_brk(TCONF | TERRNO, "ntfs3g does not support FS_IOC_GETFLAGS"); } tst_brk(TBROK | TERRNO, "ioctl(%i, FS_IOC_GETFLAGS, ...)", fd); } attr |= FS_COMPR_FL | FS_APPEND_FL | FS_IMMUTABLE_FL | FS_NODUMP_FL; ret = ioctl(fd, FS_IOC_SETFLAGS, &attr); if (ret < 0) { if (errno == EOPNOTSUPP) tst_brk(TCONF, "Flags not supported"); tst_brk(TBROK | TERRNO, "ioctl(%i, FS_IOC_SETFLAGS, %i)", fd, attr); } clear_flags = 1; }
static void run(void) { pid_t pid; int status; retry: pid = SAFE_FORK(); if (!pid) { setup_cgroup_paths(getpid()); child(); } setup_cgroup_paths(pid); SAFE_WAIT(&status); cleanup(); /* * Rarely cgroup OOM kills both children not only the one that allocates * memory in loop, hence we retry here if that happens. */ if (WIFSIGNALED(status)) { tst_res(TINFO, "Both children killed, retrying..."); goto retry; } if (WIFEXITED(status) && WEXITSTATUS(status) == TCONF) tst_brk(TCONF, "MADV_FREE is not supported"); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) tst_brk(TBROK, "Child %s", tst_strstatus(status)); }
static void run_tests(void) { unsigned int i; struct results saved_results; if (!tst_test->test) { saved_results = *results; tst_test->test_all(); if (getpid() != main_pid) { exit(0); } reap_children(); if (results_equal(&saved_results, results)) tst_brk(TBROK, "Test haven't reported results!"); return; } for (i = 0; i < tst_test->tcnt; i++) { saved_results = *results; tst_test->test(i); if (getpid() != main_pid) { exit(0); } reap_children(); if (results_equal(&saved_results, results)) tst_brk(TBROK, "Test %i haven't reported results!", i); } }
/* Warning: *DO NOT* use this function in child */ unsigned int get_a_numa_node(void) { unsigned int nd1, nd2; int ret; ret = get_allowed_nodes(0, 2, &nd1, &nd2); switch (ret) { case 0: break; case -3: tst_brk(TCONF, "requires a NUMA system."); default: tst_brk(TBROK | TERRNO, "1st get_allowed_nodes"); } ret = get_allowed_nodes(NH_MEMS | NH_CPUS, 1, &nd1); switch (ret) { case 0: tst_res(TINFO, "get node%u.", nd1); return nd1; case -3: tst_brk(TCONF, "requires a NUMA system that has " "at least one node with both memory and CPU " "available."); default: tst_brk(TBROK | TERRNO, "2nd get_allowed_nodes"); } /* not reached */ abort(); }
int range_is_mapped(unsigned long low, unsigned long high) { FILE *fp; fp = fopen("/proc/self/maps", "r"); if (fp == NULL) tst_brk(TBROK | TERRNO, "Failed to open /proc/self/maps."); while (!feof(fp)) { unsigned long start, end; int ret; ret = fscanf(fp, "%lx-%lx %*[^\n]\n", &start, &end); if (ret != 2) { fclose(fp); tst_brk(TBROK | TERRNO, "Couldn't parse /proc/self/maps line."); } if ((start >= low) && (start < high)) { fclose(fp); return 1; } if ((end >= low) && (end < high)) { fclose(fp); return 1; } } fclose(fp); return 0; }
static void parse_mtest_options(char *str_chunksize, int *chunksize, char *str_maxbytes, long *maxbytes, char *str_maxpercent, int *maxpercent) { if (str_chunksize) if (tst_parse_int(str_chunksize, chunksize, 1, INT_MAX)) tst_brk(TBROK, "Invalid chunksize '%s'", str_chunksize); if (str_maxbytes) { if (tst_parse_long(str_maxbytes, maxbytes, 1, LONG_MAX)) { tst_brk(TBROK, "Invalid maxbytes '%s'", str_maxbytes); } else if (str_maxpercent) { tst_brk(TBROK, "ERROR: -b option cannot be used with -p " "option at the same time"); } alloc_maxbytes = (unsigned long long)maxbytes; } if (str_maxpercent) { if (tst_parse_int(str_maxpercent, maxpercent, 1, 99)) { tst_brk(TBROK, "Invalid maxpercent '%s'", str_maxpercent); } else if (str_maxbytes) { tst_brk(TBROK, "ERROR: -p option cannot be used with -b " "option at the same time"); } } }
static void verify_epoll_create1(void) { int fd, coe; fd = tst_syscall(__NR_epoll_create1, 0); if (fd == -1) tst_brk(TFAIL | TERRNO, "epoll_create1(0) failed"); coe = SAFE_FCNTL(fd, F_GETFD); if (coe & FD_CLOEXEC) tst_brk(TFAIL, "flags=0 set close-on-exec flag"); SAFE_CLOSE(fd); fd = tst_syscall(__NR_epoll_create1, EPOLL_CLOEXEC); if (fd == -1) tst_brk(TFAIL | TERRNO, "epoll_create1(EPOLL_CLOEXEC) failed"); coe = SAFE_FCNTL(fd, F_GETFD); if ((coe & FD_CLOEXEC) == 0) tst_brk(TFAIL, "flags=EPOLL_CLOEXEC didn't set close-on-exec"); SAFE_CLOSE(fd); tst_res(TPASS, "epoll_create1(EPOLL_CLOEXEC) PASSED"); }
void run(void) { int i; struct crypto_user_alg a = { .cru_driver_name = "pcrypt(authenc(hmac(sha256-generic),cbc(aes-generic)))", .cru_type = CRYPTO_ALG_TYPE_AEAD, .cru_mask = CRYPTO_ALG_TYPE_MASK, }; for (i = 0; i < ATTEMPTS; ++i) { TEST(tst_crypto_add_alg(&ses, &a)); if (TST_RET && TST_RET == -ENOENT) { tst_brk(TCONF | TRERRNO, "pcrypt, hmac, sha256, cbc or aes not supported"); } if (TST_RET && TST_RET != -EEXIST) tst_brk(TBROK | TRERRNO, "add_alg"); TEST(tst_crypto_del_alg(&ses, &a)); if (TST_RET) tst_brk(TBROK | TRERRNO, "del_alg"); } tst_res(TPASS, "Nothing bad appears to have happened"); } void cleanup(void) { tst_crypto_close(&ses); }
static void setup(void) { int memnode, ret; if (!is_numa(NULL, NH_MEMS, 1)) tst_brk(TCONF, "requires NUMA with at least 1 node"); overcommit = get_sys_tune("overcommit_memory"); set_sys_tune("overcommit_memory", 1, 1); mount_mem("cpuset", "cpuset", NULL, CPATH, CPATH_NEW); cpuset_mounted = 1; /* * Some nodes do not contain memory, so use * get_allowed_nodes(NH_MEMS) to get a memory * node. This operation also applies to Non-NUMA * systems. */ ret = get_allowed_nodes(NH_MEMS, 1, &memnode); if (ret < 0) tst_brk(TBROK, "Failed to get a memory node " "using get_allowed_nodes()"); write_cpusets(memnode); }
static void check_swapping(void) { int status, i; long swap_free_now, swapped; /* wait child stop */ SAFE_WAITPID(pid, &status, WUNTRACED); if (!WIFSTOPPED(status)) tst_brk(TBROK, "child was not stopped."); /* Still occupying memory, loop for a while */ i = 0; while (i < 10) { swap_free_now = SAFE_READ_MEMINFO("SwapFree:"); sleep(1); if (abs(swap_free_now - SAFE_READ_MEMINFO("SwapFree:")) < 512) break; i++; } swap_free_now = SAFE_READ_MEMINFO("SwapFree:"); swapped = swap_free_init - swap_free_now; if (swapped > mem_over_max) { kill(pid, SIGCONT); tst_brk(TFAIL, "heavy swapping detected: " "%ld MB swapped.", swapped / 1024); } tst_res(TPASS, "no heavy swapping detected, %ld MB swapped.", swapped / 1024); kill(pid, SIGCONT); /* wait child exit */ SAFE_WAITPID(pid, &status, 0); }
static void setup(void) { if (tst_parse_int(str_reads, &reads, 1, INT_MAX)) tst_brk(TBROK, "Invalid reads (-r) argument: '%s'", str_reads); if (tst_parse_long(str_max_workers, &max_workers, 1, LONG_MAX)) { tst_brk(TBROK, "Invalid max workers (-w) argument: '%s'", str_max_workers); } if (tst_parse_long(str_worker_count, &worker_count, 1, LONG_MAX)) { tst_brk(TBROK, "Invalid worker count (-W) argument: '%s'", str_worker_count); } if (!root_dir) tst_brk(TBROK, "The directory argument (-d) is required"); if (!worker_count) worker_count = MIN(MAX(tst_ncpus() - 1, 1), max_workers); workers = SAFE_MALLOC(worker_count * sizeof(*workers)); }
void test_chmod(void) { struct stat stat_buf; /* * Call chmod(2) with specified mode argument * (sticky-bit set) on testfile. */ TEST(chmod(TESTFILE, PERMS)); if (TST_RET == -1) { tst_brk(TFAIL | TTERRNO, "chmod(%s, %#o) failed", TESTFILE, PERMS); } if (stat(TESTFILE, &stat_buf) == -1) { tst_brk(TFAIL | TTERRNO, "stat failed"); } /* Check for expected mode permissions */ if ((stat_buf.st_mode & PERMS) == PERMS) { tst_res(TPASS, "Functionality of chmod(%s, %#o) successful", TESTFILE, PERMS); } else { tst_res(TFAIL, "%s: Incorrect modes 0%03o; expected 0%03o", TESTFILE, stat_buf.st_mode, PERMS); } }
static void setup(void) { check_hugepage(); hugepagesize = SAFE_READ_MEMINFO("Hugepagesize:") * 1024; init_sys_sz_paths(); if (opt_sysfs) { path = path_sys_sz_huge; pathover = path_sys_sz_over; } else { path = PATH_PROC_HUGE; pathover = PATH_PROC_OVER; } if (opt_alloc) { size = atoi(opt_alloc); length = (size + size * 0.5) * 2; } if (opt_shmid) { SAFE_FILE_SCANF(PATH_SHMMAX, "%llu", &shmmax); if (shmmax < (unsigned long long)(length / 2 * hugepagesize)) { restore_shmmax = 1; SAFE_FILE_PRINTF(PATH_SHMMAX, "%ld", (length / 2 * hugepagesize)); } } SAFE_FILE_SCANF(path, "%ld", &nr_hugepages); tst_res(TINFO, "original nr_hugepages is %ld", nr_hugepages); /* Reset. */ SAFE_FILE_PRINTF(path, "%ld", size); restore_nr_hgpgs = 1; if (access(pathover, F_OK)) { tst_brk(TCONF, "file %s does not exist in the system", pathover); } SAFE_FILE_SCANF(pathover, "%ld", &nr_overcommit_hugepages); tst_res(TINFO, "original nr_overcommit_hugepages is %ld", nr_overcommit_hugepages); /* Reset. */ SAFE_FILE_PRINTF(pathover, "%ld", size); restore_overcomm_hgpgs = 1; SAFE_MKDIR(MOUNT_DIR, 0700); SAFE_MOUNT(NULL, MOUNT_DIR, "hugetlbfs", 0, NULL); mounted = 1; if (opt_shmid) { /* Use /proc/meminfo to generate an IPC key. */ key = ftok(PATH_MEMINFO, strlen(PATH_MEMINFO)); if (key == -1) tst_brk(TBROK | TERRNO, "ftok"); } }
/* * Fatal error handler */ static void io_error(const char *func, int rc) { if (rc == -ENOSYS) tst_brk(TCONF, "AIO not in this kernel\n"); else if (rc < 0) tst_brk(TFAIL, "%s: %s\n", func, strerror(-rc)); else tst_brk(TFAIL, "%s: error %d\n", func, rc); }
static void drop_cap_sys_admin(void) { cap_value_t cap_value[] = { CAP_SYS_ADMIN }; cap_t cap = cap_get_proc(); if (!cap) tst_brk(TBROK | TERRNO, "cap_get_proc failed"); if (cap_set_flag(cap, CAP_EFFECTIVE, 1, cap_value, CAP_CLEAR)) tst_brk(TBROK | TERRNO, "cap_set_flag failed"); if (cap_set_proc(cap)) tst_brk(TBROK | TERRNO, "cap_set_proc failed"); }
static int has_file(const char *fname, int required) { struct stat buf; if (stat(fname, &buf) == -1) { if (errno != ENOENT) tst_brk(TBROK | TERRNO, "stat %s", fname); if (required) tst_brk(TCONF, "%s not available", fname); return 0; } return 1; }
void tst_flush(void) { int rval; rval = fflush(stderr); if (rval != 0) tst_brk(TBROK | TERRNO, "fflush(stderr) failed"); rval = fflush(stderr); if (rval != 0) tst_brk(TBROK | TERRNO, "fflush(stdout) failed"); }
static void vmsplice_test(void) { int pipes[2]; long written; int ret; int fd_out; struct iovec v; loff_t offset; v.iov_base = buffer; v.iov_len = TEST_BLOCK_SIZE; fd_out = SAFE_OPEN(TESTFILE, O_WRONLY | O_CREAT | O_TRUNC, 0644); SAFE_PIPE(pipes); struct pollfd pfd = {.fd = pipes[1], .events = POLLOUT}; offset = 0; while (v.iov_len) { /* * in a real app you'd be more clever with poll of course, * here we are basically just blocking on output room and * not using the free time for anything interesting. */ if (poll(&pfd, 1, -1) < 0) tst_brk(TBROK | TERRNO, "poll() failed"); written = vmsplice(pipes[1], &v, 1, 0); if (written < 0) { tst_brk(TBROK | TERRNO, "vmsplice() failed"); } else { if (written == 0) { break; } else { v.iov_base += written; v.iov_len -= written; } } ret = splice(pipes[0], NULL, fd_out, &offset, written, 0); if (ret < 0) tst_brk(TBROK | TERRNO, "splice() failed"); //printf("offset = %lld\n", (long long)offset); } SAFE_CLOSE(pipes[0]); SAFE_CLOSE(pipes[1]); SAFE_CLOSE(fd_out); check_file(); }
int main(int argc, char *argv[]) { tst_reinit(); if (argc != 2) tst_brk(TFAIL, "argc is %d, expected 2", argc); if (strcmp(argv[1], "canary")) tst_brk(TFAIL, "argv[1] is %s, expected 'canary'", argv[1]); tst_res(TPASS, "%s executed", argv[0]); return 0; }
static void create_ksm_child(int child_num, int size, int unit, struct ksm_merge_data *ksm_merge_data) { int j, total_unit; char **memory; /* The total units in all */ total_unit = size / unit; /* Apply for the space for memory */ memory = SAFE_MALLOC(total_unit * sizeof(char *)); for (j = 0; j < total_unit; j++) { memory[j] = SAFE_MMAP(NULL, unit * MB, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); #ifdef HAVE_MADV_MERGEABLE if (madvise(memory[j], unit * MB, MADV_MERGEABLE) == -1) tst_brk(TBROK|TERRNO, "madvise"); #endif } tst_res(TINFO, "child %d stops.", child_num); if (raise(SIGSTOP) == -1) tst_brk(TBROK|TERRNO, "kill"); fflush(stdout); for (j = 0; j < 4; j++) { ksm_child_memset(child_num, size, total_unit, ksm_merge_data[j], memory); fflush(stdout); tst_res(TINFO, "child %d stops.", child_num); if (raise(SIGSTOP) == -1) tst_brk(TBROK|TERRNO, "kill"); if (ksm_merge_data[j].mergeable_size < size * MB) { verify(memory, 'e', child_num, total_unit - 1, total_unit, unit * MB - 1, unit * MB); verify(memory, ksm_merge_data[j].data, child_num, 0, total_unit, 0, unit * MB - 1); } else { verify(memory, ksm_merge_data[j].data, child_num, 0, total_unit, 0, unit * MB); } } tst_res(TINFO, "child %d finished.", child_num); }
static void setup(void) { epfd = epoll_create(2); if (epfd == -1) tst_brk(TBROK | TERRNO, "fail to create epoll instance"); SAFE_PIPE(fd); events[0].data.fd = fd[0]; events[1].data.fd = fd[1]; TEST(epoll_ctl(epfd, EPOLL_CTL_ADD, fd[0], &events[0])); if (TEST_RETURN == -1) tst_brk(TFAIL | TTERRNO, "epoll_ctl() fails to init"); }
static void run_targets(const char *dirname, char *cfile, pid_t tid) { int i, k, fd; char subdir[PATH_MAX] = {0}; char *output_file; char buf[11]; const char *const cmd_run[] = {cfile, NULL}; SAFE_ASPRINTF(&output_file, "%s/cmd.out", dirname); /* run each binary */ for (i = 0; i < dirs_num; ++i) { for (k = 0; k < file_num; ++k) { snprintf(cfile, PATH_MAX, "%s%s/%d.%d.%d", dirname, subdir, tid, i, k); tst_run_cmd(cmd_run, output_file, NULL, 0); fd = SAFE_OPEN(output_file, O_RDONLY); SAFE_READ(1, fd, buf, 11); if (strncmp(buf, "hello world", 11)) tst_brk(TFAIL, "command printed wrong message"); SAFE_CLOSE(fd); } strcat(subdir, "/dir"); } free(output_file); }
static void alloc_and_check(long size, int expect_result) { int result; /* try to alloc size kB memory */ result = heavy_malloc(size); switch (expect_result) { case EXPECT_PASS: if (result == 0) tst_res(TPASS, "alloc passed as expected"); else tst_res(TFAIL, "alloc failed, expected to pass"); break; case EXPECT_FAIL: if (result != 0) tst_res(TPASS, "alloc failed as expected"); else tst_res(TFAIL, "alloc passed, expected to fail"); break; default: tst_brk(TBROK, "Invaild numbler parameter: %d", expect_result); } }
static void overcommit_memory_test(void) { #if __WORDSIZE == 32 tst_brk(TCONF, "test is not designed for 32-bit system."); #endif /* start to test overcommit_memory=2 */ set_sys_tune("overcommit_memory", 2, 1); update_mem_commit(); alloc_and_check(commit_left * 2, EXPECT_FAIL); alloc_and_check(commit_limit, EXPECT_FAIL); update_mem_commit(); alloc_and_check(commit_left / 2, EXPECT_PASS); /* start to test overcommit_memory=0 */ set_sys_tune("overcommit_memory", 0, 1); update_mem(); alloc_and_check(free_total / 2, EXPECT_PASS); update_mem(); alloc_and_check(free_total * 2, EXPECT_FAIL); alloc_and_check(sum_total, EXPECT_FAIL); /* start to test overcommit_memory=1 */ set_sys_tune("overcommit_memory", 1, 1); alloc_and_check(sum_total / 2, EXPECT_PASS); alloc_and_check(sum_total, EXPECT_PASS); alloc_and_check(sum_total * 2, EXPECT_PASS); }
static void check_mark(char *file, unsigned long long flag, char *flagstr, int expect, void (*test_event)(char *)) { if (fanotify_mark(fd_notify, FAN_MARK_ADD | flag, FAN_OPEN, AT_FDCWD, file) != expect) { tst_res(TFAIL, "fanotify_mark (%d, FAN_MARK_ADD | %s, FAN_OPEN, AT_FDCWD, " "'%s') %s", fd_notify, flagstr, file, expect_str_fail(expect)); } else { tst_res(TPASS, "fanotify_mark (%d, FAN_MARK_ADD | %s, FAN_OPEN, AT_FDCWD, " "'%s') %s", fd_notify, flagstr, file, expect_str_pass(expect)); /* If we expected failure there's nothing to clean up */ if (expect == -1) return; if (test_event) test_event(file); if (fanotify_mark(fd_notify, FAN_MARK_REMOVE | flag, FAN_OPEN, AT_FDCWD, file) < 0) { tst_brk(TBROK | TERRNO, "fanotify_mark (%d, FAN_MARK_REMOVE | %s, " "FAN_OPEN, AT_FDCWD, '%s') failed", fd_notify, flagstr, file); } } }
static void setup(void) { struct sysinfo sys_buf; sysinfo(&sys_buf); if (sys_buf.totalram < 2L * GB_SZ) tst_brk(TCONF, "Test requires more than 2GB of RAM"); if (sys_buf.totalram > 100L * GB_SZ) tst_brk(TCONF, "System RAM is too large, skip test"); dst_max = sys_buf.totalram / GB_SZ; tst_res(TINFO, "dst_max = %ld", dst_max); pg_sz = getpagesize(); }
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)); }