• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0-or-later
3# Copyright (c) 2015 Fujitsu Ltd.
4# Author: Zeng Linggang <zenglg.jy@cn.fujitsu.com>
5#
6# This is a regression test for commit:
7# http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=bb2bc55
8#
9# A newly created cpuset group crashed the kernel, if exclusive was set to 1,
10# before a cpuset was set.
11
12TST_SETUP=setup
13TST_CLEANUP=cleanup
14TST_TESTFUNC=test
15TST_NEEDS_ROOT=1
16TST_NEEDS_TMPDIR=1
17TST_MIN_KVER="3.18"
18
19. cgroup_lib.sh
20
21LOCAL_MOUNTPOINT="cpuset_test"
22BACKUP_DIRECTORY="cpuset_backup"
23
24cpu_num=
25root_cpuset_dir=
26cpu_exclusive="cpuset.cpu_exclusive"
27cpus="cpuset.cpus"
28old_cpu_exclusive_value=1
29
30# Check if there are cpuset groups
31cpuset_has_groups()
32{
33	find ${root_cpuset_dir} -mindepth 1 -type d -exec echo 1 \; -quit
34}
35
36# cpuset_find_parent_first <what>
37# Do a parent first find of <what>
38cpuset_find_parent_first()
39{
40	local what=$1
41
42	find . -mindepth 2 -name ${what} |
43	    awk '{print length($0) " " $0}' |
44	    sort -n | cut -d " " -f 2-
45}
46
47# cpuset_find_child_first <what>
48# Do a child first find of <what>
49cpuset_find_child_first()
50{
51	local what=$1
52
53	find . -mindepth 2 -name ${what} |
54	    awk '{print length($0) " " $0}' |
55	    sort -nr | cut -d " " -f 2-
56}
57
58# cpuset_backup_and_update <backup_dir> <what>
59# Create backup of the values of a specific file (<what>)
60# in all cpuset groups and set the value to 1
61# The backup is written to <backup_dir> in the same structure
62# as in the cpuset filesystem
63cpuset_backup_and_update()
64{
65	local backup_dir=$1
66	local what=$2
67	local old_dir=$PWD
68	local cpu_max=$((cpu_num - 1))
69	local res
70
71	cd ${root_cpuset_dir}
72
73
74	cpuset_find_parent_first ${what} |
75	while read -r file; do
76		[ "$(cat "${file}")" = "" ] && continue
77
78		mkdir -p "$(dirname "${backup_dir}/${file}")"
79		cat "${file}" > "${backup_dir}/${file}"
80		echo "0-$cpu_max" > "${file}" || exit 1
81	done
82	if [ $? -ne 0 ]; then
83		cd $old_dir
84		return 1
85	fi
86
87	cpuset_find_child_first ${what} |
88	while read -r file; do
89		[ "$(cat "${file}")" = "" ] && continue
90		echo "1" > "${file}"
91	done
92	res=$?
93
94	cd $old_dir
95
96	return $res
97}
98
99# cpuset_restore <backup_dir> <what>
100# Restores the value of a file (<what>) in all cpuset
101# groups from the backup created by cpuset_backup_and_update
102cpuset_restore()
103{
104	local backup_dir=$1
105	local what=$2
106	local old_dir=$PWD
107	local cpu_max=$((cpu_num - 1))
108
109	cd ${backup_dir}
110
111	cpuset_find_parent_first ${what} |
112	while read -r file; do
113		echo "0-$cpu_max" > "${root_cpuset_dir}/${file}"
114	done
115
116	cpuset_find_child_first ${what} |
117	while read -r file; do
118		cat "${file}" > "${root_cpuset_dir}/${file}"
119	done
120
121	cd $old_dir
122}
123
124setup()
125{
126	if ! is_cgroup_subsystem_available_and_enabled "cpuset"; then
127		tst_brk TCONF "Either kernel does not support cpuset controller or feature not enabled"
128	fi
129
130	# We need to mount cpuset if it is not found.
131	root_cpuset_dir=$(get_cgroup_mountpoint cpuset)
132	if [ -z "$root_cpuset_dir" ]; then
133		root_cpuset_dir="$LOCAL_MOUNTPOINT"
134
135		ROD_SILENT mkdir -p ${root_cpuset_dir}
136		ROD_SILENT mount -t cpuset cpuset ${root_cpuset_dir}
137	fi
138
139	if ! [ -f ${root_cpuset_dir}/${cpu_exclusive} ]; then
140		cpu_exclusive=cpu_exclusive
141		cpus=cpus
142	fi
143
144	if ! [ -f ${root_cpuset_dir}/${cpu_exclusive} ]; then
145		tst_brk TBROK "Both cpuset.cpu_exclusive and cpu_exclusive do not exist"
146	fi
147
148	# Ensure that we can use cpu 0 exclusively
149	if [ "$(cpuset_has_groups)" = "1" ]; then
150		cpu_num=$(tst_getconf _NPROCESSORS_ONLN)
151		if [ $cpu_num -lt 2 ]; then
152			tst_brk TCONF "There are already cpuset groups, so at least two cpus are required."
153		fi
154
155		# Use cpu 1 for all existing cpuset cgroups
156		mkdir ${BACKUP_DIRECTORY}
157		cpuset_backup_and_update "${PWD}/${BACKUP_DIRECTORY}" ${cpus}
158		[ $? -ne 0 ] && tst_brk TBROK "Unable to prepare existing cpuset cgroups"
159	fi
160
161	old_cpu_exclusive_value=$(cat ${root_cpuset_dir}/${cpu_exclusive})
162	if [ "${old_cpu_exclusive_value}" != "1" ];then
163		echo 1 > ${root_cpuset_dir}/${cpu_exclusive}
164		[ $? -ne 0 ] && tst_brk TBROK "'echo 1 > ${root_cpuset_dir}/${cpu_exclusive}' failed"
165	fi
166}
167
168cleanup()
169{
170	if [ -d "${root_cpuset_dir}/testdir" ]; then
171		rmdir ${root_cpuset_dir}/testdir
172	fi
173
174	if [ -d "${BACKUP_DIRECTORY}" ]; then
175		cpuset_restore "${PWD}/${BACKUP_DIRECTORY}" ${cpus}
176	fi
177
178	if [ "$old_cpu_exclusive_value" != 1 ]; then
179		# Need to flush, or write may fail with: "Device or resource busy"
180		sync
181		echo ${old_cpu_exclusive_value} > ${root_cpuset_dir}/${cpu_exclusive}
182	fi
183
184	if [ -d "$LOCAL_MOUNTPOINT" ]; then
185		umount ${LOCAL_MOUNTPOINT}
186		if [ $? -ne 0 ]; then
187			tst_res TWARN "'umount ${LOCAL_MOUNTPOINT}' failed"
188		fi
189
190		rmdir ${LOCAL_MOUNTPOINT}
191	fi
192}
193
194test()
195{
196	local cpu_exclusive_tmp cpus_value
197
198	ROD_SILENT mkdir ${root_cpuset_dir}/testdir
199
200	# Creat an exclusive cpuset.
201	echo 1 > ${root_cpuset_dir}/testdir/${cpu_exclusive}
202	[ $? -ne 0 ] && tst_brk TFAIL "'echo 1 > ${root_cpuset_dir}/testdir/${cpu_exclusive}' failed"
203
204	cpu_exclusive_tmp=$(cat ${root_cpuset_dir}/testdir/${cpu_exclusive})
205	if [ "${cpu_exclusive_tmp}" != "1" ]; then
206		tst_brk TFAIL "${cpu_exclusive} is '${cpu_exclusive_tmp}', expected '1'"
207	fi
208
209	# This may trigger the kernel crash
210	echo 0 > ${root_cpuset_dir}/testdir/${cpus}
211	[ $? -ne 0 ] && tst_brk TFAIL "'echo 0 > ${root_cpuset_dir}/testdir/${cpus}' failed"
212
213	cpus_value=$(cat ${root_cpuset_dir}/testdir/${cpus})
214	if [ "${cpus_value}" != "0" ]; then
215		tst_brk TFAIL "${cpus} is '${cpus_value}', expected '0'"
216	fi
217
218	tst_res TPASS "Bug is not reproducible"
219}
220
221tst_run
222