xref: /OK3568_Linux_fs/kernel/tools/testing/selftests/memory-hotplug/mem-on-off-test.sh (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#!/bin/bash
2*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0
3*4882a593Smuzhiyun
4*4882a593SmuzhiyunSYSFS=
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun# Kselftest framework requirement - SKIP code is 4.
7*4882a593Smuzhiyunksft_skip=4
8*4882a593Smuzhiyun
9*4882a593Smuzhiyunprerequisite()
10*4882a593Smuzhiyun{
11*4882a593Smuzhiyun	msg="skip all tests:"
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun	if [ $UID != 0 ]; then
14*4882a593Smuzhiyun		echo $msg must be run as root >&2
15*4882a593Smuzhiyun		exit $ksft_skip
16*4882a593Smuzhiyun	fi
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun	SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'`
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun	if [ ! -d "$SYSFS" ]; then
21*4882a593Smuzhiyun		echo $msg sysfs is not mounted >&2
22*4882a593Smuzhiyun		exit $ksft_skip
23*4882a593Smuzhiyun	fi
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun	if ! ls $SYSFS/devices/system/memory/memory* > /dev/null 2>&1; then
26*4882a593Smuzhiyun		echo $msg memory hotplug is not supported >&2
27*4882a593Smuzhiyun		exit $ksft_skip
28*4882a593Smuzhiyun	fi
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun	if ! grep -q 1 $SYSFS/devices/system/memory/memory*/removable; then
31*4882a593Smuzhiyun		echo $msg no hot-pluggable memory >&2
32*4882a593Smuzhiyun		exit $ksft_skip
33*4882a593Smuzhiyun	fi
34*4882a593Smuzhiyun}
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun#
37*4882a593Smuzhiyun# list all hot-pluggable memory
38*4882a593Smuzhiyun#
39*4882a593Smuzhiyunhotpluggable_memory()
40*4882a593Smuzhiyun{
41*4882a593Smuzhiyun	local state=${1:-.\*}
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun	for memory in $SYSFS/devices/system/memory/memory*; do
44*4882a593Smuzhiyun		if grep -q 1 $memory/removable &&
45*4882a593Smuzhiyun		   grep -q $state $memory/state; then
46*4882a593Smuzhiyun			echo ${memory##/*/memory}
47*4882a593Smuzhiyun		fi
48*4882a593Smuzhiyun	done
49*4882a593Smuzhiyun}
50*4882a593Smuzhiyun
51*4882a593Smuzhiyunhotpluggable_offline_memory()
52*4882a593Smuzhiyun{
53*4882a593Smuzhiyun	hotpluggable_memory offline
54*4882a593Smuzhiyun}
55*4882a593Smuzhiyun
56*4882a593Smuzhiyunhotpluggable_online_memory()
57*4882a593Smuzhiyun{
58*4882a593Smuzhiyun	hotpluggable_memory online
59*4882a593Smuzhiyun}
60*4882a593Smuzhiyun
61*4882a593Smuzhiyunmemory_is_online()
62*4882a593Smuzhiyun{
63*4882a593Smuzhiyun	grep -q online $SYSFS/devices/system/memory/memory$1/state
64*4882a593Smuzhiyun}
65*4882a593Smuzhiyun
66*4882a593Smuzhiyunmemory_is_offline()
67*4882a593Smuzhiyun{
68*4882a593Smuzhiyun	grep -q offline $SYSFS/devices/system/memory/memory$1/state
69*4882a593Smuzhiyun}
70*4882a593Smuzhiyun
71*4882a593Smuzhiyunonline_memory()
72*4882a593Smuzhiyun{
73*4882a593Smuzhiyun	echo online > $SYSFS/devices/system/memory/memory$1/state
74*4882a593Smuzhiyun}
75*4882a593Smuzhiyun
76*4882a593Smuzhiyunoffline_memory()
77*4882a593Smuzhiyun{
78*4882a593Smuzhiyun	echo offline > $SYSFS/devices/system/memory/memory$1/state
79*4882a593Smuzhiyun}
80*4882a593Smuzhiyun
81*4882a593Smuzhiyunonline_memory_expect_success()
82*4882a593Smuzhiyun{
83*4882a593Smuzhiyun	local memory=$1
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun	if ! online_memory $memory; then
86*4882a593Smuzhiyun		echo $FUNCNAME $memory: unexpected fail >&2
87*4882a593Smuzhiyun		return 1
88*4882a593Smuzhiyun	elif ! memory_is_online $memory; then
89*4882a593Smuzhiyun		echo $FUNCNAME $memory: unexpected offline >&2
90*4882a593Smuzhiyun		return 1
91*4882a593Smuzhiyun	fi
92*4882a593Smuzhiyun	return 0
93*4882a593Smuzhiyun}
94*4882a593Smuzhiyun
95*4882a593Smuzhiyunonline_memory_expect_fail()
96*4882a593Smuzhiyun{
97*4882a593Smuzhiyun	local memory=$1
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun	if online_memory $memory 2> /dev/null; then
100*4882a593Smuzhiyun		echo $FUNCNAME $memory: unexpected success >&2
101*4882a593Smuzhiyun		return 1
102*4882a593Smuzhiyun	elif ! memory_is_offline $memory; then
103*4882a593Smuzhiyun		echo $FUNCNAME $memory: unexpected online >&2
104*4882a593Smuzhiyun		return 1
105*4882a593Smuzhiyun	fi
106*4882a593Smuzhiyun	return 0
107*4882a593Smuzhiyun}
108*4882a593Smuzhiyun
109*4882a593Smuzhiyunoffline_memory_expect_success()
110*4882a593Smuzhiyun{
111*4882a593Smuzhiyun	local memory=$1
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun	if ! offline_memory $memory; then
114*4882a593Smuzhiyun		echo $FUNCNAME $memory: unexpected fail >&2
115*4882a593Smuzhiyun		return 1
116*4882a593Smuzhiyun	elif ! memory_is_offline $memory; then
117*4882a593Smuzhiyun		echo $FUNCNAME $memory: unexpected offline >&2
118*4882a593Smuzhiyun		return 1
119*4882a593Smuzhiyun	fi
120*4882a593Smuzhiyun	return 0
121*4882a593Smuzhiyun}
122*4882a593Smuzhiyun
123*4882a593Smuzhiyunoffline_memory_expect_fail()
124*4882a593Smuzhiyun{
125*4882a593Smuzhiyun	local memory=$1
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun	if offline_memory $memory 2> /dev/null; then
128*4882a593Smuzhiyun		echo $FUNCNAME $memory: unexpected success >&2
129*4882a593Smuzhiyun		return 1
130*4882a593Smuzhiyun	elif ! memory_is_online $memory; then
131*4882a593Smuzhiyun		echo $FUNCNAME $memory: unexpected offline >&2
132*4882a593Smuzhiyun		return 1
133*4882a593Smuzhiyun	fi
134*4882a593Smuzhiyun	return 0
135*4882a593Smuzhiyun}
136*4882a593Smuzhiyun
137*4882a593Smuzhiyunerror=-12
138*4882a593Smuzhiyunpriority=0
139*4882a593Smuzhiyun# Run with default of ratio=2 for Kselftest run
140*4882a593Smuzhiyunratio=2
141*4882a593Smuzhiyunretval=0
142*4882a593Smuzhiyun
143*4882a593Smuzhiyunwhile getopts e:hp:r: opt; do
144*4882a593Smuzhiyun	case $opt in
145*4882a593Smuzhiyun	e)
146*4882a593Smuzhiyun		error=$OPTARG
147*4882a593Smuzhiyun		;;
148*4882a593Smuzhiyun	h)
149*4882a593Smuzhiyun		echo "Usage $0 [ -e errno ] [ -p notifier-priority ] [ -r percent-of-memory-to-offline ]"
150*4882a593Smuzhiyun		exit
151*4882a593Smuzhiyun		;;
152*4882a593Smuzhiyun	p)
153*4882a593Smuzhiyun		priority=$OPTARG
154*4882a593Smuzhiyun		;;
155*4882a593Smuzhiyun	r)
156*4882a593Smuzhiyun		ratio=$OPTARG
157*4882a593Smuzhiyun		if [ "$ratio" -gt 100 ] || [ "$ratio" -lt 0 ]; then
158*4882a593Smuzhiyun			echo "The percentage should be an integer within 0~100 range"
159*4882a593Smuzhiyun			exit 1
160*4882a593Smuzhiyun		fi
161*4882a593Smuzhiyun		;;
162*4882a593Smuzhiyun	esac
163*4882a593Smuzhiyundone
164*4882a593Smuzhiyun
165*4882a593Smuzhiyunif ! [ "$error" -ge -4095 -a "$error" -lt 0 ]; then
166*4882a593Smuzhiyun	echo "error code must be -4095 <= errno < 0" >&2
167*4882a593Smuzhiyun	exit 1
168*4882a593Smuzhiyunfi
169*4882a593Smuzhiyun
170*4882a593Smuzhiyunprerequisite
171*4882a593Smuzhiyun
172*4882a593Smuzhiyunecho "Test scope: $ratio% hotplug memory"
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun#
175*4882a593Smuzhiyun# Online all hot-pluggable memory
176*4882a593Smuzhiyun#
177*4882a593Smuzhiyunhotpluggable_num=`hotpluggable_offline_memory | wc -l`
178*4882a593Smuzhiyunecho -e "\t online all hot-pluggable memory in offline state:"
179*4882a593Smuzhiyunif [ "$hotpluggable_num" -gt 0 ]; then
180*4882a593Smuzhiyun	for memory in `hotpluggable_offline_memory`; do
181*4882a593Smuzhiyun		echo "offline->online memory$memory"
182*4882a593Smuzhiyun		if ! online_memory_expect_success $memory; then
183*4882a593Smuzhiyun			retval=1
184*4882a593Smuzhiyun		fi
185*4882a593Smuzhiyun	done
186*4882a593Smuzhiyunelse
187*4882a593Smuzhiyun	echo -e "\t\t SKIPPED - no hot-pluggable memory in offline state"
188*4882a593Smuzhiyunfi
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun#
191*4882a593Smuzhiyun# Offline $ratio percent of hot-pluggable memory
192*4882a593Smuzhiyun#
193*4882a593Smuzhiyunhotpluggable_num=`hotpluggable_online_memory | wc -l`
194*4882a593Smuzhiyuntarget=`echo "a=$hotpluggable_num*$ratio; if ( a%100 ) a/100+1 else a/100" | bc`
195*4882a593Smuzhiyunecho -e "\t offline $ratio% hot-pluggable memory in online state"
196*4882a593Smuzhiyunecho -e "\t trying to offline $target out of $hotpluggable_num memory block(s):"
197*4882a593Smuzhiyunfor memory in `hotpluggable_online_memory`; do
198*4882a593Smuzhiyun	if [ "$target" -gt 0 ]; then
199*4882a593Smuzhiyun		echo "online->offline memory$memory"
200*4882a593Smuzhiyun		if offline_memory_expect_success $memory; then
201*4882a593Smuzhiyun			target=$(($target - 1))
202*4882a593Smuzhiyun		fi
203*4882a593Smuzhiyun	fi
204*4882a593Smuzhiyundone
205*4882a593Smuzhiyunif [ "$target" -gt 0 ]; then
206*4882a593Smuzhiyun	retval=1
207*4882a593Smuzhiyun	echo -e "\t\t FAILED - unable to offline some memory blocks, device busy?"
208*4882a593Smuzhiyunfi
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun#
211*4882a593Smuzhiyun# Online all hot-pluggable memory again
212*4882a593Smuzhiyun#
213*4882a593Smuzhiyunhotpluggable_num=`hotpluggable_offline_memory | wc -l`
214*4882a593Smuzhiyunecho -e "\t online all hot-pluggable memory in offline state:"
215*4882a593Smuzhiyunif [ "$hotpluggable_num" -gt 0 ]; then
216*4882a593Smuzhiyun	for memory in `hotpluggable_offline_memory`; do
217*4882a593Smuzhiyun		echo "offline->online memory$memory"
218*4882a593Smuzhiyun		if ! online_memory_expect_success $memory; then
219*4882a593Smuzhiyun			retval=1
220*4882a593Smuzhiyun		fi
221*4882a593Smuzhiyun	done
222*4882a593Smuzhiyunelse
223*4882a593Smuzhiyun	echo -e "\t\t SKIPPED - no hot-pluggable memory in offline state"
224*4882a593Smuzhiyunfi
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun#
227*4882a593Smuzhiyun# Test with memory notifier error injection
228*4882a593Smuzhiyun#
229*4882a593Smuzhiyun
230*4882a593SmuzhiyunDEBUGFS=`mount -t debugfs | head -1 | awk '{ print $3 }'`
231*4882a593SmuzhiyunNOTIFIER_ERR_INJECT_DIR=$DEBUGFS/notifier-error-inject/memory
232*4882a593Smuzhiyun
233*4882a593Smuzhiyunprerequisite_extra()
234*4882a593Smuzhiyun{
235*4882a593Smuzhiyun	msg="skip extra tests:"
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun	/sbin/modprobe -q -r memory-notifier-error-inject
238*4882a593Smuzhiyun	/sbin/modprobe -q memory-notifier-error-inject priority=$priority
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun	if [ ! -d "$DEBUGFS" ]; then
241*4882a593Smuzhiyun		echo $msg debugfs is not mounted >&2
242*4882a593Smuzhiyun		exit $retval
243*4882a593Smuzhiyun	fi
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun	if [ ! -d $NOTIFIER_ERR_INJECT_DIR ]; then
246*4882a593Smuzhiyun		echo $msg memory-notifier-error-inject module is not available >&2
247*4882a593Smuzhiyun		exit $retval
248*4882a593Smuzhiyun	fi
249*4882a593Smuzhiyun}
250*4882a593Smuzhiyun
251*4882a593Smuzhiyunecho -e "\t Test with memory notifier error injection"
252*4882a593Smuzhiyunprerequisite_extra
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun#
255*4882a593Smuzhiyun# Offline $ratio percent of hot-pluggable memory
256*4882a593Smuzhiyun#
257*4882a593Smuzhiyunecho 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error
258*4882a593Smuzhiyunfor memory in `hotpluggable_online_memory`; do
259*4882a593Smuzhiyun	if [ $((RANDOM % 100)) -lt $ratio ]; then
260*4882a593Smuzhiyun		offline_memory_expect_success $memory
261*4882a593Smuzhiyun	fi
262*4882a593Smuzhiyundone
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun#
265*4882a593Smuzhiyun# Test memory hot-add error handling (offline => online)
266*4882a593Smuzhiyun#
267*4882a593Smuzhiyunecho $error > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_ONLINE/error
268*4882a593Smuzhiyunfor memory in `hotpluggable_offline_memory`; do
269*4882a593Smuzhiyun	online_memory_expect_fail $memory
270*4882a593Smuzhiyundone
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun#
273*4882a593Smuzhiyun# Online all hot-pluggable memory
274*4882a593Smuzhiyun#
275*4882a593Smuzhiyunecho 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_ONLINE/error
276*4882a593Smuzhiyunfor memory in `hotpluggable_offline_memory`; do
277*4882a593Smuzhiyun	online_memory_expect_success $memory
278*4882a593Smuzhiyundone
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun#
281*4882a593Smuzhiyun# Test memory hot-remove error handling (online => offline)
282*4882a593Smuzhiyun#
283*4882a593Smuzhiyunecho $error > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error
284*4882a593Smuzhiyunfor memory in `hotpluggable_online_memory`; do
285*4882a593Smuzhiyun	offline_memory_expect_fail $memory
286*4882a593Smuzhiyundone
287*4882a593Smuzhiyun
288*4882a593Smuzhiyunecho 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error
289*4882a593Smuzhiyun/sbin/modprobe -q -r memory-notifier-error-inject
290*4882a593Smuzhiyun
291*4882a593Smuzhiyunexit $retval
292