Linux cgroups development
 help / color / mirror / Atom feed
From: Albert Esteve <aesteve@redhat.com>
To: "Tejun Heo" <tj@kernel.org>,
	"Johannes Weiner" <hannes@cmpxchg.org>,
	"Michal Koutný" <mkoutny@suse.com>,
	"Shuah Khan" <shuah@kernel.org>
Cc: linux-kernel@vger.kernel.org, cgroups@vger.kernel.org,
	 linux-kselftest@vger.kernel.org,
	Albert Esteve <aesteve@redhat.com>
Subject: [PATCH v5 3/4] selftests: cgroup: Add vmtest-dmem runner script
Date: Mon, 06 Jul 2026 14:06:42 +0200	[thread overview]
Message-ID: <20260706-kunit_cgroups-v5-3-6c42c8753468@redhat.com> (raw)
In-Reply-To: <20260706-kunit_cgroups-v5-0-6c42c8753468@redhat.com>

Currently, test_dmem relies on the dmem_selftest helper module
and a VM setup that may not have the helper preinstalled.
This makes automated coverage of dmem charge paths harder in
virtme-based runs.

Add tools/testing/selftests/cgroup/vmtest-dmem.sh to provide a
repeatable VM workflow for dmem tests. The script uses vng --exec
to run the test directly inside a virtme-ng guest with minimal
setup.

The script boots a virtme-ng guest, validates dmem controller
availability, ensures the dmem helper path is present, and runs
tools/testing/selftests/cgroup/test_dmem. If the helper is not
available as a loaded module, it attempts module build/load for
the running guest kernel before executing the test binary.

The runner also supports interactive shell mode (-s) and reuses
the verbosity and KTAP exit-code conventions used by other vmtest
scripts, so it integrates with existing kselftest workflows.

vmtest-dmem.sh is placed in TEST_FILES rather than TEST_PROGS so
it is installed alongside the test suite but not invoked
automatically by run_kselftest.sh. It requires a VM-capable host
and is intended to be run manually.

Signed-off-by: Albert Esteve <aesteve@redhat.com>
---
 tools/testing/selftests/cgroup/Makefile       |   2 +-
 tools/testing/selftests/cgroup/vmtest-dmem.sh | 149 ++++++++++++++++++++++++++
 2 files changed, 150 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/cgroup/Makefile b/tools/testing/selftests/cgroup/Makefile
index e1a5e9316620e..2c407710c6e3b 100644
--- a/tools/testing/selftests/cgroup/Makefile
+++ b/tools/testing/selftests/cgroup/Makefile
@@ -3,7 +3,7 @@ CFLAGS += -Wall -pthread
 
 all: ${HELPER_PROGS}
 
-TEST_FILES     := with_stress.sh
+TEST_FILES     := with_stress.sh vmtest-dmem.sh
 TEST_PROGS     := test_stress.sh test_cpuset_prs.sh test_cpuset_v1_hp.sh
 TEST_GEN_FILES := wait_inotify
 # Keep the lists lexicographically sorted
diff --git a/tools/testing/selftests/cgroup/vmtest-dmem.sh b/tools/testing/selftests/cgroup/vmtest-dmem.sh
new file mode 100755
index 0000000000000..0bb6529112b54
--- /dev/null
+++ b/tools/testing/selftests/cgroup/vmtest-dmem.sh
@@ -0,0 +1,149 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (c) 2026 Red Hat, Inc.
+#
+# Run cgroup test_dmem inside a virtme-ng VM.
+# Dependencies:
+#		* virtme-ng
+#		* qemu	(used by virtme-ng)
+
+set -euo pipefail
+
+readonly SCRIPT_DIR="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
+readonly KERNEL_CHECKOUT="$(realpath "${SCRIPT_DIR}"/../../../../)"
+
+source "${SCRIPT_DIR}"/../kselftest/ktap_helpers.sh
+
+QEMU="qemu-system-$(uname -m)"
+VERBOSE=0
+SHELL_MODE=0
+GUEST_TREE="${GUEST_TREE:-$KERNEL_CHECKOUT}"
+
+VM_SCRIPT=""
+
+function usage() {
+	cat <<EOF
+$0 [OPTIONS]
+Options:
+	-q	QEMU binary/path (default: ${QEMU})
+	-s	Start interactive shell in VM instead of running tests
+	-v	Verbose output (vng boot logs on stdout)
+	-h	Display this help
+EOF
+}
+
+function cleanup() {
+	rm -f "${VM_SCRIPT}"
+}
+trap cleanup EXIT
+
+function skip() {
+	local msg=${1:-""}
+
+	ktap_test_skip "${msg}"
+	exit "${KSFT_SKIP}"
+}
+
+function fail() {
+	local msg=${1:-""}
+
+	ktap_test_fail "${msg}"
+	exit "${KSFT_FAIL}"
+}
+
+function check_deps() {
+	for dep in vng "${QEMU}"; do
+		if ! command -v "${dep}" >/dev/null 2>&1; then
+			skip "dependency ${dep} not found"
+		fi
+	done
+}
+
+# Run vng with common flags. Extra arguments are appended by the caller:
+#   --exec <script>  for automated test runs
+#   (nothing)        for interactive shell mode
+function run_vm() {
+	local verbose_opt=""
+
+	[[ "${VERBOSE}" -eq 1 ]] && verbose_opt="--verbose"
+
+	vng \
+		--run \
+		${verbose_opt:+"${verbose_opt}"} \
+		--qemu="$(command -v "${QEMU}")" \
+		--user root \
+		--rw \
+		"$@"
+}
+
+function main() {
+	while getopts ':hvq:s' opt; do
+		case "${opt}" in
+		v) VERBOSE=1 ;;
+		q) QEMU="${OPTARG}" ;;
+		s) SHELL_MODE=1 ;;
+		h) usage; exit 0 ;;
+		*) usage; exit 1 ;;
+		esac
+	done
+
+	check_deps
+
+	if [[ "${SHELL_MODE}" -eq 1 ]]; then
+		echo "Starting interactive shell in VM. Exit to stop VM."
+		run_vm
+		exit 0
+	fi
+
+	# Write the VM-side script into the script directory so it is
+	# accessible in the guest via the --rw host filesystem mount.
+	VM_SCRIPT="$(mktemp --suffix=.sh "${SCRIPT_DIR}/.dmem_vmtest_XXXX")"
+
+	cat > "${VM_SCRIPT}" << EOF
+#!/bin/bash
+set -euo pipefail
+
+mountpoint -q /sys/kernel/debug || mount -t debugfs none /sys/kernel/debug
+
+# Verify cgroup controllers are available.
+if ! grep -q dmem /sys/fs/cgroup/cgroup.controllers || \
+   ! grep -q memory /sys/fs/cgroup/cgroup.controllers; then
+	echo "guest kernel missing CONFIG_CGROUP_DMEM or CONFIG_MEMCG" >&2
+	exit 1
+fi
+
+# Load dmem_selftest: try built-in, then modprobe, then build + insmod.
+if [[ -e /sys/kernel/debug/dmem_selftest/charge ]]; then
+	echo "dmem_selftest ready (built-in or already loaded)"
+elif modprobe -q dmem_selftest 2>/dev/null && \
+     [[ -e /sys/kernel/debug/dmem_selftest/charge ]]; then
+	echo "dmem_selftest ready (modprobe)"
+else
+	kdir="/lib/modules/\$(uname -r)/build"
+	if [[ -d "\$kdir" ]]; then
+		echo "Building dmem_selftest.ko against running guest kernel..."
+		if make -C "\$kdir" M="${GUEST_TREE}/kernel/cgroup" \
+				CONFIG_DMEM_SELFTEST=m modules; then
+			insmod "${GUEST_TREE}/kernel/cgroup/dmem_selftest.ko" \
+				2>/dev/null || modprobe -q dmem_selftest 2>/dev/null || true
+		fi
+	fi
+	if [[ ! -e /sys/kernel/debug/dmem_selftest/charge ]]; then
+		echo "dmem_selftest unavailable (modprobe/build+insmod failed)" >&2
+		exit 1
+	fi
+	echo "dmem_selftest ready (built + insmod)"
+fi
+
+echo "Running cgroup/test_dmem in VM..."
+cd "${GUEST_TREE}"
+make -C tools/testing/selftests TARGETS=cgroup
+./tools/testing/selftests/cgroup/test_dmem
+EOF
+
+	echo "Booting virtme-ng VM..."
+	run_vm --exec "bash ${VM_SCRIPT}"
+}
+
+main "$@"

-- 
2.54.0


  parent reply	other threads:[~2026-07-06 12:09 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-06 12:06 [PATCH v5 0/4] cgroup: dmem: add selftest helper, coverage, and VM runner Albert Esteve
2026-07-06 12:06 ` [PATCH v5 1/4] cgroup: Add dmem_selftest module Albert Esteve
2026-07-06 12:06 ` [PATCH v5 2/4] selftests: cgroup: Add dmem selftest coverage Albert Esteve
2026-07-06 12:06 ` Albert Esteve [this message]
2026-07-06 12:06 ` [PATCH v5 4/4] selftests: cgroup: handle vmtest-dmem -b to test locally built kernel Albert Esteve

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260706-kunit_cgroups-v5-3-6c42c8753468@redhat.com \
    --to=aesteve@redhat.com \
    --cc=cgroups@vger.kernel.org \
    --cc=hannes@cmpxchg.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=mkoutny@suse.com \
    --cc=shuah@kernel.org \
    --cc=tj@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox