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