[Devel] [PATCH vz10] selftests: build test modules against the kernel tree
Konstantin Khorenko
khorenko at virtuozzo.com
Mon Aug 10 19:29:40 MSK 2026
1. the patch should go along with changes in kernel.spec i believe because at the moment "livepatch" is not even in the TARGETS list in kerne.spec
2. before committing this please show me
* the PR with successfully built those .ko files
* and list of files which are included now in the kselftests rpm
* and the successful run of the kselftests - logs of all those 3 TARGETS, how did they run.
3. Please note https://virtuozzo.atlassian.net/browse/VSTOR-139647?focusedCommentId=3980596
when you'll update kernel.spec.
On 8/9/26 20:18, Eva Kurchatova wrote:
> Selftests livepatch, cgroup and mm/page_frag build out-of-tree kernel
> modules and default KDIR to /lib/modules/$(uname -r)/build, which is
> the running kernel build tree on the currently building host.
> That is wrong whenever the selftests are built as part of a kernel
> package: `uname -r` is not the kernel being packaged, so the modules
> either are not built at all (no source tree for the builders kernel)
> or come out with the wrong vermagic and symbol layout.
> Either way no usable test modules end up in the packaged test suite,
> and a testing host may not have the kernel build tree to compile them
> either, so the tests will fail.
>
> Default KDIR to the kernel tree the tests are built from, or to its O=
> build directory, whenever that tree is configured and built.
> This is exactly what bpf/test_kmods has been already doing all along,
> and its modules are packaged and loaded successfully today.
> Testing for include/config/auto.conf and Module.symvers keeps the previous
> behaviour for a bare source checkout, and for a source tree that was
> mrpropered after the kernel had been built (packaging copies
> Module.symvers back into such a tree), so nothing that builds today
> starts failing.
>
> Also test for $(KDIR)/Makefile rather than for $(KDIR) itself before
> descending into the kernel tree: /lib/modules/$(uname -r)/build is
> commonly a dangling symlink, which the previous test accepted before
> failing in make -C. Same protection is applied to bpf/page_frag, as it
> had no such check at all.
>
> With this, `make kselftest TARGETS=livepatch` in a built kernel tree
> builds the modules for that kernel and `make install` ships them, so an
> installed testsuite runs against pre-built modules and needs no kernel
> build tree at all.
>
> Signed-off-by: Eva Kurchatova <eva.kurchatova at virtuozzo.com>
>
> https://virtuozzo.atlassian.net/browse/VSTOR-139647
> Feature: fix selftests
> ---
> .../selftests/cgroup/test_modules/Makefile | 25 ++++++++++++++++---
> .../selftests/livepatch/test_modules/Makefile | 25 ++++++++++++++++---
> tools/testing/selftests/mm/Makefile | 14 +++++++++++
> tools/testing/selftests/mm/page_frag/Makefile | 22 ++++++++++++++++
> 4 files changed, 78 insertions(+), 8 deletions(-)
>
> diff --git a/tools/testing/selftests/cgroup/test_modules/Makefile b/tools/testing/selftests/cgroup/test_modules/Makefile
> index 3f39eeda3a92..a47af9b7f18a 100644
> --- a/tools/testing/selftests/cgroup/test_modules/Makefile
> +++ b/tools/testing/selftests/cgroup/test_modules/Makefile
> @@ -1,17 +1,34 @@
> TESTMODS_DIR := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
> +
> +# Kernel build tree to compile the test modules against. Prefer the
> +# kernel tree these tests are part of (or its O= build directory) when it
> +# is configured and built, like bpf/test_kmods already does: When the
s/When/when/
> +# selftests are built as part of a kernel package, uname -r is the build
> +# host's kernel and not the kernel being packaged, so the resulting
> +# modules would carry the wrong vermagic and symbol layout. Fall back to
> +# the running kernel's build tree for standalone builds.
> +KDIR_TREE := $(if $(O),$(abspath $(O)),$(abspath $(TESTMODS_DIR)/../../../../..))
> +ifneq (,$(wildcard $(KDIR_TREE)/include/config/auto.conf))
> +ifneq (,$(wildcard $(KDIR_TREE)/Module.symvers))
> +KDIR ?= $(KDIR_TREE)
> +endif
> +endif
> KDIR ?= /lib/modules/$(shell uname -r)/build
>
> obj-m += cg_freezer_hang.o \
> cg_freezer_kthread.o
>
> -# Ensure that KDIR exists, otherwise skip the compilation
> +# Ensure that KDIR is a kernel build tree, otherwise skip the compilation.
> +# Testing for the Makefile rather than for the directory itself also covers
> +# a dangling /lib/modules/$(uname -r)/build symlink, and an installed
> +# testsuite, which ships pre-built modules and has no kernel tree above it.
> modules:
> -ifneq ("$(wildcard $(KDIR))", "")
> +ifneq ("$(wildcard $(KDIR)/Makefile)", "")
> $(Q)$(MAKE) -C $(KDIR) modules KBUILD_EXTMOD=$(TESTMODS_DIR)
> endif
>
> -# Ensure that KDIR exists, otherwise skip the clean target
> +# Ensure that KDIR is a kernel build tree, otherwise skip the clean target
> clean:
> -ifneq ("$(wildcard $(KDIR))", "")
> +ifneq ("$(wildcard $(KDIR)/Makefile)", "")
> $(Q)$(MAKE) -C $(KDIR) clean KBUILD_EXTMOD=$(TESTMODS_DIR)
> endif
> diff --git a/tools/testing/selftests/livepatch/test_modules/Makefile b/tools/testing/selftests/livepatch/test_modules/Makefile
> index 939230e571f5..7dc026fd42f7 100644
> --- a/tools/testing/selftests/livepatch/test_modules/Makefile
> +++ b/tools/testing/selftests/livepatch/test_modules/Makefile
> @@ -1,4 +1,18 @@
> TESTMODS_DIR := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
> +
> +# Kernel build tree to compile the test modules against. Prefer the
> +# kernel tree these tests are part of (or its O= build directory) when it
> +# is configured and built, like bpf/test_kmods already does: when the
> +# selftests are built as part of a kernel package, uname -r is the build
> +# host's kernel and not the kernel being packaged, so the resulting
> +# modules would carry the wrong vermagic and symbol CRCs. Fall back to
> +# the running kernel's build tree for standalone builds.
> +KDIR_TREE := $(if $(O),$(abspath $(O)),$(abspath $(TESTMODS_DIR)/../../../../..))
> +ifneq (,$(wildcard $(KDIR_TREE)/include/config/auto.conf))
> +ifneq (,$(wildcard $(KDIR_TREE)/Module.symvers))
> +KDIR ?= $(KDIR_TREE)
> +endif
> +endif
> KDIR ?= /lib/modules/$(shell uname -r)/build
i do not think we need to fix this right now, but just for the record:
if we are in <kernel tree>/selftests/livepatch and call
make -C livepatch O=../../../../out3
the compilation will fail (because of the relative path in O=)
>
> obj-m += test_klp_atomic_replace.o \
> @@ -14,14 +28,17 @@ obj-m += test_klp_atomic_replace.o \
> test_klp_state3.o \
> test_klp_syscall.o
>
> -# Ensure that KDIR exists, otherwise skip the compilation
> +# Ensure that KDIR is a kernel build tree, otherwise skip the compilation.
> +# Testing for the Makefile rather than for the directory itself also covers
> +# a dangling /lib/modules/$(uname -r)/build symlink, and an installed
> +# testsuite, which ships pre-built modules and has no kernel tree above it.
> modules:
> -ifneq ("$(wildcard $(KDIR))", "")
> +ifneq ("$(wildcard $(KDIR)/Makefile)", "")
> $(Q)$(MAKE) -C $(KDIR) modules KBUILD_EXTMOD=$(TESTMODS_DIR)
> endif
>
> -# Ensure that KDIR exists, otherwise skip the clean target
> +# Ensure that KDIR is a kernel build tree, otherwise skip the clean target
> clean:
> -ifneq ("$(wildcard $(KDIR))", "")
> +ifneq ("$(wildcard $(KDIR)/Makefile)", "")
> $(Q)$(MAKE) -C $(KDIR) clean KBUILD_EXTMOD=$(TESTMODS_DIR)
> endif
> diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile
> index 3de23ea4663f..3e643834d3a2 100644
> --- a/tools/testing/selftests/mm/Makefile
> +++ b/tools/testing/selftests/mm/Makefile
> @@ -36,6 +36,20 @@ MAKEFLAGS += --no-builtin-rules
> CFLAGS = -Wall -I $(top_srcdir) $(EXTRA_CFLAGS) $(KHDR_INCLUDES) $(TOOLS_INCLUDES)
> LDLIBS = -lrt -lpthread -lm
>
> +# Kernel build tree to compile page_frag_test.ko against. Prefer the
> +# kernel tree these tests are part of (or its O= build directory) when it
> +# is configured and built, like bpf/test_kmods already does: when the
> +# selftests are built as part of a kernel package, uname -r is the build
> +# host's kernel and not the kernel being packaged, so the resulting module
> +# would carry the wrong vermagic and symbol CRCs. Fall back to the
> +# running kernel's build tree for standalone builds. Keep this in sync
> +# with page_frag/Makefile, which is invoked separately by lib.mk.
> +KDIR_TREE := $(if $(O),$(abspath $(O)),$(abspath $(CURDIR)/../../../..))
> +ifneq (,$(wildcard $(KDIR_TREE)/include/config/auto.conf))
> +ifneq (,$(wildcard $(KDIR_TREE)/Module.symvers))
> +KDIR ?= $(KDIR_TREE)
> +endif
> +endif
> KDIR ?= /lib/modules/$(shell uname -r)/build
> ifneq (,$(wildcard $(KDIR)/Module.symvers))
> ifneq (,$(wildcard $(KDIR)/include/linux/page_frag_cache.h))
> diff --git a/tools/testing/selftests/mm/page_frag/Makefile b/tools/testing/selftests/mm/page_frag/Makefile
> index 8c8bb39ffa28..2c2918bbe0eb 100644
> --- a/tools/testing/selftests/mm/page_frag/Makefile
> +++ b/tools/testing/selftests/mm/page_frag/Makefile
> @@ -1,4 +1,18 @@
> PAGE_FRAG_TEST_DIR := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
> +
> +# Kernel build tree to compile the test module against. Prefer the kernel
> +# tree this test is part of (or its O= build directory) when it is
> +# configured and built, like bpf/test_kmods already does: when the
> +# selftests are built as part of a kernel package, uname -r is the build
> +# host's kernel and not the kernel being packaged, so the resulting module
> +# would carry the wrong vermagic and symbol CRCs. Fall back to the
> +# running kernel's build tree for standalone builds.
> +KDIR_TREE := $(if $(O),$(abspath $(O)),$(abspath $(PAGE_FRAG_TEST_DIR)/../../../../..))
> +ifneq (,$(wildcard $(KDIR_TREE)/include/config/auto.conf))
> +ifneq (,$(wildcard $(KDIR_TREE)/Module.symvers))
> +KDIR ?= $(KDIR_TREE)
> +endif
> +endif
> KDIR ?= /lib/modules/$(shell uname -r)/build
make O=/tmp/vz10-obj -j$(nproc) # to generate include/config/auto.conf and Module.symvers
make O=/tmp/vz10-obj kselftest-all TARGETS=mm
You will see:
Warning: missing page_frag_cache.h, please use a newer kernel. page_frag test will be skipped.
The O= kernel build breaks, and only for one module - page_frag_test.ko. The other three Makefiles from the patch
(livepatch, cgroup, page_frag/Makefile) handle O= correctly.
In tools/testing/selftests/mm/Makefile, right below the new block, there is an old check the patch did not touch:
KDIR ?= /lib/modules/$(shell uname -r)/build
ifneq (,$(wildcard $(KDIR)/Module.symvers))
ifneq (,$(wildcard $(KDIR)/include/linux/page_frag_cache.h))
TEST_GEN_MODS_DIR := page_frag
else
PAGE_FRAG_WARNING = "missing page_frag_cache.h, please use a newer kernel"
It looks for the source header include/linux/page_frag_cache.h inside KDIR. After the patch, in an O= build KDIR points at
the build directory ($(O)), which only contains include/config/ and include/generated/ - the source headers stay in the
source tree. The first check (Module.symvers) passes, the second one does not.
Further down the chain: TEST_GEN_MODS_DIR is not set, lib.mk never descends into the page_frag/ directory, the module is
not built and does not get into make install, and test_page_frag.sh hits if [ ! -f $DRIVER ] at run time and exits with
the skip code. On top of that, the build prints missing page_frag_cache.h, please use a newer kernel, which points at an
entirely wrong cause.
Before the patch, in this scenario KDIR was /lib/modules/$(uname -r)/build, where the header is present, so the module was
built and loaded on that same machine. In other words, the commit message claim "nothing that builds today starts
failing" does not hold for this case.
An in-tree build (no O=) is fine: there both Module.symvers and the header live in the same directory.
How to fix it
The minimal and safe option is to also look for the header through the source symlink that outputmakefile creates in the
build directory (ln -fsn $(srctree) source, present in this tree):
PAGE_FRAG_HDR := $(firstword $(wildcard \
$(KDIR)/include/linux/page_frag_cache.h \
$(KDIR)/source/include/linux/page_frag_cache.h))
ifneq (,$(PAGE_FRAG_HDR))
TEST_GEN_MODS_DIR := page_frag
>
> ifeq ($(V),1)
> @@ -11,8 +25,16 @@ MODULES = page_frag_test.ko
>
> obj-m += page_frag_test.o
>
> +# Ensure that KDIR is a kernel build tree, otherwise skip the compilation.
> +# Testing for the Makefile rather than for the directory itself also covers
> +# a dangling /lib/modules/$(uname -r)/build symlink, and an installed
> +# testsuite, which ships a pre-built module and has no kernel tree above it.
> all:
> +ifneq ("$(wildcard $(KDIR)/Makefile)", "")
> +$(Q)make -C $(KDIR) M=$(PAGE_FRAG_TEST_DIR) modules
> +endif
>
> clean:
> +ifneq ("$(wildcard $(KDIR)/Makefile)", "")
> +$(Q)make -C $(KDIR) M=$(PAGE_FRAG_TEST_DIR) clean
> +endif
More information about the Devel
mailing list