xref: /spdk/test/setup/hugepages.sh (revision 0070858e33ec0937e93e68b06a7f170b02a352b6)
1d60bc771SMichal Berger#!/usr/bin/env bash
2eb53c232Spaul luse#  SPDX-License-Identifier: BSD-3-Clause
3eb53c232Spaul luse#  Copyright (C) 2020 Intel Corporation
4eb53c232Spaul luse#  All rights reserved.
5eb53c232Spaul luse#
6d60bc771SMichal Bergertestdir=$(readlink -f "$(dirname "$0")")
7d60bc771SMichal Bergerrootdir=$(readlink -f "$testdir/../../")
8d60bc771SMichal Bergersource "$testdir/common.sh"
9d60bc771SMichal Berger
10d60bc771SMichal Bergerdeclare -a nodes_sys=()
11d60bc771SMichal Berger
12c9c7c281SJosh Sorefdeclare -i default_hugepages=0
13d60bc771SMichal Bergerdeclare -i no_nodes=0
14d60bc771SMichal Bergerdeclare -i nr_hugepages=0
15d60bc771SMichal Berger
16c9c7c281SJosh Sorefdefault_hugepages=$(get_meminfo Hugepagesize)
17c9c7c281SJosh Sorefdefault_huge_nr=/sys/kernel/mm/hugepages/hugepages-${default_hugepages}kB/nr_hugepages
18d60bc771SMichal Bergerglobal_huge_nr=/proc/sys/vm/nr_hugepages
19d60bc771SMichal Berger
20227428c3SMichal Berger# Make sure environment doesn't affect the tests
21227428c3SMichal Bergerunset -v HUGEMEM
22227428c3SMichal Bergerunset -v HUGENODE
23227428c3SMichal Bergerunset -v NRHUGE
24227428c3SMichal Berger
25d60bc771SMichal Bergerget_nodes() {
26d60bc771SMichal Berger	local node
27d60bc771SMichal Berger
28d60bc771SMichal Berger	for node in /sys/devices/system/node/node+([0-9]); do
29c9c7c281SJosh Soref		nodes_sys[${node##*node}]=$(< "$node/hugepages/hugepages-${default_hugepages}kB/nr_hugepages")
30d60bc771SMichal Berger	done
31d60bc771SMichal Berger	no_nodes=${#nodes_sys[@]}
32d60bc771SMichal Berger	((no_nodes > 0))
33d60bc771SMichal Berger}
34d60bc771SMichal Berger
35d60bc771SMichal Bergerclear_hp() {
36d60bc771SMichal Berger	local node hp
37d60bc771SMichal Berger
38d60bc771SMichal Berger	for node in "${!nodes_sys[@]}"; do
39d60bc771SMichal Berger		for hp in "/sys/devices/system/node/node$node/hugepages/hugepages-"*; do
40d60bc771SMichal Berger			echo 0 > "$hp/nr_hugepages"
41d60bc771SMichal Berger		done
42d60bc771SMichal Berger	done
43d60bc771SMichal Berger
44d60bc771SMichal Berger	export CLEAR_HUGE=yes
45d60bc771SMichal Berger}
46d60bc771SMichal Berger
47d60bc771SMichal Bergerget_test_nr_hugepages() {
48d60bc771SMichal Berger	local size=$1 # kB
49d60bc771SMichal Berger	if (($# > 1)); then
50d60bc771SMichal Berger		shift
51d60bc771SMichal Berger		local node_ids=("$@")
52d60bc771SMichal Berger	fi
53d60bc771SMichal Berger
54c9c7c281SJosh Soref	((size >= default_hugepages))
55d60bc771SMichal Berger
56c9c7c281SJosh Soref	nr_hugepages=$(((size + default_hugepages - 1) / default_hugepages))
57d60bc771SMichal Berger	get_test_nr_hugepages_per_node "${node_ids[@]}"
58d60bc771SMichal Berger}
59d60bc771SMichal Berger
60d60bc771SMichal Bergerget_test_nr_hugepages_per_node() {
61d60bc771SMichal Berger	local user_nodes=("$@")
62d60bc771SMichal Berger
63d60bc771SMichal Berger	local _nr_hugepages=$nr_hugepages
64d60bc771SMichal Berger	local _no_nodes=$no_nodes
65d60bc771SMichal Berger
66d60bc771SMichal Berger	local -g nodes_test=()
67d60bc771SMichal Berger
68d60bc771SMichal Berger	if ((${#user_nodes[@]} > 0)); then
69d60bc771SMichal Berger		for _no_nodes in "${user_nodes[@]}"; do
70d60bc771SMichal Berger			nodes_test[_no_nodes]=$nr_hugepages
71d60bc771SMichal Berger		done
72d60bc771SMichal Berger		return 0
73d60bc771SMichal Berger	elif ((${#nodes_hp[@]} > 0)); then
74d60bc771SMichal Berger		for _no_nodes in "${!nodes_hp[@]}"; do
75d60bc771SMichal Berger			nodes_test[_no_nodes]=${nodes_hp[_no_nodes]}
76d60bc771SMichal Berger		done
77d60bc771SMichal Berger		return 0
78d60bc771SMichal Berger	fi
79d60bc771SMichal Berger
80d60bc771SMichal Berger	while ((_no_nodes > 0)); do
81d60bc771SMichal Berger		nodes_test[_no_nodes - 1]=$((_nr_hugepages / _no_nodes))
82d60bc771SMichal Berger		: $((_nr_hugepages -= nodes_test[_no_nodes - 1]))
83d60bc771SMichal Berger		: $((--_no_nodes))
84d60bc771SMichal Berger	done
85d60bc771SMichal Berger}
86d60bc771SMichal Berger
87d60bc771SMichal Bergerverify_nr_hugepages() {
88d60bc771SMichal Berger	local node
89d60bc771SMichal Berger	local sorted_t
90d60bc771SMichal Berger	local sorted_s
91327f69eaSMichal Berger	local surp
92327f69eaSMichal Berger	local resv
93327f69eaSMichal Berger	local anon
94327f69eaSMichal Berger
95327f69eaSMichal Berger	if [[ $(< /sys/kernel/mm/transparent_hugepage/enabled) != *"[never]"* ]]; then
96327f69eaSMichal Berger		anon=$(get_meminfo AnonHugePages)
97327f69eaSMichal Berger	fi
98327f69eaSMichal Berger	surp=$(get_meminfo HugePages_Surp)
99327f69eaSMichal Berger	resv=$(get_meminfo HugePages_Rsvd)
100d60bc771SMichal Berger
101d60bc771SMichal Berger	echo "nr_hugepages=$nr_hugepages"
102327f69eaSMichal Berger	echo "resv_hugepages=$resv"
103327f69eaSMichal Berger	echo "surplus_hugepages=$surp"
104327f69eaSMichal Berger	echo "anon_hugepages=${anon:-disabled}"
105327f69eaSMichal Berger
106327f69eaSMichal Berger	(($(< "$default_huge_nr") == nr_hugepages + surp + resv))
107327f69eaSMichal Berger	# This knob doesn't account for the surp, resv hugepages
108d60bc771SMichal Berger	(($(< "$global_huge_nr") == nr_hugepages))
109327f69eaSMichal Berger	(($(get_meminfo HugePages_Total) == nr_hugepages + surp + resv))
110d60bc771SMichal Berger
111d60bc771SMichal Berger	get_nodes
112d60bc771SMichal Berger
113327f69eaSMichal Berger	# Take global resv and per-node surplus hugepages into account
114327f69eaSMichal Berger	for node in "${!nodes_test[@]}"; do
115327f69eaSMichal Berger		((nodes_test[node] += resv))
116327f69eaSMichal Berger		((nodes_test[node] += $(get_meminfo HugePages_Surp "$node")))
117327f69eaSMichal Berger	done
118327f69eaSMichal Berger
119d60bc771SMichal Berger	# There's no obvious way of determining which NUMA node is going to end
120d60bc771SMichal Berger	# up with an odd number of hugepages in case such number was actually
121d60bc771SMichal Berger	# allocated by the kernel. Considering that, let's simply check if our
122c9c7c281SJosh Soref	# expectation is met by sorting and comparing it with nr of hugepages that
123d60bc771SMichal Berger	# was actually allocated on each node.
124d60bc771SMichal Berger
125d60bc771SMichal Berger	for node in "${!nodes_test[@]}"; do
126d60bc771SMichal Berger		sorted_t[nodes_test[node]]=1 sorted_s[nodes_sys[node]]=1
127327f69eaSMichal Berger		echo "node$node=${nodes_sys[node]} expecting ${nodes_test[node]}"
128d60bc771SMichal Berger	done
129d60bc771SMichal Berger	[[ ${!sorted_s[*]} == "${!sorted_t[*]}" ]]
130d60bc771SMichal Berger}
131d60bc771SMichal Berger
132d60bc771SMichal Berger# Test cases
133*0070858eSMichal Bergersingle_node_setup() {
134*0070858eSMichal Berger	# HUGEMEM (2G) alloc on node0
135227428c3SMichal Berger	get_test_nr_hugepages $((2048 * 1024)) 0
136*0070858eSMichal Berger	NRHUGE=$nr_hugepages HUGENODE=0 setup output
137d60bc771SMichal Berger	verify_nr_hugepages
138d60bc771SMichal Berger}
139d60bc771SMichal Berger
140d60bc771SMichal Bergereven_2G_alloc() {
141d60bc771SMichal Berger	# 2G alloc spread across N nodes
142d60bc771SMichal Berger	get_test_nr_hugepages $((2048 * 1024))
143*0070858eSMichal Berger	NRHUGE=$nr_hugepages setup output
144d60bc771SMichal Berger	verify_nr_hugepages
145d60bc771SMichal Berger}
146d60bc771SMichal Berger
147d60bc771SMichal Bergerodd_alloc() {
148d60bc771SMichal Berger	# Odd 2049MB alloc across N nodes
149d60bc771SMichal Berger	get_test_nr_hugepages $((2049 * 1024))
150*0070858eSMichal Berger	HUGEMEM=2049 setup output
151d60bc771SMichal Berger	verify_nr_hugepages
152d60bc771SMichal Berger}
153d60bc771SMichal Berger
154d60bc771SMichal Bergercustom_alloc() {
1553f674e1eSMichal Berger	# Custom alloc: node0 == 1GB [node1 == 2 GB]
156d60bc771SMichal Berger
157d60bc771SMichal Berger	local IFS=","
158d60bc771SMichal Berger
159d60bc771SMichal Berger	local node
160d60bc771SMichal Berger	local nodes_hp=()
161d60bc771SMichal Berger
1623f674e1eSMichal Berger	local nr_hugepages=0 _nr_hugepages=0
163d60bc771SMichal Berger
1643f674e1eSMichal Berger	get_test_nr_hugepages $((1024 * 1024))
1653f674e1eSMichal Berger	nodes_hp[0]=$nr_hugepages
166d60bc771SMichal Berger	if ((${#nodes_sys[@]} > 1)); then
1673f674e1eSMichal Berger		get_test_nr_hugepages $((2048 * 1024))
1683f674e1eSMichal Berger		nodes_hp[1]=$nr_hugepages
169d60bc771SMichal Berger	fi
170d60bc771SMichal Berger
171d60bc771SMichal Berger	for node in "${!nodes_hp[@]}"; do
172d60bc771SMichal Berger		HUGENODE+=("nodes_hp[$node]=${nodes_hp[node]}")
1733f674e1eSMichal Berger		((_nr_hugepages += nodes_hp[node]))
174d60bc771SMichal Berger	done
175d60bc771SMichal Berger
176d60bc771SMichal Berger	get_test_nr_hugepages_per_node
17745dc5f12SMichal Berger	HUGENODE="${HUGENODE[*]}" setup output
1783f674e1eSMichal Berger	nr_hugepages=$_nr_hugepages verify_nr_hugepages
179d60bc771SMichal Berger}
180d60bc771SMichal Berger
18128bfb876SMichal Bergerno_shrink_alloc() {
182*0070858eSMichal Berger	# HUGEMEM (2G) alloc on node0
18328bfb876SMichal Berger	# attempt to shrink by half: 2G should remain
18428bfb876SMichal Berger
18528bfb876SMichal Berger	get_test_nr_hugepages $((2048 * 1024)) 0
18628bfb876SMichal Berger
18728bfb876SMichal Berger	# Verify the default first
188*0070858eSMichal Berger	NRHUGE=$nr_hugepages HUGENODE=0 setup output
18928bfb876SMichal Berger	verify_nr_hugepages
19028bfb876SMichal Berger
19128bfb876SMichal Berger	# Now attempt to shrink the hp number
192*0070858eSMichal Berger	CLEAR_HUGE=no NRHUGE=$((nr_hugepages / 2)) HUGENODE=0 setup output
19328bfb876SMichal Berger	# 2G should remain
19428bfb876SMichal Berger	verify_nr_hugepages
19528bfb876SMichal Berger}
19628bfb876SMichal Berger
197d60bc771SMichal Bergerget_nodes
198d60bc771SMichal Bergerclear_hp
199d60bc771SMichal Berger
200*0070858eSMichal Bergerrun_test "single_node_setup" single_node_setup
201d60bc771SMichal Bergerrun_test "even_2G_alloc" even_2G_alloc
202d60bc771SMichal Bergerrun_test "odd_alloc" odd_alloc
203d60bc771SMichal Bergerrun_test "custom_alloc" custom_alloc
20428bfb876SMichal Bergerrun_test "no_shrink_alloc" no_shrink_alloc
205d60bc771SMichal Berger
206d60bc771SMichal Bergerclear_hp
207