tools/testing/selftests/mm/mrelease_test.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/mm/mrelease_test.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/mm/mrelease_test.c
Extension
.c
Size
4547 bytes
Lines
185
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

if (errno == ENOSYS) {
			ksft_test_result_skip("process_mrelease not implemented\n");
			ksft_finished();
		} else {
			ksft_exit_fail_msg("process_mrelease with wrong pidfd: %s",
					   strerror(errno));
		}
	}

	/* Start the test with 1MB child memory allocation */
	size = 1;
retry:
	/*
	 * Pipe for the child to signal when it's done allocating
	 * memory
	 */
	if (pipe(pipefd))
		ksft_exit_fail_msg("pipe: %s\n", strerror(errno));

	pid = fork();
	if (pid < 0) {
		close(pipefd[0]);
		close(pipefd[1]);
		ksft_exit_fail_msg("fork: %s\n", strerror(errno));
	}

	if (pid == 0) {
		/* Child main routine */
		res = child_main(pipefd, size);
		exit(res);
	}

	/*
	 * Parent main routine:
	 * Wait for the child to finish allocations, then kill and reap
	 */
	close(pipefd[1]);
	/* Block until the child is ready */
	res = read(pipefd[0], &byte, 1);
	close(pipefd[0]);
	if (res < 0) {
		if (!kill(pid, SIGKILL))
			waitpid(pid, NULL, 0);
		ksft_exit_fail_msg("read: %s\n", strerror(errno));
	}

	pidfd = syscall(__NR_pidfd_open, pid, 0);
	if (pidfd < 0) {
		if (!kill(pid, SIGKILL))
			waitpid(pid, NULL, 0);
		ksft_exit_fail_msg("pidfd_open: %s\n", strerror(errno));
	}

	/* Run negative tests which require a live child */
	run_negative_tests(pidfd);

	if (kill(pid, SIGKILL))
		ksft_exit_fail_msg("kill: %s\n", strerror(errno));

	success = (syscall(__NR_process_mrelease, pidfd, 0) == 0);
	if (!success) {
		/*
		 * If we failed to reap because the child exited too soon,
		 * before we could call process_mrelease. Double child's memory
		 * which causes it to spend more time on cleanup and increases
		 * our chances of reaping its memory before it exits.
		 * Retry until we succeed or reach MAX_SIZE_MB.
		 */
		if (errno == ESRCH) {
			retry = (size <= MAX_SIZE_MB);
		} else {
			waitpid(pid, NULL, 0);
			ksft_exit_fail_msg("process_mrelease: %s\n", strerror(errno));
		}
	}

	/* Cleanup to prevent zombies */
	if (waitpid(pid, NULL, 0) < 0)
		ksft_exit_fail_msg("waitpid: %s\n", strerror(errno));

	close(pidfd);

	if (!success) {
		if (retry) {
			size *= 2;
			goto retry;
		}
		ksft_exit_fail_msg("All process_mrelease attempts failed!\n");
	}

Annotation

Implementation Notes