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 <miaox@cn.fujitsu.com>                                    ##
24##                                                                            ##
25################################################################################
26
27. test.sh
28
29NR_CPUS=`tst_ncpus`
30if [ -f "/sys/devices/system/node/has_high_memory" ]; then
31	N_NODES="`cat /sys/devices/system/node/has_high_memory`"
32else
33	N_NODES="`cat /sys/devices/system/node/has_normal_memory`"
34fi
35N_NODES=${N_NODES#*-*}
36N_NODES=$(($N_NODES + 1))
37
38CPUSET="/dev/cpuset"
39CPUSET_TMP="/tmp/cpuset_tmp"
40
41HOTPLUG_CPU="1"
42
43cpuset_log()
44{
45	tst_resm TINFO "$*"
46}
47
48# cpuset_log_error <error_file>
49cpuset_log_error()
50{
51	local error_message=
52
53	while read error_message
54	do
55		cpuset_log "$error_message"
56	done < "$1"
57}
58
59version_check()
60{
61	if tst_kvcmp -lt "2.6.28"; then
62		tst_brkm TCONF "kernel is below 2.6.28"
63	fi
64}
65
66ncpus_check()
67{
68	if [ $NR_CPUS -lt $1 ]; then
69		tst_brkm TCONF "The total of CPUs is less than $1"
70	fi
71}
72
73nnodes_check()
74{
75	if [ $N_NODES -lt $1 ]; then
76		tst_brkm TCONF "The total of nodes is less than $1"
77	fi
78}
79
80user_check()
81{
82	if [ $(id -u) != 0 ]; then
83		tst_brkm TCONF "Test must be run as root"
84	fi
85}
86
87cpuset_check()
88{
89        if [ -f /proc/cgroups ]; then
90		CPUSET_CONTROLLER=`grep -w cpuset /proc/cgroups | cut -f1`
91		CPUSET_CONTROLLER_VALUE=`grep -w cpuset /proc/cgroups | cut -f4`
92
93		if [ "$CPUSET_CONTROLLER" = "cpuset" ] && [ "$CPUSET_CONTROLLER_VALUE" = "1" ]
94		then
95			return 0
96		fi
97	fi
98
99	tst_brkm TCONF "Cpuset is not supported"
100}
101
102# optional parameters (pass both or none of them):
103# $1 - required number of cpus (default 2)
104# $2 - required number of memory nodes (default 2)
105check()
106{
107	user_check
108
109	cpuset_check
110
111	version_check
112
113	ncpus_check ${1:-2}
114
115	nnodes_check ${2:-2}
116
117}
118
119# Create /dev/cpuset & mount the cgroup file system with cpuset
120# clean any group created eralier (if any)
121setup()
122{
123	if [ -e "$CPUSET" ]
124	then
125		tst_resm TWARN "$CPUSET already exist.. overwriting"
126		cleanup || tst_brkm TFAIL "Can't cleanup... Exiting"
127	fi
128
129	mkdir -p "$CPUSET_TMP"
130	mkdir "$CPUSET"
131	mount -t cgroup -o cpuset cpuset "$CPUSET" 2> /dev/null
132	if [ $? -ne 0 ]; then
133		cleanup
134		tst_brkm TFAIL "Could not mount cgroup filesystem with"\
135					" cpuset on $CPUSET..Exiting test"
136	fi
137}
138
139# Write the cleanup function
140cleanup()
141{
142	grep "$CPUSET" /proc/mounts >/dev/null 2>&1 || {
143		rm -rf "$CPUSET" >/dev/null 2>&1
144		return 0
145	}
146
147	find "$CPUSET" -type d | sort | sed -n '2,$p' | tac | while read subdir
148	do
149		while read pid
150		do
151			/bin/kill -9 $pid > /dev/null 2>&1
152			if [ $? -ne 0 ]; then
153				tst_brkm TFAIL "Couldn't kill task - "\
154							"$pid in the cpuset"
155			fi
156		done < "$subdir/tasks"
157		rmdir "$subdir"
158		if [ $? -ne 0 ]; then
159			tst_brkm TFAIL "Couldn't remove subdir - "
160						"$subdir in the cpuset"
161		fi
162	done
163
164	umount "$CPUSET"
165	if [ $? -ne 0 ]; then
166		tst_brkm TFAIL "Couldn't umount cgroup filesystem with"\
167					" cpuset on $CPUSET..Exiting test"
168	fi
169	rmdir "$CPUSET" > /dev/null 2>&1
170	rm -rf "$CPUSET_TMP" > /dev/null 2>&1
171}
172
173# set the cpuset's parameter
174# cpuset_set <cpusetpath> <cpus> <mems> <load_balance>
175cpuset_set()
176{
177	local path="$1"
178	mkdir -p "$path"
179	if [ $? -ne 0 ]; then
180		return 1
181	fi
182
183	local cpus="$2"
184	local mems="$3"
185	local load_balance="$4"
186
187	if [ "$path" != "$CPUSET" ]; then
188		if [ "$cpus" != "-" ]; then
189			/bin/echo $cpus > $path/cpuset.cpus
190			if [ $? -ne 0 ]; then
191				return 1
192			fi
193		fi
194
195		/bin/echo $mems > $path/cpuset.mems
196		if [ $? -ne 0 ]; then
197			return 1
198		fi
199	fi
200
201	/bin/echo $load_balance > $path/cpuset.sched_load_balance
202	if [ $? -ne 0 ]; then
203		return 1
204	fi
205}
206
207# cpu_hotplug cpu_id offline/online
208cpu_hotplug()
209{
210	if [ "$2" = "online" ]; then
211		/bin/echo 1 > "/sys/devices/system/cpu/cpu$1/online"
212		if [ $? -ne 0 ]; then
213			return 1
214		fi
215	elif [ "$2" = "offline" ]; then
216		/bin/echo 0 > "/sys/devices/system/cpu/cpu$1/online"
217		if [ $? -ne 0 ]; then
218			return 1
219		fi
220	fi
221}
222
223# setup_test_environment <online | offline>
224#   online  - online a CPU in testing, so we must offline a CPU first
225#   offline - offline a CPU in testing, we needn't do anything
226setup_test_environment()
227{
228	if [ "$1" = "online" ]; then
229		cpu_hotplug $HOTPLUG_CPU offline
230		if [ $? -ne 0 ]; then
231			return 1
232		fi
233	fi
234}
235
236cpu_hotplug_cleanup()
237{
238	local cpus_array="$(seq -s' ' 1 $((NR_CPUS-1)))"
239	local cpuid=
240	for cpuid in $cpus_array
241	do
242		local file="/sys/devices/system/cpu/cpu$cpuid/online"
243		local offline="$(cat $file)"
244		if [ $offline -eq 0 ]; then
245			cpu_hotplug $cpuid "online"
246		fi
247	done
248}
249
250