File Index
Files and directories
Sign in
FILE

kmem_cache_iter.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/bpf/prog_tests/kmem_cache_iter.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2024 Google */
  3
  4#include <test_progs.h>
  5#include <bpf/libbpf.h>
  6#include <bpf/btf.h>
  7#include "kmem_cache_iter.skel.h"
  8
  9#define SLAB_NAME_MAX  32
 10
 11struct kmem_cache_result {
 12	char name[SLAB_NAME_MAX];
 13	long obj_size;
 14};
 15
 16static void subtest_kmem_cache_iter_check_task_struct(struct kmem_cache_iter *skel)
 17{
 18	LIBBPF_OPTS(bpf_test_run_opts, opts,
 19		.flags = 0,  /* Run it with the current task */
 20	);
 21	int prog_fd = bpf_program__fd(skel->progs.check_task_struct);
 22
 23	/* Get task_struct and check it if's from a slab cache */
 24	ASSERT_OK(bpf_prog_test_run_opts(prog_fd, &opts), "prog_test_run");
 25
 26	/* The BPF program should set 'found' variable */
 27	ASSERT_EQ(skel->bss->task_struct_found, 1, "task_struct_found");
 28}
 29
 30static void subtest_kmem_cache_iter_check_slabinfo(struct kmem_cache_iter *skel)
 31{
 32	FILE *fp;
 33	int map_fd;
 34	char name[SLAB_NAME_MAX];
 35	unsigned long objsize;
 36	char rest_of_line[1000];
 37	struct kmem_cache_result r;
 38	int seen = 0;
 39
 40	fp = fopen("/proc/slabinfo", "r");
 41	if (fp == NULL) {
 42		/* CONFIG_SLUB_DEBUG is not enabled */
 43		return;
 44	}
 45
 46	map_fd = bpf_map__fd(skel->maps.slab_result);
 47
 48	/* Ignore first two lines for header */
 49	fscanf(fp, "slabinfo - version: %*d.%*d\n");
 50	fscanf(fp, "# %*s %*s %*s %*s %*s %*s : %[^\n]\n", rest_of_line);
 51
 52	/* Compare name and objsize only - others can be changes frequently */
 53	while (fscanf(fp, "%s %*u %*u %lu %*u %*u : %[^\n]\n",
 54		      name, &objsize, rest_of_line) == 3) {
 55		int ret = bpf_map_lookup_elem(map_fd, &seen, &r);
 56
 57		if (!ASSERT_OK(ret, "kmem_cache_lookup"))
 58			break;
 59
 60		ASSERT_STRNEQ(r.name, name, sizeof(r.name) - 1,
 61			      "kmem_cache_name");
 62		ASSERT_EQ(r.obj_size, objsize, "kmem_cache_objsize");
 63
 64		seen++;
 65	}
 66
 67	ASSERT_EQ(skel->bss->kmem_cache_seen, seen, "kmem_cache_seen_eq");
 68
 69	fclose(fp);
 70}
 71
 72static void subtest_kmem_cache_iter_open_coded(struct kmem_cache_iter *skel)
 73{
 74	LIBBPF_OPTS(bpf_test_run_opts, topts);
 75	int err, fd;
 76
 77	/* No need to attach it, just run it directly */
 78	fd = bpf_program__fd(skel->progs.open_coded_iter);
 79
 80	err = bpf_prog_test_run_opts(fd, &topts);
 81	if (!ASSERT_OK(err, "test_run_opts err"))
 82		return;
 83	if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
 84		return;
 85
 86	/* It should be same as we've seen from the explicit iterator */
 87	ASSERT_EQ(skel->bss->open_coded_seen, skel->bss->kmem_cache_seen, "open_code_seen_eq");
 88}
 89
 90void test_kmem_cache_iter(void)
 91{
 92	struct kmem_cache_iter *skel = NULL;
 93	char buf[256];
 94	int iter_fd;
 95
 96	skel = kmem_cache_iter__open_and_load();
 97	if (!ASSERT_OK_PTR(skel, "kmem_cache_iter__open_and_load"))
 98		return;
 99
100	if (!ASSERT_OK(kmem_cache_iter__attach(skel), "skel_attach"))
101		goto destroy;
102
103	iter_fd = bpf_iter_create(bpf_link__fd(skel->links.slab_info_collector));
104	if (!ASSERT_GE(iter_fd, 0, "iter_create"))
105		goto destroy;
106
107	memset(buf, 0, sizeof(buf));
108	while (read(iter_fd, buf, sizeof(buf)) > 0) {
109		/* Read out all contents */
110		printf("%s", buf);
111	}
112
113	/* Next reads should return 0 */
114	ASSERT_EQ(read(iter_fd, buf, sizeof(buf)), 0, "read");
115
116	if (test__start_subtest("check_task_struct"))
117		subtest_kmem_cache_iter_check_task_struct(skel);
118	if (test__start_subtest("check_slabinfo"))
119		subtest_kmem_cache_iter_check_slabinfo(skel);
120	if (test__start_subtest("open_coded_iter"))
121		subtest_kmem_cache_iter_open_coded(skel);
122
123	close(iter_fd);
124
125destroy:
126	kmem_cache_iter__destroy(skel);
127}
~/ Read-only file preview.