1#!/bin/sh 2############################################################################## 3# # 4# Copyright (c) International Business Machines Corp., 2007 # 5# Sivakumar Chinnaiah, Sivakumar.C@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 37TST_ID="numa01" 38TST_CNT=10 39TST_SETUP=setup 40TST_TESTFUNC=test 41TST_NEEDS_TMPDIR=1 42TST_NEEDS_ROOT=1 43TST_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# 53extract_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 61wait_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 82setup() 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 107test1() 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 131test2() 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 165test3() 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 200test4() 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 226test5() 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 253test6() 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 285test7() 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 309test8() 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# 348test9() 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 368test10() 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 402tst_run 403