]>
Commit | Line | Data |
---|---|---|
d89dffa9 | 1 | #!/bin/bash |
b2441318 | 2 | # SPDX-License-Identifier: GPL-2.0 |
d89dffa9 AM |
3 | |
4 | SYSFS= | |
5 | ||
e1890c50 SKSO |
6 | # Kselftest framework requirement - SKIP code is 4. |
7 | ksft_skip=4 | |
8 | ||
d89dffa9 AM |
9 | prerequisite() |
10 | { | |
11 | msg="skip all tests:" | |
12 | ||
13 | if [ $UID != 0 ]; then | |
14 | echo $msg must be run as root >&2 | |
e1890c50 | 15 | exit $ksft_skip |
d89dffa9 AM |
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 | |
e1890c50 | 22 | exit $ksft_skip |
d89dffa9 AM |
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 | |
e1890c50 | 27 | exit $ksft_skip |
d89dffa9 | 28 | fi |
a34b28c9 PHL |
29 | |
30 | if ! grep -q 1 $SYSFS/devices/system/memory/memory*/removable; then | |
31 | echo $msg no hot-pluggable memory >&2 | |
e1890c50 | 32 | exit $ksft_skip |
a34b28c9 | 33 | fi |
d89dffa9 AM |
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 | ||
593f9278 | 51 | hotpluggable_offline_memory() |
d89dffa9 AM |
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 | |
5ff0c60b | 87 | return 1 |
d89dffa9 AM |
88 | elif ! memory_is_online $memory; then |
89 | echo $FUNCNAME $memory: unexpected offline >&2 | |
5ff0c60b | 90 | return 1 |
d89dffa9 | 91 | fi |
5ff0c60b | 92 | return 0 |
d89dffa9 AM |
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 | |
5ff0c60b | 101 | return 1 |
d89dffa9 AM |
102 | elif ! memory_is_offline $memory; then |
103 | echo $FUNCNAME $memory: unexpected online >&2 | |
5ff0c60b | 104 | return 1 |
d89dffa9 | 105 | fi |
5ff0c60b | 106 | return 0 |
d89dffa9 AM |
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 | |
5ff0c60b | 115 | return 1 |
d89dffa9 AM |
116 | elif ! memory_is_offline $memory; then |
117 | echo $FUNCNAME $memory: unexpected offline >&2 | |
5ff0c60b | 118 | return 1 |
d89dffa9 | 119 | fi |
5ff0c60b | 120 | return 0 |
d89dffa9 AM |
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 | |
5ff0c60b | 129 | return 1 |
d89dffa9 AM |
130 | elif ! memory_is_online $memory; then |
131 | echo $FUNCNAME $memory: unexpected offline >&2 | |
5ff0c60b | 132 | return 1 |
d89dffa9 | 133 | fi |
5ff0c60b | 134 | return 0 |
d89dffa9 AM |
135 | } |
136 | ||
137 | error=-12 | |
138 | priority=0 | |
4ed8b153 SKSO |
139 | # Run with default of ratio=2 for Kselftest run |
140 | ratio=2 | |
5ff0c60b | 141 | retval=0 |
d89dffa9 AM |
142 | |
143 | while getopts e:hp:r: opt; do | |
144 | case $opt in | |
145 | e) | |
146 | error=$OPTARG | |
147 | ;; | |
148 | h) | |
149 | echo "Usage $0 [ -e errno ] [ -p notifier-priority ] [ -r percent-of-memory-to-offline ]" | |
150 | exit | |
151 | ;; | |
152 | p) | |
153 | priority=$OPTARG | |
154 | ;; | |
155 | r) | |
156 | ratio=$OPTARG | |
72441ea5 PHL |
157 | if [ "$ratio" -gt 100 ] || [ "$ratio" -lt 0 ]; then |
158 | echo "The percentage should be an integer within 0~100 range" | |
159 | exit 1 | |
160 | fi | |
d89dffa9 AM |
161 | ;; |
162 | esac | |
163 | done | |
164 | ||
165 | if ! [ "$error" -ge -4095 -a "$error" -lt 0 ]; then | |
166 | echo "error code must be -4095 <= errno < 0" >&2 | |
167 | exit 1 | |
168 | fi | |
169 | ||
170 | prerequisite | |
171 | ||
ddddda9b | 172 | echo "Test scope: $ratio% hotplug memory" |
ddddda9b | 173 | |
d89dffa9 AM |
174 | # |
175 | # Online all hot-pluggable memory | |
176 | # | |
5ff0c60b PHL |
177 | hotpluggable_num=`hotpluggable_offline_memory | wc -l` |
178 | echo -e "\t online all hot-pluggable memory in offline state:" | |
179 | if [ "$hotpluggable_num" -gt 0 ]; then | |
180 | for memory in `hotpluggable_offline_memory`; do | |
181 | echo "offline->online memory$memory" | |
182 | if ! online_memory_expect_success $memory; then | |
183 | retval=1 | |
184 | fi | |
185 | done | |
186 | else | |
187 | echo -e "\t\t SKIPPED - no hot-pluggable memory in offline state" | |
188 | fi | |
d89dffa9 AM |
189 | |
190 | # | |
191 | # Offline $ratio percent of hot-pluggable memory | |
192 | # | |
5ff0c60b PHL |
193 | hotpluggable_num=`hotpluggable_online_memory | wc -l` |
194 | target=`echo "a=$hotpluggable_num*$ratio; if ( a%100 ) a/100+1 else a/100" | bc` | |
195 | echo -e "\t offline $ratio% hot-pluggable memory in online state" | |
196 | echo -e "\t trying to offline $target out of $hotpluggable_num memory block(s):" | |
d89dffa9 | 197 | for memory in `hotpluggable_online_memory`; do |
5ff0c60b PHL |
198 | if [ "$target" -gt 0 ]; then |
199 | echo "online->offline memory$memory" | |
200 | if offline_memory_expect_success $memory; then | |
201 | target=$(($target - 1)) | |
202 | fi | |
d89dffa9 AM |
203 | fi |
204 | done | |
5ff0c60b PHL |
205 | if [ "$target" -gt 0 ]; then |
206 | retval=1 | |
207 | echo -e "\t\t FAILED - unable to offline some memory blocks, device busy?" | |
208 | fi | |
d89dffa9 AM |
209 | |
210 | # | |
211 | # Online all hot-pluggable memory again | |
212 | # | |
5ff0c60b PHL |
213 | hotpluggable_num=`hotpluggable_offline_memory | wc -l` |
214 | echo -e "\t online all hot-pluggable memory in offline state:" | |
215 | if [ "$hotpluggable_num" -gt 0 ]; then | |
216 | for memory in `hotpluggable_offline_memory`; do | |
217 | echo "offline->online memory$memory" | |
218 | if ! online_memory_expect_success $memory; then | |
219 | retval=1 | |
220 | fi | |
221 | done | |
222 | else | |
223 | echo -e "\t\t SKIPPED - no hot-pluggable memory in offline state" | |
224 | fi | |
d89dffa9 AM |
225 | |
226 | # | |
227 | # Test with memory notifier error injection | |
228 | # | |
229 | ||
230 | DEBUGFS=`mount -t debugfs | head -1 | awk '{ print $3 }'` | |
231 | NOTIFIER_ERR_INJECT_DIR=$DEBUGFS/notifier-error-inject/memory | |
232 | ||
233 | prerequisite_extra() | |
234 | { | |
235 | msg="skip extra tests:" | |
236 | ||
237 | /sbin/modprobe -q -r memory-notifier-error-inject | |
238 | /sbin/modprobe -q memory-notifier-error-inject priority=$priority | |
239 | ||
240 | if [ ! -d "$DEBUGFS" ]; then | |
241 | echo $msg debugfs is not mounted >&2 | |
5ff0c60b | 242 | exit $retval |
d89dffa9 AM |
243 | fi |
244 | ||
245 | if [ ! -d $NOTIFIER_ERR_INJECT_DIR ]; then | |
246 | echo $msg memory-notifier-error-inject module is not available >&2 | |
5ff0c60b | 247 | exit $retval |
d89dffa9 AM |
248 | fi |
249 | } | |
250 | ||
02d8f075 | 251 | echo -e "\t Test with memory notifier error injection" |
d89dffa9 AM |
252 | prerequisite_extra |
253 | ||
254 | # | |
255 | # Offline $ratio percent of hot-pluggable memory | |
256 | # | |
257 | echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error | |
258 | for memory in `hotpluggable_online_memory`; do | |
259 | if [ $((RANDOM % 100)) -lt $ratio ]; then | |
260 | offline_memory_expect_success $memory | |
261 | fi | |
262 | done | |
263 | ||
264 | # | |
265 | # Test memory hot-add error handling (offline => online) | |
266 | # | |
267 | echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_ONLINE/error | |
593f9278 | 268 | for memory in `hotpluggable_offline_memory`; do |
d89dffa9 AM |
269 | online_memory_expect_fail $memory |
270 | done | |
271 | ||
272 | # | |
273 | # Online all hot-pluggable memory | |
274 | # | |
275 | echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_ONLINE/error | |
593f9278 | 276 | for memory in `hotpluggable_offline_memory`; do |
d89dffa9 AM |
277 | online_memory_expect_success $memory |
278 | done | |
279 | ||
280 | # | |
281 | # Test memory hot-remove error handling (online => offline) | |
282 | # | |
283 | echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error | |
284 | for memory in `hotpluggable_online_memory`; do | |
285 | offline_memory_expect_fail $memory | |
286 | done | |
287 | ||
288 | echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error | |
289 | /sbin/modprobe -q -r memory-notifier-error-inject | |
5ff0c60b PHL |
290 | |
291 | exit $retval |