[RFC PATCH 3/3] samples/bpf: add example memcg eBPF program

Hui Zhu posted 3 patches 1 week, 6 days ago
[RFC PATCH 3/3] samples/bpf: add example memcg eBPF program
Posted by Hui Zhu 1 week, 6 days ago
From: Hui Zhu <zhuhui@kylinos.cn>

Add a sample eBPF program demonstrating the new memory
controller eBPF support. This example serves as both a reference
implementation and a validation tool for the memcg eBPF
functionality.

The sample includes:

- memcg_printk.bpf.c: An eBPF program that attaches to the
  try_charge_memcg hook and prints detailed information about
  memory charging events, including:
  * Memory cgroup name
  * GFP flags and page count
  * Reclamation options
  * Affected memory cgroup (when applicable)

- memcg_printk.c: A userspace loader program that:
  * Loads the eBPF object file
  * Finds and attaches the memcg_ops struct ops
  * Keeps the program attached until interrupted
  * Provides proper error handling and cleanup

Usage:
  $ ./samples/bpf/memcg_printk

This will attach the eBPF program to the memcg charging path.
Output can be viewed via kernel trace events (e.g.,
trace_printk logs).

The program demonstrates:
- Accessing memory cgroup context fields
- Using bpf_printk for debugging and monitoring
- Proper struct ops registration via libbpf
- Integration with the kernel's BPF infrastructure

Signed-off-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Hui Zhu <zhuhui@kylinos.cn>
---
 MAINTAINERS                    |  2 +
 samples/bpf/Makefile           |  2 +
 samples/bpf/memcg_printk.bpf.c | 30 +++++++++++++
 samples/bpf/memcg_printk.c     | 82 ++++++++++++++++++++++++++++++++++
 4 files changed, 116 insertions(+)
 create mode 100644 samples/bpf/memcg_printk.bpf.c
 create mode 100644 samples/bpf/memcg_printk.c

diff --git a/MAINTAINERS b/MAINTAINERS
index dc3aa53d2346..c8f32f7dad3f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6356,6 +6356,8 @@ F:	mm/memcontrol_bpf.h
 F:	mm/page_counter.c
 F:	mm/swap_cgroup.c
 F:	samples/cgroup/*
+F:	samples/memcg_printk.bpf.c
+F:	samples/memcg_printk.c
 F:	tools/testing/selftests/bpf/*/memcg_ops.c
 F:	tools/testing/selftests/cgroup/memcg_protection.m
 F:	tools/testing/selftests/cgroup/test_hugetlb_memcg.c
diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index 95a4fa1f1e44..d50e958fc8d5 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -37,6 +37,7 @@ tprogs-y += xdp_fwd
 tprogs-y += task_fd_query
 tprogs-y += ibumad
 tprogs-y += hbm
+tprogs-y += memcg_printk
 
 # Libbpf dependencies
 LIBBPF_SRC = $(TOOLS_PATH)/lib/bpf
@@ -122,6 +123,7 @@ always-y += task_fd_query_kern.o
 always-y += ibumad_kern.o
 always-y += hbm_out_kern.o
 always-y += hbm_edt_kern.o
+always-y += memcg_printk.bpf.o
 
 COMMON_CFLAGS = $(TPROGS_USER_CFLAGS)
 TPROGS_LDFLAGS = $(TPROGS_USER_LDFLAGS)
diff --git a/samples/bpf/memcg_printk.bpf.c b/samples/bpf/memcg_printk.bpf.c
new file mode 100644
index 000000000000..66c87bf4cbcb
--- /dev/null
+++ b/samples/bpf/memcg_printk.bpf.c
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include "vmlinux.h"
+
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+
+SEC("struct_ops/try_charge_memcg")
+int BPF_PROG(handle_try_charge_memcg, struct try_charge_memcg *tcm)
+{
+	bpf_printk(
+		"memcg %s gfp_mask 0x%x nr_pages %lu reclaim_options 0x%lx\n",
+		tcm->memcg->css.cgroup->kn->name,
+		tcm->gfp_mask,
+		tcm->nr_pages,
+		tcm->reclaim_options);
+	if (!tcm->charge_done)
+		bpf_printk("memcg %s mem_over_limit %s\n",
+			   tcm->memcg->css.cgroup->kn->name,
+			   tcm->mem_over_limit->css.cgroup->kn->name);
+
+	return 0;
+}
+
+SEC(".struct_ops")
+struct memcg_ops mcg_ops = {
+	.try_charge_memcg = (void *)handle_try_charge_memcg,
+};
+
+char _license[] SEC("license") = "GPL";
diff --git a/samples/bpf/memcg_printk.c b/samples/bpf/memcg_printk.c
new file mode 100644
index 000000000000..a2c5be2415ea
--- /dev/null
+++ b/samples/bpf/memcg_printk.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <signal.h>
+#include <bpf/libbpf.h>
+
+static bool exiting;
+
+static void sig_handler(int sig)
+{
+	exiting = true;
+}
+
+static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
+{
+	return vfprintf(stderr, format, args);
+}
+
+int main(int argc, char **argv)
+{
+	struct bpf_object *obj = NULL;
+	struct bpf_link *link = NULL;
+	struct bpf_map *map;
+	char filename[256];
+	int err;
+
+	exiting = false;
+
+	signal(SIGINT, sig_handler);
+	signal(SIGTERM, sig_handler);
+
+	libbpf_set_print(libbpf_print_fn);
+
+	snprintf(filename, sizeof(filename), "%s.bpf.o", argv[0]);
+	obj = bpf_object__open_file(filename, NULL);
+	err = libbpf_get_error(obj);
+	if (err) {
+		fprintf(stderr, "Failed to open BPF object file: %d\n",
+			err);
+		obj = NULL;
+		goto cleanup;
+	}
+
+	err = bpf_object__load(obj);
+	if (err) {
+		fprintf(stderr, "Failed to loading BPF object file: %d\n",
+			err);
+		goto cleanup;
+	}
+
+	map = bpf_object__find_map_by_name(obj, "mcg_ops");
+	if (!map) {
+		fprintf(stderr, "Failed to find struct_ops map 'mcg_ops'\n");
+		err = -ENOENT;
+		goto cleanup;
+	}
+
+	link = bpf_map__attach_struct_ops(map);
+	err = libbpf_get_error(link);
+	if (err) {
+		fprintf(stderr, "Failed to attach struct ops: %d\n",
+			err);
+		link = NULL;
+		goto cleanup;
+	}
+
+	printf("Press Ctrl+C to exit...\n");
+
+	while (!exiting)
+		sleep(1);
+
+	printf("Bye!\n");
+
+cleanup:
+	if (link)
+		bpf_link__destroy(link);
+	if (obj)
+		bpf_object__close(obj);
+
+	return err;
+}
-- 
2.43.0
Re: [RFC PATCH 3/3] samples/bpf: add example memcg eBPF program
Posted by bot+bpf-ci@kernel.org 1 week, 6 days ago
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 78b414902..3a70521cf 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -6357,6 +6357,8 @@ F:	mm/memcontrol_bpf.h
>  F:	mm/page_counter.c
>  F:	mm/swap_cgroup.c
>  F:	samples/cgroup/*
> +F:	samples/memcg_printk.bpf.c
> +F:	samples/memcg_printk.c
                     ^^^^

The paths here are missing the bpf/ directory component. The actual
files are located at samples/bpf/memcg_printk.bpf.c and
samples/bpf/memcg_printk.c. Should these paths include the bpf/
directory to match where the files are actually created?

>  F:	tools/testing/selftests/bpf/*/memcg_ops.c
>  F:	tools/testing/selftests/cgroup/memcg_protection.m
>  F:	tools/testing/selftests/cgroup/test_hugetlb_memcg.c

[ ... ]


---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

CI run summary: https://github.com/kernel-patches/bpf/actions/runs/19486904708