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