Exemplo n.º 1
0
/*
 *  spawn()
 *	spawn a process
 */
static pid_t spawn(
	const char *name,
	void (*func)(const char *name, const pid_t pid,
		uint64_t *counter, const uint64_t max_ops),
	pid_t pid_arg,
	uint64_t *counter,
	uint64_t max_ops)
{
	pid_t pid;

again:
	pid = fork();
	if (pid < 0) {
		if (opt_do_run && (errno == EAGAIN))
			goto again;
		return -1;
	}
	if (pid == 0) {
		setpgid(0, pgrp);
		stress_parent_died_alarm();

		func(name, pid_arg, counter, max_ops);
		exit(EXIT_SUCCESS);
	}
	setpgid(pid, pgrp);
	return pid;
}
Exemplo n.º 2
0
/*
 *  stress_userfaultfd_child()
 *	generate page faults for parent to handle
 */
static int stress_userfaultfd_child(void *arg)
{
	context_t *c = (context_t *)arg;
	const args_t *args = c->args;

	(void)setpgid(0, g_pgrp);
	stress_parent_died_alarm();
	if (stress_sighandler(args->name, SIGALRM, stress_child_alarm_handler, NULL) < 0)
		return EXIT_NO_RESOURCE;

	do {
		uint8_t *ptr, *end = c->data + c->sz;

		/* hint we don't need these pages */
		if (shim_madvise(c->data, c->sz, MADV_DONTNEED) < 0) {
			pr_fail_err("userfaultfd madvise failed");
			(void)kill(c->parent, SIGALRM);
			return -1;
		}
		/* and trigger some page faults */
		for (ptr = c->data; ptr < end; ptr += c->page_size)
			*ptr = 0xff;
	} while (keep_stressing());

	return 0;
}
Exemplo n.º 3
0
/*
 *  epoll_spawn()
 *	spawn a process
 */
static pid_t epoll_spawn(
	epoll_func_t func,
	const int child,
	uint64_t *const counter,
	const uint32_t instance,
	const uint64_t max_ops,
	const char *name,
	const pid_t ppid)
{
	pid_t pid;

again:
	pid = fork();
	if (pid < 0) {
		if (opt_do_run && (errno == EAGAIN))
			goto again;
		return -1;
	}
	if (pid == 0) {
		setpgid(0, pgrp);
		stress_parent_died_alarm();
		func(child, counter, instance, max_ops, name, ppid);
		exit(EXIT_SUCCESS);
	}
	setpgid(pid, pgrp);
	return pid;
}
Exemplo n.º 4
0
/*
 *  stress_sigq
 *	stress by heavy sigqueue message sending
 */
static int stress_sigq(const args_t *args)
{
	pid_t pid;

	if (stress_sighandler(args->name, SIGUSR1, stress_sigqhandler, NULL) < 0)
		return EXIT_FAILURE;

again:
	pid = fork();
	if (pid < 0) {
		if (g_keep_stressing_flag && (errno == EAGAIN))
			goto again;
		pr_fail_dbg("fork");
		return EXIT_FAILURE;
	} else if (pid == 0) {
		sigset_t mask;

		(void)setpgid(0, g_pgrp);
		stress_parent_died_alarm();

		(void)sigemptyset(&mask);
		(void)sigaddset(&mask, SIGUSR1);

		while (g_keep_stressing_flag) {
			siginfo_t info;
			if (sigwaitinfo(&mask, &info) < 0)
				break;
			if (info.si_value.sival_int)
				break;
		}
		pr_dbg("%s: child got termination notice\n", args->name);
		pr_dbg("%s: exited on pid [%d] (instance %" PRIu32 ")\n",
			args->name, (int)getpid(), args->instance);
		_exit(0);
	} else {
		/* Parent */
		union sigval s;
		int status;

		do {
			(void)memset(&s, 0, sizeof(s));
			s.sival_int = 0;
			(void)sigqueue(pid, SIGUSR1, s);
			inc_counter(args);
		} while (keep_stressing());

		pr_dbg("%s: parent sent termination notice\n", args->name);
		(void)memset(&s, 0, sizeof(s));
		s.sival_int = 1;
		(void)sigqueue(pid, SIGUSR1, s);
		(void)shim_usleep(250);
		/* And ensure child is really dead */
		(void)kill(pid, SIGKILL);
		(void)shim_waitpid(pid, &status, 0);
	}

	return EXIT_SUCCESS;
}
Exemplo n.º 5
0
/*
 *  stress_fork_fn()
 *	stress by forking and exiting using
 *	fork function fork_fn (fork or vfork)
 */
int stress_fork_fn(
	uint64_t *const counter,
	const uint32_t instance,
	const uint64_t max_ops,
	const char *name,
	pid_t (*fork_fn)(void),
	const uint64_t fork_max)
{
	(void)instance;

	pid_t pids[MAX_FORKS];

	do {
		unsigned int i;

		memset(pids, 0, sizeof(pids));

		for (i = 0; i < fork_max; i++) {
			pids[i] = fork_fn();

			if (pids[i] == 0) {
				setpgid(0, pgrp);
				stress_parent_died_alarm();

				/* Child, immediately exit */
				_exit(0);
			}
			if (pids[i] > -1)
				setpgid(pids[i], pgrp);
			if (!opt_do_run)
				break;
		}
		for (i = 0; i < fork_max; i++) {
			if (pids[i] > 0) {
				int status;
				/* Parent, wait for child */
				(void)waitpid(pids[i], &status, 0);
				(*counter)++;
			}
		}

		for (i = 0; i < fork_max; i++) {
			if ((pids[i] < 0) && (opt_flags & OPT_FLAGS_VERIFY)) {
				pr_fail(stderr, "%s: fork failed\n", name);
			}
		}
	} while (opt_do_run && (!max_ops || *counter < max_ops));

	return EXIT_SUCCESS;
}
Exemplo n.º 6
0
/*
 *  stress_fiemap_spawn()
 *	helper to spawn off fiemap stressor
 */
static inline pid_t stress_fiemap_spawn(
	const char *name,
	const int fd,
	uint64_t *const counter,
	const uint64_t max_ops)
{
        pid_t pid;

        pid = fork();
        if (pid < 0)
                return -1;
        if (pid == 0) {
                setpgid(0, pgrp);
                stress_parent_died_alarm();
		stress_fiemap_ioctl(name, fd, counter, max_ops);
                exit(EXIT_SUCCESS);
        }
        setpgid(pid, pgrp);
        return pid;
}
/*
 *  stress_bind_mount_child()
 *	aggressively perform bind mounts, this can force out of memory
 *	situations
 */
int stress_bind_mount_child(void *arg)
{
	context_t *context = (context_t *)arg;

	setpgid(0, pgrp);
	stress_parent_died_alarm();

	do {
		if (mount("/", "/", "", MS_BIND | MS_REC, 0) < 0) {
			pr_fail(stderr, "%s: mount failed: errno=%d (%s)\n",
				context->name, errno, strerror(errno));
			break;
		}
		/*
		 *  The following fails with -EBUSY, but try it anyhow
	`	 *  just to make the kernel work harder
		 */
		(void)umount("/");
	} while (opt_do_run &&
		 (!context->max_ops || *(context->counter) < context->max_ops));

	return 0;
}
Exemplo n.º 8
0
/*
 *  stress_lease_spawn()
 *	spawn a process
 */
static pid_t stress_lease_spawn(
	const args_t *args,
	const char *filename)
{
	pid_t pid;

again:
	pid = fork();
	if (pid < 0) {
		if (g_keep_stressing_flag &&
		    ((errno == EAGAIN) || (errno == ENOMEM)))
			goto again;
		return -1;
	}
	if (pid == 0) {
		(void)setpgid(0, g_pgrp);
		stress_parent_died_alarm();

		do {
			int fd;

			errno = 0;
			fd = open(filename, O_NONBLOCK | O_WRONLY, S_IRUSR | S_IWUSR);
			if (fd < 0) {
				if (errno != EWOULDBLOCK && errno != EACCES) {
					pr_dbg("%s: open failed (child): errno=%d: (%s)\n",
						args->name, errno, strerror(errno));
				}
				continue;
			}
			(void)close(fd);
		} while (keep_stressing());
		_exit(EXIT_SUCCESS);
	}
	(void)setpgid(pid, g_pgrp);
	return pid;
}
Exemplo n.º 9
0
/*
 *  semaphore_posix_spawn()
 *	spawn a process
 */
static pid_t semaphore_posix_spawn(
	const char *name,
	const uint64_t max_ops,
	uint64_t *counter)
{
	pid_t pid;

again:
	pid = fork();
	if (pid < 0) {
		if (opt_do_run && (errno == EAGAIN))
			goto again;
		return -1;
	}
	if (pid == 0) {
		setpgid(0, pgrp);
		stress_parent_died_alarm();

		semaphore_posix_thrash(name, max_ops, counter);
		exit(EXIT_SUCCESS);
	}
	setpgid(pid, pgrp);
	return pid;
}
Exemplo n.º 10
0
/*
 *  stress_stackmmap
 *	stress a file memory map'd stack
 */
static int stress_stackmmap(const args_t *args)
{
	int fd;
	volatile int rc = EXIT_FAILURE;		/* could be clobbered */
	char filename[PATH_MAX];

	page_size = args->page_size;
	page_mask = ~(page_size - 1);

	/* Create file back'd mmaping for the stack */
	if (stress_temp_dir_mk_args(args) < 0)
		return EXIT_FAILURE;
	(void)stress_temp_filename_args(args,
		filename, sizeof(filename), mwc32());

	fd = open(filename, O_SYNC | O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
	if (fd < 0) {
		pr_fail_err("mmap'd stack file open");
		goto tidy_dir;
	}
	(void)unlink(filename);
	if (ftruncate(fd, MMAPSTACK_SIZE) < 0) {
		pr_fail_err("ftruncate");
		(void)close(fd);
		goto tidy_dir;
	}
	stack_mmap = mmap(NULL, MMAPSTACK_SIZE, PROT_READ | PROT_WRITE,
		MAP_SHARED, fd, 0);
	if (stack_mmap == MAP_FAILED) {
		if (errno == ENXIO) {
			pr_inf("%s: skipping stressor, mmap not possible on file %s\n",
				args->name, filename);
			rc = EXIT_NO_RESOURCE;
			(void)close(fd);
			goto tidy_dir;
		}
		pr_fail_err("mmap");
		(void)close(fd);
		goto tidy_dir;
	}
	(void)close(fd);

	if (shim_madvise(stack_mmap, MMAPSTACK_SIZE, MADV_RANDOM) < 0) {
		pr_dbg("%s: madvise failed: errno=%d (%s)\n",
			args->name, errno, strerror(errno));
	}
	(void)memset(stack_mmap, 0, MMAPSTACK_SIZE);
	(void)memset(&c_test, 0, sizeof(c_test));
	if (getcontext(&c_test) < 0) {
		pr_fail_err("getcontext");
		goto tidy_mmap;
	}
	c_test.uc_stack.ss_sp = stack_mmap;
	c_test.uc_stack.ss_size = MMAPSTACK_SIZE;
	c_test.uc_link = &c_main;

	/*
	 *  set jmp handler to jmp back into the loop on a full
	 *  stack segfault.  Use swapcontext to jump into a
	 *  new context using the new mmap'd stack
	 */
	do {
		pid_t pid;
again:
		if (!g_keep_stressing_flag)
			break;
		pid = fork();
		if (pid < 0) {
			if ((errno == EAGAIN) || (errno == ENOMEM))
				goto again;
			pr_err("%s: fork failed: errno=%d (%s)\n",
				args->name, errno, strerror(errno));
		} else if (pid > 0) {
			int status, waitret;

			/* Parent, wait for child */
			(void)setpgid(pid, g_pgrp);
			waitret = shim_waitpid(pid, &status, 0);
			if (waitret < 0) {
				if (errno != EINTR)
					pr_dbg("%s: waitpid(): errno=%d (%s)\n",
						args->name, errno, strerror(errno));
				(void)kill(pid, SIGTERM);
				(void)kill(pid, SIGKILL);
				(void)shim_waitpid(pid, &status, 0);
			}
		} else if (pid == 0) {
			/* Child */

			(void)setpgid(0, g_pgrp);
			stress_parent_died_alarm();

			/* Make sure this is killable by OOM killer */
			set_oom_adjustment(args->name, true);

			(void)makecontext(&c_test, stress_stackmmap_push_start, 0);
			(void)swapcontext(&c_main, &c_test);

			_exit(0);
		}
		inc_counter(args);
	} while (keep_stressing());

	rc = EXIT_SUCCESS;

tidy_mmap:
	(void)munmap(stack_mmap, MMAPSTACK_SIZE);
tidy_dir:
	(void)stress_temp_dir_rm_args(args);
	return rc;
}
Exemplo n.º 11
0
/*
 *  stress_socket_pair
 *	stress by heavy socket_pair I/O
 */
int stress_socket_pair(
	uint64_t *const counter,
	const uint32_t instance,
	const uint64_t max_ops,
	const char *name)
{
	pid_t pid;
	int socket_pair_fds[MAX_SOCKET_PAIRS][2], i, max;

	(void)instance;

	for (max = 0; max < MAX_SOCKET_PAIRS; max++) {
		if (socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair_fds[max]) < 0)
			break;
	}

	if (max == 0) {
		pr_fail_dbg(name, "socket_pair");
		return EXIT_FAILURE;
	}

again:
	pid = fork();
	if (pid < 0) {
		if (opt_do_run && (errno == EAGAIN))
			goto again;
		socket_pair_close(socket_pair_fds, max, 0);
		socket_pair_close(socket_pair_fds, max, 1);
		pr_fail_dbg(name, "fork");
		return EXIT_FAILURE;
	} else if (pid == 0) {
		setpgid(0, pgrp);
		stress_parent_died_alarm();

		socket_pair_close(socket_pair_fds, max, 1);
		while (opt_do_run) {
			uint8_t buf[SOCKET_PAIR_BUF];
			ssize_t n;

			for (i = 0; opt_do_run && (i < max); i++) {
				n = read(socket_pair_fds[i][0], buf, sizeof(buf));
				if (n <= 0) {
					if ((errno == EAGAIN) || (errno == EINTR))
						continue;
					if (errno == ENFILE) /* Too many files! */
						goto abort;
					if (errno == EMFILE) /* Occurs on socket shutdown */
						goto abort;
					if (errno) {
						pr_fail_dbg(name, "read");
						break;
					}
					continue;
				}
				if ((opt_flags & OPT_FLAGS_VERIFY) &&
				    socket_pair_memchk(buf, (size_t)n)) {
					pr_fail(stderr, "%s: socket_pair read error detected, "
						"failed to read expected data\n", name);
				}
			}
		}
abort:
		socket_pair_close(socket_pair_fds, max, 0);
		exit(EXIT_SUCCESS);
	} else {
		uint8_t buf[SOCKET_PAIR_BUF];
		int val = 0, status;

		setpgid(pid, pgrp);
		/* Parent */
		socket_pair_close(socket_pair_fds, max, 0);
		do {
			for (i = 0; opt_do_run && (i < max); i++) {
				ssize_t ret;

				socket_pair_memset(buf, val++, sizeof(buf));
				ret = write(socket_pair_fds[i][1], buf, sizeof(buf));
				if (ret <= 0) {
					if ((errno == EAGAIN) || (errno == EINTR))
						continue;
					if (errno) {
						pr_fail_dbg(name, "write");
						break;
					}
					continue;
				}
				(*counter)++;
			}
		} while (opt_do_run && (!max_ops || *counter < max_ops));

		for (i = 0; i < max; i++) {
			if (shutdown(socket_pair_fds[i][1], SHUT_RDWR) < 0)
				pr_fail_dbg(name, "socket shutdown");
		}
		(void)kill(pid, SIGKILL);
		(void)waitpid(pid, &status, 0);
		socket_pair_close(socket_pair_fds, max, 1);
	}
	return EXIT_SUCCESS;
}
Exemplo n.º 12
0
/*
 *  stress_eventfd
 *	stress eventfd read/writes
 */
int stress_eventfd(
	uint64_t *const counter,
	const uint32_t instance,
	const uint64_t max_ops,
	const char *name)
{
	pid_t pid;
	int fd1, fd2, rc;

	(void)instance;

	fd1 = eventfd(0, 0);
	if (fd1 < 0) {
		rc = exit_status(errno);
		pr_fail_dbg(name, "eventfd");
		return rc;
	}
	fd2 = eventfd(0, 0);
	if (fd2 < 0) {
		rc = exit_status(errno);
		pr_fail_dbg(name, "eventfd");
		(void)close(fd1);
		return rc;
	}

again:
	pid = fork();
	if (pid < 0) {
		if (opt_do_run && (errno == EAGAIN))
			goto again;
		pr_fail_dbg(name, "fork");
		(void)close(fd1);
		(void)close(fd2);
		return EXIT_FAILURE;
	} else if (pid == 0) {
		setpgid(0, pgrp);
		stress_parent_died_alarm();

		while (opt_do_run) {
			uint64_t val;
			ssize_t ret;

			for (;;) {
				if (!opt_do_run)
					goto exit_child;
				ret = read(fd1, &val, sizeof(val));
				if (ret < 0) {
					if ((errno == EAGAIN) || (errno == EINTR))
						continue;
					pr_fail_dbg(name, "child read");
					goto exit_child;
				}
				if (ret < (ssize_t)sizeof(val)) {
					pr_fail_dbg(name, "child short read");
					goto exit_child;
				}
				break;
			}
			val = 1;

			for (;;) {
				if (!opt_do_run)
					goto exit_child;
				ret = write(fd2, &val, sizeof(val));
				if (ret < 0) {
					if ((errno == EAGAIN) || (errno == EINTR))
						continue;
					pr_fail_dbg(name, "child write");
					goto exit_child;
				}
				if (ret  < (ssize_t)sizeof(val)) {
					pr_fail_dbg(name, "child short write");
					goto exit_child;
				}
				break;
			}
		}
exit_child:
		(void)close(fd1);
		(void)close(fd2);
		exit(EXIT_SUCCESS);
	} else {
		int status;

		do {
			uint64_t val = 1;
			int ret;

			for (;;) {
				if (!opt_do_run)
					goto exit_parent;

				ret = write(fd1, &val, sizeof(val));
				if (ret < 0) {
					if ((errno == EAGAIN) || (errno == EINTR))
						continue;
					pr_fail_dbg(name, "parent write");
					goto exit_parent;
				}
				if (ret < (ssize_t)sizeof(val)) {
					pr_fail_dbg(name, "parent short write");
					goto exit_parent;
				}
				break;
			}

			for (;;) {
				if (!opt_do_run)
					goto exit_parent;

				ret = read(fd2, &val, sizeof(val));
				if (ret < 0) {
					if ((errno == EAGAIN) || (errno == EINTR))
						continue;
					pr_fail_dbg(name, "parent read");
					goto exit_parent;
				}
				if (ret < (ssize_t)sizeof(val)) {
					pr_fail_dbg(name, "parent short read");
					goto exit_parent;
				}
				break;
			}
			(*counter)++;
		} while (opt_do_run && (!max_ops || *counter < max_ops));
exit_parent:
		(void)kill(pid, SIGKILL);
		(void)waitpid(pid, &status, 0);
		(void)close(fd1);
		(void)close(fd2);
	}
	return EXIT_SUCCESS;
}
Exemplo n.º 13
0
int stress_vm_child(void *arg)
{
	context_t *ctxt = (context_t *)arg;

	uint8_t *buf;
	int ret = EXIT_SUCCESS;
	addr_msg_t msg_rd, msg_wr;

	setpgid(0, pgrp);
	stress_parent_died_alarm();

	/* Close unwanted ends */
	(void)close(ctxt->pipe_wr[0]);
	(void)close(ctxt->pipe_rd[1]);

	buf = mmap(NULL, ctxt->sz, PROT_READ | PROT_WRITE,
		MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
	if (buf == MAP_FAILED) {
		ret = exit_status(errno);
		pr_fail_dbg(ctxt->name, "mmap");
		goto cleanup;
	}

	while (opt_do_run) {
		uint8_t *ptr, *end = buf + ctxt->sz;
		int ret;

		memset(&msg_wr, 0, sizeof(msg_wr));
		msg_wr.addr = buf;
		msg_wr.val = 0;

		/* Send address of buffer to parent */
redo_wr1:
		ret = write(ctxt->pipe_wr[1], &msg_wr, sizeof(msg_wr));
		if (ret < 0) {
			if ((errno == EAGAIN) || (errno == EINTR))
				goto redo_wr1;
			if (errno != EBADF)
				pr_fail_dbg(ctxt->name, "write");
			break;
		}
redo_rd1:
		/* Wait for parent to populate data */
		ret = read(ctxt->pipe_rd[0], &msg_rd, sizeof(msg_rd));
		if (ret < 0) {
			if ((errno == EAGAIN) || (errno == EINTR))
				goto redo_rd1;
			pr_fail_dbg(ctxt->name, "read");
			break;
		}
		if (ret == 0)
			break;
		if (ret != sizeof(msg_rd)) {
			pr_fail_dbg(ctxt->name, "read");
			break;
		}

		if (opt_flags & OPT_FLAGS_VERIFY) {
			/* Check memory altered by parent is sane */
			for (ptr = buf; ptr < end; ptr += ctxt->page_size) {
				if (*ptr != msg_rd.val) {
					pr_fail(stderr, "%s: memory at %p: %d vs %d\n",
						ctxt->name, ptr, *ptr, msg_rd.val);
					goto cleanup;
				}
				*ptr = 0;
			}
		}
	}
cleanup:
	/* Tell parent we're done */
	msg_wr.addr = 0;
	msg_wr.val = 0;
	if (write(ctxt->pipe_wr[1], &msg_wr, sizeof(msg_wr)) <= 0) {
		if (errno != EBADF)
			pr_dbg(stderr, "%s: failed to write termination message "
				"over pipe: errno=%d (%s)\n",
				ctxt->name, errno, strerror(errno));
	}

	(void)close(ctxt->pipe_wr[1]);
	(void)close(ctxt->pipe_rd[0]);
	(void)munmap(buf, ctxt->sz);
	return ret;
}
Exemplo n.º 14
0
/*
 *  stress_ptrace()
 *	stress ptracing
 */
static int stress_ptrace(const args_t *args)
{
	pid_t pid;

	pid = fork();
	if (pid < 0) {
		pr_fail_dbg("fork");
		return EXIT_FAILURE;
	} else if (pid == 0) {
		(void)setpgid(0, g_pgrp);
		stress_parent_died_alarm();

		/*
		 * Child to be traced, we abort if we detect
		 * we are already being traced by someone else
		 * as this makes life way too complex
		 */
		if (ptrace(PTRACE_TRACEME) != 0) {
			pr_fail("%s: ptrace child being traced "
				"already, aborting\n", args->name);
			_exit(0);
		}
		/* Wait for parent to start tracing me */
		(void)kill(getpid(), SIGSTOP);

		/*
		 *  A simple mix of system calls
		 */
		while (g_keep_stressing_flag) {
			pid_t pidtmp;
			gid_t gidtmp;
			uid_t uidtmp;
			time_t ttmp;

			pidtmp = getppid();
			(void)pidtmp;

#if defined(HAVE_GETPGRP)
			pidtmp = getpgrp();
			(void)pidtmp;
#endif

			gidtmp = getgid();
			(void)gidtmp;

			gidtmp = getegid();
			(void)gidtmp;

			uidtmp = getuid();
			(void)uidtmp;

			uidtmp = geteuid();
			(void)uidtmp;

			ttmp = time(NULL);
			(void)ttmp;
		}
		_exit(0);
	} else {
		/* Parent to do the tracing */
		int status;

		(void)setpgid(pid, g_pgrp);

		if (shim_waitpid(pid, &status, 0) < 0) {
			if (errno != EINTR) {
				pr_fail_dbg("waitpid");
				return EXIT_FAILURE;
			}
			return EXIT_SUCCESS;
		}
		if (ptrace(PTRACE_SETOPTIONS, pid,
			0, PTRACE_O_TRACESYSGOOD) < 0) {
			pr_fail_dbg("ptrace");
			return EXIT_FAILURE;
		}

		do {
			/*
			 *  We do two of the following per syscall,
			 *  one at the start, and one at the end to catch
			 *  the return.  In this stressor we don't really
			 *  care which is which, we just care about counting
			 *  them
			 */
			if (stress_syscall_wait(args, pid))
				break;
			inc_counter(args);
		} while (keep_stressing());

		/* Terminate child */
		(void)kill(pid, SIGKILL);
		if (shim_waitpid(pid, &status, 0) < 0)
			pr_fail_dbg("waitpid");
	}
	return EXIT_SUCCESS;
}
Exemplo n.º 15
0
/*
 *  stress_shm_sysv()
 *	stress SYSTEM V shared memory
 */
int stress_shm_sysv(
	uint64_t *const counter,
	const uint32_t instance,
	const uint64_t max_ops,
	const char *name)
{
	const size_t page_size = stress_get_pagesize();
	size_t orig_sz, sz;
	int pipefds[2];
	int rc = EXIT_SUCCESS;
	ssize_t i;
	pid_t pid;
	bool retry = true;
	uint32_t restarts = 0;

	if (!set_shm_sysv_bytes) {
		if (opt_flags & OPT_FLAGS_MAXIMIZE)
			opt_shm_sysv_bytes = MAX_SHM_SYSV_BYTES;
		if (opt_flags & OPT_FLAGS_MINIMIZE)
			opt_shm_sysv_bytes = MIN_SHM_SYSV_BYTES;
	}

	if (!set_shm_sysv_segments) {
		if (opt_flags & OPT_FLAGS_MAXIMIZE)
			opt_shm_sysv_segments = MAX_SHM_SYSV_SEGMENTS;
		if (opt_flags & OPT_FLAGS_MINIMIZE)
			opt_shm_sysv_segments = MIN_SHM_SYSV_SEGMENTS;
	}
	orig_sz = sz = opt_shm_sysv_bytes & ~(page_size - 1);

	while (opt_do_run && retry) {
		if (pipe(pipefds) < 0) {
			pr_fail_dbg(name, "pipe");
			return EXIT_FAILURE;
		}
fork_again:
		pid = fork();
		if (pid < 0) {
			/* Can't fork, retry? */
			if (errno == EAGAIN)
				goto fork_again;
			pr_err(stderr, "%s: fork failed: errno=%d: (%s)\n",
				name, errno, strerror(errno));
			(void)close(pipefds[0]);
			(void)close(pipefds[1]);

			/* Nope, give up! */
			return EXIT_FAILURE;
		} else if (pid > 0) {
			/* Parent */
			int status, shm_ids[MAX_SHM_SYSV_SEGMENTS];
			ssize_t n;

			setpgid(pid, pgrp);
			set_oom_adjustment(name, false);
			(void)close(pipefds[1]);

			for (i = 0; i < (ssize_t)opt_shm_sysv_segments; i++)
				shm_ids[i] = -1;

			while (opt_do_run) {
				shm_msg_t 	msg;

				/*
				 *  Blocking read on child shm ID info
				 *  pipe.  We break out if pipe breaks
				 *  on child death, or child tells us
				 *  off its demise.
				 */
				n = read(pipefds[0], &msg, sizeof(msg));
				if (n <= 0) {
					if ((errno == EAGAIN) || (errno == EINTR))
						continue;
					if (errno) {
						pr_fail_dbg(name, "read");
						break;
					}
					pr_fail_dbg(name, "zero byte read");
					break;
				}
				if ((msg.index < 0) ||
				    (msg.index >= MAX_SHM_SYSV_SEGMENTS)) {
					retry = false;
					break;
				}
				shm_ids[msg.index] = msg.shm_id;
			}
			(void)kill(pid, SIGALRM);
			(void)waitpid(pid, &status, 0);
			if (WIFSIGNALED(status)) {
				if ((WTERMSIG(status) == SIGKILL) ||
				    (WTERMSIG(status) == SIGBUS)) {
					pr_dbg(stderr, "%s: assuming killed by OOM killer, "
						"restarting again (instance %d)\n",
						name, instance);
					restarts++;
				}
			}
			(void)close(pipefds[1]);
			/*
			 *  The child may have been killed by the OOM killer or
			 *  some other way, so it may have left the shared
			 *  memory segment around.  At this point the child
			 *  has died, so we should be able to remove the
			 *  shared memory segment.
			 */
			for (i = 0; i < (ssize_t)opt_shm_sysv_segments; i++) {
				if (shm_ids[i] != -1)
					(void)shmctl(shm_ids[i], IPC_RMID, NULL);
			}
		} else if (pid == 0) {
			/* Child, stress memory */
			setpgid(0, pgrp);
			stress_parent_died_alarm();

			/*
			 * Nicing the child may OOM it first as this
			 * doubles the OOM score
			 */
			if (nice(5) < 0)
				pr_dbg(stderr, "%s: nice of child failed, "
					"(instance %d)\n", name, instance);

			(void)close(pipefds[0]);
			rc = stress_shm_sysv_child(pipefds[1], counter,
				max_ops, name, sz, page_size);
			(void)close(pipefds[1]);
			_exit(rc);
		}
	}
	if (orig_sz != sz)
		pr_dbg(stderr, "%s: reduced shared memory size from "
			"%zu to %zu bytes\n", name, orig_sz, sz);
	if (restarts) {
		pr_dbg(stderr, "%s: OOM restarts: %" PRIu32 "\n",
			name, restarts);
	}
	return rc;
}
Exemplo n.º 16
0
/*
 *  stress_mlock()
 *	stress mlock with pages being locked/unlocked
 */
int stress_mlock(
	uint64_t *const counter,
	const uint32_t instance,
	const uint64_t max_ops,
	const char *name)
{
	const size_t page_size = stress_get_pagesize();
	pid_t pid;
	size_t max = sysconf(_SC_MAPPED_FILES);
	max = max > MLOCK_MAX ? MLOCK_MAX : max;

again:
	pid = fork();
	if (pid < 0) {
		if (opt_do_run && (errno == EAGAIN))
			goto again;
		pr_err(stderr, "%s: fork failed: errno=%d: (%s)\n",
			name, errno, strerror(errno));
	} else if (pid > 0) {
		int status, ret;

		setpgid(pid, pgrp);
		stress_parent_died_alarm();

		/* Parent, wait for child */
		ret = waitpid(pid, &status, 0);
		if (ret < 0) {
			if (errno != EINTR)
				pr_dbg(stderr, "%s: waitpid(): errno=%d (%s)\n",
					name, errno, strerror(errno));
			(void)kill(pid, SIGTERM);
			(void)kill(pid, SIGKILL);
			(void)waitpid(pid, &status, 0);
		} else if (WIFSIGNALED(status)) {
			pr_dbg(stderr, "%s: child died: %s (instance %d)\n",
				name, stress_strsignal(WTERMSIG(status)),
				instance);
			/* If we got killed by OOM killer, re-start */
			if (WTERMSIG(status) == SIGKILL) {
				pr_dbg(stderr, "%s: assuming killed by OOM "
					"killer, restarting again "
					"(instance %d)\n", name, instance);
				goto again;
			}
		}
	} else if (pid == 0) {
		uint8_t *mappings[max];
		size_t i, n;

		setpgid(0, pgrp);

		/* Make sure this is killable by OOM killer */
		set_oom_adjustment(name, true);

		do {
			for (n = 0; opt_do_run && (n < max); n++) {
				int ret;
				if (!opt_do_run || (max_ops && *counter >= max_ops))
					break;

				mappings[n] = mmap(NULL, page_size * 3,
					PROT_READ | PROT_WRITE,
					MAP_SHARED | MAP_ANONYMOUS, -1, 0);
				if (mappings[n] == MAP_FAILED)
					break;
				ret = mlock_shim(mappings[n] + page_size, page_size);
				if (ret < 0) {
					if (errno == EAGAIN)
						continue;
					if (errno == ENOMEM)
						break;
					pr_fail_err(name, "mlock");
					break;
				} else {
					/*
					 * Mappings are always page aligned so
					 * we can use the bottom bit to
					 * indicate if the page has been
					 * mlocked or not
				 	 */
					mappings[n] = (uint8_t *)
						((ptrdiff_t)mappings[n] | 1);
					(*counter)++;
				}
			}

			for (i = 0; i < n;  i++) {
				ptrdiff_t addr = (ptrdiff_t)mappings[i];
				ptrdiff_t mlocked = addr & 1;

				addr ^= mlocked;
				if (mlocked)
					(void)munlock((uint8_t *)addr + page_size, page_size);
				munmap((void *)addr, page_size * 3);
			}
#if !defined(__gnu_hurd__)
			(void)mlockall(MCL_CURRENT);
			(void)mlockall(MCL_FUTURE);
#if defined(MCL_ONFAULT)
			(void)mlockall(MCL_ONFAULT);
#endif
#endif
			for (n = 0; opt_do_run && (n < max); n++) {
				if (!opt_do_run || (max_ops && *counter >= max_ops))
					break;

				mappings[n] = mmap(NULL, page_size,
					PROT_READ | PROT_WRITE,
					MAP_SHARED | MAP_ANONYMOUS, -1, 0);
				if (mappings[n] == MAP_FAILED)
					break;
			}
#if !defined(__gnu_hurd__)
			(void)munlockall();
#endif
			for (i = 0; i < n;  i++)
				munmap(mappings[i], page_size);
		} while (opt_do_run && (!max_ops || *counter < max_ops));
	}

	return EXIT_SUCCESS;
}
Exemplo n.º 17
0
/*
 *  stress_mremap()
 *	stress mmap
 */
static int stress_mremap(const args_t *args)
{
	const size_t page_size = args->page_size;
	size_t sz, new_sz;
	int rc = EXIT_SUCCESS, flags = MAP_PRIVATE | MAP_ANONYMOUS;
	pid_t pid;
	uint32_t ooms = 0, segvs = 0, buserrs = 0;
	size_t mremap_bytes = DEFAULT_MREMAP_BYTES;

#if defined(MAP_POPULATE)
	flags |= MAP_POPULATE;
#endif
	if (!get_setting("mremap-bytes", &mremap_bytes)) {
		if (g_opt_flags & OPT_FLAGS_MAXIMIZE)
			mremap_bytes = MAX_MREMAP_BYTES;
		if (g_opt_flags & OPT_FLAGS_MINIMIZE)
			mremap_bytes = MIN_MREMAP_BYTES;
	}
	mremap_bytes /= args->num_instances;
	if (mremap_bytes < MIN_MREMAP_BYTES)
		mremap_bytes = MIN_MREMAP_BYTES;
	if (mremap_bytes < page_size)
		mremap_bytes= page_size;
	new_sz = sz = mremap_bytes & ~(page_size - 1);

	/* Make sure this is killable by OOM killer */
	set_oom_adjustment(args->name, true);

again:
	if (!g_keep_stressing_flag)
		return EXIT_SUCCESS;
	pid = fork();
	if (pid < 0) {
		if ((errno == EAGAIN) || (errno == ENOMEM))
			goto again;
		pr_err("%s: fork failed: errno=%d: (%s)\n",
			args->name, errno, strerror(errno));
	} else if (pid > 0) {
		int status, ret;

		(void)setpgid(pid, g_pgrp);
		/* Parent, wait for child */
		ret = shim_waitpid(pid, &status, 0);
		if (ret < 0) {
			if (errno != EINTR)
				pr_dbg("%s: waitpid(): errno=%d (%s)\n",
					args->name, errno, strerror(errno));
			(void)kill(pid, SIGTERM);
			(void)kill(pid, SIGKILL);
			(void)shim_waitpid(pid, &status, 0);
		} else if (WIFSIGNALED(status)) {
			/* If we got killed by sigbus, re-start */
			if (WTERMSIG(status) == SIGBUS) {
				/* Happens frequently, so be silent */
				buserrs++;
				goto again;
			}

			pr_dbg("%s: child died: %s (instance %d)\n",
				args->name, stress_strsignal(WTERMSIG(status)),
				args->instance);
			/* If we got killed by OOM killer, re-start */
			if (WTERMSIG(status) == SIGKILL) {
				if (g_opt_flags & OPT_FLAGS_OOMABLE) {
					log_system_mem_info();
					pr_dbg("%s: assuming killed by OOM "
						"killer, bailing out "
						"(instance %d)\n",
						args->name, args->instance);
					_exit(0);
				} else {
					log_system_mem_info();
					pr_dbg("%s: assuming killed by OOM "
						"killer, restarting again "
						"(instance %d)\n",
						args->name, args->instance);
					ooms++;
				}
				goto again;
			}
			/* If we got killed by sigsegv, re-start */
			if (WTERMSIG(status) == SIGSEGV) {
				pr_dbg("%s: killed by SIGSEGV, "
					"restarting again "
					"(instance %d)\n",
					args->name, args->instance);
				segvs++;
				goto again;
			}
		} else {
			rc = WEXITSTATUS(status);
		}
	} else if (pid == 0) {
		(void)setpgid(0, g_pgrp);
		stress_parent_died_alarm();

		/* Make sure this is killable by OOM killer */
		set_oom_adjustment(args->name, true);

		rc = stress_mremap_child(args, sz,
			new_sz, page_size, mremap_bytes, &flags);
		_exit(rc);
	}

	if (ooms + segvs + buserrs > 0)
		pr_dbg("%s: OOM restarts: %" PRIu32
			", SEGV restarts: %" PRIu32
			", SIGBUS signals: %" PRIu32 "\n",
			args->name, ooms, segvs, buserrs);

	return rc;
}
Exemplo n.º 18
0
/*
 *  stress_vforkmany()
 *	stress by vfork'ing as many processes as possible.
 *	vfork has interesting semantics, the parent blocks
 *	until the child has exited, plus child processes
 *	share the same address space. So we need to be
 *	careful not to overrite shared variables across
 *	all the processes.
 */
static int stress_vforkmany(const args_t *args)
{
	static int status;
	static pid_t chpid;
	static volatile int instance = 0;
	static uint8_t stack_sig[SIGSTKSZ + SIGSTKSZ];
	static volatile bool *terminate;
	static bool *terminate_mmap;

	/* We should use an alterative signal stack */
	(void)memset(stack_sig, 0, sizeof(stack_sig));
	if (stress_sigaltstack(stack_sig, SIGSTKSZ) < 0)
		return EXIT_FAILURE;

	terminate = terminate_mmap =
		(bool *)mmap(NULL, args->page_size,
				PROT_READ | PROT_WRITE,
				MAP_SHARED | MAP_ANONYMOUS, -1, 0);
	if (terminate_mmap == MAP_FAILED) {
		pr_inf("%s: mmap failed: %d (%s)\n",
			args->name, errno, strerror(errno));
		return EXIT_NO_RESOURCE;
	}
	*terminate = false;

fork_again:
	if (!g_keep_stressing_flag)
		goto tidy;
	chpid = fork();
	if (chpid < 0) {
		if (errno == EAGAIN)
			goto fork_again;
		pr_err("%s: fork failed: errno=%d: (%s)\n",
			args->name, errno, strerror(errno));
		munmap((void *)terminate_mmap, args->page_size);
		return EXIT_FAILURE;
	} else if (chpid == 0) {
		static uint8_t *waste;
		static size_t waste_size = WASTE_SIZE;

		(void)setpgid(0, g_pgrp);

		/*
		 *  We want the children to be OOM'd if we
		 *  eat up too much memory
		 */
		set_oom_adjustment(args->name, true);
		stress_parent_died_alarm();

		/*
		 *  Allocate some wasted space so this child
		 *  scores more on the OOMable score than the
		 *  parent waiter so in theory it should be
		 *  OOM'd before the parent.
		 */
		do {
			waste = (uint8_t *)mmap(NULL, waste_size, PROT_READ | PROT_WRITE,
					MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
			if (waste != MAP_FAILED)
				break;

			waste_size >>= 1;
		} while (waste_size > 4096);

		if (waste != MAP_FAILED)
			(void)memset(waste, 0, WASTE_SIZE);
		do {
			/*
			 *  Force pid to be a register, if it's
			 *  stashed on the stack or as a global
			 *  then waitpid will pick up the one
			 *  shared by all the vfork children
			 *  which is problematic on the wait
			 */
			register pid_t pid;
			register bool first = (instance == 0);

vfork_again:
			/*
			 * SIGALRM is not inherited over vfork so
			 * instead poll the run time and break out
			 * of the loop if we've run out of run time
			 */
			if (*terminate) {
				g_keep_stressing_flag = false;
				break;
			}
			inc_counter(args);
			instance++;
			if (first) {
				pid = fork();
			} else {
PRAGMA_PUSH
PRAGMA_WARN_OFF
#if defined(__NR_vfork)
				pid = (pid_t)syscall(__NR_vfork);
#else
				pid = vfork();
#endif
PRAGMA_POP
			}

			if (pid < 0) {
				/* failed, only exit of not the top parent */
				if (!first)
					_exit(0);
			} else if (pid == 0) {
				if (waste != MAP_FAILED) {
					register size_t i;

					for (i = 0; i < WASTE_SIZE; i += 4096)
						waste[i] = 0;
				}

				/* child, parent is blocked, spawn new child */
				if (!args->max_ops || get_counter(args) < args->max_ops)
					goto vfork_again;
				_exit(0);
			}
			/* parent, wait for child, and exit if not top parent */
			(void)shim_waitpid(pid, &status, 0);
			if (!first)
				_exit(0);
		} while (keep_stressing());

		if (waste != MAP_FAILED)
			munmap((void *)waste, WASTE_SIZE);
		_exit(0);
	} else {
Exemplo n.º 19
0
/*
 *  stress_switch
 *	stress by heavy context switching
 */
int stress_switch(
	uint64_t *const counter,
	const uint32_t instance,
	const uint64_t max_ops,
	const char *name)
{
	pid_t pid;
	int pipefds[2];
	size_t buf_size;

	(void)instance;

#if defined(__linux__) && NEED_GLIBC(2,9,0)
	if (pipe2(pipefds, O_DIRECT) < 0) {
		pr_fail_dbg(name, "pipe2");
		return EXIT_FAILURE;
	}
	buf_size = 1;
#else
	if (pipe(pipefds) < 0) {
		pr_fail_dbg(name, "pipe");
		return EXIT_FAILURE;
	}
	buf_size = stress_get_pagesize();
#endif

#if defined(F_SETPIPE_SZ)
	if (fcntl(pipefds[0], F_SETPIPE_SZ, buf_size) < 0) {
		pr_dbg(stderr, "%s: could not force pipe size to 1 page, "
			"errno = %d (%s)\n",
			name, errno, strerror(errno));
	}
	if (fcntl(pipefds[1], F_SETPIPE_SZ, buf_size) < 0) {
		pr_dbg(stderr, "%s: could not force pipe size to 1 page, "
			"errno = %d (%s)\n",
			name, errno, strerror(errno));
	}
#endif

again:
	pid = fork();
	if (pid < 0) {
		if (opt_do_run && (errno == EAGAIN))
			goto again;
		(void)close(pipefds[0]);
		(void)close(pipefds[1]);
		pr_fail_dbg(name, "fork");
		return EXIT_FAILURE;
	} else if (pid == 0) {
		char buf[buf_size];

		setpgid(0, pgrp);
		stress_parent_died_alarm();

		(void)close(pipefds[1]);

		while (opt_do_run) {
			ssize_t ret;

			ret = read(pipefds[0], buf, sizeof(buf));
			if (ret < 0) {
				if ((errno == EAGAIN) || (errno == EINTR))
					continue;
				pr_fail_dbg(name, "read");
				break;
			}
			if (ret == 0)
				break;
			if (*buf == SWITCH_STOP)
				break;
		}
		(void)close(pipefds[0]);
		exit(EXIT_SUCCESS);
	} else {
		char buf[buf_size];
		int status;

		/* Parent */
		setpgid(pid, pgrp);
		(void)close(pipefds[0]);

		memset(buf, '_', buf_size);

		do {
			ssize_t ret;

			ret = write(pipefds[1], buf, sizeof(buf));
			if (ret <= 0) {
				if ((errno == EAGAIN) || (errno == EINTR))
					continue;
				if (errno) {
					pr_fail_dbg(name, "write");
					break;
				}
				continue;
			}
			(*counter)++;
		} while (opt_do_run && (!max_ops || *counter < max_ops));

		memset(buf, SWITCH_STOP, sizeof(buf));
		if (write(pipefds[1], buf, sizeof(buf)) <= 0)
			pr_fail_dbg(name, "termination write");
		(void)kill(pid, SIGKILL);
		(void)waitpid(pid, &status, 0);
	}

	return EXIT_SUCCESS;
}
Exemplo n.º 20
0
/*
 *  stress_sigq
 *	stress by heavy sigqueue message sending
 */
int stress_sigq(
	uint64_t *const counter,
	const uint32_t instance,
	const uint64_t max_ops,
	const char *name)
{
	pid_t pid;

	if (stress_sighandler(name, SIGUSR1, stress_sigqhandler, NULL) < 0)
		return EXIT_FAILURE;

again:
	pid = fork();
	if (pid < 0) {
		if (opt_do_run && (errno == EAGAIN))
			goto again;
		pr_fail_dbg(name, "fork");
		return EXIT_FAILURE;
	} else if (pid == 0) {
		sigset_t mask;

		setpgid(0, pgrp);
		stress_parent_died_alarm();

		sigemptyset(&mask);
		sigaddset(&mask, SIGUSR1);

		while (opt_do_run) {
			siginfo_t info;
			sigwaitinfo(&mask, &info);
			if (info.si_value.sival_int)
				break;
		}
		pr_dbg(stderr, "%s: child got termination notice\n", name);
		pr_dbg(stderr, "%s: exited on pid [%d] (instance %" PRIu32 ")\n",
			name, getpid(), instance);
		_exit(0);
	} else {
		/* Parent */
		union sigval s;
		int status;

		do {
			memset(&s, 0, sizeof(s));
			s.sival_int = 0;
			sigqueue(pid, SIGUSR1, s);
			(*counter)++;
		} while (opt_do_run && (!max_ops || *counter < max_ops));

		pr_dbg(stderr, "%s: parent sent termination notice\n", name);
		memset(&s, 0, sizeof(s));
		s.sival_int = 1;
		sigqueue(pid, SIGUSR1, s);
		usleep(250);
		/* And ensure child is really dead */
		(void)kill(pid, SIGKILL);
		(void)waitpid(pid, &status, 0);
	}

	return EXIT_SUCCESS;
}
Exemplo n.º 21
0
/*
 *  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_fail_err(name, "open");
		return EXIT_FAILURE;
	}

again:
	pid1 = fork();
	if (pid1 < 0) {
		if (opt_do_run && (errno == EAGAIN))
			goto again;

		pr_fail_dbg(name, "fork");
		(void)close(fd1);
		return EXIT_FAILURE;
	} else if (pid1 == 0) {
		setpgid(0, pgrp);
		stress_parent_died_alarm();

		/* 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_fail_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;
}
Exemplo n.º 22
0
/*
 *  stress_bigheap()
 *	stress heap allocation
 */
int stress_bigheap(
	uint64_t *const counter,
	const uint32_t instance,
	const uint64_t max_ops,
	const char *name)
{
	void *ptr = NULL, *last_ptr = NULL;
	uint8_t *last_ptr_end = NULL;
	size_t size = 0;
	const size_t stride = stress_get_pagesize();
	pid_t pid;
	uint32_t restarts = 0, nomems = 0;
	const size_t page_size = stress_get_pagesize();

	if (!set_bigheap_growth) {
		if (opt_flags & OPT_FLAGS_MAXIMIZE)
			opt_bigheap_growth = MAX_BIGHEAP_GROWTH;
		if (opt_flags & OPT_FLAGS_MINIMIZE)
			opt_bigheap_growth = MIN_BIGHEAP_GROWTH;
	}
again:
	if (!opt_do_run)
		return EXIT_SUCCESS;
	pid = fork();
	if (pid < 0) {
		if (errno == EAGAIN)
			goto again;
		pr_err(stderr, "%s: fork failed: errno=%d: (%s)\n",
			name, errno, strerror(errno));
	} else if (pid > 0) {
		int status, ret;

		setpgid(pid, pgrp);
		/* Parent, wait for child */
		ret = waitpid(pid, &status, 0);
		if (ret < 0) {
			if (errno != EINTR)
				pr_dbg(stderr, "%s: waitpid(): errno=%d (%s)\n",
					name, errno, strerror(errno));
			(void)kill(pid, SIGTERM);
			(void)kill(pid, SIGKILL);
			(void)waitpid(pid, &status, 0);
		} else if (WIFSIGNALED(status)) {
			pr_dbg(stderr, "%s: child died: %s (instance %d)\n",
				name, stress_strsignal(WTERMSIG(status)),
				instance);
			/* If we got killed by OOM killer, re-start */
			if (WTERMSIG(status) == SIGKILL) {
				pr_dbg(stderr, "%s: assuming killed by OOM "
					"killer, restarting again "
					"(instance %d)\n",
					name, instance);
				restarts++;
				goto again;
			}
		}
	} else if (pid == 0) {
		setpgid(0, pgrp);
		stress_parent_died_alarm();

		/* Make sure this is killable by OOM killer */
		set_oom_adjustment(name, true);

		do {
			void *old_ptr = ptr;
			size += (size_t)opt_bigheap_growth;

			/*
			 * With many instances running it is wise to
			 * double check before the next realloc as
			 * sometimes process start up is delayed for
			 * some time and we should bail out before
			 * exerting any more memory pressure
			 */
			if (!opt_do_run)
				goto abort;

			ptr = realloc(old_ptr, size);
			if (ptr == NULL) {
				pr_dbg(stderr, "%s: out of memory at %" PRIu64
					" MB (instance %d)\n",
					name, (uint64_t)(4096ULL * size) >> 20,
					instance);
				free(old_ptr);
				size = 0;
				nomems++;
			} else {
				size_t i, n;
				uint8_t *u8ptr, *tmp;

				if (last_ptr == ptr) {
					tmp = u8ptr = last_ptr_end;
					n = (size_t)opt_bigheap_growth;
				} else {
					tmp = u8ptr = ptr;
					n = size;
				}

				if (page_size > 0) {
					size_t sz = page_size - 1;
					uintptr_t pg_ptr = ((uintptr_t)ptr + sz) & ~sz;
					size_t len = size - (pg_ptr - (uintptr_t)ptr);
					(void)mincore_touch_pages((void *)pg_ptr, len);
				}

				for (i = 0; i < n; i+= stride, u8ptr += stride) {
					if (!opt_do_run)
						goto abort;
					*u8ptr = (uint8_t)i;
				}

				if (opt_flags & OPT_FLAGS_VERIFY) {
					for (i = 0; i < n; i+= stride, tmp += stride) {
						if (!opt_do_run)
							goto abort;
						if (*tmp != (uint8_t)i)
							pr_fail(stderr, "%s: byte at location %p was 0x%" PRIx8
								" instead of 0x%" PRIx8 "\n",
								name, u8ptr, *tmp, (uint8_t)i);
					}
				}

				last_ptr = ptr;
				last_ptr_end = u8ptr;

			}
			(*counter)++;
		} while (opt_do_run && (!max_ops || *counter < max_ops));
Exemplo n.º 23
0
/*
 *  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;
}
Exemplo n.º 24
0
/*
 *  stress_userfaultfd()
 *	stress userfaultfd
 */
static int stress_userfaultfd(const args_t *args)
{
	pid_t pid;
	int rc = EXIT_FAILURE;
	size_t userfaultfd_bytes = DEFAULT_MMAP_BYTES;

	if (!get_setting("userfaultfd-bytes", &userfaultfd_bytes)) {
		if (g_opt_flags & OPT_FLAGS_MAXIMIZE)
			userfaultfd_bytes = MAX_MMAP_BYTES;
		if (g_opt_flags & OPT_FLAGS_MINIMIZE)
			userfaultfd_bytes = MIN_MMAP_BYTES;
	}
	userfaultfd_bytes /= args->num_instances;
	if (userfaultfd_bytes < MIN_MMAP_BYTES)
		userfaultfd_bytes = MIN_MMAP_BYTES;
	if (userfaultfd_bytes < args->page_size)
		userfaultfd_bytes = args->page_size;

	pid = fork();
	if (pid < 0) {
		if (errno == EAGAIN)
			return EXIT_NO_RESOURCE;
		pr_err("%s: fork failed: errno=%d: (%s)\n",
			args->name, errno, strerror(errno));
	} else if (pid > 0) {
		/* Parent */
		int status, ret;

		(void)setpgid(pid, g_pgrp);
		ret = shim_waitpid(pid, &status, 0);
		if (ret < 0) {
			if (errno != EINTR)
				pr_dbg("%s: waitpid(): errno=%d (%s)\n",
					args->name, errno, strerror(errno));
			(void)kill(pid, SIGTERM);
			(void)kill(pid, SIGKILL);
			(void)shim_waitpid(pid, &status, 0);
		} else if (WIFSIGNALED(status)) {
			pr_dbg("%s: child died: %s (instance %d)\n",
				args->name, stress_strsignal(WTERMSIG(status)),
				args->instance);
			/* If we got killed by OOM killer, report this */
			if (WTERMSIG(status) == SIGKILL) {
				log_system_mem_info();
				pr_dbg("%s: assuming killed by OOM "
					"killer, aborting "
					"(instance %d)\n",
					args->name, args->instance);
				return EXIT_NO_RESOURCE;
			}
			return EXIT_FAILURE;
		}
		rc = WEXITSTATUS(status);
	} else if (pid == 0) {
		/* Child */
		(void)setpgid(0, g_pgrp);
		stress_parent_died_alarm();

		_exit(stress_userfaultfd_oomable(args, userfaultfd_bytes));
	}
	return rc;
}
Exemplo n.º 25
0
/*
 *  stress_tlb_shootdown()
 *	stress out TLB shootdowns
 */
static int stress_tlb_shootdown(const args_t *args)
{
	const size_t page_size = args->page_size;
	const size_t mmap_size = page_size * MMAP_PAGES;
	pid_t pids[MAX_TLB_PROCS];
	cpu_set_t proc_mask_initial;

	if (sched_getaffinity(0, sizeof(proc_mask_initial), &proc_mask_initial) < 0) {
		pr_fail_err("could not get CPU affinity");
		return EXIT_FAILURE;
	}

	do {
		uint8_t *mem, *ptr;
		int retry = 128;
		cpu_set_t proc_mask;
		int32_t tlb_procs, i;
		const int32_t max_cpus = stress_get_processors_configured();

		CPU_ZERO(&proc_mask);
		CPU_OR(&proc_mask, &proc_mask_initial, &proc_mask);

		tlb_procs = max_cpus;
		if (tlb_procs > MAX_TLB_PROCS)
			tlb_procs = MAX_TLB_PROCS;
		if (tlb_procs < MIN_TLB_PROCS)
			tlb_procs = MIN_TLB_PROCS;

		for (;;) {
			mem = mmap(NULL, mmap_size, PROT_WRITE | PROT_READ,
				MAP_SHARED | MAP_ANONYMOUS, -1, 0);
			if ((void *)mem == MAP_FAILED) {
				if ((errno == EAGAIN) ||
				    (errno == ENOMEM) ||
				    (errno == ENFILE)) {
					if (--retry < 0)
						return EXIT_NO_RESOURCE;
				} else {
					pr_fail_err("mmap");
				}
			} else {
				break;
			}
		}
		(void)memset(mem, 0, mmap_size);

		for (i = 0; i < tlb_procs; i++)
			pids[i] = -1;

		for (i = 0; i < tlb_procs; i++) {
			int32_t j, cpu = -1;

			for (j = 0; j < max_cpus; j++) {
				if (CPU_ISSET(j, &proc_mask)) {
					cpu = j;
					CPU_CLR(j, &proc_mask);
					break;
				}
			}
			if (cpu == -1)
				break;

			pids[i] = fork();
			if (pids[i] < 0)
				break;
			if (pids[i] == 0) {
				cpu_set_t mask;
				char buffer[page_size];

				(void)setpgid(0, g_pgrp);
				stress_parent_died_alarm();

				/* Make sure this is killable by OOM killer */
				set_oom_adjustment(args->name, true);

				CPU_ZERO(&mask);
				CPU_SET(cpu % max_cpus, &mask);
				(void)sched_setaffinity(args->pid, sizeof(mask), &mask);

				for (ptr = mem; ptr < mem + mmap_size; ptr += page_size) {
					/* Force tlb shoot down on page */
					(void)mprotect(ptr, page_size, PROT_READ);
					(void)memcpy(buffer, ptr, page_size);
					(void)munmap(ptr, page_size);
				}
				_exit(0);
			}
		}

		for (i = 0; i < tlb_procs; i++) {
			if (pids[i] != -1) {
				int status, ret;

				ret = shim_waitpid(pids[i], &status, 0);
				if ((ret < 0) && (errno == EINTR)) {
					int j;

					/*
					 * We got interrupted, so assume
					 * it was the alarm (timedout) or
					 * SIGINT so force terminate
					 */
					for (j = i; j < tlb_procs; j++) {
						if (pids[j] != -1)
							(void)kill(pids[j], SIGKILL);
					}

					/* re-wait on the failed wait */
					(void)shim_waitpid(pids[i], &status, 0);

					/* and continue waitpid on the pids */
				}
			}
		}
		(void)munmap(mem, mmap_size);
		(void)sched_setaffinity(0, sizeof(proc_mask_initial), &proc_mask_initial);
		inc_counter(args);
	} while (keep_stressing());

	return EXIT_SUCCESS;
}
Exemplo n.º 26
0
/*
 *  stress_socket_client()
 *	client reader
 */
static void stress_socket_client(
	uint64_t *const counter,
	const uint32_t instance,
	const uint64_t max_ops,
	const char *name,
	const pid_t ppid)
{
	struct sockaddr *addr;

	setpgid(0, pgrp);
	stress_parent_died_alarm();

	do {
		char buf[SOCKET_BUF];
		int fd;
		int retries = 0;
		socklen_t addr_len = 0;
retry:
		if (!opt_do_run) {
			(void)kill(getppid(), SIGALRM);
			exit(EXIT_FAILURE);
		}
		if ((fd = socket(opt_socket_domain, SOCK_STREAM, 0)) < 0) {
			pr_fail_dbg(name, "socket");
			/* failed, kick parent to finish */
			(void)kill(getppid(), SIGALRM);
			exit(EXIT_FAILURE);
		}

		stress_set_sockaddr(name, instance, ppid,
			opt_socket_domain, opt_socket_port,
			&addr, &addr_len);
		if (connect(fd, addr, addr_len) < 0) {
			(void)close(fd);
			usleep(10000);
			retries++;
			if (retries > 100) {
				/* Give up.. */
				pr_fail_dbg(name, "connect");
				(void)kill(getppid(), SIGALRM);
				exit(EXIT_FAILURE);
			}
			goto retry;
		}

		do {
			ssize_t n = recv(fd, buf, sizeof(buf), 0);
			if (n == 0)
				break;
			if (n < 0) {
				if (errno != EINTR)
					pr_fail_dbg(name, "recv");
				break;
			}
		} while (opt_do_run && (!max_ops || *counter < max_ops));
		(void)shutdown(fd, SHUT_RDWR);
		(void)close(fd);
	} while (opt_do_run && (!max_ops || *counter < max_ops));

#ifdef AF_UNIX
	if (opt_socket_domain == AF_UNIX) {
		struct sockaddr_un *addr_un = (struct sockaddr_un *)addr;
		(void)unlink(addr_un->sun_path);
	}
#endif
	/* Inform parent we're all done */
	(void)kill(getppid(), SIGALRM);
}