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