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