tools/testing/selftests/bpf/prog_tests/cgroup_hierarchical_stats.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/bpf/prog_tests/cgroup_hierarchical_stats.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/bpf/prog_tests/cgroup_hierarchical_stats.c
Extension
.c
Size
9168 bytes
Lines
340
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) {
				if (join_parent_cgroup(cgroups[i].path))
					exit(EACCES);
				exit(0);
			}

			/* Cleanup child */
			waitpid(pid, &status, 0);
			if (!ASSERT_TRUE(WIFEXITED(status), "child process exited"))
				return 1;
			if (!ASSERT_EQ(WEXITSTATUS(status), 0,
				       "child process exit code"))
				return 1;
		}
	}
	return 0;
}

static unsigned long long
get_attach_counter(unsigned long long cgroup_id, const char *file_name)
{
	unsigned long long attach_counter = 0, id = 0;
	static char buf[128], path[128];

	/* For every cgroup, read the file generated by cgroup_iter */
	snprintf(path, 128, "%s%s", BPFFS_ATTACH_COUNTERS, file_name);
	if (!ASSERT_OK(read_from_file(path, buf, 128), "read cgroup_iter"))
		return 0;

	/* Check the output file formatting */
	ASSERT_EQ(sscanf(buf, "cg_id: %llu, attach_counter: %llu\n",
			 &id, &attach_counter), 2, "output format");

	/* Check that the cgroup_id is displayed correctly */
	ASSERT_EQ(id, cgroup_id, "cgroup_id");
	/* Check that the counter is non-zero */
	ASSERT_GT(attach_counter, 0, "attach counter non-zero");
	return attach_counter;
}

static void check_attach_counters(void)
{
	unsigned long long attach_counters[N_CGROUPS], root_attach_counter;
	int i;

	for (i = 0; i < N_CGROUPS; i++)
		attach_counters[i] = get_attach_counter(cgroups[i].id,
							cgroups[i].name);

	/* Read stats for root too */
	root_attach_counter = get_attach_counter(CG_ROOT_ID, CG_ROOT_NAME);

	/* Check that all leafs cgroups have an attach counter of 3 */
	for (i = N_NON_LEAF_CGROUPS; i < N_CGROUPS; i++)
		ASSERT_EQ(attach_counters[i], PROCESSES_PER_CGROUP,
			  "leaf cgroup attach counter");

	/* Check that child1 == child1_1 + child1_2 */
	ASSERT_EQ(attach_counters[1], attach_counters[3] + attach_counters[4],
		  "child1_counter");
	/* Check that child2 == child2_1 + child2_2 */
	ASSERT_EQ(attach_counters[2], attach_counters[5] + attach_counters[6],
		  "child2_counter");
	/* Check that test == child1 + child2 */
	ASSERT_EQ(attach_counters[0], attach_counters[1] + attach_counters[2],
		  "test_counter");
	/* Check that root >= test */
	ASSERT_GE(root_attach_counter, attach_counters[1], "root_counter");
}

/* Creates iter link and pins in bpffs, returns 0 on success, -errno on failure.
 */
static int setup_cgroup_iter(struct cgroup_hierarchical_stats *obj,
			     int cgroup_fd, const char *file_name)
{
	DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, opts);
	union bpf_iter_link_info linfo = {};
	struct bpf_link *link;
	static char path[128];
	int err;

	/*
	 * Create an iter link, parameterized by cgroup_fd. We only want to
	 * traverse one cgroup, so set the traversal order to "self".
	 */
	linfo.cgroup.cgroup_fd = cgroup_fd;
	linfo.cgroup.order = BPF_CGROUP_ITER_SELF_ONLY;
	opts.link_info = &linfo;
	opts.link_info_len = sizeof(linfo);
	link = bpf_program__attach_iter(obj->progs.dumper, &opts);

Annotation

Implementation Notes