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
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.