]> Git Repo - linux.git/blob - tools/testing/selftests/memory-hotplug/mem-on-off-test.sh
x86/kaslr: Expose and use the end of the physical memory address space
[linux.git] / tools / testing / selftests / memory-hotplug / mem-on-off-test.sh
1 #!/bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3
4 SYSFS=
5
6 # Kselftest framework requirement - SKIP code is 4.
7 ksft_skip=4
8
9 prerequisite()
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 #
39 hotpluggable_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
51 hotpluggable_offline_memory()
52 {
53         hotpluggable_memory offline
54 }
55
56 hotpluggable_online_memory()
57 {
58         hotpluggable_memory online
59 }
60
61 memory_is_online()
62 {
63         grep -q online $SYSFS/devices/system/memory/memory$1/state
64 }
65
66 memory_is_offline()
67 {
68         grep -q offline $SYSFS/devices/system/memory/memory$1/state
69 }
70
71 online_memory()
72 {
73         echo online > $SYSFS/devices/system/memory/memory$1/state
74 }
75
76 offline_memory()
77 {
78         echo offline > $SYSFS/devices/system/memory/memory$1/state
79 }
80
81 online_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
95 online_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
109 offline_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
123 offline_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
137 online_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
146 error=-12
147 priority=0
148 # Run with default of ratio=2 for Kselftest run
149 ratio=2
150 retval=0
151
152 while 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
172 done
173
174 if ! [ "$error" -ge -4095 -a "$error" -lt 0 ]; then
175         echo "error code must be -4095 <= errno < 0" >&2
176         exit 1
177 fi
178
179 prerequisite
180
181 echo "Test scope: $ratio% hotplug memory"
182
183 #
184 # Online all hot-pluggable memory
185 #
186 hotpluggable_num=`hotpluggable_offline_memory | wc -l`
187 echo -e "\t online all hot-pluggable memory in offline state:"
188 if [ "$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
195 else
196         echo -e "\t\t SKIPPED - no hot-pluggable memory in offline state"
197 fi
198
199 #
200 # Offline $ratio percent of hot-pluggable memory
201 #
202 hotpluggable_num=`hotpluggable_online_memory | wc -l`
203 target=`echo "a=$hotpluggable_num*$ratio; if ( a%100 ) a/100+1 else a/100" | bc`
204 echo -e "\t offline $ratio% hot-pluggable memory in online state"
205 echo -e "\t trying to offline $target out of $hotpluggable_num memory block(s):"
206 for 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
216 done
217 if [ "$target" -gt 0 ]; then
218         retval=1
219         echo -e "\t\t FAILED - unable to offline some memory blocks, device busy?"
220 fi
221
222 #
223 # Online all hot-pluggable memory again
224 #
225 hotpluggable_num=`hotpluggable_offline_memory | wc -l`
226 echo -e "\t online all hot-pluggable memory in offline state:"
227 if [ "$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
234 else
235         echo -e "\t\t SKIPPED - no hot-pluggable memory in offline state"
236 fi
237
238 #
239 # Test with memory notifier error injection
240 #
241
242 DEBUGFS=`mount -t debugfs | head -1 | awk '{ print $3 }'`
243 NOTIFIER_ERR_INJECT_DIR=$DEBUGFS/notifier-error-inject/memory
244
245 prerequisite_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
263 echo -e "\t Test with memory notifier error injection"
264 prerequisite_extra
265
266 #
267 # Offline $ratio percent of hot-pluggable memory
268 #
269 echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error
270 for memory in `hotpluggable_online_memory`; do
271         if [ $((RANDOM % 100)) -lt $ratio ]; then
272                 offline_memory_expect_success $memory &>/dev/null
273         fi
274 done
275
276 #
277 # Test memory hot-add error handling (offline => online)
278 #
279 echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_ONLINE/error
280 for memory in `hotpluggable_offline_memory`; do
281         if ! online_memory_expect_fail $memory; then
282                 retval=1
283         fi
284 done
285
286 #
287 # Online all hot-pluggable memory
288 #
289 echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_ONLINE/error
290 online_all_offline_memory
291
292 #
293 # Test memory hot-remove error handling (online => offline)
294 #
295 echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error
296 for 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
302 done
303
304 echo 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 #
310 online_all_offline_memory
311
312 exit $retval
This page took 0.052333 seconds and 4 git commands to generate.