mem-on-off-test.sh 6.0 KB

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