/* * stress_kcmp * stress sys_kcmp */ static int stress_kcmp(const args_t *args) { pid_t pid1; int fd1; #if defined(HAVE_SYS_EPOLL_H) && NEED_GLIBC(2,3,2) int efd, sfd; int so_reuseaddr = 1; struct epoll_event ev; struct sockaddr *addr = NULL; socklen_t addr_len = 0; #endif int ret = EXIT_SUCCESS; static const char *capfail = "need CAP_SYS_PTRACE capability to run kcmp stressor, " "aborting stress test\n"; if ((fd1 = open("/dev/null", O_WRONLY)) < 0) { pr_fail_err("open"); return EXIT_FAILURE; } #if defined(HAVE_SYS_EPOLL_H) && NEED_GLIBC(2,3,2) efd = -1; if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { sfd = -1; goto again; } if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr, sizeof(so_reuseaddr)) < 0) { (void)close(sfd); sfd = -1; goto again; } stress_set_sockaddr(args->name, args->instance, args->ppid, AF_INET, 23000, &addr, &addr_len, NET_ADDR_ANY); if (bind(sfd, addr, addr_len) < 0) { (void)close(sfd); sfd = -1; goto again; } if (listen(sfd, SOMAXCONN) < 0) { (void)close(sfd); sfd = -1; goto again; } efd = epoll_create1(0); if (efd < 0) { (void)close(sfd); sfd = -1; efd = -1; goto again; } (void)memset(&ev, 0, sizeof(ev)); ev.data.fd = efd; ev.events = EPOLLIN | EPOLLET; if (epoll_ctl(efd, EPOLL_CTL_ADD, sfd, &ev) < 0) { (void)close(sfd); (void)close(efd); sfd = -1; efd = -1; } #endif again: pid1 = fork(); if (pid1 < 0) { if (g_keep_stressing_flag && ((errno == EAGAIN) || (errno == ENOMEM))) goto again; pr_fail_dbg("fork"); (void)close(fd1); #if defined(HAVE_SYS_EPOLL_H) && NEED_GLIBC(2,3,2) if (sfd != -1) (void)close(sfd); #endif return EXIT_FAILURE; } else if (pid1 == 0) { (void)setpgid(0, g_pgrp); stress_parent_died_alarm(); /* Child */ while (g_keep_stressing_flag) (void)pause(); /* will never get here */ (void)close(fd1); #if defined(HAVE_SYS_EPOLL_H) && NEED_GLIBC(2,3,2) if (efd != -1) (void)close(efd); if (sfd != -1) (void)close(sfd); #endif _exit(EXIT_SUCCESS); } else { /* Parent */ int fd2, status, pid2; (void)setpgid(pid1, g_pgrp); pid2 = getpid(); if ((fd2 = open("/dev/null", O_WRONLY)) < 0) { pr_fail_err("open"); ret = EXIT_FAILURE; goto reap; } do { KCMP(pid1, pid2, SHIM_KCMP_FILE, fd1, fd2); KCMP(pid1, pid1, SHIM_KCMP_FILE, fd1, fd1); KCMP(pid2, pid2, SHIM_KCMP_FILE, fd1, fd1); KCMP(pid2, pid2, SHIM_KCMP_FILE, fd2, fd2); KCMP(pid1, pid2, SHIM_KCMP_FILES, 0, 0); KCMP(pid1, pid1, SHIM_KCMP_FILES, 0, 0); KCMP(pid2, pid2, SHIM_KCMP_FILES, 0, 0); KCMP(pid1, pid2, SHIM_KCMP_FS, 0, 0); KCMP(pid1, pid1, SHIM_KCMP_FS, 0, 0); KCMP(pid2, pid2, SHIM_KCMP_FS, 0, 0); KCMP(pid1, pid2, SHIM_KCMP_IO, 0, 0); KCMP(pid1, pid1, SHIM_KCMP_IO, 0, 0); KCMP(pid2, pid2, SHIM_KCMP_IO, 0, 0); KCMP(pid1, pid2, SHIM_KCMP_SIGHAND, 0, 0); KCMP(pid1, pid1, SHIM_KCMP_SIGHAND, 0, 0); KCMP(pid2, pid2, SHIM_KCMP_SIGHAND, 0, 0); KCMP(pid1, pid2, SHIM_KCMP_SYSVSEM, 0, 0); KCMP(pid1, pid1, SHIM_KCMP_SYSVSEM, 0, 0); KCMP(pid2, pid2, SHIM_KCMP_SYSVSEM, 0, 0); KCMP(pid1, pid2, SHIM_KCMP_VM, 0, 0); KCMP(pid1, pid1, SHIM_KCMP_VM, 0, 0); KCMP(pid2, pid2, SHIM_KCMP_VM, 0, 0); #if defined(HAVE_SYS_EPOLL_H) && NEED_GLIBC(2,3,2) if (efd != -1) { struct kcmp_epoll_slot slot; slot.efd = efd; slot.tfd = sfd; slot.toff = 0; KCMP(pid1, pid2, SHIM_KCMP_EPOLL_TFD, efd, (unsigned long)&slot); KCMP(pid2, pid1, SHIM_KCMP_EPOLL_TFD, efd, (unsigned long)&slot); KCMP(pid2, pid2, SHIM_KCMP_EPOLL_TFD, efd, (unsigned long)&slot); } #endif /* Same simple checks */ if (g_opt_flags & OPT_FLAGS_VERIFY) { KCMP_VERIFY(pid1, pid1, SHIM_KCMP_FILE, fd1, fd1, 0); KCMP_VERIFY(pid1, pid1, SHIM_KCMP_FILES, 0, 0, 0); KCMP_VERIFY(pid1, pid1, SHIM_KCMP_FS, 0, 0, 0); KCMP_VERIFY(pid1, pid1, SHIM_KCMP_IO, 0, 0, 0); KCMP_VERIFY(pid1, pid1, SHIM_KCMP_SIGHAND, 0, 0, 0); KCMP_VERIFY(pid1, pid1, SHIM_KCMP_SYSVSEM, 0, 0, 0); KCMP_VERIFY(pid1, pid1, SHIM_KCMP_VM, 0, 0, 0); KCMP_VERIFY(pid1, pid2, SHIM_KCMP_SYSVSEM, 0, 0, 0); #if defined(HAVE_SYS_EPOLL_H) && NEED_GLIBC(2,3,2) if (efd != -1) { struct kcmp_epoll_slot slot; slot.efd = efd; slot.tfd = sfd; slot.toff = 0; KCMP(pid1, pid2, SHIM_KCMP_EPOLL_TFD, efd, (unsigned long)&slot); } #endif } inc_counter(args); } while (keep_stressing()); reap: if (fd2 >= 0) (void)close(fd2); (void)kill(pid1, SIGKILL); (void)shim_waitpid(pid1, &status, 0); (void)close(fd1); } #if defined(HAVE_SYS_EPOLL_H) && NEED_GLIBC(2,3,2) if (efd != -1) (void)close(efd); if (sfd != -1) (void)close(sfd); #endif return ret; }
/* * stress_kcmp * stress sys_kcmp */ int stress_kcmp( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pid1; int fd1; int ret = EXIT_SUCCESS; (void)instance; if ((fd1 = open("/dev/null", O_WRONLY)) < 0) { pr_failed_err(name, "open"); return EXIT_FAILURE; } again: pid1 = fork(); if (pid1 < 0) { if (opt_do_run && (errno == EAGAIN)) goto again; pr_failed_dbg(name, "fork"); (void)close(fd1); return EXIT_FAILURE; } else if (pid1 == 0) { setpgid(0, pgrp); /* Child */ while (opt_do_run) pause(); /* will never get here */ (void)close(fd1); exit(EXIT_SUCCESS); } else { /* Parent */ int fd2, status, pid2; setpgid(pid1, pgrp); pid2 = getpid(); if ((fd2 = open("/dev/null", O_WRONLY)) < 0) { pr_failed_err(name, "open"); ret = EXIT_FAILURE; goto reap; } do { KCMP(pid1, pid2, KCMP_FILE, fd1, fd2); KCMP(pid1, pid1, KCMP_FILE, fd1, fd1); KCMP(pid2, pid2, KCMP_FILE, fd1, fd1); KCMP(pid2, pid2, KCMP_FILE, fd2, fd2); KCMP(pid1, pid2, KCMP_FILES, 0, 0); KCMP(pid1, pid1, KCMP_FILES, 0, 0); KCMP(pid2, pid2, KCMP_FILES, 0, 0); KCMP(pid1, pid2, KCMP_FS, 0, 0); KCMP(pid1, pid1, KCMP_FS, 0, 0); KCMP(pid2, pid2, KCMP_FS, 0, 0); KCMP(pid1, pid2, KCMP_IO, 0, 0); KCMP(pid1, pid1, KCMP_IO, 0, 0); KCMP(pid2, pid2, KCMP_IO, 0, 0); KCMP(pid1, pid2, KCMP_SIGHAND, 0, 0); KCMP(pid1, pid1, KCMP_SIGHAND, 0, 0); KCMP(pid2, pid2, KCMP_SIGHAND, 0, 0); KCMP(pid1, pid2, KCMP_SYSVSEM, 0, 0); KCMP(pid1, pid1, KCMP_SYSVSEM, 0, 0); KCMP(pid2, pid2, KCMP_SYSVSEM, 0, 0); KCMP(pid1, pid2, KCMP_VM, 0, 0); KCMP(pid1, pid1, KCMP_VM, 0, 0); KCMP(pid2, pid2, KCMP_VM, 0, 0); /* Same simple checks */ if (opt_flags & OPT_FLAGS_VERIFY) { KCMP_VERIFY(pid1, pid1, KCMP_FILE, fd1, fd1, 0); KCMP_VERIFY(pid1, pid1, KCMP_FILES, 0, 0, 0); KCMP_VERIFY(pid1, pid1, KCMP_FS, 0, 0, 0); KCMP_VERIFY(pid1, pid1, KCMP_IO, 0, 0, 0); KCMP_VERIFY(pid1, pid1, KCMP_SIGHAND, 0, 0, 0); KCMP_VERIFY(pid1, pid1, KCMP_SYSVSEM, 0, 0, 0); KCMP_VERIFY(pid1, pid1, KCMP_VM, 0, 0, 0); KCMP_VERIFY(pid1, pid2, KCMP_SYSVSEM, 0, 0, 0); } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); reap: if (fd2 >= 0) (void)close(fd2); (void)kill(pid1, SIGKILL); (void)waitpid(pid1, &status, 0); (void)close(fd1); } return ret; }