test_cpuset_prs.sh 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006
  1. #!/bin/bash
  2. # SPDX-License-Identifier: GPL-2.0
  3. #
  4. # Test for cpuset v2 partition root state (PRS)
  5. #
  6. # The sched verbose flag can be optionally set so that the console log
  7. # can be examined for the correct setting of scheduling domain.
  8. #
  9. skip_test() {
  10. echo "$1"
  11. echo "Test SKIPPED"
  12. exit 4 # ksft_skip
  13. }
  14. [[ $(id -u) -eq 0 ]] || skip_test "Test must be run as root!"
  15. # Get wait_inotify location
  16. WAIT_INOTIFY=$(cd $(dirname $0); pwd)/wait_inotify
  17. # Find cgroup v2 mount point
  18. CGROUP2=$(mount -t cgroup2 | head -1 | awk -e '{print $3}')
  19. [[ -n "$CGROUP2" ]] || skip_test "Cgroup v2 mount point not found!"
  20. SUBPARTS_CPUS=$CGROUP2/.__DEBUG__.cpuset.cpus.subpartitions
  21. CPULIST=$(cat $CGROUP2/cpuset.cpus.effective)
  22. NR_CPUS=$(lscpu | grep "^CPU(s):" | sed -e "s/.*:[[:space:]]*//")
  23. [[ $NR_CPUS -lt 8 ]] && skip_test "Test needs at least 8 cpus available!"
  24. # Check to see if /dev/console exists and is writable
  25. if [[ -c /dev/console && -w /dev/console ]]
  26. then
  27. CONSOLE=/dev/console
  28. else
  29. CONSOLE=/dev/null
  30. fi
  31. # Set verbose flag and delay factor
  32. PROG=$1
  33. VERBOSE=0
  34. DELAY_FACTOR=1
  35. SCHED_DEBUG=
  36. while [[ "$1" = -* ]]
  37. do
  38. case "$1" in
  39. -v) ((VERBOSE++))
  40. # Enable sched/verbose can slow thing down
  41. [[ $DELAY_FACTOR -eq 1 ]] &&
  42. DELAY_FACTOR=2
  43. ;;
  44. -d) DELAY_FACTOR=$2
  45. shift
  46. ;;
  47. *) echo "Usage: $PROG [-v] [-d <delay-factor>"
  48. exit
  49. ;;
  50. esac
  51. shift
  52. done
  53. # Set sched verbose flag if available when "-v" option is specified
  54. if [[ $VERBOSE -gt 0 && -d /sys/kernel/debug/sched ]]
  55. then
  56. # Used to restore the original setting during cleanup
  57. SCHED_DEBUG=$(cat /sys/kernel/debug/sched/verbose)
  58. echo Y > /sys/kernel/debug/sched/verbose
  59. fi
  60. cd $CGROUP2
  61. echo +cpuset > cgroup.subtree_control
  62. #
  63. # If cpuset has been set up and used in child cgroups, we may not be able to
  64. # create partition under root cgroup because of the CPU exclusivity rule.
  65. # So we are going to skip the test if this is the case.
  66. #
  67. [[ -d test ]] || mkdir test
  68. echo 0-6 > test/cpuset.cpus
  69. echo root > test/cpuset.cpus.partition
  70. cat test/cpuset.cpus.partition | grep -q invalid
  71. RESULT=$?
  72. echo member > test/cpuset.cpus.partition
  73. echo "" > test/cpuset.cpus
  74. [[ $RESULT -eq 0 ]] && skip_test "Child cgroups are using cpuset!"
  75. #
  76. # If isolated CPUs have been reserved at boot time (as shown in
  77. # cpuset.cpus.isolated), these isolated CPUs should be outside of CPUs 0-8
  78. # that will be used by this script for testing purpose. If not, some of
  79. # the tests may fail incorrectly. These pre-isolated CPUs should stay in
  80. # an isolated state throughout the testing process for now.
  81. #
  82. BOOT_ISOLCPUS=$(cat $CGROUP2/cpuset.cpus.isolated)
  83. if [[ -n "$BOOT_ISOLCPUS" ]]
  84. then
  85. [[ $(echo $BOOT_ISOLCPUS | sed -e "s/[,-].*//") -le 8 ]] &&
  86. skip_test "Pre-isolated CPUs ($BOOT_ISOLCPUS) overlap CPUs to be tested"
  87. echo "Pre-isolated CPUs: $BOOT_ISOLCPUS"
  88. fi
  89. cleanup()
  90. {
  91. online_cpus
  92. cd $CGROUP2
  93. rmdir A1/A2/A3 A1/A2 A1 B1 > /dev/null 2>&1
  94. rmdir test > /dev/null 2>&1
  95. [[ -n "$SCHED_DEBUG" ]] &&
  96. echo "$SCHED_DEBUG" > /sys/kernel/debug/sched/verbose
  97. }
  98. # Pause in ms
  99. pause()
  100. {
  101. DELAY=$1
  102. LOOP=0
  103. while [[ $LOOP -lt $DELAY_FACTOR ]]
  104. do
  105. sleep $DELAY
  106. ((LOOP++))
  107. done
  108. return 0
  109. }
  110. console_msg()
  111. {
  112. MSG=$1
  113. echo "$MSG"
  114. echo "" > $CONSOLE
  115. echo "$MSG" > $CONSOLE
  116. pause 0.01
  117. }
  118. test_partition()
  119. {
  120. EXPECTED_VAL=$1
  121. echo $EXPECTED_VAL > cpuset.cpus.partition
  122. [[ $? -eq 0 ]] || exit 1
  123. ACTUAL_VAL=$(cat cpuset.cpus.partition)
  124. [[ $ACTUAL_VAL != $EXPECTED_VAL ]] && {
  125. echo "cpuset.cpus.partition: expect $EXPECTED_VAL, found $ACTUAL_VAL"
  126. echo "Test FAILED"
  127. exit 1
  128. }
  129. }
  130. test_effective_cpus()
  131. {
  132. EXPECTED_VAL=$1
  133. ACTUAL_VAL=$(cat cpuset.cpus.effective)
  134. [[ "$ACTUAL_VAL" != "$EXPECTED_VAL" ]] && {
  135. echo "cpuset.cpus.effective: expect '$EXPECTED_VAL', found '$ACTUAL_VAL'"
  136. echo "Test FAILED"
  137. exit 1
  138. }
  139. }
  140. # Adding current process to cgroup.procs as a test
  141. test_add_proc()
  142. {
  143. OUTSTR="$1"
  144. ERRMSG=$((echo $$ > cgroup.procs) |& cat)
  145. echo $ERRMSG | grep -q "$OUTSTR"
  146. [[ $? -ne 0 ]] && {
  147. echo "cgroup.procs: expect '$OUTSTR', got '$ERRMSG'"
  148. echo "Test FAILED"
  149. exit 1
  150. }
  151. echo $$ > $CGROUP2/cgroup.procs # Move out the task
  152. }
  153. #
  154. # Cpuset controller state transition test matrix.
  155. #
  156. # Cgroup test hierarchy
  157. #
  158. # root -- A1 -- A2 -- A3
  159. # +- B1
  160. #
  161. # P<v> = set cpus.partition (0:member, 1:root, 2:isolated)
  162. # C<l> = add cpu-list to cpuset.cpus
  163. # X<l> = add cpu-list to cpuset.cpus.exclusive
  164. # S<p> = use prefix in subtree_control
  165. # T = put a task into cgroup
  166. # O<c>=<v> = Write <v> to CPU online file of <c>
  167. #
  168. # ECPUs - effective CPUs of cpusets
  169. # Pstate - partition root state
  170. # ISOLCPUS - isolated CPUs (<icpus>[,<icpus2>])
  171. #
  172. # Note that if there are 2 fields in ISOLCPUS, the first one is for
  173. # sched-debug matching which includes offline CPUs and single-CPU partitions
  174. # while the second one is for matching cpuset.cpus.isolated.
  175. #
  176. SETUP_A123_PARTITIONS="C1-3:P1:S+ C2-3:P1:S+ C3:P1"
  177. TEST_MATRIX=(
  178. # old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS
  179. # ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ --------
  180. " C0-1 . . C2-3 S+ C4-5 . . 0 A2:0-1"
  181. " C0-1 . . C2-3 P1 . . . 0 "
  182. " C0-1 . . C2-3 P1:S+ C0-1:P1 . . 0 "
  183. " C0-1 . . C2-3 P1:S+ C1:P1 . . 0 "
  184. " C0-1:S+ . . C2-3 . . . P1 0 "
  185. " C0-1:P1 . . C2-3 S+ C1 . . 0 "
  186. " C0-1:P1 . . C2-3 S+ C1:P1 . . 0 "
  187. " C0-1:P1 . . C2-3 S+ C1:P1 . P1 0 "
  188. " C0-1:P1 . . C2-3 C4-5 . . . 0 A1:4-5"
  189. " C0-1:P1 . . C2-3 S+:C4-5 . . . 0 A1:4-5"
  190. " C0-1 . . C2-3:P1 . . . C2 0 "
  191. " C0-1 . . C2-3:P1 . . . C4-5 0 B1:4-5"
  192. "C0-3:P1:S+ C2-3:P1 . . . . . . 0 A1:0-1,A2:2-3"
  193. "C0-3:P1:S+ C2-3:P1 . . C1-3 . . . 0 A1:1,A2:2-3"
  194. "C2-3:P1:S+ C3:P1 . . C3 . . . 0 A1:,A2:3 A1:P1,A2:P1"
  195. "C2-3:P1:S+ C3:P1 . . C3 P0 . . 0 A1:3,A2:3 A1:P1,A2:P0"
  196. "C2-3:P1:S+ C2:P1 . . C2-4 . . . 0 A1:3-4,A2:2"
  197. "C2-3:P1:S+ C3:P1 . . C3 . . C0-2 0 A1:,B1:0-2 A1:P1,A2:P1"
  198. "$SETUP_A123_PARTITIONS . C2-3 . . . 0 A1:,A2:2,A3:3 A1:P1,A2:P1,A3:P1"
  199. # CPU offlining cases:
  200. " C0-1 . . C2-3 S+ C4-5 . O2=0 0 A1:0-1,B1:3"
  201. "C0-3:P1:S+ C2-3:P1 . . O2=0 . . . 0 A1:0-1,A2:3"
  202. "C0-3:P1:S+ C2-3:P1 . . O2=0 O2=1 . . 0 A1:0-1,A2:2-3"
  203. "C0-3:P1:S+ C2-3:P1 . . O1=0 . . . 0 A1:0,A2:2-3"
  204. "C0-3:P1:S+ C2-3:P1 . . O1=0 O1=1 . . 0 A1:0-1,A2:2-3"
  205. "C2-3:P1:S+ C3:P1 . . O3=0 O3=1 . . 0 A1:2,A2:3 A1:P1,A2:P1"
  206. "C2-3:P1:S+ C3:P2 . . O3=0 O3=1 . . 0 A1:2,A2:3 A1:P1,A2:P2"
  207. "C2-3:P1:S+ C3:P1 . . O2=0 O2=1 . . 0 A1:2,A2:3 A1:P1,A2:P1"
  208. "C2-3:P1:S+ C3:P2 . . O2=0 O2=1 . . 0 A1:2,A2:3 A1:P1,A2:P2"
  209. "C2-3:P1:S+ C3:P1 . . O2=0 . . . 0 A1:,A2:3 A1:P1,A2:P1"
  210. "C2-3:P1:S+ C3:P1 . . O3=0 . . . 0 A1:2,A2: A1:P1,A2:P1"
  211. "C2-3:P1:S+ C3:P1 . . T:O2=0 . . . 0 A1:3,A2:3 A1:P1,A2:P-1"
  212. "C2-3:P1:S+ C3:P1 . . . T:O3=0 . . 0 A1:2,A2:2 A1:P1,A2:P-1"
  213. "$SETUP_A123_PARTITIONS . O1=0 . . . 0 A1:,A2:2,A3:3 A1:P1,A2:P1,A3:P1"
  214. "$SETUP_A123_PARTITIONS . O2=0 . . . 0 A1:1,A2:,A3:3 A1:P1,A2:P1,A3:P1"
  215. "$SETUP_A123_PARTITIONS . O3=0 . . . 0 A1:1,A2:2,A3: A1:P1,A2:P1,A3:P1"
  216. "$SETUP_A123_PARTITIONS . T:O1=0 . . . 0 A1:2-3,A2:2-3,A3:3 A1:P1,A2:P-1,A3:P-1"
  217. "$SETUP_A123_PARTITIONS . . T:O2=0 . . 0 A1:1,A2:3,A3:3 A1:P1,A2:P1,A3:P-1"
  218. "$SETUP_A123_PARTITIONS . . . T:O3=0 . 0 A1:1,A2:2,A3:2 A1:P1,A2:P1,A3:P-1"
  219. "$SETUP_A123_PARTITIONS . T:O1=0 O1=1 . . 0 A1:1,A2:2,A3:3 A1:P1,A2:P1,A3:P1"
  220. "$SETUP_A123_PARTITIONS . . T:O2=0 O2=1 . 0 A1:1,A2:2,A3:3 A1:P1,A2:P1,A3:P1"
  221. "$SETUP_A123_PARTITIONS . . . T:O3=0 O3=1 0 A1:1,A2:2,A3:3 A1:P1,A2:P1,A3:P1"
  222. "$SETUP_A123_PARTITIONS . T:O1=0 O2=0 O1=1 . 0 A1:1,A2:,A3:3 A1:P1,A2:P1,A3:P1"
  223. "$SETUP_A123_PARTITIONS . T:O1=0 O2=0 O2=1 . 0 A1:2-3,A2:2-3,A3:3 A1:P1,A2:P-1,A3:P-1"
  224. # old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS
  225. # ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ --------
  226. #
  227. # Remote partition and cpuset.cpus.exclusive tests
  228. #
  229. " C0-3:S+ C1-3:S+ C2-3 . X2-3 . . . 0 A1:0-3,A2:1-3,A3:2-3,XA1:2-3"
  230. " C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3:P2 . . 0 A1:0-1,A2:2-3,A3:2-3 A1:P0,A2:P2 2-3"
  231. " C0-3:S+ C1-3:S+ C2-3 . X2-3 X3:P2 . . 0 A1:0-2,A2:3,A3:3 A1:P0,A2:P2 3"
  232. " C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2 . 0 A1:0-1,A2:1,A3:2-3 A1:P0,A3:P2 2-3"
  233. " C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2:C3 . 0 A1:0-1,A2:1,A3:2-3 A1:P0,A3:P2 2-3"
  234. " C0-3:S+ C1-3:S+ C2-3 C2-3 . . . P2 0 A1:0-3,A2:1-3,A3:2-3,B1:2-3 A1:P0,A3:P0,B1:P-2"
  235. " C0-3:S+ C1-3:S+ C2-3 C4-5 . . . P2 0 B1:4-5 B1:P2 4-5"
  236. " C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3 X2-3:P2 P2 0 A3:2-3,B1:4 A3:P2,B1:P2 2-4"
  237. " C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3 X2-3:P2:C1-3 P2 0 A3:2-3,B1:4 A3:P2,B1:P2 2-4"
  238. " C0-3:S+ C1-3:S+ C2-3 C4 X1-3 X1-3:P2 P2 . 0 A2:1,A3:2-3 A2:P2,A3:P2 1-3"
  239. " C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3 X2-3:P2 P2:C4-5 0 A3:2-3,B1:4-5 A3:P2,B1:P2 2-5"
  240. " C4:X0-3:S+ X1-3:S+ X2-3 . . P2 . . 0 A1:4,A2:1-3,A3:1-3 A2:P2 1-3"
  241. " C4:X0-3:S+ X1-3:S+ X2-3 . . . P2 . 0 A1:4,A2:4,A3:2-3 A3:P2 2-3"
  242. # Nested remote/local partition tests
  243. " C0-3:S+ C1-3:S+ C2-3 C4-5 X2-3 X2-3:P1 P2 P1 0 A1:0-1,A2:,A3:2-3,B1:4-5 \
  244. A1:P0,A2:P1,A3:P2,B1:P1 2-3"
  245. " C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3:P1 P2 P1 0 A1:0-1,A2:,A3:2-3,B1:4 \
  246. A1:P0,A2:P1,A3:P2,B1:P1 2-4,2-3"
  247. " C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3:P1 . P1 0 A1:0-1,A2:2-3,A3:2-3,B1:4 \
  248. A1:P0,A2:P1,A3:P0,B1:P1"
  249. " C0-3:S+ C1-3:S+ C3 C4 X2-3 X2-3:P1 P2 P1 0 A1:0-1,A2:2,A3:3,B1:4 \
  250. A1:P0,A2:P1,A3:P2,B1:P1 2-4,3"
  251. " C0-4:S+ C1-4:S+ C2-4 . X2-4 X2-4:P2 X4:P1 . 0 A1:0-1,A2:2-3,A3:4 \
  252. A1:P0,A2:P2,A3:P1 2-4,2-3"
  253. " C0-4:S+ C1-4:S+ C2-4 . X2-4 X2-4:P2 X3-4:P1 . 0 A1:0-1,A2:2,A3:3-4 \
  254. A1:P0,A2:P2,A3:P1 2"
  255. " C0-4:X2-4:S+ C1-4:X2-4:S+:P2 C2-4:X4:P1 \
  256. . . X5 . . 0 A1:0-4,A2:1-4,A3:2-4 \
  257. A1:P0,A2:P-2,A3:P-1"
  258. " C0-4:X2-4:S+ C1-4:X2-4:S+:P2 C2-4:X4:P1 \
  259. . . . X1 . 0 A1:0-1,A2:2-4,A3:2-4 \
  260. A1:P0,A2:P2,A3:P-1 2-4"
  261. # Remote partition offline tests
  262. " C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2:O2=0 . 0 A1:0-1,A2:1,A3:3 A1:P0,A3:P2 2-3"
  263. " C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2:O2=0 O2=1 0 A1:0-1,A2:1,A3:2-3 A1:P0,A3:P2 2-3"
  264. " C0-3:S+ C1-3:S+ C3 . X2-3 X2-3 P2:O3=0 . 0 A1:0-2,A2:1-2,A3: A1:P0,A3:P2 3"
  265. " C0-3:S+ C1-3:S+ C3 . X2-3 X2-3 T:P2:O3=0 . 0 A1:0-2,A2:1-2,A3:1-2 A1:P0,A3:P-2 3,"
  266. # An invalidated remote partition cannot self-recover from hotplug
  267. " C0-3:S+ C1-3:S+ C2 . X2-3 X2-3 T:P2:O2=0 O2=1 0 A1:0-3,A2:1-3,A3:2 A1:P0,A3:P-2"
  268. # cpus.exclusive.effective clearing test
  269. " C0-3:S+ C1-3:S+ C2 . X2-3:X . . . 0 A1:0-3,A2:1-3,A3:2,XA1:"
  270. # Invalid to valid remote partition transition test
  271. " C0-3:S+ C1-3 . . . X3:P2 . . 0 A1:0-3,A2:1-3,XA2: A2:P-2"
  272. " C0-3:S+ C1-3:X3:P2
  273. . . X2-3 P2 . . 0 A1:0-2,A2:3,XA2:3 A2:P2 3"
  274. # Invalid to valid local partition direct transition tests
  275. " C1-3:S+:P2 X4:P2 . . . . . . 0 A1:1-3,XA1:1-3,A2:1-3:XA2: A1:P2,A2:P-2 1-3"
  276. " C1-3:S+:P2 X4:P2 . . . X3:P2 . . 0 A1:1-2,XA1:1-3,A2:3:XA2:3 A1:P2,A2:P2 1-3"
  277. " C0-3:P2 . . C4-6 C0-4 . . . 0 A1:0-4,B1:4-6 A1:P-2,B1:P0"
  278. " C0-3:P2 . . C4-6 C0-4:C0-3 . . . 0 A1:0-3,B1:4-6 A1:P2,B1:P0 0-3"
  279. " C0-3:P2 . . C3-5:C4-5 . . . . 0 A1:0-3,B1:4-5 A1:P2,B1:P0 0-3"
  280. # Local partition invalidation tests
  281. " C0-3:X1-3:S+:P2 C1-3:X2-3:S+:P2 C2-3:X3:P2 \
  282. . . . . . 0 A1:1,A2:2,A3:3 A1:P2,A2:P2,A3:P2 1-3"
  283. " C0-3:X1-3:S+:P2 C1-3:X2-3:S+:P2 C2-3:X3:P2 \
  284. . . X4 . . 0 A1:1-3,A2:1-3,A3:2-3,XA2:,XA3: A1:P2,A2:P-2,A3:P-2 1-3"
  285. " C0-3:X1-3:S+:P2 C1-3:X2-3:S+:P2 C2-3:X3:P2 \
  286. . . C4:X . . 0 A1:1-3,A2:1-3,A3:2-3,XA2:,XA3: A1:P2,A2:P-2,A3:P-2 1-3"
  287. # Local partition CPU change tests
  288. " C0-5:S+:P2 C4-5:S+:P1 . . . C3-5 . . 0 A1:0-2,A2:3-5 A1:P2,A2:P1 0-2"
  289. " C0-5:S+:P2 C4-5:S+:P1 . . C1-5 . . . 0 A1:1-3,A2:4-5 A1:P2,A2:P1 1-3"
  290. # cpus_allowed/exclusive_cpus update tests
  291. " C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3 \
  292. . X:C4 . P2 . 0 A1:4,A2:4,XA2:,XA3:,A3:4 \
  293. A1:P0,A3:P-2"
  294. " C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3 \
  295. . X1 . P2 . 0 A1:0-3,A2:1-3,XA1:1,XA2:,XA3:,A3:2-3 \
  296. A1:P0,A3:P-2"
  297. " C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3 \
  298. . . X3 P2 . 0 A1:0-2,A2:1-2,XA2:3,XA3:3,A3:3 \
  299. A1:P0,A3:P2 3"
  300. " C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3:P2 \
  301. . . X3 . . 0 A1:0-3,A2:1-3,XA2:3,XA3:3,A3:2-3 \
  302. A1:P0,A3:P-2"
  303. " C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3:P2 \
  304. . X4 . . . 0 A1:0-3,A2:1-3,A3:2-3,XA1:4,XA2:,XA3 \
  305. A1:P0,A3:P-2"
  306. # old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS
  307. # ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ --------
  308. #
  309. # Incorrect change to cpuset.cpus[.exclusive] invalidates partition root
  310. #
  311. # Adding CPUs to partition root that are not in parent's
  312. # cpuset.cpus is allowed, but those extra CPUs are ignored.
  313. "C2-3:P1:S+ C3:P1 . . . C2-4 . . 0 A1:,A2:2-3 A1:P1,A2:P1"
  314. # Taking away all CPUs from parent or itself if there are tasks
  315. # will make the partition invalid.
  316. "C2-3:P1:S+ C3:P1 . . T C2-3 . . 0 A1:2-3,A2:2-3 A1:P1,A2:P-1"
  317. " C3:P1:S+ C3 . . T P1 . . 0 A1:3,A2:3 A1:P1,A2:P-1"
  318. "$SETUP_A123_PARTITIONS . T:C2-3 . . . 0 A1:2-3,A2:2-3,A3:3 A1:P1,A2:P-1,A3:P-1"
  319. "$SETUP_A123_PARTITIONS . T:C2-3:C1-3 . . . 0 A1:1,A2:2,A3:3 A1:P1,A2:P1,A3:P1"
  320. # Changing a partition root to member makes child partitions invalid
  321. "C2-3:P1:S+ C3:P1 . . P0 . . . 0 A1:2-3,A2:3 A1:P0,A2:P-1"
  322. "$SETUP_A123_PARTITIONS . C2-3 P0 . . 0 A1:2-3,A2:2-3,A3:3 A1:P1,A2:P0,A3:P-1"
  323. # cpuset.cpus can contains cpus not in parent's cpuset.cpus as long
  324. # as they overlap.
  325. "C2-3:P1:S+ . . . . C3-4:P1 . . 0 A1:2,A2:3 A1:P1,A2:P1"
  326. # Deletion of CPUs distributed to child cgroup is allowed.
  327. "C0-1:P1:S+ C1 . C2-3 C4-5 . . . 0 A1:4-5,A2:4-5"
  328. # To become a valid partition root, cpuset.cpus must overlap parent's
  329. # cpuset.cpus.
  330. " C0-1:P1 . . C2-3 S+ C4-5:P1 . . 0 A1:0-1,A2:0-1 A1:P1,A2:P-1"
  331. # Enabling partition with child cpusets is allowed
  332. " C0-1:S+ C1 . C2-3 P1 . . . 0 A1:0-1,A2:1 A1:P1"
  333. # A partition root with non-partition root parent is invalid, but it
  334. # can be made valid if its parent becomes a partition root too.
  335. " C0-1:S+ C1 . C2-3 . P2 . . 0 A1:0-1,A2:1 A1:P0,A2:P-2"
  336. " C0-1:S+ C1:P2 . C2-3 P1 . . . 0 A1:0,A2:1 A1:P1,A2:P2"
  337. # A non-exclusive cpuset.cpus change will invalidate partition and its siblings
  338. " C0-1:P1 . . C2-3 C0-2 . . . 0 A1:0-2,B1:2-3 A1:P-1,B1:P0"
  339. " C0-1:P1 . . P1:C2-3 C0-2 . . . 0 A1:0-2,B1:2-3 A1:P-1,B1:P-1"
  340. " C0-1 . . P1:C2-3 C0-2 . . . 0 A1:0-2,B1:2-3 A1:P0,B1:P-1"
  341. # cpuset.cpus can overlap with sibling cpuset.cpus.exclusive but not subsumed by it
  342. " C0-3 . . C4-5 X5 . . . 0 A1:0-3,B1:4-5"
  343. # Child partition root that try to take all CPUs from parent partition
  344. # with tasks will remain invalid.
  345. " C1-4:P1:S+ P1 . . . . . . 0 A1:1-4,A2:1-4 A1:P1,A2:P-1"
  346. " C1-4:P1:S+ P1 . . . C1-4 . . 0 A1,A2:1-4 A1:P1,A2:P1"
  347. " C1-4:P1:S+ P1 . . T C1-4 . . 0 A1:1-4,A2:1-4 A1:P1,A2:P-1"
  348. # Clearing of cpuset.cpus with a preset cpuset.cpus.exclusive shouldn't
  349. # affect cpuset.cpus.exclusive.effective.
  350. " C1-4:X3:S+ C1:X3 . . . C . . 0 A2:1-4,XA2:3"
  351. # old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS
  352. # ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ --------
  353. # Failure cases:
  354. # A task cannot be added to a partition with no cpu
  355. "C2-3:P1:S+ C3:P1 . . O2=0:T . . . 1 A1:,A2:3 A1:P1,A2:P1"
  356. # Changes to cpuset.cpus.exclusive that violate exclusivity rule is rejected
  357. " C0-3 . . C4-5 X0-3 . . X3-5 1 A1:0-3,B1:4-5"
  358. # cpuset.cpus cannot be a subset of sibling cpuset.cpus.exclusive
  359. " C0-3 . . C4-5 X3-5 . . . 1 A1:0-3,B1:4-5"
  360. )
  361. #
  362. # Write to the cpu online file
  363. # $1 - <c>=<v> where <c> = cpu number, <v> value to be written
  364. #
  365. write_cpu_online()
  366. {
  367. CPU=${1%=*}
  368. VAL=${1#*=}
  369. CPUFILE=//sys/devices/system/cpu/cpu${CPU}/online
  370. if [[ $VAL -eq 0 ]]
  371. then
  372. OFFLINE_CPUS="$OFFLINE_CPUS $CPU"
  373. else
  374. [[ -n "$OFFLINE_CPUS" ]] && {
  375. OFFLINE_CPUS=$(echo $CPU $CPU $OFFLINE_CPUS | fmt -1 |\
  376. sort | uniq -u)
  377. }
  378. fi
  379. echo $VAL > $CPUFILE
  380. pause 0.05
  381. }
  382. #
  383. # Set controller state
  384. # $1 - cgroup directory
  385. # $2 - state
  386. # $3 - showerr
  387. #
  388. # The presence of ":" in state means transition from one to the next.
  389. #
  390. set_ctrl_state()
  391. {
  392. TMPMSG=/tmp/.msg_$$
  393. CGRP=$1
  394. STATE=$2
  395. SHOWERR=${3}
  396. CTRL=${CTRL:=$CONTROLLER}
  397. HASERR=0
  398. REDIRECT="2> $TMPMSG"
  399. [[ -z "$STATE" || "$STATE" = '.' ]] && return 0
  400. [[ $VERBOSE -gt 0 ]] && SHOWERR=1
  401. rm -f $TMPMSG
  402. for CMD in $(echo $STATE | sed -e "s/:/ /g")
  403. do
  404. TFILE=$CGRP/cgroup.procs
  405. SFILE=$CGRP/cgroup.subtree_control
  406. PFILE=$CGRP/cpuset.cpus.partition
  407. CFILE=$CGRP/cpuset.cpus
  408. XFILE=$CGRP/cpuset.cpus.exclusive
  409. S=$(expr substr $CMD 1 1)
  410. if [[ $S = S ]]
  411. then
  412. PREFIX=${CMD#?}
  413. COMM="echo ${PREFIX}${CTRL} > $SFILE"
  414. eval $COMM $REDIRECT
  415. elif [[ $S = X ]]
  416. then
  417. CPUS=${CMD#?}
  418. COMM="echo $CPUS > $XFILE"
  419. eval $COMM $REDIRECT
  420. elif [[ $S = C ]]
  421. then
  422. CPUS=${CMD#?}
  423. COMM="echo $CPUS > $CFILE"
  424. eval $COMM $REDIRECT
  425. elif [[ $S = P ]]
  426. then
  427. VAL=${CMD#?}
  428. case $VAL in
  429. 0) VAL=member
  430. ;;
  431. 1) VAL=root
  432. ;;
  433. 2) VAL=isolated
  434. ;;
  435. *)
  436. echo "Invalid partition state - $VAL"
  437. exit 1
  438. ;;
  439. esac
  440. COMM="echo $VAL > $PFILE"
  441. eval $COMM $REDIRECT
  442. elif [[ $S = O ]]
  443. then
  444. VAL=${CMD#?}
  445. write_cpu_online $VAL
  446. elif [[ $S = T ]]
  447. then
  448. COMM="echo 0 > $TFILE"
  449. eval $COMM $REDIRECT
  450. fi
  451. RET=$?
  452. [[ $RET -ne 0 ]] && {
  453. [[ -n "$SHOWERR" ]] && {
  454. echo "$COMM"
  455. cat $TMPMSG
  456. }
  457. HASERR=1
  458. }
  459. pause 0.01
  460. rm -f $TMPMSG
  461. done
  462. return $HASERR
  463. }
  464. set_ctrl_state_noerr()
  465. {
  466. CGRP=$1
  467. STATE=$2
  468. [[ -d $CGRP ]] || mkdir $CGRP
  469. set_ctrl_state $CGRP $STATE 1
  470. [[ $? -ne 0 ]] && {
  471. echo "ERROR: Failed to set $2 to cgroup $1!"
  472. exit 1
  473. }
  474. }
  475. online_cpus()
  476. {
  477. [[ -n "OFFLINE_CPUS" ]] && {
  478. for C in $OFFLINE_CPUS
  479. do
  480. write_cpu_online ${C}=1
  481. done
  482. }
  483. }
  484. #
  485. # Return 1 if the list of effective cpus isn't the same as the initial list.
  486. #
  487. reset_cgroup_states()
  488. {
  489. echo 0 > $CGROUP2/cgroup.procs
  490. online_cpus
  491. rmdir A1/A2/A3 A1/A2 A1 B1 > /dev/null 2>&1
  492. pause 0.02
  493. set_ctrl_state . R-
  494. pause 0.01
  495. }
  496. dump_states()
  497. {
  498. for DIR in . A1 A1/A2 A1/A2/A3 B1
  499. do
  500. CPUS=$DIR/cpuset.cpus
  501. ECPUS=$DIR/cpuset.cpus.effective
  502. XCPUS=$DIR/cpuset.cpus.exclusive
  503. XECPUS=$DIR/cpuset.cpus.exclusive.effective
  504. PRS=$DIR/cpuset.cpus.partition
  505. PCPUS=$DIR/.__DEBUG__.cpuset.cpus.subpartitions
  506. ISCPUS=$DIR/cpuset.cpus.isolated
  507. [[ -e $CPUS ]] && echo "$CPUS: $(cat $CPUS)"
  508. [[ -e $XCPUS ]] && echo "$XCPUS: $(cat $XCPUS)"
  509. [[ -e $ECPUS ]] && echo "$ECPUS: $(cat $ECPUS)"
  510. [[ -e $XECPUS ]] && echo "$XECPUS: $(cat $XECPUS)"
  511. [[ -e $PRS ]] && echo "$PRS: $(cat $PRS)"
  512. [[ -e $PCPUS ]] && echo "$PCPUS: $(cat $PCPUS)"
  513. [[ -e $ISCPUS ]] && echo "$ISCPUS: $(cat $ISCPUS)"
  514. done
  515. }
  516. #
  517. # Check effective cpus
  518. # $1 - check string, format: <cgroup>:<cpu-list>[,<cgroup>:<cpu-list>]*
  519. #
  520. check_effective_cpus()
  521. {
  522. CHK_STR=$1
  523. for CHK in $(echo $CHK_STR | sed -e "s/,/ /g")
  524. do
  525. set -- $(echo $CHK | sed -e "s/:/ /g")
  526. CGRP=$1
  527. CPUS=$2
  528. if [[ $CGRP = X* ]]
  529. then
  530. CGRP=${CGRP#X}
  531. FILE=cpuset.cpus.exclusive.effective
  532. else
  533. FILE=cpuset.cpus.effective
  534. fi
  535. [[ $CGRP = A2 ]] && CGRP=A1/A2
  536. [[ $CGRP = A3 ]] && CGRP=A1/A2/A3
  537. [[ -e $CGRP/$FILE ]] || return 1
  538. [[ $CPUS = $(cat $CGRP/$FILE) ]] || return 1
  539. done
  540. }
  541. #
  542. # Check cgroup states
  543. # $1 - check string, format: <cgroup>:<state>[,<cgroup>:<state>]*
  544. #
  545. check_cgroup_states()
  546. {
  547. CHK_STR=$1
  548. for CHK in $(echo $CHK_STR | sed -e "s/,/ /g")
  549. do
  550. set -- $(echo $CHK | sed -e "s/:/ /g")
  551. CGRP=$1
  552. CGRP_DIR=$CGRP
  553. STATE=$2
  554. FILE=
  555. EVAL=$(expr substr $STATE 2 2)
  556. [[ $CGRP = A2 ]] && CGRP_DIR=A1/A2
  557. [[ $CGRP = A3 ]] && CGRP_DIR=A1/A2/A3
  558. case $STATE in
  559. P*) FILE=$CGRP_DIR/cpuset.cpus.partition
  560. ;;
  561. *) echo "Unknown state: $STATE!"
  562. exit 1
  563. ;;
  564. esac
  565. VAL=$(cat $FILE)
  566. case "$VAL" in
  567. member) VAL=0
  568. ;;
  569. root) VAL=1
  570. ;;
  571. isolated)
  572. VAL=2
  573. ;;
  574. "root invalid"*)
  575. VAL=-1
  576. ;;
  577. "isolated invalid"*)
  578. VAL=-2
  579. ;;
  580. esac
  581. [[ $EVAL != $VAL ]] && return 1
  582. #
  583. # For root partition, dump sched-domains info to console if
  584. # verbose mode set for manual comparison with sched debug info.
  585. #
  586. [[ $VAL -eq 1 && $VERBOSE -gt 0 ]] && {
  587. DOMS=$(cat $CGRP_DIR/cpuset.cpus.effective)
  588. [[ -n "$DOMS" ]] &&
  589. echo " [$CGRP] sched-domain: $DOMS" > $CONSOLE
  590. }
  591. done
  592. return 0
  593. }
  594. #
  595. # Get isolated (including offline) CPUs by looking at
  596. # /sys/kernel/debug/sched/domains and cpuset.cpus.isolated control file,
  597. # if available, and compare that with the expected value.
  598. #
  599. # Note that isolated CPUs from the sched/domains context include offline
  600. # CPUs as well as CPUs in non-isolated 1-CPU partition. Those CPUs may
  601. # not be included in the cpuset.cpus.isolated control file which contains
  602. # only CPUs in isolated partitions as well as those that are isolated at
  603. # boot time.
  604. #
  605. # $1 - expected isolated cpu list(s) <isolcpus1>{,<isolcpus2>}
  606. # <isolcpus1> - expected sched/domains value
  607. # <isolcpus2> - cpuset.cpus.isolated value = <isolcpus1> if not defined
  608. #
  609. check_isolcpus()
  610. {
  611. EXPECT_VAL=$1
  612. ISOLCPUS=
  613. LASTISOLCPU=
  614. SCHED_DOMAINS=/sys/kernel/debug/sched/domains
  615. ISCPUS=${CGROUP2}/cpuset.cpus.isolated
  616. if [[ $EXPECT_VAL = . ]]
  617. then
  618. EXPECT_VAL=
  619. EXPECT_VAL2=
  620. elif [[ $(expr $EXPECT_VAL : ".*,.*") > 0 ]]
  621. then
  622. set -- $(echo $EXPECT_VAL | sed -e "s/,/ /g")
  623. EXPECT_VAL=$1
  624. EXPECT_VAL2=$2
  625. else
  626. EXPECT_VAL2=$EXPECT_VAL
  627. fi
  628. #
  629. # Appending pre-isolated CPUs
  630. # Even though CPU #8 isn't used for testing, it can't be pre-isolated
  631. # to make appending those CPUs easier.
  632. #
  633. [[ -n "$BOOT_ISOLCPUS" ]] && {
  634. EXPECT_VAL=${EXPECT_VAL:+${EXPECT_VAL},}${BOOT_ISOLCPUS}
  635. EXPECT_VAL2=${EXPECT_VAL2:+${EXPECT_VAL2},}${BOOT_ISOLCPUS}
  636. }
  637. #
  638. # Check cpuset.cpus.isolated cpumask
  639. #
  640. [[ "$EXPECT_VAL2" != "$ISOLCPUS" ]] && {
  641. # Take a 50ms pause and try again
  642. pause 0.05
  643. ISOLCPUS=$(cat $ISCPUS)
  644. }
  645. [[ "$EXPECT_VAL2" != "$ISOLCPUS" ]] && return 1
  646. ISOLCPUS=
  647. #
  648. # Use the sched domain in debugfs to check isolated CPUs, if available
  649. #
  650. [[ -d $SCHED_DOMAINS ]] || return 0
  651. for ((CPU=0; CPU < $NR_CPUS; CPU++))
  652. do
  653. [[ -n "$(ls ${SCHED_DOMAINS}/cpu$CPU)" ]] && continue
  654. if [[ -z "$LASTISOLCPU" ]]
  655. then
  656. ISOLCPUS=$CPU
  657. LASTISOLCPU=$CPU
  658. elif [[ "$LASTISOLCPU" -eq $((CPU - 1)) ]]
  659. then
  660. echo $ISOLCPUS | grep -q "\<$LASTISOLCPU\$"
  661. if [[ $? -eq 0 ]]
  662. then
  663. ISOLCPUS=${ISOLCPUS}-
  664. fi
  665. LASTISOLCPU=$CPU
  666. else
  667. if [[ $ISOLCPUS = *- ]]
  668. then
  669. ISOLCPUS=${ISOLCPUS}$LASTISOLCPU
  670. fi
  671. ISOLCPUS=${ISOLCPUS},$CPU
  672. LASTISOLCPU=$CPU
  673. fi
  674. done
  675. [[ "$ISOLCPUS" = *- ]] && ISOLCPUS=${ISOLCPUS}$LASTISOLCPU
  676. [[ "$EXPECT_VAL" = "$ISOLCPUS" ]]
  677. }
  678. test_fail()
  679. {
  680. TESTNUM=$1
  681. TESTTYPE=$2
  682. ADDINFO=$3
  683. echo "Test $TEST[$TESTNUM] failed $TESTTYPE check!"
  684. [[ -n "$ADDINFO" ]] && echo "*** $ADDINFO ***"
  685. eval echo \${$TEST[$I]}
  686. echo
  687. dump_states
  688. exit 1
  689. }
  690. #
  691. # Check to see if there are unexpected isolated CPUs left beyond the boot
  692. # time isolated ones.
  693. #
  694. null_isolcpus_check()
  695. {
  696. [[ $VERBOSE -gt 0 ]] || return 0
  697. # Retry a few times before printing error
  698. RETRY=0
  699. while [[ $RETRY -lt 8 ]]
  700. do
  701. pause 0.02
  702. check_isolcpus "."
  703. [[ $? -eq 0 ]] && return 0
  704. ((RETRY++))
  705. done
  706. echo "Unexpected isolated CPUs: $ISOLCPUS"
  707. dump_states
  708. exit 1
  709. }
  710. #
  711. # Run cpuset state transition test
  712. # $1 - test matrix name
  713. #
  714. # This test is somewhat fragile as delays (sleep x) are added in various
  715. # places to make sure state changes are fully propagated before the next
  716. # action. These delays may need to be adjusted if running in a slower machine.
  717. #
  718. run_state_test()
  719. {
  720. TEST=$1
  721. CONTROLLER=cpuset
  722. I=0
  723. eval CNT="\${#$TEST[@]}"
  724. reset_cgroup_states
  725. console_msg "Running state transition test ..."
  726. while [[ $I -lt $CNT ]]
  727. do
  728. echo "Running test $I ..." > $CONSOLE
  729. [[ $VERBOSE -gt 1 ]] && {
  730. echo ""
  731. eval echo \${$TEST[$I]}
  732. }
  733. eval set -- "\${$TEST[$I]}"
  734. OLD_A1=$1
  735. OLD_A2=$2
  736. OLD_A3=$3
  737. OLD_B1=$4
  738. NEW_A1=$5
  739. NEW_A2=$6
  740. NEW_A3=$7
  741. NEW_B1=$8
  742. RESULT=$9
  743. ECPUS=${10}
  744. STATES=${11}
  745. ICPUS=${12}
  746. set_ctrl_state_noerr B1 $OLD_B1
  747. set_ctrl_state_noerr A1 $OLD_A1
  748. set_ctrl_state_noerr A1/A2 $OLD_A2
  749. set_ctrl_state_noerr A1/A2/A3 $OLD_A3
  750. RETVAL=0
  751. set_ctrl_state A1 $NEW_A1; ((RETVAL += $?))
  752. set_ctrl_state A1/A2 $NEW_A2; ((RETVAL += $?))
  753. set_ctrl_state A1/A2/A3 $NEW_A3; ((RETVAL += $?))
  754. set_ctrl_state B1 $NEW_B1; ((RETVAL += $?))
  755. [[ $RETVAL -ne $RESULT ]] && test_fail $I result
  756. [[ -n "$ECPUS" && "$ECPUS" != . ]] && {
  757. check_effective_cpus $ECPUS
  758. [[ $? -ne 0 ]] && test_fail $I "effective CPU"
  759. }
  760. [[ -n "$STATES" && "$STATES" != . ]] && {
  761. check_cgroup_states $STATES
  762. [[ $? -ne 0 ]] && test_fail $I states
  763. }
  764. # Compare the expected isolated CPUs with the actual ones,
  765. # if available
  766. [[ -n "$ICPUS" ]] && {
  767. check_isolcpus $ICPUS
  768. [[ $? -ne 0 ]] && {
  769. [[ -n "$BOOT_ISOLCPUS" ]] && ICPUS=${ICPUS},${BOOT_ISOLCPUS}
  770. test_fail $I "isolated CPU" \
  771. "Expect $ICPUS, get $ISOLCPUS instead"
  772. }
  773. }
  774. reset_cgroup_states
  775. #
  776. # Check to see if effective cpu list changes
  777. #
  778. NEWLIST=$(cat cpuset.cpus.effective)
  779. RETRY=0
  780. while [[ $NEWLIST != $CPULIST && $RETRY -lt 8 ]]
  781. do
  782. # Wait a bit longer & recheck a few times
  783. pause 0.02
  784. ((RETRY++))
  785. NEWLIST=$(cat cpuset.cpus.effective)
  786. done
  787. [[ $NEWLIST != $CPULIST ]] && {
  788. echo "Effective cpus changed to $NEWLIST after test $I!"
  789. exit 1
  790. }
  791. null_isolcpus_check
  792. [[ $VERBOSE -gt 0 ]] && echo "Test $I done."
  793. ((I++))
  794. done
  795. echo "All $I tests of $TEST PASSED."
  796. }
  797. #
  798. # Testing the new "isolated" partition root type
  799. #
  800. test_isolated()
  801. {
  802. cd $CGROUP2/test
  803. echo 2-3 > cpuset.cpus
  804. TYPE=$(cat cpuset.cpus.partition)
  805. [[ $TYPE = member ]] || echo member > cpuset.cpus.partition
  806. console_msg "Change from member to root"
  807. test_partition root
  808. console_msg "Change from root to isolated"
  809. test_partition isolated
  810. console_msg "Change from isolated to member"
  811. test_partition member
  812. console_msg "Change from member to isolated"
  813. test_partition isolated
  814. console_msg "Change from isolated to root"
  815. test_partition root
  816. console_msg "Change from root to member"
  817. test_partition member
  818. #
  819. # Testing partition root with no cpu
  820. #
  821. console_msg "Distribute all cpus to child partition"
  822. echo +cpuset > cgroup.subtree_control
  823. test_partition root
  824. mkdir A1
  825. cd A1
  826. echo 2-3 > cpuset.cpus
  827. test_partition root
  828. test_effective_cpus 2-3
  829. cd ..
  830. test_effective_cpus ""
  831. console_msg "Moving task to partition test"
  832. test_add_proc "No space left"
  833. cd A1
  834. test_add_proc ""
  835. cd ..
  836. console_msg "Shrink and expand child partition"
  837. cd A1
  838. echo 2 > cpuset.cpus
  839. cd ..
  840. test_effective_cpus 3
  841. cd A1
  842. echo 2-3 > cpuset.cpus
  843. cd ..
  844. test_effective_cpus ""
  845. # Cleaning up
  846. console_msg "Cleaning up"
  847. echo $$ > $CGROUP2/cgroup.procs
  848. [[ -d A1 ]] && rmdir A1
  849. null_isolcpus_check
  850. }
  851. #
  852. # Wait for inotify event for the given file and read it
  853. # $1: cgroup file to wait for
  854. # $2: file to store the read result
  855. #
  856. wait_inotify()
  857. {
  858. CGROUP_FILE=$1
  859. OUTPUT_FILE=$2
  860. $WAIT_INOTIFY $CGROUP_FILE
  861. cat $CGROUP_FILE > $OUTPUT_FILE
  862. }
  863. #
  864. # Test if inotify events are properly generated when going into and out of
  865. # invalid partition state.
  866. #
  867. test_inotify()
  868. {
  869. ERR=0
  870. PRS=/tmp/.prs_$$
  871. cd $CGROUP2/test
  872. [[ -f $WAIT_INOTIFY ]] || {
  873. echo "wait_inotify not found, inotify test SKIPPED."
  874. return
  875. }
  876. pause 0.01
  877. echo 1 > cpuset.cpus
  878. echo 0 > cgroup.procs
  879. echo root > cpuset.cpus.partition
  880. pause 0.01
  881. rm -f $PRS
  882. wait_inotify $PWD/cpuset.cpus.partition $PRS &
  883. pause 0.01
  884. set_ctrl_state . "O1=0"
  885. pause 0.01
  886. check_cgroup_states ".:P-1"
  887. if [[ $? -ne 0 ]]
  888. then
  889. echo "FAILED: Inotify test - partition not invalid"
  890. ERR=1
  891. elif [[ ! -f $PRS ]]
  892. then
  893. echo "FAILED: Inotify test - event not generated"
  894. ERR=1
  895. kill %1
  896. elif [[ $(cat $PRS) != "root invalid"* ]]
  897. then
  898. echo "FAILED: Inotify test - incorrect state"
  899. cat $PRS
  900. ERR=1
  901. fi
  902. online_cpus
  903. echo member > cpuset.cpus.partition
  904. echo 0 > ../cgroup.procs
  905. if [[ $ERR -ne 0 ]]
  906. then
  907. exit 1
  908. else
  909. echo "Inotify test PASSED"
  910. fi
  911. }
  912. trap cleanup 0 2 3 6
  913. run_state_test TEST_MATRIX
  914. test_isolated
  915. test_inotify
  916. echo "All tests PASSED."