Home | History | Annotate | Download | only in numa
      1 #!/bin/sh
      2 ##############################################################################
      3 #                                                                            #
      4 # Copyright (c) International Business Machines  Corp., 2007                 #
      5 #               Sivakumar Chinnaiah, Sivakumar.C (at] in.ibm.com                  #
      6 # Copyright (c) Linux Test Project, 2016                                     #
      7 #                                                                            #
      8 # This program is free software: you can redistribute it and/or modify       #
      9 # it under the terms of the GNU General Public License as published by       #
     10 # the Free Software Foundation, either version 3 of the License, or          #
     11 # (at your option) any later version.                                        #
     12 #                                                                            #
     13 # This program is distributed in the hope that it will be useful,            #
     14 # but WITHOUT ANY WARRANTY; without even the implied warranty of             #
     15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              #
     16 # GNU General Public License for more details.                               #
     17 #                                                                            #
     18 # You should have received a copy of the GNU General Public License          #
     19 # along with this program. If not, see <http://www.gnu.org/licenses/>.       #
     20 #                                                                            #
     21 ##############################################################################
     22 #                                                                            #
     23 # Description:  Test Basic functionality of numactl command.                 #
     24 #               Test #1: Verifies cpunodebind and membind                    #
     25 #               Test #2: Verifies preferred node bind for memory allocation  #
     26 #               Test #3: Verifies share memory allocation on preferred node  #
     27 #               Test #4: Verifies memory interleave on all nodes             #
     28 #               Test #5: Verifies share memory interleave on all nodes       #
     29 #               Test #6: Verifies physcpubind                                #
     30 #               Test #7: Verifies localalloc                                 #
     31 #               Test #8: Verifies memhog                                     #
     32 #               Test #9: Verifies numa_node_size api                         #
     33 #               Test #10:Verifies Migratepages                               #
     34 #                                                                            #
     35 ##############################################################################
     36 
     37 TST_ID="numa01"
     38 TST_CNT=10
     39 TST_SETUP=setup
     40 TST_TESTFUNC=test
     41 TST_NEEDS_TMPDIR=1
     42 TST_NEEDS_ROOT=1
     43 TST_NEEDS_CMDS="numactl numastat awk"
     44 
     45 . tst_test.sh
     46 
     47 #
     48 # Extracts the value of given numa node from the `numastat -p` output.
     49 #
     50 # $1 - Pid number.
     51 # $2 - Node number.
     52 #
     53 extract_numastat_p()
     54 {
     55 	local pid=$1
     56 	local node=$(($2 + 2))
     57 
     58 	echo $(numastat -p $pid |grep '^Total' |awk '{print $'$node'}')
     59 }
     60 
     61 wait_for_support_numa()
     62 {
     63 	local pid=$1
     64 	local retries=20
     65 
     66 	while [ $retries -gt 0 ]; do
     67 		local state=$(awk '{print $3}' /proc/$pid/stat)
     68 
     69 		if [ $state = 'T' ]; then
     70 			break
     71 		fi
     72 
     73 		retries=$((retries-1))
     74 		tst_sleep 50ms
     75 	done
     76 
     77 	if [ $retries -le 0 ]; then
     78 		tst_brk TBROK "Timeouted while waiting for support_numa ($pid)"
     79 	fi
     80 }
     81 
     82 setup()
     83 {
     84 	export MB=$((1024*1024))
     85 	export PAGE_SIZE=$(getconf PAGE_SIZE)
     86 
     87 	# arguments to memory exercise program support_numa.c
     88 	ALLOC_1MB=1
     89 	SHARE_1MB=2
     90 	PAUSE=3
     91 
     92 	total_nodes=0
     93 
     94 	nodes_list=$(numactl --show | grep nodebind | cut -d ':' -f 2)
     95 	for node in $nodes_list; do
     96 		total_nodes=$((total_nodes+1))
     97 	done
     98 
     99 	tst_res TINFO "The system contains $total_nodes nodes: $nodes_list"
    100 	if [ $total_nodes -le 1 ]; then
    101 		tst_brk TCONF "your machine does not support numa policy
    102 		or your machine is not a NUMA machine"
    103 	fi
    104 }
    105 
    106 # Verification of memory allocated on a node
    107 test1()
    108 {
    109 	Mem_curr=0
    110 
    111 	for node in $nodes_list; do
    112 		numactl --cpunodebind=$node --membind=$node support_numa $ALLOC_1MB &
    113 		pid=$!
    114 
    115 		wait_for_support_numa $pid
    116 
    117 		Mem_curr=$(echo "$(extract_numastat_p $pid $node) * $MB" |bc)
    118 		if [ $(echo "$Mem_curr < $MB" | bc) -eq 1 ]; then
    119 			tst_res TFAIL \
    120 				"NUMA memory allocated in node$node is less than expected"
    121 			return
    122 		fi
    123 
    124 		kill -CONT $pid >/dev/null 2>&1
    125 	done
    126 
    127 	tst_res TPASS "NUMA local node and memory affinity"
    128 }
    129 
    130 # Verification of memory allocated on preferred node
    131 test2()
    132 {
    133 	Mem_curr=0
    134 
    135 	COUNTER=1
    136 	for node in $nodes_list; do
    137 
    138 		if [ $COUNTER -eq $total_nodes ]; then   #wrap up for last node
    139 			Preferred_node=$(echo $nodes_list | cut -d ' ' -f 1)
    140 		else
    141 			# always next node is preferred node
    142 			Preferred_node=$(echo $nodes_list | cut -d ' ' -f $((COUNTER+1)))
    143 		fi
    144 
    145 		numactl --cpunodebind=$node --preferred=$Preferred_node support_numa $ALLOC_1MB &
    146 		pid=$!
    147 
    148 		wait_for_support_numa $pid
    149 
    150 		Mem_curr=$(echo "$(extract_numastat_p $pid $Preferred_node) * $MB" |bc)
    151 		if [ $(echo "$Mem_curr < $MB" |bc ) -eq 1 ]; then
    152 			tst_res TFAIL \
    153 				"NUMA memory allocated in node$Preferred_node is less than expected"
    154 			return
    155 		fi
    156 
    157 		COUNTER=$((COUNTER+1))
    158 		kill -CONT $pid >/dev/null 2>&1
    159 	done
    160 
    161 	tst_res TPASS "NUMA preferred node policy"
    162 }
    163 
    164 # Verification of share memory allocated on preferred node
    165 test3()
    166 {
    167 	Mem_curr=0
    168 	COUNTER=1
    169 
    170 	for node in $nodes_list; do
    171 
    172 		if [ $COUNTER -eq $total_nodes ]   #wrap up for last node
    173 		then
    174 			Preferred_node=$(echo $nodes_list | cut -d ' ' -f 1)
    175 		else
    176 			# always next node is preferred node
    177 			Preferred_node=$(echo $nodes_list | cut -d ' ' -f $((COUNTER+1)))
    178 		fi
    179 
    180 		numactl --cpunodebind=$node --preferred=$Preferred_node support_numa $SHARE_1MB &
    181 		pid=$!
    182 
    183 		wait_for_support_numa $pid
    184 
    185 		Mem_curr=$(echo "$(extract_numastat_p $pid $Preferred_node) * $MB" |bc)
    186 		if [ $(echo "$Mem_curr < $MB" |bc ) -eq 1 ]; then
    187 			tst_res TFAIL \
    188 				"NUMA share memory allocated in node$Preferred_node is less than expected"
    189 			return
    190 		fi
    191 
    192 		COUNTER=$((COUNTER+1))
    193 		kill -CONT $pid >/dev/null 2>&1
    194 	done
    195 
    196 	tst_res TPASS "NUMA share memory allocated in preferred node"
    197 }
    198 
    199 # Verification of memory interleaved on all nodes
    200 test4()
    201 {
    202 	Mem_curr=0
    203 	# Memory will be allocated using round robin on nodes.
    204 	Exp_incr=$(echo "$MB / $total_nodes" |bc)
    205 
    206 	numactl --interleave=all support_numa $ALLOC_1MB &
    207 	pid=$!
    208 
    209 	wait_for_support_numa $pid
    210 
    211 	for node in $nodes_list; do
    212 		Mem_curr=$(echo "$(extract_numastat_p $pid $node) * $MB" |bc)
    213 
    214 		if [ $(echo "$Mem_curr < $Exp_incr" |bc ) -eq 1 ]; then
    215 			tst_res TFAIL \
    216 				"NUMA interleave memory allocated in node$node is less than expected"
    217 			return
    218 		fi
    219 	done
    220 
    221 	kill -CONT $pid >/dev/null 2>&1
    222 	tst_res TPASS "NUMA interleave policy"
    223 }
    224 
    225 # Verification of shared memory interleaved on all nodes
    226 test5()
    227 {
    228 	Mem_curr=0
    229 	# Memory will be allocated using round robin on nodes.
    230 	Exp_incr=$(echo "$MB / $total_nodes" |bc)
    231 
    232 	numactl --interleave=all support_numa $SHARE_1MB &
    233 	pid=$!
    234 
    235 	wait_for_support_numa $pid
    236 
    237 	for node in $nodes_list; do
    238 		Mem_curr=$(echo "$(extract_numastat_p $pid $node) * $MB" |bc)
    239 
    240 		if [ $(echo "$Mem_curr < $Exp_incr" |bc ) -eq 1 ]; then
    241 			tst_res TFAIL \
    242 				"NUMA interleave share memory allocated in node$node is less than expected"
    243 			return
    244 		fi
    245 	done
    246 
    247 	kill -CONT $pid >/dev/null 2>&1
    248 
    249 	tst_res TPASS "NUMA interleave policy on shared memory"
    250 }
    251 
    252 # Verification of physical cpu bind
    253 test6()
    254 {
    255 	no_of_cpus=0	#no. of cpu's exist
    256 	run_on_cpu=0
    257 	running_on_cpu=0
    258 
    259 	no_of_cpus=$(tst_ncpus)
    260 	# not sure whether cpu's can't be in odd number
    261 	run_on_cpu=$(($((no_of_cpus+1))/2))
    262 	numactl --physcpubind=$run_on_cpu support_numa $PAUSE & #just waits for sigint
    263 	pid=$!
    264 	var=`awk '{ print $2 }' /proc/$pid/stat`
    265 	while [ $var = '(numactl)' ]; do
    266 		var=`awk '{ print $2 }' /proc/$pid/stat`
    267 		tst_sleep 100ms
    268 	done
    269 	# Warning !! 39 represents cpu number, on which process pid is currently running and
    270 	# this may change if Some more fields are added in the middle, may be in future
    271 	running_on_cpu=$(awk '{ print $39; }' /proc/$pid/stat)
    272 	if [ $running_on_cpu -ne $run_on_cpu ]; then
    273 		tst_res TFAIL \
    274 			"Process running on cpu$running_on_cpu but expected to run on cpu$run_on_cpu"
    275 		ROD kill -INT $pid
    276 		return
    277 	fi
    278 
    279 	ROD kill -INT $pid
    280 
    281 	tst_res TPASS "NUMA phycpubind policy"
    282 }
    283 
    284 # Verification of local node allocation
    285 test7()
    286 {
    287 	Mem_curr=0
    288 
    289 	for node in $nodes_list; do
    290 		numactl --cpunodebind=$node --localalloc support_numa $ALLOC_1MB &
    291 		pid=$!
    292 
    293 		wait_for_support_numa $pid
    294 
    295 		Mem_curr=$(echo "$(extract_numastat_p $pid $node) * $MB" |bc)
    296 		if [ $(echo "$Mem_curr < $MB" |bc ) -eq 1 ]; then
    297 			tst_res TFAIL \
    298 				"NUMA localnode memory allocated in node$node is less than expected"
    299 			return
    300 		fi
    301 
    302 		kill -CONT $pid >/dev/null 2>&1
    303 	done
    304 
    305 	tst_res TPASS "NUMA local node allocation"
    306 }
    307 
    308 # Verification of memhog with interleave policy
    309 test8()
    310 {
    311 	Mem_curr=0
    312 	# Memory will be allocated using round robin on nodes.
    313 	Exp_incr=$(echo "$MB / $total_nodes" |bc)
    314 
    315 	numactl --interleave=all memhog -r1000000 1MB 2>&1 >/dev/null &
    316 	pid=$!
    317 
    318 	for node in $nodes_list; do
    319 		Mem_curr=$(echo "$(extract_numastat_p $pid $node) * $MB" |bc)
    320 
    321 		if [ $(echo "$Mem_curr < $Exp_incr" |bc ) -eq 1 ]; then
    322 			tst_res TFAIL \
    323 				"NUMA interleave memhog in node$node is less than expected"
    324 			return
    325 		fi
    326 	done
    327 
    328 	kill -9 $pid >/dev/null 2>&1
    329 	tst_res TPASS "NUMA MEMHOG policy"
    330 }
    331 
    332 # Function:     hardware cheking with numa_node_size api
    333 #
    334 # Description:  - Returns the size of available nodes if success.
    335 #
    336 # Input:        - o/p of numactl --hardware command which is expected in the format
    337 #                 shown below
    338 #               available: 2 nodes (0-1)
    339 #               node 0 size: 7808 MB
    340 #               node 0 free: 7457 MB
    341 #               node 1 size: 5807 MB
    342 #               node 1 free: 5731 MB
    343 #               node distances:
    344 #               node   0   1
    345 #                 0:  10  20
    346 #                 1:  20  10
    347 #
    348 test9()
    349 {
    350 	RC=0
    351 
    352 	numactl --hardware > gavail_nodes
    353 	RC=$(awk '{ if ( NR == 1 ) {print $1;} }' gavail_nodes)
    354 	if [ $RC = "available:" ]; then
    355 		RC=$(awk '{ if ( NR == 1 ) {print $3;} }' gavail_nodes)
    356 		if [ $RC = "nodes" ]; then
    357 			RC=$(awk '{ if ( NR == 1 ) {print $2;} }' gavail_nodes)
    358 			tst_res TPASS "NUMA policy on lib NUMA_NODE_SIZE API"
    359 		else
    360 			tst_res TFAIL "Failed with numa policy"
    361 		fi
    362 	else
    363 		tst_res TFAIL "Failed with numa policy"
    364 	fi
    365 }
    366 
    367 # Verification of migratepages
    368 test10()
    369 {
    370 	Mem_curr=0
    371 	COUNTER=1
    372 
    373 	for node in $nodes_list; do
    374 
    375 		if [ $COUNTER -eq $total_nodes ]; then
    376 			Preferred_node=$(echo $nodes_list | cut -d ' ' -f 1)
    377 		else
    378 			Preferred_node=$(echo $nodes_list | cut -d ' ' -f $((COUNTER+1)))
    379 		fi
    380 
    381 		numactl --preferred=$node support_numa $ALLOC_1MB &
    382 		pid=$!
    383 
    384 		wait_for_support_numa $pid
    385 
    386 		migratepages $pid $node $Preferred_node
    387 
    388 		Mem_curr=$(echo "$(extract_numastat_p $pid $Preferred_node) * $MB" |bc)
    389 		if [ $(echo "$Mem_curr < $MB" |bc ) -eq 1 ]; then
    390 			tst_res TFAIL \
    391 				"NUMA migratepages is not working fine"
    392 			return
    393 		fi
    394 
    395 		COUNTER=$((COUNTER+1))
    396 		kill -CONT $pid >/dev/null 2>&1
    397 	done
    398 
    399 	tst_res TPASS "NUMA MIGRATEPAGES policy"
    400 }
    401 
    402 tst_run
    403