#!/bin/bash -e # # cpuset_test - regression test for Linux kernel cpuset support. # # Copyright (c) 2005 Silicon Graphic, Inc. All rights reserved. # ### # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # ### # # This is a regression test for cpusets. It tests the various # functions, displays successes and failures to stdout and stderr. # # If successful, it exits with a value of 0, and the last line # of output is: # # cpuset test success !!! # # If failed, it exits with a value of 1, and the last line of # output is: # # cpuset test failed ;););) # # It needs to be run with root permissions, and it requires # being run on a system with at least 4 CPUs to actually test # anything. # # If run on a system without cpuset support in the kernel, it # will fail with an exit status of 1, and output of: # # mount: fs type cpuset not supported by kernel # Failed: mount -t cpuset cpuset /dev/cpuset at LINE 46 # cpuset test failed ;););) # # If run on a system with 3 or fewer CPUs, it does nothing much, # successfully, and exits with a value of 0. # # All success and fail lines for specific tests provide the # LINE number in this shell script of the test command, for # convenient analysis. # # Paul Jackson # pj@sgi.com # 26 Jan 2005 exitval=1 trap ' test $exitval -eq 0 && r="success !!!" || r="failed ;););)" echo cpuset test $r trap 0 exit $exitval ' 0 1 2 3 15 fail() { echo Failed: $* exitval=1 exit } succeed() { echo Succeeded: $* exitval=0 exit } verbose() { line=$1 shift $* || fail $* at LINE $line echo $* at LINE $line ok } do_echo() { /bin/echo $1 > $2 && echo echo $1 '>' $2 at LINE $3 ok || fail echo $1 '>' $2 at LINE $3 } test -d /dev/cpuset && echo directory /dev/cpuset exists at LINE $LINENO || verbose $LINENO mkdir /dev/cpuset mount | grep '/dev/cpuset type cpuset' >/dev/null && echo /dev/cpuset mounted at LINE $LINENO || verbose $LINENO mount -t cpuset cpuset /dev/cpuset # If run on a system with < 4 CPUs, do nothing, successfully. test $(grep -c processor /proc/cpuinfo) -ge 4 || succeed cpuset testing skipped for lack of at least 4 CPUs # Do all testing in our own cpuset subtree 'cpuset_test_tree' test -d /dev/cpuset/cpuset_test_tree && echo cpuset cpuset_test_tree exists at LINE $LINENO || verbose $LINENO mkdir /dev/cpuset/cpuset_test_tree verbose $LINENO cd /dev/cpuset/cpuset_test_tree rmdir ? 2>&- || true do_echo 0-3 cpus $LINENO do_echo 0-1 mems $LINENO do_echo 0 cpu_exclusive $LINENO do_echo 0 mem_exclusive $LINENO do_echo $$ tasks $LINENO test $( 0/cpu_exclusive 2>&- && fail nested cpu_exclusive at LINE $LINENO echo nested cpu_exclusive at LINE $LINENO ok # Now make the parent cpuset exclusive. do_echo 1 cpu_exclusive $LINENO # Now making the child cpuset 0 exclusive should work. /bin/echo 1 > 0/cpu_exclusive 2>&- || fail nested cpu_exclusive at LINE $LINENO echo nested cpu_exclusive at LINE $LINENO ok # As above, for Memory exclusive instead of CPU exclusive. /bin/echo 1 > 0/mem_exclusive 2>&- && fail nested mem_exclusive at LINE $LINENO echo nested mem_exclusive at LINE $LINENO ok do_echo 1 mem_exclusive $LINENO # Even with parent mem_exclusive set, cpuset 0 # should refuse to set mem_exclusive, since it # shares the same mems as child cpuset 1. /bin/echo 1 > 0/mem_exclusive 2>&- && fail sibling mem_exclusive at LINE $LINENO echo sibling mem_exclusive at LINE $LINENO ok # Remove child cpuset "1". verbose $LINENO rmdir 1 # Now finally should be able to make cpuset 0 mems_exclusive. /bin/echo 1 > 0/mem_exclusive 2>&- || fail sibling mem_exclusive at LINE $LINENO echo sibling mem_exclusive at LINE $LINENO ok # Now lets chdir to 0, and work in that cpuset a while. verbose $LINENO cd /dev/cpuset/cpuset_test_tree/0 # Attach current task to cpuset 0, verifying attachment. do_echo $$ tasks $LINENO j=$(awk < /proc/self/stat '{print $39}') test 0 -eq $j || fail bind to CPU 0 failed - on CPU $j instead LINE $LINENO echo bind to CPU 0 at LINE $LINENO ok # Should be unable to change cpus to 0-2, because we're # still cpu_exclusive (from above) and 0-2 would overlap # our sibling cpuset ../1. /bin/echo 0-2 > cpus 2>&- && fail exclusive cpus growth at LINE $LINENO echo exclusive cpus growth at LINE $LINENO ok # Remove our cpu_exclusive. do_echo 0 cpu_exclusive $LINENO # Now we should be able to change CPUs to 0-2. /bin/echo 0-2 > cpus 2>&- || fail exclusive cpus growth at LINE $LINENO echo exclusive cpus growth at LINE $LINENO ok # And we should be able to use taskset (sched_setaffinity) # to run a task on each of the CPUs in our cpuset, 0-2. for i in 0 1 2 do verbose $LINENO taskset -c $i /bin/true done # But we should be unable to taskset a task onto CPU 3. taskset -c 3 echo testing taskset on CPU 3 2>&- && fail testing taskset on invalid CPU 3 at LINE $LINENO echo testing taskset on invalid CPU 3 at LINE $LINENO ok # Here lies information on which CPUs are on which nodes. sys=/sys/devices/system/node # Test numactl (set_mempolicy) on each of the first 4 nodes, # verifying we can only use numactl to run on a Memory Node # or CPU if it is in our current cpuset. for node in 0 1 2 3 do # Skip non-existant nodes test -d $sys/node$node || continue # Only nodes that have at least one of cpus 0, 1 or 2 # (cpus in our current cpuset) can numactl --cpubind. shouldwork=false for cpu in 0 1 2 do test -L $sys/node$node/cpu$cpu && shouldwork=true done if $shouldwork then verbose $LINENO numactl --cpubind=$node /bin/true else numactl --cpubind=$node /bin/true 2>&- && fail test numactl on cpubind $node at LINE $LINENO echo test numactl on invalid cpubind $node at LINE $LINENO ok fi # Only node 0 (the mems in our current cpuset) can numactl --membind if test $node -eq 0 then verbose $LINENO numactl --membind=$node /bin/true else numactl --membind=$node /bin/true 2>&- && fail test numactl on membind $node at LINE $LINENO echo test numactl on membind $node at LINE $LINENO ok fi done # Back to top of our cpuset test tree verbose $LINENO cd /dev/cpuset/cpuset_test_tree do_echo $$ ../tasks $LINENO # Mark all test cpusets to be removed on release. echo 1 | tee $(find . -name notify_on_release) >/dev/null verbose $LINENO cd /dev/cpuset rmdir cpuset_test_tree/? || fail rmdir sub cpusets at LINE $LINENO sleep 3 # time for /sbin/cpuset_release_agent to rmdir test -d cpuset_test_tree && fail notify_on_release at LINE $LINENO exitval=0