xref: /aosp_15_r20/external/ltp/testcases/kernel/controllers/cpuset/cpuset_funcs.sh (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1#!/bin/sh
2# usage: . cpuset_funcs.sh
3# functions for cpuset test
4
5################################################################################
6##                                                                            ##
7## Copyright (c) 2009 FUJITSU LIMITED                                         ##
8##                                                                            ##
9## This program is free software;  you can redistribute it and#or modify      ##
10## it under the terms of the GNU General Public License as published by       ##
11## the Free Software Foundation; either version 2 of the License, or          ##
12## (at your option) any later version.                                        ##
13##                                                                            ##
14## This program is distributed in the hope that it will be useful, but        ##
15## WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ##
16## or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License   ##
17## for more details.                                                          ##
18##                                                                            ##
19## You should have received a copy of the GNU General Public License          ##
20## along with this program;  if not, write to the Free Software               ##
21## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA    ##
22##                                                                            ##
23## Author: Miao Xie <[email protected]>                                    ##
24##                                                                            ##
25################################################################################
26
27. test.sh
28
29cpu_string="`cat /sys/devices/system/cpu/online`"
30NR_CPUS=`tst_ncpus`
31
32if [ -f "/sys/devices/system/node/has_high_memory" ]; then
33	mem_string="`cat /sys/devices/system/node/has_high_memory`"
34else
35	mem_string="`cat /sys/devices/system/node/has_normal_memory`"
36fi
37N_NODES="`echo $mem_string | tr ',' ' '`"
38count=0
39final_node=0
40for item in $N_NODES; do
41	delta=1
42	if [ "${item#*-*}" != "$item" ]; then
43		delta=$((${item#*-*} - ${item%*-*} + 1))
44	fi
45	final_node=${item#*-*}
46	count=$((count + $delta))
47done
48final_node=$((final_node + 1))
49N_NODES=$count
50
51final_cpu=0
52N_CPUS="`echo $cpu_string | tr ',' ' '`"
53for item in $N_CPUS; do
54	final_cpu=${item#*-*}
55done
56final_cpu=$((final_cpu + 1))
57
58CPUSET="/dev/cpuset"
59CPUSET_TMP="/tmp/cpuset_tmp"
60CLONE_CHILDREN="/dev/cpuset/cgroup.clone_children"
61CHILDREN_VALUE="0"
62HOTPLUG_CPU="1"
63SCHED_LB="/dev/cpuset/cpuset.sched_load_balance"
64SCHED_LB_VALUE="0"
65
66cpuset_log()
67{
68	tst_resm TINFO "$*"
69}
70
71# cpuset_log_error <error_file>
72cpuset_log_error()
73{
74	local error_message=
75
76	while read error_message
77	do
78		cpuset_log "$error_message"
79	done < "$1"
80}
81
82ncpus_check()
83{
84	if [ $NR_CPUS -lt $1 ]; then
85		tst_brkm TCONF "The total of CPUs is less than $1"
86	fi
87	# check online cpus whether match 0-num
88	if [ $final_cpu -eq $NR_CPUS ]; then
89		tst_resm TINFO "CPUs are numbered continuously starting at 0 ($cpu_string)"
90	else
91		tst_brkm TCONF "CPUs are not numbered continuously starting at 0 ($cpu_string)"
92	fi
93}
94
95nnodes_check()
96{
97	if [ $N_NODES -lt $1 ]; then
98		tst_brkm TCONF "The total of nodes is less than $1"
99	fi
100	# check online nodes whether match 0-num
101	if [ $final_node -eq $N_NODES ]; then
102		tst_resm TINFO "Nodes are numbered continuously starting at 0 ($mem_string)"
103	else
104		tst_brkm TCONF "Nodes are not numbered continuously starting at 0 ($mem_string)"
105	fi
106}
107
108user_check()
109{
110	if [ $(id -u) != 0 ]; then
111		tst_brkm TCONF "Test must be run as root"
112	fi
113}
114
115cpuset_check()
116{
117        if [ -f /proc/cgroups ]; then
118		CPUSET_CONTROLLER=`grep -w cpuset /proc/cgroups | cut -f1`
119		CPUSET_CONTROLLER_VALUE=`grep -w cpuset /proc/cgroups | cut -f4`
120
121		if [ "$CPUSET_CONTROLLER" = "cpuset" ] && [ "$CPUSET_CONTROLLER_VALUE" = "1" ]
122		then
123			return 0
124		fi
125	fi
126
127	tst_brkm TCONF "Cpuset is not supported"
128}
129
130machine_check()
131{
132	if tst_virt_hyperv; then
133		tst_brkm TCONF "Microsoft Hyper-V detected, no support for CPU hotplug"
134	fi
135}
136
137# optional parameters (pass both or none of them):
138# $1 - required number of cpus (default 2)
139# $2 - required number of memory nodes (default 2)
140check()
141{
142	user_check
143
144	cpuset_check
145
146	ncpus_check ${1:-2}
147
148	nnodes_check ${2:-2}
149
150	machine_check
151}
152
153# Create /dev/cpuset & mount the cgroup file system with cpuset
154# clean any group created eralier (if any)
155setup()
156{
157	if [ -e "$CPUSET" ]
158	then
159		tst_resm TWARN "$CPUSET already exist.. overwriting"
160		cleanup || tst_brkm TFAIL "Can't cleanup... Exiting"
161	fi
162
163	mkdir -p "$CPUSET_TMP"
164	mkdir "$CPUSET"
165	mount -t cgroup -o cpuset cpuset "$CPUSET" 2> /dev/null
166	if [ $? -ne 0 ]; then
167		cleanup
168		tst_brkm TCONF "Could not mount cgroup filesystem with cpuset on $CPUSET"
169	fi
170
171	CHILDREN_VALUE="`cat $CLONE_CHILDREN`"
172	SCHED_LB_VALUE="`cat $SCHED_LB`"
173}
174
175# Write the cleanup function
176cleanup()
177{
178	grep "$CPUSET" /proc/mounts >/dev/null 2>&1 || {
179		rm -rf "$CPUSET" >/dev/null 2>&1
180		return 0
181	}
182
183	echo $CHILDREN_VALUE > $CLONE_CHILDREN
184	echo $SCHED_LB_VALUE > $SCHED_LB
185
186	find "$CPUSET" -type d | sort | sed -n '2,$p' | tac | while read -r subdir
187	do
188		while read pid
189		do
190			/bin/kill -9 $pid > /dev/null 2>&1
191			if [ $? -ne 0 ]; then
192				tst_brkm TFAIL "Couldn't kill task - "\
193							"$pid in the cpuset"
194			fi
195		done < "$subdir/tasks"
196		rmdir "$subdir"
197		if [ $? -ne 0 ]; then
198			tst_brkm TFAIL "Couldn't remove subdir - "
199						"$subdir in the cpuset"
200		fi
201	done
202
203	umount "$CPUSET"
204	if [ $? -ne 0 ]; then
205		tst_brkm TFAIL "Couldn't umount cgroup filesystem with"\
206					" cpuset on $CPUSET..Exiting test"
207	fi
208	rmdir "$CPUSET" > /dev/null 2>&1
209	rm -rf "$CPUSET_TMP" > /dev/null 2>&1
210}
211
212# set the cpuset's parameter
213# cpuset_set <cpusetpath> <cpus> <mems> <load_balance>
214cpuset_set()
215{
216	local path="$1"
217	mkdir -p "$path"
218	if [ $? -ne 0 ]; then
219		return 1
220	fi
221
222	local cpus="$2"
223	local mems="$3"
224	local load_balance="$4"
225
226	if [ "$path" != "$CPUSET" ]; then
227		if [ "$cpus" != "-" ]; then
228			/bin/echo $cpus > $path/cpuset.cpus
229			if [ $? -ne 0 ]; then
230				return 1
231			fi
232		fi
233
234		/bin/echo $mems > $path/cpuset.mems
235		if [ $? -ne 0 ]; then
236			return 1
237		fi
238	fi
239
240	/bin/echo $load_balance > $path/cpuset.sched_load_balance
241	if [ $? -ne 0 ]; then
242		return 1
243	fi
244}
245
246# cpu_hotplug cpu_id offline/online
247cpu_hotplug()
248{
249	if [ "$2" = "online" ]; then
250		/bin/echo 1 > "/sys/devices/system/cpu/cpu$1/online"
251		if [ $? -ne 0 ]; then
252			return 1
253		fi
254	elif [ "$2" = "offline" ]; then
255		/bin/echo 0 > "/sys/devices/system/cpu/cpu$1/online"
256		if [ $? -ne 0 ]; then
257			return 1
258		fi
259	fi
260}
261
262# setup_test_environment <online | offline>
263#   online  - online a CPU in testing, so we must offline a CPU first
264#   offline - offline a CPU in testing, we needn't do anything
265setup_test_environment()
266{
267	if [ "$1" = "online" ]; then
268		cpu_hotplug $HOTPLUG_CPU offline
269		if [ $? -ne 0 ]; then
270			return 1
271		fi
272	fi
273}
274
275cpu_hotplug_cleanup()
276{
277	local cpus_array="$(seq -s' ' 1 $((NR_CPUS-1)))"
278	local cpuid=
279	for cpuid in $cpus_array
280	do
281		local file="/sys/devices/system/cpu/cpu$cpuid/online"
282		local offline="$(cat $file)"
283		if [ $offline -eq 0 ]; then
284			cpu_hotplug $cpuid "online"
285		fi
286	done
287}
288
289