* [LTP] [PATCH] cgroup: make regression test compatible with cgroup v2
@ 2026-04-02 8:25 Soma Das
2026-04-03 2:30 ` Li Wang via ltp
0 siblings, 1 reply; 2+ messages in thread
From: Soma Das @ 2026-04-02 8:25 UTC (permalink / raw)
To: ltp; +Cc: somadas1
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
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [LTP] [PATCH] cgroup: make regression test compatible with cgroup v2
2026-04-02 8:25 [LTP] [PATCH] cgroup: make regression test compatible with cgroup v2 Soma Das
@ 2026-04-03 2:30 ` Li Wang via ltp
0 siblings, 0 replies; 2+ messages in thread
From: Li Wang via ltp @ 2026-04-03 2:30 UTC (permalink / raw)
To: Soma Das; +Cc: ltp
Hi Soma,
First, thank you for cleanup this test. Yes, it is only compatible
on Cgroup v1, and it's definately could compatible v2 just with
some adjutment.
But I'd like suggest to make use of the LTP standard Cgroup API, for
version-check, mount/unmount, ctrl-file set, etc.
You can take a look at the cgroup_lib.sh, I think it will be more
convenient to reuse the mature APIs.
> 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
The code you removed here is actually what we recommended as a way to
check the system's cgroup version :).
We can not simply rely on kernel versions to think the cgroup versions,
because for different Linux distributions, it may backport the new
feature to old kernels, and kind of Linux supports v1 and v2 flexibly.
--
Regards,
Li Wang
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-04-03 2:31 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-02 8:25 [LTP] [PATCH] cgroup: make regression test compatible with cgroup v2 Soma Das
2026-04-03 2:30 ` Li Wang via ltp
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox