123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386 |
- #!/bin/sh
- # SPDX-License-Identifier: GPL-2.0-or-later
- # Copyright (c) International Business Machines Corp., 2007
- # Copyright (c) Linux Test Project, 2016-2020
- # Author: Sivakumar Chinnaiah <Sivakumar.C@in.ibm.com>
- #
- # Test Basic functionality of numactl command.
- # Test #1: Verifies cpunodebind and membind
- # Test #2: Verifies preferred node bind for memory allocation
- # Test #3: Verifies memory interleave on all nodes
- # Test #4: Verifies physcpubind
- # Test #5: Verifies localalloc
- # Test #6: Verifies memhog
- # Test #7: Verifies numa_node_size api
- # Test #8: Verifies hugepage alloacted on specified node
- # Test #9: Verifies THP memory allocated on preferred node
- TST_CNT=9
- TST_SETUP=setup
- TST_TESTFUNC=test
- TST_NEEDS_TMPDIR=1
- TST_NEEDS_ROOT=1
- TST_NEEDS_CMDS="awk bc numactl numastat"
- . tst_test.sh
- # Awk the field matching the node value for numastat
- # $1 - Pid number
- # $2 - Node number
- get_node_index()
- {
- local pid=$1
- local nid="Node $2"
- echo $(numastat -p $pid | sed '3q;d' | awk -F '[[:space:]][[:space:]]+' \
- -v node="$nid" '{ for (i = 1; i <= NF; ++i) if($i==node) print i; exit }')
- }
- # Convert the value of given numa node from the `numastat -p` output,
- # multiply by size.
- # $1 - Pid number
- # $2 - Node number
- # $3 - Size for multiplication (e.g. 1024, $MB)
- get_mem_cur()
- {
- local pid=$1
- local index=$(echo "$(get_node_index $pid $2)")
- local size=$3
- local numstat=$(numastat -p $pid |awk '/^Total/ {print $'$index'}')
- if [ -z "$numstat" ]; then
- echo 0
- return
- fi
- echo $(echo "$numstat * $size" | bc)
- }
- check_for_support_numa()
- {
- local pid=$1
- local state=$(awk '{print $3}' /proc/$pid/stat)
- if [ $state = 'T' ]; then
- return 0
- fi
- return 1
- }
- setup()
- {
- export MB=$((1024*1024))
- export PAGE_SIZE=$(tst_getconf PAGESIZE)
- export HPAGE_SIZE=$(awk '/Hugepagesize:/ {print $2}' /proc/meminfo)
- total_nodes=0
- nodes_list=$(numactl --show | grep nodebind | cut -d ':' -f 2)
- for node in $nodes_list; do
- total_nodes=$((total_nodes+1))
- done
- tst_res TINFO "The system contains $total_nodes nodes: $nodes_list"
- if [ $total_nodes -le 1 ]; then
- tst_brk TCONF "your machine does not support numa policy
- or your machine is not a NUMA machine"
- fi
- }
- # Verification of memory allocated on a node
- test1()
- {
- local mem_curr
- for node in $nodes_list; do
- numactl --cpunodebind=$node --membind=$node support_numa alloc_1MB &
- pid=$!
- TST_RETRY_FUNC "check_for_support_numa $pid" 0
- mem_curr=$(get_mem_cur $pid $node $MB)
- if [ $(echo "$mem_curr < $MB" | bc) -eq 1 ]; then
- tst_res TFAIL \
- "NUMA memory allocated in node$node is less than expected"
- kill -CONT $pid >/dev/null 2>&1
- return
- fi
- kill -CONT $pid >/dev/null 2>&1
- done
- tst_res TPASS "NUMA local node and memory affinity"
- }
- # Verification of memory allocated on preferred node
- test2()
- {
- local mem_curr
- local cnt=1
- for node in $nodes_list; do
- if [ $cnt -eq $total_nodes ]; then #wrap up for last node
- Preferred_node=$(echo $nodes_list | cut -d ' ' -f 1)
- else
- # always next node is preferred node
- Preferred_node=$(echo $nodes_list | cut -d ' ' -f $((cnt+1)))
- fi
- numactl --cpunodebind=$node --preferred=$Preferred_node support_numa alloc_1MB &
- pid=$!
- TST_RETRY_FUNC "check_for_support_numa $pid" 0
- mem_curr=$(get_mem_cur $pid $Preferred_node $MB)
- if [ $(echo "$mem_curr < $MB" |bc ) -eq 1 ]; then
- tst_res TFAIL \
- "NUMA memory allocated in node$Preferred_node is less than expected"
- kill -CONT $pid >/dev/null 2>&1
- return
- fi
- cnt=$((cnt+1))
- kill -CONT $pid >/dev/null 2>&1
- done
- tst_res TPASS "NUMA preferred node policy"
- }
- # Verification of memory interleaved on all nodes
- test3()
- {
- local mem_curr
- # Memory will be allocated using round robin on nodes.
- Exp_incr=$(echo "$MB / $total_nodes" |bc)
- numactl --interleave=all support_numa alloc_1MB &
- pid=$!
- TST_RETRY_FUNC "check_for_support_numa $pid" 0
- for node in $nodes_list; do
- mem_curr=$(get_mem_cur $pid $node $MB)
- if [ $(echo "$mem_curr < $Exp_incr" |bc ) -eq 1 ]; then
- tst_res TFAIL \
- "NUMA interleave memory allocated in node$node is less than expected"
- kill -CONT $pid >/dev/null 2>&1
- return
- fi
- done
- kill -CONT $pid >/dev/null 2>&1
- tst_res TPASS "NUMA interleave policy"
- }
- # Verification of physical cpu bind
- test4()
- {
- no_of_cpus=0 #no. of cpu's exist
- run_on_cpu=0
- running_on_cpu=0
- no_of_cpus=$(tst_ncpus)
- # not sure whether cpu's can't be in odd number
- run_on_cpu=$(($((no_of_cpus+1))/2))
- numactl --physcpubind=$run_on_cpu support_numa pause & #just waits for sigint
- pid=$!
- var=`awk '{ print $2 }' /proc/$pid/stat`
- while [ $var = '(numactl)' ]; do
- var=`awk '{ print $2 }' /proc/$pid/stat`
- tst_sleep 100ms
- done
- # Warning !! 39 represents cpu number, on which process pid is currently running and
- # this may change if Some more fields are added in the middle, may be in future
- running_on_cpu=$(awk '{ print $39; }' /proc/$pid/stat)
- if [ $running_on_cpu -ne $run_on_cpu ]; then
- tst_res TFAIL \
- "Process running on cpu$running_on_cpu but expected to run on cpu$run_on_cpu"
- ROD kill -INT $pid
- return
- fi
- ROD kill -INT $pid
- tst_res TPASS "NUMA phycpubind policy"
- }
- # Verification of local node allocation
- test5()
- {
- local mem_curr
- for node in $nodes_list; do
- numactl --cpunodebind=$node --localalloc support_numa alloc_1MB &
- pid=$!
- TST_RETRY_FUNC "check_for_support_numa $pid" 0
- mem_curr=$(get_mem_cur $pid $node $MB)
- if [ $(echo "$mem_curr < $MB" |bc ) -eq 1 ]; then
- tst_res TFAIL \
- "NUMA localnode memory allocated in node$node is less than expected"
- kill -CONT $pid >/dev/null 2>&1
- return
- fi
- kill -CONT $pid >/dev/null 2>&1
- done
- tst_res TPASS "NUMA local node allocation"
- }
- check_ltp_numa_test8_log()
- {
- grep -m1 -q '.' ltp_numa_test8.log
- }
- # Verification of memhog with interleave policy
- test6()
- {
- local mem_curr
- # Memory will be allocated using round robin on nodes.
- Exp_incr=$(echo "$MB / $total_nodes" |bc)
- numactl --interleave=all memhog -r1000000 1MB >ltp_numa_test8.log 2>&1 &
- pid=$!
- TST_RETRY_FUNC "check_ltp_numa_test8_log" 0
- for node in $nodes_list; do
- mem_curr=$(get_mem_cur $pid $node $MB)
- if [ $(echo "$mem_curr < $Exp_incr" |bc ) -eq 1 ]; then
- tst_res TFAIL \
- "NUMA interleave memhog in node$node is less than expected"
- kill -KILL $pid >/dev/null 2>&1
- return
- fi
- done
- kill -KILL $pid >/dev/null 2>&1
- tst_res TPASS "NUMA MEMHOG policy"
- }
- # Function: hardware cheking with numa_node_size api
- #
- # Description: - Returns the size of available nodes if success.
- #
- # Input: - o/p of numactl --hardware command which is expected in the format
- # shown below
- # available: 2 nodes (0-1)
- # node 0 size: 7808 MB
- # node 0 free: 7457 MB
- # node 1 size: 5807 MB
- # node 1 free: 5731 MB
- # node distances:
- # node 0 1
- # 0: 10 20
- # 1: 20 10
- #
- test7()
- {
- RC=0
- numactl --hardware > gavail_nodes
- RC=$(awk '{ if ( NR == 1 ) {print $1;} }' gavail_nodes)
- if [ $RC = "available:" ]; then
- RC=$(awk '{ if ( NR == 1 ) {print $3;} }' gavail_nodes)
- if [ $RC = "nodes" ]; then
- RC=$(awk '{ if ( NR == 1 ) {print $2;} }' gavail_nodes)
- tst_res TPASS "NUMA policy on lib NUMA_NODE_SIZE API"
- else
- tst_res TFAIL "Failed with numa policy"
- fi
- else
- tst_res TFAIL "Failed with numa policy"
- fi
- }
- # Verification of hugepage memory allocated on a node
- test8()
- {
- Mem_huge=0
- Sys_node=/sys/devices/system/node
- if [ ! -d "/sys/kernel/mm/hugepages/" ]; then
- tst_res TCONF "hugepage is not supported"
- return
- fi
- for node in $nodes_list; do
- Ori_hpgs=$(cat ${Sys_node}/node${node}/hugepages/hugepages-${HPAGE_SIZE}kB/nr_hugepages)
- New_hpgs=$((Ori_hpgs + 1))
- echo $New_hpgs >${Sys_node}/node${node}/hugepages/hugepages-${HPAGE_SIZE}kB/nr_hugepages
- Chk_hpgs=$(cat ${Sys_node}/node${node}/hugepages/hugepages-${HPAGE_SIZE}kB/nr_hugepages)
- if [ "$Chk_hpgs" -ne "$New_hpgs" ]; then
- tst_res TCONF "hugepage is not enough to test"
- return
- fi
- numactl --cpunodebind=$node --membind=$node support_numa alloc_1huge_page &
- pid=$!
- TST_RETRY_FUNC "check_for_support_numa $pid" 0
- local index=$(echo "$(get_node_index $pid $node)")
- Mem_huge=$(echo $(numastat -p $pid |awk '/^Huge/ {print $'$index'}'))
- Mem_huge=$((${Mem_huge%.*} * 1024))
- if [ "$Mem_huge" -lt "$HPAGE_SIZE" ]; then
- tst_res TFAIL \
- "NUMA memory allocated in node$node is less than expected"
- kill -CONT $pid >/dev/null 2>&1
- echo $Ori_hpgs >${Sys_node}/node${node}/hugepages/hugepages-${HPAGE_SIZE}kB/nr_hugepages
- return
- fi
- kill -CONT $pid >/dev/null 2>&1
- echo $Ori_hpgs >${Sys_node}/node${node}/hugepages/hugepages-${HPAGE_SIZE}kB/nr_hugepages
- done
- tst_res TPASS "NUMA local node hugepage memory allocated"
- }
- # Verification of THP memory allocated on preferred node
- test9()
- {
- local mem_curr
- local cnt=1
- if ! grep -q '\[always\]' /sys/kernel/mm/transparent_hugepage/enabled; then
- tst_res TCONF "THP is not supported/enabled"
- return
- fi
- for node in $nodes_list; do
- if [ $cnt -eq $total_nodes ]; then #wrap up for last node
- Preferred_node=$(echo $nodes_list | cut -d ' ' -f 1)
- else
- # always next node is preferred node
- Preferred_node=$(echo $nodes_list | cut -d ' ' -f $((cnt+1)))
- fi
- numactl --cpunodebind=$node --preferred=$Preferred_node support_numa alloc_2HPSZ_THP &
- pid=$!
- TST_RETRY_FUNC "check_for_support_numa $pid" 0
- mem_curr=$(get_mem_cur $pid $Preferred_node 1024)
- if [ $(echo "$mem_curr < $HPAGE_SIZE * 2" |bc ) -eq 1 ]; then
- tst_res TFAIL \
- "NUMA memory allocated in node$Preferred_node is less than expected"
- kill -CONT $pid >/dev/null 2>&1
- return
- fi
- cnt=$((cnt+1))
- kill -CONT $pid >/dev/null 2>&1
- done
- tst_res TPASS "NUMA preferred node policy verified with THP enabled"
- }
- tst_run
|