tools/testing/selftests/namespaces/listns_efault_test.c

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

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/namespaces/listns_efault_test.c
Extension
.c
Size
13245 bytes
Lines
551
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

while (1) {
			iter_ret = sys_listns(&req, ns_ids, 2, 0);

			if (iter_ret == -1 && errno == ENOSYS)
				_exit(PIDFD_SKIP);
		}
	}

	/* Small delay to let iterator start looping */
	usleep(50000);

	/*
	 * Create several child processes, each in its own mount namespace.
	 * These will be destroyed while the iterator is running listns().
	 */
	for (i = 0; i < 5; i++) {
		/* Create socketpair for synchronization */
		ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sv[i]), 0);

		pid = create_child(&pidfds[i], CLONE_NEWNS);
		ASSERT_NE(pid, -1);
		ns_pids[i] = pid;

		if (pid == 0) {
			close(sv[i][0]); /* Close parent end */

			if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0))
				_exit(1);

			/* Child: create a couple of tmpfs mounts */
			if (mkdir("/tmp/test_mnt1", 0755) == -1 && errno != EEXIST)
				_exit(1);
			if (mkdir("/tmp/test_mnt2", 0755) == -1 && errno != EEXIST)
				_exit(1);

			if (mount("tmpfs", "/tmp/test_mnt1", "tmpfs", 0, NULL) == -1)
				_exit(1);
			if (mount("tmpfs", "/tmp/test_mnt2", "tmpfs", 0, NULL) == -1)
				_exit(1);

			/* Signal parent that setup is complete */
			if (write_nointr(sv[i][1], "R", 1) != 1)
				_exit(1);

			/* Wait for parent to signal us to exit */
			if (read_nointr(sv[i][1], &c, 1) != 1)
				_exit(1);

			close(sv[i][1]);
			_exit(0);
		}

		close(sv[i][1]); /* Close child end */
	}

	/* Wait for all children to finish setup */
	for (i = 0; i < 5; i++) {
		ret = read_nointr(sv[i][0], &c, 1);
		ASSERT_EQ(ret, 1);
		ASSERT_EQ(c, 'R');
	}

	/*
	 * Signal children to exit. This will destroy their mount namespaces
	 * while listns() is iterating the namespace tree.
	 * This tests that cleanup happens outside the RCU read lock.
	 */
	for (i = 0; i < 5; i++)
		write_nointr(sv[i][0], "X", 1);

	/* Wait for all mount namespace children to exit and cleanup */
	for (i = 0; i < 5; i++) {
		waitpid(ns_pids[i], NULL, 0);
		close(sv[i][0]);
		close(pidfds[i]);
	}

	/* Kill iterator and wait for it */
	sys_pidfd_send_signal(iter_pidfd, SIGKILL, NULL, 0);
	ret = waitpid(iter_pid, &status, 0);
	ASSERT_EQ(ret, iter_pid);
	close(iter_pidfd);

	/* If listns() is not supported the iterator exits cleanly via ENOSYS */
	if (WIFEXITED(status) && WEXITSTATUS(status) == PIDFD_SKIP) {
		munmap(map, page_size);
		SKIP(return, "listns() not supported");
	}

	/* Should have been killed */

Annotation

Implementation Notes