Skip to content

cgroup: regression test fails on kernel >= 5.8 due to cgroup v2 default mount #1302

@somadas1-code

Description

@somadas1-code

A fix for this issue has already been submitted to the LTP mailing list:
https://lore.kernel.org/ltp/20260402082546.3245433-1-somadas1@linux.ibm.com/T/#u

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.

Failure output (before fix):

===== cgroup =====
command: cgroup_regression_test.sh
[115020.644391] ./kirk[625449]: starting test cgroup (cgroup_regression_test.sh)
cgroup_regression_test 1 TINFO: Running: cgroup_regression_test.sh 
cgroup_regression_test 1 TINFO: Tested kernel: Linux fitlp117.isst.tadn.ibm.com 6.12.0-211.1.1.el10_2.ppc64le #1 SMP Tue Mar  3 11:30:56 EST 2026 ppc64le GNU/Linux
cgroup_regression_test 1 TINFO: Using /tmp/LTP_cgroup_regression_test.uzKZfc5S2o as tmpdir (ext2/ext3 filesystem)
cgroup_regression_test 1 TINFO: ceiling LTP_TIMEOUT_MUL to 11
cgroup_regression_test 1 TINFO: timeout per run is 0h 55m 0s
cgroup_regression_test 1 TPASS: no kernel bug was found
mount: /tmp/LTP_cgroup_regression_test.uzKZfc5S2o/cgroup: cgroup already mounted or mount point busy.
       dmesg(1) may have more information after failed mount system call.
cgroup_regression_test 2 TFAIL: Failed to mount cgroup filesystem
cgroup_regression_test 3 TCONF: CONFIG_SCHED_DEBUG is not enabled
cgroup_regression_test 4 TCONF: CONFIG_LOCKDEP is not enabled
cgroup_regression_test 5 TINFO: The '/tmp/LTP_cgroup_regression_test.uzKZfc5S2o/cgroup' is not mounted, skipping umount
cgroup_regression_test 5 TPASS: no kernel bug was found
cgroup_regression_test 6 TPASS: no kernel bug was found
cgroup_regression_test 7 TPASS: no kernel bug was found for test 1
[115081.893545] option changes via remount are deprecated (pid=774812 comm=mount)
cgroup_regression_test 7 TCONF: skip rest of testing due possible oops triggered by reading /proc/sched_debug
cgroup_regression_test 7 TPASS: no kernel bug was found for test 2
[115081.904213] netlink: 'cgroup_regressi': attribute type 1 has an invalid length.
cgroup_regression_test 8 TPASS: no kernel bug was found

Summary:
passed   6
failed   1
broken   0
skipped  3
warnings 0

Duration: 2m 41s

Output after fix:

root@fitlp112:~/ltp/testcases/kernel/controllers/cgroup ./cgroup_regression_test.sh
cgroup_regression_test 1 TINFO: Running: cgroup_regression_test.sh 
cgroup_regression_test 1 TINFO: Tested kernel: Linux fitlp112.isst.tadn.ibm.com 6.12.0-211.1.1.el10_2.ppc64le #1 SMP Tue Mar  3 11:30:56 EST 2026 ppc64le GNU/Linux
cgroup_regression_test 1 TINFO: trying to disable AppArmor (requires super/root)
cgroup_regression_test 1 TINFO: Using /tmp/LTP_cgroup_regression_test.O6wiOHjT9k as tmpdir (xfs filesystem)
cgroup_regression_test 1 TINFO: timeout per run is 3h 20m 0s
cgroup_regression_test 1 TINFO: Kernel 6.12.0-211.1.1.el10_2.ppc64le: version >= 5.8 (mounts cgroup v2 by default)
cgroup_regression_test 1 TCONF: cgroup v2 already active - cannot mount v1 on this kernel
cgroup_regression_test 2 TCONF: cgroup v2 already active - cannot mount v1 on this kernel
cgroup_regression_test 3 TCONF: CONFIG_SCHED_DEBUG is not enabled
cgroup_regression_test 4 TCONF: cgroup v2 already active - skipping v1 test
cgroup_regression_test 5 TCONF: cgroup v2 already active - skipping v1 test
cgroup_regression_test 6 TPASS: no kernel bug was found
cgroup_regression_test 7 TPASS: no kernel bug was found for test 1
cgroup_regression_test 7 TCONF: skip rest of testing due possible oops triggered by reading /proc/sched_debug
cgroup_regression_test 7 TPASS: no kernel bug was found for test 2
cgroup_regression_test 8 TCONF: cgroup v2 already active - skipping v1 test

Summary:
passed   3
failed   0
broken   0
skipped  7
warnings 0

System info:

  • Kernel: 6.12.0-211.1.1.el10_2.ppc64le
  • Architecture: ppc64le
  • Distribution: Red Hat Enterprise Linux 10.2 Beta (Coughlan)

Patch is attached below:

.../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>](mailto:pvorel@suse.cz)
 # Copyright (c) 2009 FUJITSU LIMITED
-# Author: Li Zefan [<lizf@cn.fujitsu.com>](mailto:lizf@cn.fujitsu.com)
-
+# Author: Li Zefan [<lizf@cn.fujitsu.com>](mailto: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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions