From: Soma Das <somadas1@linux.ibm.com>
To: ltp@lists.linux.it
Cc: somadas1@linux.ibm.com
Subject: [LTP] [PATCH] cgroup: make regression test compatible with cgroup v2
Date: Thu, 2 Apr 2026 08:25:46 +0000 [thread overview]
Message-ID: <20260402082546.3245433-1-somadas1@linux.ibm.com> (raw)
On kernels >= 5.8, cgroup v2 is mounted by default, causing
cgroup v1 mount operations in the regression tests to fail.
Add kernel version detection to skip v1-specific tests on
systems where cgroup v2 is active by default. Also fix the
cleanup function to handle cases where umount fails gracefully
using retry logic and lazy unmount fallback.
Signed-off-by: Soma Das <somadas1@linux.ibm.com>
---
.../cgroup/cgroup_regression_test.sh | 215 +++++++++++++-----
1 file changed, 160 insertions(+), 55 deletions(-)
diff --git a/testcases/kernel/controllers/cgroup/cgroup_regression_test.sh b/testcases/kernel/controllers/cgroup/cgroup_regression_test.sh
index a91c400f8..86b79f424 100755
--- a/testcases/kernel/controllers/cgroup/cgroup_regression_test.sh
+++ b/testcases/kernel/controllers/cgroup/cgroup_regression_test.sh
@@ -2,8 +2,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) 2019-2022 Petr Vorel <pvorel@suse.cz>
# Copyright (c) 2009 FUJITSU LIMITED
-# Author: Li Zefan <lizf@cn.fujitsu.com>
-
+# Author: Li Zefan <lizf@cn.fujitsu.com>
TST_TESTFUNC=test
TST_SETUP=do_setup
TST_CLEANUP=do_cleanup
@@ -20,6 +19,13 @@ do_setup()
tst_brk TCONF ignored "Kernel does not support for control groups; skipping testcases";
fi
+ local kver=$(uname -r)
+ if kernel_supports_v2_by_default; then
+ tst_res TINFO "Kernel $kver: version >= 5.8 (mounts cgroup v2 by default)"
+ else
+ tst_res TINFO "Kernel $kver: version < 5.8 (no default v2 support)"
+ fi
+
dmesg -c > /dev/null
NR_BUG=`dmesg | grep -c "kernel BUG"`
NR_NULL=`dmesg | grep -c "kernel NULL pointer dereference"`
@@ -29,11 +35,28 @@ do_setup()
do_cleanup()
{
- if mountpoint -q cgroup/; then
- find cgroup/ -maxdepth 1 -depth -exec rmdir {} +
- umount cgroup/
- rmdir cgroup
- fi
+ local cgroup_mount="$PWD/cgroup"
+ local attempts=0
+
+ while [ $attempts -lt 5 ]; do
+ if ! mount | grep -q "on $cgroup_mount type"; then
+ break
+ fi
+
+ find "$cgroup_mount" -maxdepth 1 -depth -exec rmdir {} + 2>/dev/null || true
+
+ umount -f "$cgroup_mount" 2>/dev/null || umount -l "$cgroup_mount" 2>/dev/null || true
+ sleep 1
+
+ if mount | grep -q "on $cgroup_mount type"; then
+ fuser -km "$cgroup_mount" 2>/dev/null || true
+ sleep 1
+ fi
+
+ attempts=$((attempts+1))
+ done
+
+ rmdir "$cgroup_mount" 2>/dev/null || true
}
check_kernel_bug()
@@ -78,6 +101,24 @@ check_kernel_bug()
return 1
}
+kernel_version()
+{
+ uname -r | cut -d. -f1,2
+}
+
+kernel_supports_v2_by_default()
+{
+ local kver=$(uname -r | cut -d. -f1,2)
+ local major=$(echo "$kver" | cut -d. -f1)
+ local minor=$(echo "$kver" | cut -d. -f2)
+
+ # Kernel 5.8+ mounts cgroup v2 by default
+ if [ $major -gt 5 ] || ([ $major -eq 5 ] && [ $minor -ge 8 ]); then
+ return 0
+ fi
+ return 1
+}
+
#---------------------------------------------------------------------------
# Bug: There was a race when keeping forking processes and at the same
# time cat /cgroup/tasks (should be the very first time to read
@@ -90,20 +131,54 @@ check_kernel_bug()
#---------------------------------------------------------------------------
test1()
{
+ if mount | grep -q "type cgroup2"; then
+ tst_res TCONF "cgroup v2 already active - cannot mount v1 on this kernel"
+ return
+ fi
+
cgroup_regression_fork_processes &
sleep 1
- mount -t cgroup -o none,name=foo cgroup cgroup/
+ mount -t cgroup -o none,name=foo cgroup "$PWD/cgroup"
if [ $? -ne 0 ]; then
tst_res TFAIL "failed to mount cgroup filesystem"
kill -TERM $!
return
fi
- cat cgroup/tasks > /dev/null
+ cat "$PWD/cgroup/tasks" > /dev/null
kill -TERM $!
wait $! 2>/dev/null
- umount cgroup/
+ sleep 2
+ killall -9 cgroup_regression_fork_processes 2>/dev/null || true
+ sleep 1
+ sync
+
+ local attempts=0
+ local cgroup_mount="$PWD/cgroup"
+
+ while [ $attempts -lt 5 ]; do
+ if ! mount | grep -q "on $cgroup_mount type cgroup"; then
+ break
+ fi
+
+ umount -f "$cgroup_mount" 2>/dev/null || umount -l "$cgroup_mount" 2>/dev/null || true
+ sleep 1
+
+ if mount | grep -q "on $cgroup_mount type cgroup"; then
+ fuser -km "$cgroup_mount" 2>/dev/null || true
+ sleep 1
+ fi
+
+ attempts=$((attempts+1))
+ done
+ sync
+
+ if mount | grep -q "on $cgroup_mount type cgroup"; then
+ tst_res TFAIL "Failed to unmount cgroup"
+ return
+ fi
+
check_kernel_bug
}
@@ -115,31 +190,39 @@ test1()
#---------------------------------------------------------------------------
test2()
{
+ if mount | grep -q "type cgroup2"; then
+ tst_res TCONF "cgroup v2 already active - cannot mount v1 on this kernel"
+ return
+ fi
+
local val1
local val2
- local cgroup_version
+ local cgroup_mount="$PWD/cgroup"
- cgroup_require "memory"
- cgroup_version=$(cgroup_get_version "memory")
- if [ "$cgroup_version" = "2" ]; then
- tst_res TCONF "This test requires cgroup v1, but system is using cgroup v2"
- cgroup_cleanup
+ fuser -km "$cgroup_mount" 2>/dev/null || true
+ grep cgroup /proc/self/mounts | awk '{print $2}' | while read m; do
+ umount -lf "$m" 2>/dev/null || true
+ done
+ sleep 1
+
+ if mount | grep -q "on $cgroup_mount type"; then
+ tst_res TFAIL "Failed to clean up $cgroup_mount before mount attempt"
return
fi
- mount -t cgroup -o none,name=foo cgroup cgroup/
+ mount -t cgroup -o none,name=foo cgroup "$cgroup_mount"
if [ $? -ne 0 ]; then
tst_res TFAIL "Failed to mount cgroup filesystem"
return
fi
- echo 0 > cgroup/notify_on_release
- mkdir cgroup/0
- val1=`cat cgroup/0/notify_on_release`
+ echo 0 > "$cgroup_mount/notify_on_release"
+ mkdir "$cgroup_mount/0"
+ val1=`cat "$cgroup_mount/0/notify_on_release"`
- echo 1 > cgroup/notify_on_release
- mkdir cgroup/1
- val2=`cat cgroup/1/notify_on_release`
+ echo 1 > "$cgroup_mount/notify_on_release"
+ mkdir "$cgroup_mount/1"
+ val2=`cat "$cgroup_mount/1/notify_on_release"`
if [ $val1 -ne 0 -o $val2 -ne 1 ]; then
tst_res TFAIL "wrong notify_on_release value"
@@ -147,8 +230,8 @@ test2()
tst_res TPASS "notify_on_release is inherited"
fi
- rmdir cgroup/0 cgroup/1
- tst_umount $PWD/cgroup
+ rmdir "$cgroup_mount/0" "$cgroup_mount/1" 2>/dev/null || true
+ umount -f "$cgroup_mount" 2>/dev/null || umount -l "$cgroup_mount" 2>/dev/null || true
}
#---------------------------------------------------------------------------
@@ -201,6 +284,11 @@ test4()
{
local lines
+ if mount | grep -q "type cgroup2"; then
+ tst_res TCONF "cgroup v2 already active - skipping v1 test"
+ return
+ fi
+
if [ ! -e /proc/lockdep ]; then
tst_res TCONF "CONFIG_LOCKDEP is not enabled"
return
@@ -213,10 +301,11 @@ test4()
return
fi
- mount -t cgroup -o none,name=foo cgroup cgroup/
- mkdir cgroup/0
- rmdir cgroup/0
- tst_umount $PWD/cgroup
+ local cgroup_mount="$PWD/cgroup"
+ mount -t cgroup -o none,name=foo cgroup "$cgroup_mount"
+ mkdir "$cgroup_mount/0"
+ rmdir "$cgroup_mount/0"
+ tst_umount "$cgroup_mount"
if dmesg | grep -q "MAX_LOCKDEP_SUBCLASSES too low"; then
tst_res TFAIL "lockdep BUG was found"
@@ -235,6 +324,11 @@ test4()
#---------------------------------------------------------------------------
test5()
{
+ if mount | grep -q "type cgroup2"; then
+ tst_res TCONF "cgroup v2 already active - skipping v1 test"
+ return
+ fi
+
cgroup_regression_5_1.sh &
local pid1=$!
cgroup_regression_5_2.sh &
@@ -245,10 +339,16 @@ test5()
wait $pid1 2>/dev/null
wait $pid2 2>/dev/null
- mount -t cgroup none cgroup 2> /dev/null
- mkdir cgroup/0
- rmdir cgroup/0
- tst_umount $PWD/cgroup
+ local cgroup_mount="$PWD/cgroup"
+ if mount | grep -q "on $cgroup_mount type"; then
+ umount -l "$cgroup_mount" 2>/dev/null || true
+ sleep 1
+ fi
+
+ mount -t cgroup none "$cgroup_mount" 2> /dev/null
+ mkdir "$cgroup_mount/0"
+ rmdir "$cgroup_mount/0"
+ tst_umount "$cgroup_mount"
check_kernel_bug
}
@@ -272,7 +372,9 @@ test6()
wait $pid1 2>/dev/null
wait $pid2 2>/dev/null
- umount cgroup/ 2> /dev/null
+ # Use absolute path with force unmount
+ local cgroup_mount="$PWD/cgroup"
+ umount -f "$cgroup_mount" 2>/dev/null || umount -l "$cgroup_mount" 2>/dev/null || true
check_kernel_bug
}
@@ -288,11 +390,7 @@ test_7_1()
{
local subsys=$1
local subsys_path
- # we should be careful to select a $subsys_path which is related to
- # cgroup only: if cgroup debugging is enabled a 'debug' $subsys
- # could be passed here as params and this will lead to ambiguity and
- # errors when grepping simply for 'debug' in /proc/mounts since we'll
- # find also /sys/kernel/debug. Helper takes care of this.
+ local cgroup_mount="$PWD/cgroup"
cgroup_require "$subsys"
subsys_path=$(cgroup_get_mountpoint "$subsys")
@@ -301,14 +399,11 @@ test_7_1()
sleep 100 < $subsys_path/0 & # add refcnt to this dir
rmdir $subsys_path/0
- # remount with new subsystems added
- # since 2.6.28, this remount will fail
-
if [ "$subsys_path" = "cgroup" ]; then
- mount -t cgroup -o remount xxx cgroup/ 2> /dev/null
+ mount -t cgroup -o remount xxx "$cgroup_mount" 2> /dev/null
kill -TERM $!
wait $! 2>/dev/null
- umount cgroup/
+ umount -f "$cgroup_mount" 2>/dev/null || umount -l "$cgroup_mount" 2>/dev/null || true
fi
cgroup_cleanup
@@ -317,23 +412,27 @@ test_7_1()
test_7_2()
{
local subsys=$1
+ local cgroup_mount="$PWD/cgroup"
- mount -t cgroup -o none,name=foo cgroup cgroup/
+ if mount | grep -q "on $cgroup_mount type"; then
+ umount -f "$cgroup_mount" 2>/dev/null || umount -l "$cgroup_mount" 2>/dev/null || true
+ sleep 1
+ fi
+
+ mount -t cgroup -o none,name=foo cgroup "$cgroup_mount"
if [ $? -ne 0 ]; then
tst_res TFAIL "failed to mount cgroup"
return
fi
- mkdir cgroup/0
- sleep 100 < cgroup/0 & # add refcnt to this dir
- rmdir cgroup/0
+ mkdir "$cgroup_mount/0"
+ sleep 100 < "$cgroup_mount/0" & # add refcnt to this dir
+ rmdir "$cgroup_mount/0"
- # remount with some subsystems removed
- # since 2.6.28, this remount will fail
- mount -t cgroup -o remount,$subsys xxx cgroup/ 2> /dev/null
+ mount -t cgroup -o remount,$subsys xxx "$cgroup_mount" 2> /dev/null
kill -TERM $!
wait $! 2>/dev/null
- umount cgroup/
+ umount -f "$cgroup_mount" 2>/dev/null || umount -l "$cgroup_mount" 2>/dev/null || true
grep -q -w "cpu" /proc/cgroups
if [ $? -ne 0 -o ! -e /proc/sched_debug ]; then
@@ -379,17 +478,23 @@ test7()
#---------------------------------------------------------------------------
test8()
{
- mount -t cgroup -o none,name=foo cgroup cgroup/
+ if mount | grep -q "type cgroup2"; then
+ tst_res TCONF "cgroup v2 already active - skipping v1 test"
+ return
+ fi
+
+ local cgroup_mount="$PWD/cgroup"
+ mount -t cgroup -o none,name=foo cgroup "$cgroup_mount"
if [ $? -ne 0 ]; then
tst_res TFAIL "failed to mount cgroup filesystem"
return
fi
- if cgroup_regression_getdelays -C cgroup/tasks > /dev/null 2>&1; then
+ if cgroup_regression_getdelays -C "$cgroup_mount/tasks" > /dev/null 2>&1; then
tst_res TFAIL "should have failed to get cgroupstat of tasks file"
fi
- umount cgroup/
+ umount -f "$cgroup_mount" 2>/dev/null || umount -l "$cgroup_mount" 2>/dev/null || true
check_kernel_bug
}
--
2.39.1
--
Mailing list info: https://lists.linux.it/listinfo/ltp
next reply other threads:[~2026-04-02 8:02 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-02 8:25 Soma Das [this message]
2026-04-03 2:30 ` [LTP] [PATCH] cgroup: make regression test compatible with cgroup v2 Li Wang via ltp
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=20260402082546.3245433-1-somadas1@linux.ibm.com \
--to=somadas1@linux.ibm.com \
--cc=ltp@lists.linux.it \
/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