123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- #!/bin/bash
- # SPDX-License-Identifier: GPL-2.0
- SYSFS=
- # Kselftest framework requirement - SKIP code is 4.
- ksft_skip=4
- prerequisite()
- {
- msg="skip all tests:"
- if [ $UID != 0 ]; then
- echo $msg must be run as root >&2
- exit $ksft_skip
- fi
- SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'`
- if [ ! -d "$SYSFS" ]; then
- echo $msg sysfs is not mounted >&2
- exit $ksft_skip
- fi
- if ! ls $SYSFS/devices/system/memory/memory* > /dev/null 2>&1; then
- echo $msg memory hotplug is not supported >&2
- exit $ksft_skip
- fi
- if ! grep -q 1 $SYSFS/devices/system/memory/memory*/removable; then
- echo $msg no hot-pluggable memory >&2
- exit $ksft_skip
- fi
- }
- #
- # list all hot-pluggable memory
- #
- hotpluggable_memory()
- {
- local state=${1:-.\*}
- for memory in $SYSFS/devices/system/memory/memory*; do
- if grep -q 1 $memory/removable &&
- grep -q $state $memory/state; then
- echo ${memory##/*/memory}
- fi
- done
- }
- hotpluggable_offline_memory()
- {
- hotpluggable_memory offline
- }
- hotpluggable_online_memory()
- {
- hotpluggable_memory online
- }
- memory_is_online()
- {
- grep -q online $SYSFS/devices/system/memory/memory$1/state
- }
- memory_is_offline()
- {
- grep -q offline $SYSFS/devices/system/memory/memory$1/state
- }
- online_memory()
- {
- echo online > $SYSFS/devices/system/memory/memory$1/state
- }
- offline_memory()
- {
- echo offline > $SYSFS/devices/system/memory/memory$1/state
- }
- online_memory_expect_success()
- {
- local memory=$1
- if ! online_memory $memory; then
- echo $FUNCNAME $memory: unexpected fail >&2
- return 1
- elif ! memory_is_online $memory; then
- echo $FUNCNAME $memory: unexpected offline >&2
- return 1
- fi
- return 0
- }
- online_memory_expect_fail()
- {
- local memory=$1
- if online_memory $memory 2> /dev/null; then
- echo $FUNCNAME $memory: unexpected success >&2
- return 1
- elif ! memory_is_offline $memory; then
- echo $FUNCNAME $memory: unexpected online >&2
- return 1
- fi
- return 0
- }
- offline_memory_expect_success()
- {
- local memory=$1
- if ! offline_memory $memory; then
- echo $FUNCNAME $memory: unexpected fail >&2
- return 1
- elif ! memory_is_offline $memory; then
- echo $FUNCNAME $memory: unexpected offline >&2
- return 1
- fi
- return 0
- }
- offline_memory_expect_fail()
- {
- local memory=$1
- if offline_memory $memory 2> /dev/null; then
- echo $FUNCNAME $memory: unexpected success >&2
- return 1
- elif ! memory_is_online $memory; then
- echo $FUNCNAME $memory: unexpected offline >&2
- return 1
- fi
- return 0
- }
- online_all_offline_memory()
- {
- for memory in `hotpluggable_offline_memory`; do
- if ! online_memory_expect_success $memory; then
- retval=1
- fi
- done
- }
- error=-12
- priority=0
- # Run with default of ratio=2 for Kselftest run
- ratio=2
- retval=0
- while getopts e:hp:r: opt; do
- case $opt in
- e)
- error=$OPTARG
- ;;
- h)
- echo "Usage $0 [ -e errno ] [ -p notifier-priority ] [ -r percent-of-memory-to-offline ]"
- exit
- ;;
- p)
- priority=$OPTARG
- ;;
- r)
- ratio=$OPTARG
- if [ "$ratio" -gt 100 ] || [ "$ratio" -lt 0 ]; then
- echo "The percentage should be an integer within 0~100 range"
- exit 1
- fi
- ;;
- esac
- done
- if ! [ "$error" -ge -4095 -a "$error" -lt 0 ]; then
- echo "error code must be -4095 <= errno < 0" >&2
- exit 1
- fi
- prerequisite
- echo "Test scope: $ratio% hotplug memory"
- #
- # Online all hot-pluggable memory
- #
- hotpluggable_num=`hotpluggable_offline_memory | wc -l`
- echo -e "\t online all hot-pluggable memory in offline state:"
- if [ "$hotpluggable_num" -gt 0 ]; then
- for memory in `hotpluggable_offline_memory`; do
- echo "offline->online memory$memory"
- if ! online_memory_expect_success $memory; then
- retval=1
- fi
- done
- else
- echo -e "\t\t SKIPPED - no hot-pluggable memory in offline state"
- fi
- #
- # Offline $ratio percent of hot-pluggable memory
- #
- hotpluggable_num=`hotpluggable_online_memory | wc -l`
- target=`echo "a=$hotpluggable_num*$ratio; if ( a%100 ) a/100+1 else a/100" | bc`
- echo -e "\t offline $ratio% hot-pluggable memory in online state"
- echo -e "\t trying to offline $target out of $hotpluggable_num memory block(s):"
- for memory in `hotpluggable_online_memory`; do
- if [ "$target" -gt 0 ]; then
- echo "online->offline memory$memory"
- if offline_memory_expect_success $memory &>/dev/null; then
- target=$(($target - 1))
- echo "-> Success"
- else
- echo "-> Failure"
- fi
- fi
- done
- if [ "$target" -gt 0 ]; then
- retval=1
- echo -e "\t\t FAILED - unable to offline some memory blocks, device busy?"
- fi
- #
- # Online all hot-pluggable memory again
- #
- hotpluggable_num=`hotpluggable_offline_memory | wc -l`
- echo -e "\t online all hot-pluggable memory in offline state:"
- if [ "$hotpluggable_num" -gt 0 ]; then
- for memory in `hotpluggable_offline_memory`; do
- echo "offline->online memory$memory"
- if ! online_memory_expect_success $memory; then
- retval=1
- fi
- done
- else
- echo -e "\t\t SKIPPED - no hot-pluggable memory in offline state"
- fi
- #
- # Test with memory notifier error injection
- #
- DEBUGFS=`mount -t debugfs | head -1 | awk '{ print $3 }'`
- NOTIFIER_ERR_INJECT_DIR=$DEBUGFS/notifier-error-inject/memory
- prerequisite_extra()
- {
- msg="skip extra tests:"
- /sbin/modprobe -q -r memory-notifier-error-inject
- /sbin/modprobe -q memory-notifier-error-inject priority=$priority
- if [ ! -d "$DEBUGFS" ]; then
- echo $msg debugfs is not mounted >&2
- exit $retval
- fi
- if [ ! -d $NOTIFIER_ERR_INJECT_DIR ]; then
- echo $msg memory-notifier-error-inject module is not available >&2
- exit $retval
- fi
- }
- echo -e "\t Test with memory notifier error injection"
- prerequisite_extra
- #
- # Offline $ratio percent of hot-pluggable memory
- #
- echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error
- for memory in `hotpluggable_online_memory`; do
- if [ $((RANDOM % 100)) -lt $ratio ]; then
- offline_memory_expect_success $memory &>/dev/null
- fi
- done
- #
- # Test memory hot-add error handling (offline => online)
- #
- echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_ONLINE/error
- for memory in `hotpluggable_offline_memory`; do
- if ! online_memory_expect_fail $memory; then
- retval=1
- fi
- done
- #
- # Online all hot-pluggable memory
- #
- echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_ONLINE/error
- online_all_offline_memory
- #
- # Test memory hot-remove error handling (online => offline)
- #
- echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error
- for memory in `hotpluggable_online_memory`; do
- if [ $((RANDOM % 100)) -lt $ratio ]; then
- if ! offline_memory_expect_fail $memory; then
- retval=1
- fi
- fi
- done
- echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error
- /sbin/modprobe -q -r memory-notifier-error-inject
- #
- # Restore memory before exit
- #
- online_all_offline_memory
- exit $retval
|