tools/testing/selftests/namespaces/stress_test.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/namespaces/stress_test.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/namespaces/stress_test.c
Extension
.c
Size
14778 bytes
Lines
627
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 (pid == 0) {
			/* Child: create user namespace and immediately exit */
			if (setup_userns() < 0)
				exit(1);
			exit(0);
		}

		/* Parent: wait for child */
		int status;
		waitpid(pid, &status, 0);
		ASSERT_TRUE(WIFEXITED(status));
		ASSERT_EQ(WEXITSTATUS(status), 0);
	}

	/* Verify we're back to baseline (no leaked namespaces) */
	ret_after = sys_listns(&req, ns_ids_after, ARRAY_SIZE(ns_ids_after), 0);
	ASSERT_GE(ret_after, 0);

	TH_LOG("After 100 rapid create/destroy cycles: %zd active user namespaces", ret_after);
	ASSERT_EQ(ret_before, ret_after);
}

/*
 * Test creating many concurrent namespaces.
 * Verify that listns() correctly tracks all of them and that they all
 * become inactive after processes exit.
 */
TEST(many_concurrent_namespaces)
{
	struct ns_id_req req = {
		.size = sizeof(req),
		.spare = 0,
		.ns_id = 0,
		.ns_type = CLONE_NEWUSER,
		.spare2 = 0,
		.user_ns_id = 0,
	};
	__u64 ns_ids_before[512], ns_ids_during[512], ns_ids_after[512];
	ssize_t ret_before, ret_during, ret_after;
	pid_t pids[50];
	int num_children = 50;
	int i;
	int sv[2];

	/* Get baseline */
	ret_before = sys_listns(&req, ns_ids_before, ARRAY_SIZE(ns_ids_before), 0);
	if (ret_before < 0) {
		if (errno == ENOSYS)
			SKIP(return, "listns() not supported");
		ASSERT_GE(ret_before, 0);
	}

	TH_LOG("Baseline: %zd active user namespaces", ret_before);

	ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), 0);

	/* Create many children, each with their own user namespace */
	for (i = 0; i < num_children; i++) {
		pids[i] = fork();
		ASSERT_GE(pids[i], 0);

		if (pids[i] == 0) {
			/* Child: create user namespace and wait for parent signal */
			char c;

			close(sv[0]);

			if (setup_userns() < 0) {
				close(sv[1]);
				exit(1);
			}

			/* Signal parent we're ready */
			if (write(sv[1], &c, 1) != 1) {
				close(sv[1]);
				exit(1);
			}

			/* Wait for parent signal to exit */
			if (read(sv[1], &c, 1) != 1) {
				close(sv[1]);
				exit(1);
			}

			close(sv[1]);
			exit(0);
		}
	}

	close(sv[1]);

Annotation

Implementation Notes