162306a36Sopenharmony_ci#!/bin/bash 262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0 362306a36Sopenharmony_ci 462306a36Sopenharmony_ciSYSFS= 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci# Kselftest framework requirement - SKIP code is 4. 762306a36Sopenharmony_ciksft_skip=4 862306a36Sopenharmony_ci 962306a36Sopenharmony_ciprerequisite() 1062306a36Sopenharmony_ci{ 1162306a36Sopenharmony_ci msg="skip all tests:" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci if [ $UID != 0 ]; then 1462306a36Sopenharmony_ci echo $msg must be run as root >&2 1562306a36Sopenharmony_ci exit $ksft_skip 1662306a36Sopenharmony_ci fi 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'` 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci if [ ! -d "$SYSFS" ]; then 2162306a36Sopenharmony_ci echo $msg sysfs is not mounted >&2 2262306a36Sopenharmony_ci exit $ksft_skip 2362306a36Sopenharmony_ci fi 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci if ! ls $SYSFS/devices/system/memory/memory* > /dev/null 2>&1; then 2662306a36Sopenharmony_ci echo $msg memory hotplug is not supported >&2 2762306a36Sopenharmony_ci exit $ksft_skip 2862306a36Sopenharmony_ci fi 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci if ! grep -q 1 $SYSFS/devices/system/memory/memory*/removable; then 3162306a36Sopenharmony_ci echo $msg no hot-pluggable memory >&2 3262306a36Sopenharmony_ci exit $ksft_skip 3362306a36Sopenharmony_ci fi 3462306a36Sopenharmony_ci} 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci# 3762306a36Sopenharmony_ci# list all hot-pluggable memory 3862306a36Sopenharmony_ci# 3962306a36Sopenharmony_cihotpluggable_memory() 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci local state=${1:-.\*} 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci for memory in $SYSFS/devices/system/memory/memory*; do 4462306a36Sopenharmony_ci if grep -q 1 $memory/removable && 4562306a36Sopenharmony_ci grep -q $state $memory/state; then 4662306a36Sopenharmony_ci echo ${memory##/*/memory} 4762306a36Sopenharmony_ci fi 4862306a36Sopenharmony_ci done 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cihotpluggable_offline_memory() 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci hotpluggable_memory offline 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cihotpluggable_online_memory() 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci hotpluggable_memory online 5962306a36Sopenharmony_ci} 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cimemory_is_online() 6262306a36Sopenharmony_ci{ 6362306a36Sopenharmony_ci grep -q online $SYSFS/devices/system/memory/memory$1/state 6462306a36Sopenharmony_ci} 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cimemory_is_offline() 6762306a36Sopenharmony_ci{ 6862306a36Sopenharmony_ci grep -q offline $SYSFS/devices/system/memory/memory$1/state 6962306a36Sopenharmony_ci} 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_cionline_memory() 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci echo online > $SYSFS/devices/system/memory/memory$1/state 7462306a36Sopenharmony_ci} 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cioffline_memory() 7762306a36Sopenharmony_ci{ 7862306a36Sopenharmony_ci echo offline > $SYSFS/devices/system/memory/memory$1/state 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cionline_memory_expect_success() 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci local memory=$1 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci if ! online_memory $memory; then 8662306a36Sopenharmony_ci echo $FUNCNAME $memory: unexpected fail >&2 8762306a36Sopenharmony_ci return 1 8862306a36Sopenharmony_ci elif ! memory_is_online $memory; then 8962306a36Sopenharmony_ci echo $FUNCNAME $memory: unexpected offline >&2 9062306a36Sopenharmony_ci return 1 9162306a36Sopenharmony_ci fi 9262306a36Sopenharmony_ci return 0 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cionline_memory_expect_fail() 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci local memory=$1 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci if online_memory $memory 2> /dev/null; then 10062306a36Sopenharmony_ci echo $FUNCNAME $memory: unexpected success >&2 10162306a36Sopenharmony_ci return 1 10262306a36Sopenharmony_ci elif ! memory_is_offline $memory; then 10362306a36Sopenharmony_ci echo $FUNCNAME $memory: unexpected online >&2 10462306a36Sopenharmony_ci return 1 10562306a36Sopenharmony_ci fi 10662306a36Sopenharmony_ci return 0 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cioffline_memory_expect_success() 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci local memory=$1 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci if ! offline_memory $memory; then 11462306a36Sopenharmony_ci echo $FUNCNAME $memory: unexpected fail >&2 11562306a36Sopenharmony_ci return 1 11662306a36Sopenharmony_ci elif ! memory_is_offline $memory; then 11762306a36Sopenharmony_ci echo $FUNCNAME $memory: unexpected offline >&2 11862306a36Sopenharmony_ci return 1 11962306a36Sopenharmony_ci fi 12062306a36Sopenharmony_ci return 0 12162306a36Sopenharmony_ci} 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cioffline_memory_expect_fail() 12462306a36Sopenharmony_ci{ 12562306a36Sopenharmony_ci local memory=$1 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci if offline_memory $memory 2> /dev/null; then 12862306a36Sopenharmony_ci echo $FUNCNAME $memory: unexpected success >&2 12962306a36Sopenharmony_ci return 1 13062306a36Sopenharmony_ci elif ! memory_is_online $memory; then 13162306a36Sopenharmony_ci echo $FUNCNAME $memory: unexpected offline >&2 13262306a36Sopenharmony_ci return 1 13362306a36Sopenharmony_ci fi 13462306a36Sopenharmony_ci return 0 13562306a36Sopenharmony_ci} 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_cionline_all_offline_memory() 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci for memory in `hotpluggable_offline_memory`; do 14062306a36Sopenharmony_ci if ! online_memory_expect_success $memory; then 14162306a36Sopenharmony_ci retval=1 14262306a36Sopenharmony_ci fi 14362306a36Sopenharmony_ci done 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cierror=-12 14762306a36Sopenharmony_cipriority=0 14862306a36Sopenharmony_ci# Run with default of ratio=2 for Kselftest run 14962306a36Sopenharmony_ciratio=2 15062306a36Sopenharmony_ciretval=0 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ciwhile getopts e:hp:r: opt; do 15362306a36Sopenharmony_ci case $opt in 15462306a36Sopenharmony_ci e) 15562306a36Sopenharmony_ci error=$OPTARG 15662306a36Sopenharmony_ci ;; 15762306a36Sopenharmony_ci h) 15862306a36Sopenharmony_ci echo "Usage $0 [ -e errno ] [ -p notifier-priority ] [ -r percent-of-memory-to-offline ]" 15962306a36Sopenharmony_ci exit 16062306a36Sopenharmony_ci ;; 16162306a36Sopenharmony_ci p) 16262306a36Sopenharmony_ci priority=$OPTARG 16362306a36Sopenharmony_ci ;; 16462306a36Sopenharmony_ci r) 16562306a36Sopenharmony_ci ratio=$OPTARG 16662306a36Sopenharmony_ci if [ "$ratio" -gt 100 ] || [ "$ratio" -lt 0 ]; then 16762306a36Sopenharmony_ci echo "The percentage should be an integer within 0~100 range" 16862306a36Sopenharmony_ci exit 1 16962306a36Sopenharmony_ci fi 17062306a36Sopenharmony_ci ;; 17162306a36Sopenharmony_ci esac 17262306a36Sopenharmony_cidone 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ciif ! [ "$error" -ge -4095 -a "$error" -lt 0 ]; then 17562306a36Sopenharmony_ci echo "error code must be -4095 <= errno < 0" >&2 17662306a36Sopenharmony_ci exit 1 17762306a36Sopenharmony_cifi 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ciprerequisite 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ciecho "Test scope: $ratio% hotplug memory" 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci# 18462306a36Sopenharmony_ci# Online all hot-pluggable memory 18562306a36Sopenharmony_ci# 18662306a36Sopenharmony_cihotpluggable_num=`hotpluggable_offline_memory | wc -l` 18762306a36Sopenharmony_ciecho -e "\t online all hot-pluggable memory in offline state:" 18862306a36Sopenharmony_ciif [ "$hotpluggable_num" -gt 0 ]; then 18962306a36Sopenharmony_ci for memory in `hotpluggable_offline_memory`; do 19062306a36Sopenharmony_ci echo "offline->online memory$memory" 19162306a36Sopenharmony_ci if ! online_memory_expect_success $memory; then 19262306a36Sopenharmony_ci retval=1 19362306a36Sopenharmony_ci fi 19462306a36Sopenharmony_ci done 19562306a36Sopenharmony_cielse 19662306a36Sopenharmony_ci echo -e "\t\t SKIPPED - no hot-pluggable memory in offline state" 19762306a36Sopenharmony_cifi 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci# 20062306a36Sopenharmony_ci# Offline $ratio percent of hot-pluggable memory 20162306a36Sopenharmony_ci# 20262306a36Sopenharmony_cihotpluggable_num=`hotpluggable_online_memory | wc -l` 20362306a36Sopenharmony_citarget=`echo "a=$hotpluggable_num*$ratio; if ( a%100 ) a/100+1 else a/100" | bc` 20462306a36Sopenharmony_ciecho -e "\t offline $ratio% hot-pluggable memory in online state" 20562306a36Sopenharmony_ciecho -e "\t trying to offline $target out of $hotpluggable_num memory block(s):" 20662306a36Sopenharmony_cifor memory in `hotpluggable_online_memory`; do 20762306a36Sopenharmony_ci if [ "$target" -gt 0 ]; then 20862306a36Sopenharmony_ci echo "online->offline memory$memory" 20962306a36Sopenharmony_ci if offline_memory_expect_success $memory &>/dev/null; then 21062306a36Sopenharmony_ci target=$(($target - 1)) 21162306a36Sopenharmony_ci echo "-> Success" 21262306a36Sopenharmony_ci else 21362306a36Sopenharmony_ci echo "-> Failure" 21462306a36Sopenharmony_ci fi 21562306a36Sopenharmony_ci fi 21662306a36Sopenharmony_cidone 21762306a36Sopenharmony_ciif [ "$target" -gt 0 ]; then 21862306a36Sopenharmony_ci retval=1 21962306a36Sopenharmony_ci echo -e "\t\t FAILED - unable to offline some memory blocks, device busy?" 22062306a36Sopenharmony_cifi 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci# 22362306a36Sopenharmony_ci# Online all hot-pluggable memory again 22462306a36Sopenharmony_ci# 22562306a36Sopenharmony_cihotpluggable_num=`hotpluggable_offline_memory | wc -l` 22662306a36Sopenharmony_ciecho -e "\t online all hot-pluggable memory in offline state:" 22762306a36Sopenharmony_ciif [ "$hotpluggable_num" -gt 0 ]; then 22862306a36Sopenharmony_ci for memory in `hotpluggable_offline_memory`; do 22962306a36Sopenharmony_ci echo "offline->online memory$memory" 23062306a36Sopenharmony_ci if ! online_memory_expect_success $memory; then 23162306a36Sopenharmony_ci retval=1 23262306a36Sopenharmony_ci fi 23362306a36Sopenharmony_ci done 23462306a36Sopenharmony_cielse 23562306a36Sopenharmony_ci echo -e "\t\t SKIPPED - no hot-pluggable memory in offline state" 23662306a36Sopenharmony_cifi 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci# 23962306a36Sopenharmony_ci# Test with memory notifier error injection 24062306a36Sopenharmony_ci# 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ciDEBUGFS=`mount -t debugfs | head -1 | awk '{ print $3 }'` 24362306a36Sopenharmony_ciNOTIFIER_ERR_INJECT_DIR=$DEBUGFS/notifier-error-inject/memory 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ciprerequisite_extra() 24662306a36Sopenharmony_ci{ 24762306a36Sopenharmony_ci msg="skip extra tests:" 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci /sbin/modprobe -q -r memory-notifier-error-inject 25062306a36Sopenharmony_ci /sbin/modprobe -q memory-notifier-error-inject priority=$priority 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci if [ ! -d "$DEBUGFS" ]; then 25362306a36Sopenharmony_ci echo $msg debugfs is not mounted >&2 25462306a36Sopenharmony_ci exit $retval 25562306a36Sopenharmony_ci fi 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci if [ ! -d $NOTIFIER_ERR_INJECT_DIR ]; then 25862306a36Sopenharmony_ci echo $msg memory-notifier-error-inject module is not available >&2 25962306a36Sopenharmony_ci exit $retval 26062306a36Sopenharmony_ci fi 26162306a36Sopenharmony_ci} 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ciecho -e "\t Test with memory notifier error injection" 26462306a36Sopenharmony_ciprerequisite_extra 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci# 26762306a36Sopenharmony_ci# Offline $ratio percent of hot-pluggable memory 26862306a36Sopenharmony_ci# 26962306a36Sopenharmony_ciecho 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error 27062306a36Sopenharmony_cifor memory in `hotpluggable_online_memory`; do 27162306a36Sopenharmony_ci if [ $((RANDOM % 100)) -lt $ratio ]; then 27262306a36Sopenharmony_ci offline_memory_expect_success $memory &>/dev/null 27362306a36Sopenharmony_ci fi 27462306a36Sopenharmony_cidone 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci# 27762306a36Sopenharmony_ci# Test memory hot-add error handling (offline => online) 27862306a36Sopenharmony_ci# 27962306a36Sopenharmony_ciecho $error > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_ONLINE/error 28062306a36Sopenharmony_cifor memory in `hotpluggable_offline_memory`; do 28162306a36Sopenharmony_ci if ! online_memory_expect_fail $memory; then 28262306a36Sopenharmony_ci retval=1 28362306a36Sopenharmony_ci fi 28462306a36Sopenharmony_cidone 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci# 28762306a36Sopenharmony_ci# Online all hot-pluggable memory 28862306a36Sopenharmony_ci# 28962306a36Sopenharmony_ciecho 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_ONLINE/error 29062306a36Sopenharmony_cionline_all_offline_memory 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci# 29362306a36Sopenharmony_ci# Test memory hot-remove error handling (online => offline) 29462306a36Sopenharmony_ci# 29562306a36Sopenharmony_ciecho $error > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error 29662306a36Sopenharmony_cifor memory in `hotpluggable_online_memory`; do 29762306a36Sopenharmony_ci if [ $((RANDOM % 100)) -lt $ratio ]; then 29862306a36Sopenharmony_ci if ! offline_memory_expect_fail $memory; then 29962306a36Sopenharmony_ci retval=1 30062306a36Sopenharmony_ci fi 30162306a36Sopenharmony_ci fi 30262306a36Sopenharmony_cidone 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ciecho 0 > $NOTIFIER_ERR_INJECT_DIR/actions/MEM_GOING_OFFLINE/error 30562306a36Sopenharmony_ci/sbin/modprobe -q -r memory-notifier-error-inject 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci# 30862306a36Sopenharmony_ci# Restore memory before exit 30962306a36Sopenharmony_ci# 31062306a36Sopenharmony_cionline_all_offline_memory 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ciexit $retval 313