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