diff mbox series

[v1] tst_cgroup.c: Force tst_cg_scan only scan specific cgroup version if needs_ver exist

Message ID 20241108053710.8639-1-wegao@suse.com
State Rejected
Headers show
Series [v1] tst_cgroup.c: Force tst_cg_scan only scan specific cgroup version if needs_ver exist | expand

Commit Message

Wei Gao Nov. 8, 2024, 5:37 a.m. UTC
tst_cgroup.c will scan cgroup mount point and check system's cgroup support status, both
cgroupv1 and cgroupv2, if your case only need check cgroupv1(such as needs_cgroup_ver = TST_CG_V1)
but your system contain cgroupv2 mount point, then TCONF will happen tell you your system already
mount cgroupv2, so test case will be skipped.

This change will fix above scenario, force check specific version of cgroup once you set needs_ver,
then test will continue try to create needs_ver of cgroup mount point.

This patch can be used by following cpuset02 case:
https://patchwork.ozlabs.org/project/ltp/patch/20240930135809.9300-1-wegao@suse.com/

Signed-off-by: Wei Gao <wegao@suse.com>
---
 include/tst_cgroup.h            |  2 +-
 lib/newlib_tests/tst_cgroup01.c |  2 +-
 lib/newlib_tests/tst_cgroup02.c |  2 +-
 lib/tst_cgroup.c                | 15 +++++++--------
 testcases/lib/tst_cgctl.c       |  4 ++--
 5 files changed, 12 insertions(+), 13 deletions(-)

Comments

Cyril Hrubis Nov. 8, 2024, 9:53 a.m. UTC | #1
Hi!
> tst_cgroup.c will scan cgroup mount point and check system's cgroup support status, both
> cgroupv1 and cgroupv2, if your case only need check cgroupv1(such as needs_cgroup_ver = TST_CG_V1)
> but your system contain cgroupv2 mount point, then TCONF will happen tell you your system already
> mount cgroupv2, so test case will be skipped.

I do not get what happens here. What is the exact test output that does
not work for you?

We have tst_cg_require() which attempts to mount either v1 or v2 as
described in options. However a controller can be mouted either in v1 or
v2 but not in both, so skipping the scan will not solve anything.
Wei Gao Nov. 8, 2024, 11:21 a.m. UTC | #2
On Fri, Nov 08, 2024 at 10:53:11AM +0100, Cyril Hrubis wrote:
> Hi!
> > tst_cgroup.c will scan cgroup mount point and check system's cgroup support status, both
> > cgroupv1 and cgroupv2, if your case only need check cgroupv1(such as needs_cgroup_ver = TST_CG_V1)
> > but your system contain cgroupv2 mount point, then TCONF will happen tell you your system already
> > mount cgroupv2, so test case will be skipped.
> 
> I do not get what happens here. What is the exact test output that does
> not work for you?

If you add .needs_cgroup_ver = TST_CG_V1 in cpuset02.c and running on sle-micro you will hit
https://github.com/linux-test-project/ltp/blob/6408294d83682635393e36c14bbd6ebd94fead94/lib/tst_cgroup.c#L892

Since sle-micro platform already create cgroupv2 mount point, the tst_cg_scan will get cgroupv2 info and
will not call cgroup_mount_v1.

> 
> We have tst_cg_require() which attempts to mount either v1 or v2 as
> described in options. However a controller can be mouted either in v1 or
> v2 but not in both, so skipping the scan will not solve anything.
> 
> -- 
> Cyril Hrubis
> chrubis@suse.cz
Cyril Hrubis Nov. 8, 2024, 11:23 a.m. UTC | #3
Hi!
> If you add .needs_cgroup_ver = TST_CG_V1 in cpuset02.c and running on sle-micro you will hit
> https://github.com/linux-test-project/ltp/blob/6408294d83682635393e36c14bbd6ebd94fead94/lib/tst_cgroup.c#L892
> 
> Since sle-micro platform already create cgroupv2 mount point, the tst_cg_scan will get cgroupv2 info and
> will not call cgroup_mount_v1.

And that is, as far as I can tell, correct. You cannot mount a
controller under v1 when it was already mounted under v2.
Wei Gao Nov. 11, 2024, 2:47 a.m. UTC | #4
On Fri, Nov 08, 2024 at 12:23:48PM +0100, Cyril Hrubis wrote:
> Hi!
> > If you add .needs_cgroup_ver = TST_CG_V1 in cpuset02.c and running on sle-micro you will hit
> > https://github.com/linux-test-project/ltp/blob/6408294d83682635393e36c14bbd6ebd94fead94/lib/tst_cgroup.c#L892
> > 
> > Since sle-micro platform already create cgroupv2 mount point, the tst_cg_scan will get cgroupv2 info and
> > will not call cgroup_mount_v1.
> 
> And that is, as far as I can tell, correct. You cannot mount a
> controller under v1 when it was already mounted under v2.
On sle-micro 6.1, you can mount v1 controller when it was already mounted under v2
And after you force mount v1 cpuset controller, the v2 cpuset controller will be removed

localhost:~ # mount | grep cgroup
cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot)

localhost:~ # ll /sys/fs/cgroup/
total 0
-r--r--r--  1 root root 0 Nov 11 01:39 cgroup.controllers
-rw-r--r--  1 root root 0 Nov 11 01:44 cgroup.max.depth
-rw-r--r--  1 root root 0 Nov 11 01:44 cgroup.max.descendants
-rw-r--r--  1 root root 0 Nov 11 01:39 cgroup.procs
-r--r--r--  1 root root 0 Nov 11 01:44 cgroup.stat
-rw-r--r--  1 root root 0 Nov 11 01:39 cgroup.subtree_control
-rw-r--r--  1 root root 0 Nov 11 01:44 cgroup.threads
-r--r--r--  1 root root 0 Nov 11 01:44 cpu.stat
-r--r--r--  1 root root 0 Nov 11 01:44 cpu.stat.local
-r--r--r--  1 root root 0 Nov 11 01:44 cpuset.cpus.effective  <<<<
-r--r--r--  1 root root 0 Nov 11 01:44 cpuset.mems.effective  <<<<
drwxr-xr-x  2 root root 0 Nov 11 01:39 dev-hugepages.mount
drwxr-xr-x  2 root root 0 Nov 11 01:39 dev-mqueue.mount
drwxr-xr-x  2 root root 0 Nov 11 01:39 init.scope
-rw-r--r--  1 root root 0 Nov 11 01:44 io.cost.model
-rw-r--r--  1 root root 0 Nov 11 01:44 io.cost.qos
-r--r--r--  1 root root 0 Nov 11 01:44 io.stat
drwxr-xr-x  2 root root 0 Nov 11 01:39 machine.slice
-r--r--r--  1 root root 0 Nov 11 01:44 memory.numa_stat
--w-------  1 root root 0 Nov 11 01:44 memory.reclaim
-r--r--r--  1 root root 0 Nov 11 01:44 memory.stat
-r--r--r--  1 root root 0 Nov 11 01:44 misc.capacity
drwxr-xr-x  2 root root 0 Nov 11 01:39 proc-fs-nfsd.mount
drwxr-xr-x  2 root root 0 Nov 11 01:39 sys-fs-fuse-connections.mount
drwxr-xr-x  2 root root 0 Nov 11 01:39 sys-kernel-config.mount
drwxr-xr-x  2 root root 0 Nov 11 01:39 sys-kernel-debug.mount
drwxr-xr-x  2 root root 0 Nov 11 01:39 sys-kernel-tracing.mount
drwxr-xr-x 40 root root 0 Nov 11 01:42 system.slice
drwxr-xr-x  2 root root 0 Nov 11 01:39 user.slice

localhost:/tmp # mkdir /var/tmp/cpuset
localhost:/tmp # mount -t cgroup -o cpuset cpuset /var/tmp/cpuset  <<<<<<
localhost:/tmp # ll /var/tmp/cpuset/
total 0
-rw-r--r-- 1 root root 0 Nov 11 01:53 cgroup.clone_children
-rw-r--r-- 1 root root 0 Nov 11 01:53 cgroup.procs
-r--r--r-- 1 root root 0 Nov 11 01:53 cgroup.sane_behavior
-rw-r--r-- 1 root root 0 Nov 11 01:53 cpuset.cpu_exclusive
-rw-r--r-- 1 root root 0 Nov 11 01:53 cpuset.cpus
-r--r--r-- 1 root root 0 Nov 11 01:53 cpuset.effective_cpus
-r--r--r-- 1 root root 0 Nov 11 01:53 cpuset.effective_mems
-rw-r--r-- 1 root root 0 Nov 11 01:53 cpuset.mem_exclusive
-rw-r--r-- 1 root root 0 Nov 11 01:53 cpuset.mem_hardwall
-rw-r--r-- 1 root root 0 Nov 11 01:53 cpuset.memory_migrate
-r--r--r-- 1 root root 0 Nov 11 01:53 cpuset.memory_pressure
-rw-r--r-- 1 root root 0 Nov 11 01:53 cpuset.memory_pressure_enabled
-rw-r--r-- 1 root root 0 Nov 11 01:53 cpuset.memory_spread_page
-rw-r--r-- 1 root root 0 Nov 11 01:53 cpuset.memory_spread_slab
-rw-r--r-- 1 root root 0 Nov 11 01:53 cpuset.mems
-rw-r--r-- 1 root root 0 Nov 11 01:53 cpuset.sched_load_balance <<<<<<
-rw-r--r-- 1 root root 0 Nov 11 01:53 cpuset.sched_relax_domain_level
-rw-r--r-- 1 root root 0 Nov 11 01:53 notify_on_release
-rw-r--r-- 1 root root 0 Nov 11 01:53 release_agent
-rw-r--r-- 1 root root 0 Nov 11 01:53 tasks

localhost:/tmp # ll /sys/fs/cgroup/
total 0
-r--r--r--  1 root root 0 Nov 11 01:44 cgroup.controllers
-rw-r--r--  1 root root 0 Nov 11 01:44 cgroup.max.depth
-rw-r--r--  1 root root 0 Nov 11 01:44 cgroup.max.descendants
-rw-r--r--  1 root root 0 Nov 11 01:44 cgroup.procs
-r--r--r--  1 root root 0 Nov 11 01:44 cgroup.stat
-rw-r--r--  1 root root 0 Nov 11 01:39 cgroup.subtree_control
-rw-r--r--  1 root root 0 Nov 11 01:44 cgroup.threads
-r--r--r--  1 root root 0 Nov 11 01:44 cpu.stat
-r--r--r--  1 root root 0 Nov 11 01:44 cpu.stat.local
drwxr-xr-x  2 root root 0 Nov 11 01:39 dev-hugepages.mount
drwxr-xr-x  2 root root 0 Nov 11 01:39 dev-mqueue.mount
drwxr-xr-x  2 root root 0 Nov 11 01:39 init.scope
-rw-r--r--  1 root root 0 Nov 11 01:44 io.cost.model
-rw-r--r--  1 root root 0 Nov 11 01:44 io.cost.qos
-r--r--r--  1 root root 0 Nov 11 01:44 io.stat
drwxr-xr-x  2 root root 0 Nov 11 01:39 machine.slice
-r--r--r--  1 root root 0 Nov 11 01:44 memory.numa_stat
--w-------  1 root root 0 Nov 11 01:44 memory.reclaim
-r--r--r--  1 root root 0 Nov 11 01:44 memory.stat
-r--r--r--  1 root root 0 Nov 11 01:44 misc.capacity
drwxr-xr-x  2 root root 0 Nov 11 01:39 proc-fs-nfsd.mount
drwxr-xr-x  2 root root 0 Nov 11 01:39 sys-fs-fuse-connections.mount
drwxr-xr-x  2 root root 0 Nov 11 01:39 sys-kernel-config.mount
drwxr-xr-x  2 root root 0 Nov 11 01:39 sys-kernel-debug.mount
drwxr-xr-x  2 root root 0 Nov 11 01:39 sys-kernel-tracing.mount
drwxr-xr-x 40 root root 0 Nov 11 02:01 system.slice
drwxr-xr-x  2 root root 0 Nov 11 01:39 user.slice

localhost:/tmp # mount | grep cgroup
cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot)
cpuset on /var/tmp/cpuset type cgroup (rw,relatime,cpuset)


> 
> -- 
> Cyril Hrubis
> chrubis@suse.cz
Cyril Hrubis Nov. 11, 2024, 12:08 p.m. UTC | #5
Hi!
> On sle-micro 6.1, you can mount v1 controller when it was already mounted under v2
> And after you force mount v1 cpuset controller, the v2 cpuset controller will be removed
>
> localhost:~ # mount | grep cgroup
> cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot)
> 
> localhost:~ # ll /sys/fs/cgroup/
> total 0
> -r--r--r--  1 root root 0 Nov 11 01:39 cgroup.controllers
> -rw-r--r--  1 root root 0 Nov 11 01:44 cgroup.max.depth
> -rw-r--r--  1 root root 0 Nov 11 01:44 cgroup.max.descendants
> -rw-r--r--  1 root root 0 Nov 11 01:39 cgroup.procs
> -r--r--r--  1 root root 0 Nov 11 01:44 cgroup.stat
> -rw-r--r--  1 root root 0 Nov 11 01:39 cgroup.subtree_control
> -rw-r--r--  1 root root 0 Nov 11 01:44 cgroup.threads
> -r--r--r--  1 root root 0 Nov 11 01:44 cpu.stat
> -r--r--r--  1 root root 0 Nov 11 01:44 cpu.stat.local
> -r--r--r--  1 root root 0 Nov 11 01:44 cpuset.cpus.effective  <<<<
> -r--r--r--  1 root root 0 Nov 11 01:44 cpuset.mems.effective  <<<<
> drwxr-xr-x  2 root root 0 Nov 11 01:39 dev-hugepages.mount
> drwxr-xr-x  2 root root 0 Nov 11 01:39 dev-mqueue.mount
> drwxr-xr-x  2 root root 0 Nov 11 01:39 init.scope
> -rw-r--r--  1 root root 0 Nov 11 01:44 io.cost.model
> -rw-r--r--  1 root root 0 Nov 11 01:44 io.cost.qos
> -r--r--r--  1 root root 0 Nov 11 01:44 io.stat
> drwxr-xr-x  2 root root 0 Nov 11 01:39 machine.slice
> -r--r--r--  1 root root 0 Nov 11 01:44 memory.numa_stat
> --w-------  1 root root 0 Nov 11 01:44 memory.reclaim
> -r--r--r--  1 root root 0 Nov 11 01:44 memory.stat
> -r--r--r--  1 root root 0 Nov 11 01:44 misc.capacity
> drwxr-xr-x  2 root root 0 Nov 11 01:39 proc-fs-nfsd.mount
> drwxr-xr-x  2 root root 0 Nov 11 01:39 sys-fs-fuse-connections.mount
> drwxr-xr-x  2 root root 0 Nov 11 01:39 sys-kernel-config.mount
> drwxr-xr-x  2 root root 0 Nov 11 01:39 sys-kernel-debug.mount
> drwxr-xr-x  2 root root 0 Nov 11 01:39 sys-kernel-tracing.mount
> drwxr-xr-x 40 root root 0 Nov 11 01:42 system.slice
> drwxr-xr-x  2 root root 0 Nov 11 01:39 user.slice
> 
> localhost:/tmp # mkdir /var/tmp/cpuset
> localhost:/tmp # mount -t cgroup -o cpuset cpuset /var/tmp/cpuset  <<<<<<

You are supposed to get an error here, at least that is what I thought.

I do get error here on vanilla 6.10 but on debian 6.1 the mount succeeds
as well. CCing Michal.

Michal I was under an impression that a controller that has been bound
to v2 cannot be removed from there and bound to v1 anymore, but it seems
that it may happen in some cases.

> localhost:/tmp # ll /var/tmp/cpuset/
> total 0
> -rw-r--r-- 1 root root 0 Nov 11 01:53 cgroup.clone_children
> -rw-r--r-- 1 root root 0 Nov 11 01:53 cgroup.procs
> -r--r--r-- 1 root root 0 Nov 11 01:53 cgroup.sane_behavior
> -rw-r--r-- 1 root root 0 Nov 11 01:53 cpuset.cpu_exclusive
> -rw-r--r-- 1 root root 0 Nov 11 01:53 cpuset.cpus
> -r--r--r-- 1 root root 0 Nov 11 01:53 cpuset.effective_cpus
> -r--r--r-- 1 root root 0 Nov 11 01:53 cpuset.effective_mems
> -rw-r--r-- 1 root root 0 Nov 11 01:53 cpuset.mem_exclusive
> -rw-r--r-- 1 root root 0 Nov 11 01:53 cpuset.mem_hardwall
> -rw-r--r-- 1 root root 0 Nov 11 01:53 cpuset.memory_migrate
> -r--r--r-- 1 root root 0 Nov 11 01:53 cpuset.memory_pressure
> -rw-r--r-- 1 root root 0 Nov 11 01:53 cpuset.memory_pressure_enabled
> -rw-r--r-- 1 root root 0 Nov 11 01:53 cpuset.memory_spread_page
> -rw-r--r-- 1 root root 0 Nov 11 01:53 cpuset.memory_spread_slab
> -rw-r--r-- 1 root root 0 Nov 11 01:53 cpuset.mems
> -rw-r--r-- 1 root root 0 Nov 11 01:53 cpuset.sched_load_balance <<<<<<
> -rw-r--r-- 1 root root 0 Nov 11 01:53 cpuset.sched_relax_domain_level
> -rw-r--r-- 1 root root 0 Nov 11 01:53 notify_on_release
> -rw-r--r-- 1 root root 0 Nov 11 01:53 release_agent
> -rw-r--r-- 1 root root 0 Nov 11 01:53 tasks
> 
> localhost:/tmp # ll /sys/fs/cgroup/
> total 0
> -r--r--r--  1 root root 0 Nov 11 01:44 cgroup.controllers
> -rw-r--r--  1 root root 0 Nov 11 01:44 cgroup.max.depth
> -rw-r--r--  1 root root 0 Nov 11 01:44 cgroup.max.descendants
> -rw-r--r--  1 root root 0 Nov 11 01:44 cgroup.procs
> -r--r--r--  1 root root 0 Nov 11 01:44 cgroup.stat
> -rw-r--r--  1 root root 0 Nov 11 01:39 cgroup.subtree_control
> -rw-r--r--  1 root root 0 Nov 11 01:44 cgroup.threads
> -r--r--r--  1 root root 0 Nov 11 01:44 cpu.stat
> -r--r--r--  1 root root 0 Nov 11 01:44 cpu.stat.local
> drwxr-xr-x  2 root root 0 Nov 11 01:39 dev-hugepages.mount
> drwxr-xr-x  2 root root 0 Nov 11 01:39 dev-mqueue.mount
> drwxr-xr-x  2 root root 0 Nov 11 01:39 init.scope
> -rw-r--r--  1 root root 0 Nov 11 01:44 io.cost.model
> -rw-r--r--  1 root root 0 Nov 11 01:44 io.cost.qos
> -r--r--r--  1 root root 0 Nov 11 01:44 io.stat
> drwxr-xr-x  2 root root 0 Nov 11 01:39 machine.slice
> -r--r--r--  1 root root 0 Nov 11 01:44 memory.numa_stat
> --w-------  1 root root 0 Nov 11 01:44 memory.reclaim
> -r--r--r--  1 root root 0 Nov 11 01:44 memory.stat
> -r--r--r--  1 root root 0 Nov 11 01:44 misc.capacity
> drwxr-xr-x  2 root root 0 Nov 11 01:39 proc-fs-nfsd.mount
> drwxr-xr-x  2 root root 0 Nov 11 01:39 sys-fs-fuse-connections.mount
> drwxr-xr-x  2 root root 0 Nov 11 01:39 sys-kernel-config.mount
> drwxr-xr-x  2 root root 0 Nov 11 01:39 sys-kernel-debug.mount
> drwxr-xr-x  2 root root 0 Nov 11 01:39 sys-kernel-tracing.mount
> drwxr-xr-x 40 root root 0 Nov 11 02:01 system.slice
> drwxr-xr-x  2 root root 0 Nov 11 01:39 user.slice
> 
> localhost:/tmp # mount | grep cgroup
> cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot)
> cpuset on /var/tmp/cpuset type cgroup (rw,relatime,cpuset)
Cyril Hrubis Dec. 5, 2024, 1:16 p.m. UTC | #6
Hi!
> > You are supposed to get an error here, at least that is what I thought.
> 
> That depends -- if the controller's tasks are all in its (only) root
> cgroup, it can be re-bind between hierarchies (v1 to v2 or vice versa).
> 
> > I do get error here on vanilla 6.10 but on debian 6.1 the mount succeeds
> > as well. CCing Michal.
> 
> If /sys/fs/cgroup/cgroup.subtree_control contains `cpuset`, it's likely
> used by some of the services, hence not all tasks are in the root cgroup
> and re-binding fails. That's what can differ between systems.
> 
> > Michal I was under an impression that a controller that has been bound
> > to v2 cannot be removed from there and bound to v1 anymore, but it seems
> > that it may happen in some cases.
> 
> It can happen under the condition above.
> (And in a future kernel it may be truly unavailable in v1 with
> !CONFIG_CPUSETS_V1.)

Thanks for the clarifications.

I still do not think that re-binding controllers to v1 is a good idea
though. Firstly v1 is being phased out and we will eventually get rid
of it, so there is no point in investing too much effort into v1 testing
in hybrid environments.

And secondly I fear that we may end up skipping v2 tests because of the
rebinding. What I think may happen is that the cgroup cleanup is
asynchronous which means that there still would be remnants of the v1
cpuset cgroup even after the particular v1 test would exit, which would
cause next test a v2 test to be skipped, because the rebinding would
fail.
Wei Gao Dec. 9, 2024, 11:25 a.m. UTC | #7
On Thu, Dec 05, 2024 at 02:16:38PM +0100, Cyril Hrubis wrote:
> Hi!
> > > You are supposed to get an error here, at least that is what I thought.
> > 
> > That depends -- if the controller's tasks are all in its (only) root
> > cgroup, it can be re-bind between hierarchies (v1 to v2 or vice versa).
> > 
> > > I do get error here on vanilla 6.10 but on debian 6.1 the mount succeeds
> > > as well. CCing Michal.
> > 
> > If /sys/fs/cgroup/cgroup.subtree_control contains `cpuset`, it's likely
> > used by some of the services, hence not all tasks are in the root cgroup
> > and re-binding fails. That's what can differ between systems.
> > 
> > > Michal I was under an impression that a controller that has been bound
> > > to v2 cannot be removed from there and bound to v1 anymore, but it seems
> > > that it may happen in some cases.
> > 
> > It can happen under the condition above.
> > (And in a future kernel it may be truly unavailable in v1 with
> > !CONFIG_CPUSETS_V1.)
> 
> Thanks for the clarifications.
> 
> I still do not think that re-binding controllers to v1 is a good idea
> though. Firstly v1 is being phased out and we will eventually get rid
> of it, so there is no point in investing too much effort into v1 testing
> in hybrid environments.
> 
> And secondly I fear that we may end up skipping v2 tests because of the
> rebinding. What I think may happen is that the cgroup cleanup is
> asynchronous which means that there still would be remnants of the v1
> cpuset cgroup even after the particular v1 test would exit, which would
> cause next test a v2 test to be skipped, because the rebinding would
> fail.

Thanks all for feedback, so we can skip this patch.

> 
> -- 
> Cyril Hrubis
> chrubis@suse.cz
diff mbox series

Patch

diff --git a/include/tst_cgroup.h b/include/tst_cgroup.h
index d23a8e652..ff1c4ece0 100644
--- a/include/tst_cgroup.h
+++ b/include/tst_cgroup.h
@@ -117,7 +117,7 @@  extern const struct tst_cg_group *const tst_cg_drain;
 /* Search the system for mounted cgroups and available
  * controllers. Called automatically by tst_cg_require.
  */
-void tst_cg_scan(void);
+void tst_cg_scan(enum tst_cg_ver needs_ver);
 /* Print the config detected by tst_cg_scan and print the internal
  * state associated with each controller. Output can be passed to
  * tst_cg_load_config to configure the internal state to that of the
diff --git a/lib/newlib_tests/tst_cgroup01.c b/lib/newlib_tests/tst_cgroup01.c
index eda0c548d..00bced72b 100644
--- a/lib/newlib_tests/tst_cgroup01.c
+++ b/lib/newlib_tests/tst_cgroup01.c
@@ -23,7 +23,7 @@  static void setup(void)
 {
 	cgopts.needs_ver = !!only_mount_v1 ? TST_CG_V1 : 0;
 
-	tst_cg_scan();
+	tst_cg_scan(0);
 	tst_cg_print_config();
 
 	tst_cg_require("memory", &cgopts);
diff --git a/lib/newlib_tests/tst_cgroup02.c b/lib/newlib_tests/tst_cgroup02.c
index de2ca1812..47d1c6b2a 100644
--- a/lib/newlib_tests/tst_cgroup02.c
+++ b/lib/newlib_tests/tst_cgroup02.c
@@ -58,7 +58,7 @@  static void setup(void)
 {
 	cgopts.needs_ver = !!only_mount_v1 ? TST_CG_V1 : 0;
 
-	tst_cg_scan();
+	tst_cg_scan(0);
 	tst_cg_print_config();
 
 	tst_cg_require("memory", &cgopts);
diff --git a/lib/tst_cgroup.c b/lib/tst_cgroup.c
index 1404116a5..652bb70b5 100644
--- a/lib/tst_cgroup.c
+++ b/lib/tst_cgroup.c
@@ -657,7 +657,7 @@  discard:
 	close(mnt_dfd);
 }
 
-void tst_cg_scan(void)
+void tst_cg_scan(enum tst_cg_ver needs_ver)
 {
 	struct mntent *mnt;
 	FILE *f = setmntent("/proc/self/mounts", "r");
@@ -674,10 +674,9 @@  void tst_cg_scan(void)
 	}
 
 	do {
-		if (strncmp(mnt->mnt_type, "cgroup", 6))
-			continue;
-
-		cgroup_root_scan(mnt->mnt_type, mnt->mnt_dir, mnt->mnt_opts);
+		if ((!strcmp(mnt->mnt_type, "cgroup") && (needs_ver != TST_CG_V2)) ||
+			(!strcmp(mnt->mnt_type, "cgroup2") && (needs_ver != TST_CG_V1)))
+			cgroup_root_scan(mnt->mnt_type, mnt->mnt_dir, mnt->mnt_opts);
 	} while ((mnt = getmntent(f)));
 }
 
@@ -717,7 +716,7 @@  mount:
 
 	if (!ret) {
 		tst_res(TINFO, "Mounted V2 CGroups on %s", mnt_path);
-		tst_cg_scan();
+		tst_cg_scan(TST_CG_V2);
 		roots[0].we_mounted_it = 1;
 		return;
 	}
@@ -775,7 +774,7 @@  mount:
 	}
 
 	tst_res(TINFO, "Mounted V1 %s CGroup on %s", ctrl->ctrl_name, mnt_path);
-	tst_cg_scan();
+	tst_cg_scan(TST_CG_V1);
 	if (!ctrl->ctrl_root)
 		return;
 
@@ -856,7 +855,7 @@  void tst_cg_require(const char *const ctrl_name,
 	if (ctrl->ctrl_root)
 		goto mkdirs;
 
-	tst_cg_scan();
+	tst_cg_scan(options->needs_ver);
 
 	if (ctrl->ctrl_root)
 		goto mkdirs;
diff --git a/testcases/lib/tst_cgctl.c b/testcases/lib/tst_cgctl.c
index 2685bef81..6f324f780 100644
--- a/testcases/lib/tst_cgctl.c
+++ b/testcases/lib/tst_cgctl.c
@@ -30,7 +30,7 @@  static int cgctl_require(const char *ctrl, int test_pid)
 
 static int cgctl_cleanup(const char *const config)
 {
-	tst_cg_scan();
+	tst_cg_scan(0);
 	tst_cg_load_config(config);
 	tst_cg_cleanup();
 
@@ -39,7 +39,7 @@  static int cgctl_cleanup(const char *const config)
 
 static int cgctl_print(void)
 {
-	tst_cg_scan();
+	tst_cg_scan(0);
 	tst_cg_print_config();
 
 	return 0;