From nobody Tue Dec 2 02:43:29 2025 Received: from out-172.mta1.migadu.com (out-172.mta1.migadu.com [95.215.58.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4F37E25484D for ; Wed, 19 Nov 2025 01:35:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763516112; cv=none; b=FY4xTfn0BmoZ+7pd8COMiw1yQXTKX40v42RMhn1Ab8qfxlHaHDS+E3601P4yS7CtGZYp3y/WtKtGM+wjrYRk93sU+2hqz11lIIZ3Sqz1o2E10HfX8kOK5QoRabkU00h/6RgaLnKxu7DUiK29zUGvIKI82/iCXHQWKkSj29EDIsg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763516112; c=relaxed/simple; bh=maViTfMIiS5GM7CVEAxKybSytdqSGW1ndoj9TRtUw1M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TIJkiDBNEWhu6y4CyAkI7MNQzeRwLF+skPUmgJc8lZtohLlDamTF1xM81p7SnTBvt2qk7SQDYjJ32bn0TeRTEILm73p1dxAZr0NNspr/kg7p7yi9rDmoE22OP8Mcl8L5UXXWg5Hca6a1bDxfLmZXfESho1qM0Goz5SCqtmhVa8U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=rJKJXVPq; arc=none smtp.client-ip=95.215.58.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="rJKJXVPq" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1763516106; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=APzUbJ1xJcLTN15RzI5Lt/FDUDhgt5Fbd2bTLMIMyeQ=; b=rJKJXVPqyQq5HjlvFiXrkhuluS7KlJTVwnsZHRW4cmL0e5TInZS9YpTGeQLiVFuBFboxuL ynaA07biE0TPd906lyYl19JS1eZgGAw6GuDGTYR+8SWz6fWPft/9epr8XY8KxPK63+d2Wu LDoZxauP/e5JFtJEM9a4z7HJVLmupOc= From: Hui Zhu To: Andrew Morton , Johannes Weiner , Michal Hocko , Roman Gushchin , Shakeel Butt , Muchun Song , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Shuah Khan , Peter Zijlstra , Miguel Ojeda , Nathan Chancellor , Kees Cook , Tejun Heo , Jeff Xu , mkoutny@suse.com, Jan Hendrik Farr , Christian Brauner , Randy Dunlap , Brian Gerst , Masahiro Yamada , linux-kernel@vger.kernel.org, linux-mm@kvack.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org Cc: Hui Zhu , Geliang Tang Subject: [RFC PATCH 2/3] selftests/bpf: add memcg eBPF struct ops test Date: Wed, 19 Nov 2025 09:34:07 +0800 Message-ID: <0017945a4297a296c87a65d62cc4bd9948f6c20c.1763457705.git.zhuhui@kylinos.cn> In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Hui Zhu Add comprehensive selftest suite for memory controller eBPF support. The tests validate the core functionality of the memcg_ops struct ops implementation. Test coverage includes: 1. test_memcg_ops_load: Validates that the eBPF object file can be successfully loaded by libbpf. 2. test_memcg_ops_attach: Tests attaching the memcg_ops struct ops to the kernel, verifying the basic attachment mechanism works correctly. 3. test_memcg_ops_double_attach: Validates that only one memcg_ops instance can be attached at a time. Attempts to attach a second program should fail, ensuring the single-handler design constraint is enforced. The test suite includes: - prog_tests/memcg_ops.c: Test entry point with individual test functions using standard BPF test framework helpers like ASSERT_OK_PTR and ASSERT_ERR_PTR - progs/memcg_ops.bpf.c: Simple eBPF program implementing the struct ops interface Uses standard test_progs framework macros for consistent error reporting and handling. All tests properly clean up resources in error paths. Signed-off-by: Geliang Tang Signed-off-by: Hui Zhu --- MAINTAINERS | 1 + .../selftests/bpf/prog_tests/memcg_ops.c | 117 ++++++++++++++++++ tools/testing/selftests/bpf/progs/memcg_ops.c | 20 +++ 3 files changed, 138 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/memcg_ops.c create mode 100644 tools/testing/selftests/bpf/progs/memcg_ops.c diff --git a/MAINTAINERS b/MAINTAINERS index 498d01c9a48e..dc3aa53d2346 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6356,6 +6356,7 @@ F: mm/memcontrol_bpf.h F: mm/page_counter.c F: mm/swap_cgroup.c F: samples/cgroup/* +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 F: tools/testing/selftests/cgroup/test_kmem.c diff --git a/tools/testing/selftests/bpf/prog_tests/memcg_ops.c b/tools/tes= ting/selftests/bpf/prog_tests/memcg_ops.c new file mode 100644 index 000000000000..3f989bcfb8c4 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/memcg_ops.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Memory controller eBPF struct ops test + */ + +#include +#include + +void test_memcg_ops_load(void) +{ + struct bpf_object *obj; + int err; + + obj =3D bpf_object__open_file("memcg_ops.bpf.o", NULL); + err =3D libbpf_get_error(obj); + if (CHECK_FAIL(err)) { + obj =3D NULL; + goto out; + } + + err =3D bpf_object__load(obj); + if (CHECK_FAIL(err)) + goto out; + +out: + if (obj) + bpf_object__close(obj); +} + +void test_memcg_ops_attach(void) +{ + struct bpf_object *obj; + struct bpf_map *map; + struct bpf_link *link =3D NULL; + int err; + + obj =3D bpf_object__open_file("memcg_ops.bpf.o", NULL); + err =3D libbpf_get_error(obj); + if (CHECK_FAIL(err)) { + obj =3D NULL; + goto out; + } + + err =3D bpf_object__load(obj); + if (CHECK_FAIL(err)) + goto out; + + map =3D bpf_object__find_map_by_name(obj, "mcg_ops"); + if (!ASSERT_OK_PTR(map, "bpf_object__find_map_by_name")) + goto out; + + link =3D bpf_map__attach_struct_ops(map); + if (!ASSERT_OK_PTR(link, "bpf_map__attach_struct_ops")) + goto out; + +out: + if (link) + bpf_link__destroy(link); + if (obj) + bpf_object__close(obj); +} + +void test_memcg_ops_double_attach(void) +{ + struct bpf_object *obj, *obj2; + struct bpf_map *map, *map2; + struct bpf_link *link =3D NULL, *link2 =3D NULL; + int err; + + obj =3D bpf_object__open_file("memcg_ops.bpf.o", NULL); + err =3D libbpf_get_error(obj); + if (CHECK_FAIL(err)) { + obj =3D NULL; + goto out; + } + + err =3D bpf_object__load(obj); + if (CHECK_FAIL(err)) + goto out; + + map =3D bpf_object__find_map_by_name(obj, "mcg_ops"); + if (!ASSERT_OK_PTR(map, "bpf_object__find_map_by_name")) + goto out; + + link =3D bpf_map__attach_struct_ops(map); + if (!ASSERT_OK_PTR(link, "bpf_map__attach_struct_ops")) + goto out; + + obj2 =3D bpf_object__open_file("memcg_ops.bpf.o", NULL); + err =3D libbpf_get_error(obj2); + if (CHECK_FAIL(err)) { + obj2 =3D NULL; + goto out; + } + + err =3D bpf_object__load(obj2); + if (CHECK_FAIL(err)) + goto out; + + map2 =3D bpf_object__find_map_by_name(obj2, "mcg_ops"); + if (!ASSERT_OK_PTR(map, "bpf_object__find_map_by_name")) + goto out; + + link2 =3D bpf_map__attach_struct_ops(map2); + if (!ASSERT_ERR_PTR(link2, "bpf_map__attach_struct_ops")) { + bpf_link__destroy(link2); + goto out; + } + +out: + if (link) + bpf_link__destroy(link); + if (obj) + bpf_object__close(obj); + if (obj2) + bpf_object__close(obj2); +} diff --git a/tools/testing/selftests/bpf/progs/memcg_ops.c b/tools/testing/= selftests/bpf/progs/memcg_ops.c new file mode 100644 index 000000000000..a21fbe859fd3 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/memcg_ops.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "vmlinux.h" + +#include +#include + +char _license[] SEC("license") =3D "GPL"; + +SEC("struct_ops/try_charge_memcg") +int BPF_PROG(test_try_charge_memcg, + struct try_charge_memcg *tcm) +{ + return 0; +} + +SEC(".struct_ops") +struct memcg_ops mcg_ops =3D { + .try_charge_memcg =3D (void *)test_try_charge_memcg, +}; --=20 2.43.0