hugetlb_reparenting_test.sh 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. #!/bin/bash
  2. # SPDX-License-Identifier: GPL-2.0
  3. # Kselftest framework requirement - SKIP code is 4.
  4. ksft_skip=4
  5. set -e
  6. if [[ $(id -u) -ne 0 ]]; then
  7. echo "This test must be run as root. Skipping..."
  8. exit $ksft_skip
  9. fi
  10. nr_hugepgs=$(cat /proc/sys/vm/nr_hugepages)
  11. usage_file=usage_in_bytes
  12. if [[ "$1" == "-cgroup-v2" ]]; then
  13. cgroup2=1
  14. usage_file=current
  15. fi
  16. if [[ $cgroup2 ]]; then
  17. CGROUP_ROOT=$(mount -t cgroup2 | head -1 | awk '{print $3}')
  18. if [[ -z "$CGROUP_ROOT" ]]; then
  19. CGROUP_ROOT=$(mktemp -d)
  20. mount -t cgroup2 none $CGROUP_ROOT
  21. do_umount=1
  22. fi
  23. echo "+hugetlb +memory" >$CGROUP_ROOT/cgroup.subtree_control
  24. else
  25. CGROUP_ROOT=$(mount -t cgroup | grep ",hugetlb" | awk '{print $3}')
  26. if [[ -z "$CGROUP_ROOT" ]]; then
  27. CGROUP_ROOT=/dev/cgroup/memory
  28. mount -t cgroup memory,hugetlb $CGROUP_ROOT
  29. do_umount=1
  30. fi
  31. fi
  32. MNT='/mnt/huge/'
  33. function get_machine_hugepage_size() {
  34. hpz=$(grep -i hugepagesize /proc/meminfo)
  35. kb=${hpz:14:-3}
  36. mb=$(($kb / 1024))
  37. echo $mb
  38. }
  39. MB=$(get_machine_hugepage_size)
  40. function cleanup() {
  41. echo cleanup
  42. set +e
  43. rm -rf "$MNT"/* 2>/dev/null
  44. umount "$MNT" 2>/dev/null
  45. rmdir "$MNT" 2>/dev/null
  46. rmdir "$CGROUP_ROOT"/a/b 2>/dev/null
  47. rmdir "$CGROUP_ROOT"/a 2>/dev/null
  48. rmdir "$CGROUP_ROOT"/test1 2>/dev/null
  49. echo 0 >/proc/sys/vm/nr_hugepages
  50. set -e
  51. }
  52. function assert_state() {
  53. local expected_a="$1"
  54. local expected_a_hugetlb="$2"
  55. local expected_b=""
  56. local expected_b_hugetlb=""
  57. if [ ! -z ${3:-} ] && [ ! -z ${4:-} ]; then
  58. expected_b="$3"
  59. expected_b_hugetlb="$4"
  60. fi
  61. local tolerance=$((5 * 1024 * 1024))
  62. local actual_a
  63. actual_a="$(cat "$CGROUP_ROOT"/a/memory.$usage_file)"
  64. if [[ $actual_a -lt $(($expected_a - $tolerance)) ]] ||
  65. [[ $actual_a -gt $(($expected_a + $tolerance)) ]]; then
  66. echo actual a = $((${actual_a%% *} / 1024 / 1024)) MB
  67. echo expected a = $((${expected_a%% *} / 1024 / 1024)) MB
  68. echo fail
  69. cleanup
  70. exit 1
  71. fi
  72. local actual_a_hugetlb
  73. actual_a_hugetlb="$(cat "$CGROUP_ROOT"/a/hugetlb.${MB}MB.$usage_file)"
  74. if [[ $actual_a_hugetlb -lt $(($expected_a_hugetlb - $tolerance)) ]] ||
  75. [[ $actual_a_hugetlb -gt $(($expected_a_hugetlb + $tolerance)) ]]; then
  76. echo actual a hugetlb = $((${actual_a_hugetlb%% *} / 1024 / 1024)) MB
  77. echo expected a hugetlb = $((${expected_a_hugetlb%% *} / 1024 / 1024)) MB
  78. echo fail
  79. cleanup
  80. exit 1
  81. fi
  82. if [[ -z "$expected_b" || -z "$expected_b_hugetlb" ]]; then
  83. return
  84. fi
  85. local actual_b
  86. actual_b="$(cat "$CGROUP_ROOT"/a/b/memory.$usage_file)"
  87. if [[ $actual_b -lt $(($expected_b - $tolerance)) ]] ||
  88. [[ $actual_b -gt $(($expected_b + $tolerance)) ]]; then
  89. echo actual b = $((${actual_b%% *} / 1024 / 1024)) MB
  90. echo expected b = $((${expected_b%% *} / 1024 / 1024)) MB
  91. echo fail
  92. cleanup
  93. exit 1
  94. fi
  95. local actual_b_hugetlb
  96. actual_b_hugetlb="$(cat "$CGROUP_ROOT"/a/b/hugetlb.${MB}MB.$usage_file)"
  97. if [[ $actual_b_hugetlb -lt $(($expected_b_hugetlb - $tolerance)) ]] ||
  98. [[ $actual_b_hugetlb -gt $(($expected_b_hugetlb + $tolerance)) ]]; then
  99. echo actual b hugetlb = $((${actual_b_hugetlb%% *} / 1024 / 1024)) MB
  100. echo expected b hugetlb = $((${expected_b_hugetlb%% *} / 1024 / 1024)) MB
  101. echo fail
  102. cleanup
  103. exit 1
  104. fi
  105. }
  106. function setup() {
  107. echo 100 >/proc/sys/vm/nr_hugepages
  108. mkdir "$CGROUP_ROOT"/a
  109. sleep 1
  110. if [[ $cgroup2 ]]; then
  111. echo "+hugetlb +memory" >$CGROUP_ROOT/a/cgroup.subtree_control
  112. else
  113. echo 0 >$CGROUP_ROOT/a/cpuset.mems
  114. echo 0 >$CGROUP_ROOT/a/cpuset.cpus
  115. fi
  116. mkdir "$CGROUP_ROOT"/a/b
  117. if [[ ! $cgroup2 ]]; then
  118. echo 0 >$CGROUP_ROOT/a/b/cpuset.mems
  119. echo 0 >$CGROUP_ROOT/a/b/cpuset.cpus
  120. fi
  121. mkdir -p "$MNT"
  122. mount -t hugetlbfs none "$MNT"
  123. }
  124. write_hugetlbfs() {
  125. local cgroup="$1"
  126. local path="$2"
  127. local size="$3"
  128. if [[ $cgroup2 ]]; then
  129. echo $$ >$CGROUP_ROOT/$cgroup/cgroup.procs
  130. else
  131. echo 0 >$CGROUP_ROOT/$cgroup/cpuset.mems
  132. echo 0 >$CGROUP_ROOT/$cgroup/cpuset.cpus
  133. echo $$ >"$CGROUP_ROOT/$cgroup/tasks"
  134. fi
  135. ./write_to_hugetlbfs -p "$path" -s "$size" -m 0 -o
  136. if [[ $cgroup2 ]]; then
  137. echo $$ >$CGROUP_ROOT/cgroup.procs
  138. else
  139. echo $$ >"$CGROUP_ROOT/tasks"
  140. fi
  141. echo
  142. }
  143. set -e
  144. size=$((${MB} * 1024 * 1024 * 25)) # 50MB = 25 * 2MB hugepages.
  145. cleanup
  146. echo
  147. echo
  148. echo Test charge, rmdir, uncharge
  149. setup
  150. echo mkdir
  151. mkdir $CGROUP_ROOT/test1
  152. echo write
  153. write_hugetlbfs test1 "$MNT"/test $size
  154. echo rmdir
  155. rmdir $CGROUP_ROOT/test1
  156. mkdir $CGROUP_ROOT/test1
  157. echo uncharge
  158. rm -rf /mnt/huge/*
  159. cleanup
  160. echo done
  161. echo
  162. echo
  163. if [[ ! $cgroup2 ]]; then
  164. echo "Test parent and child hugetlb usage"
  165. setup
  166. echo write
  167. write_hugetlbfs a "$MNT"/test $size
  168. echo Assert memory charged correctly for parent use.
  169. assert_state 0 $size 0 0
  170. write_hugetlbfs a/b "$MNT"/test2 $size
  171. echo Assert memory charged correctly for child use.
  172. assert_state 0 $(($size * 2)) 0 $size
  173. rmdir "$CGROUP_ROOT"/a/b
  174. sleep 5
  175. echo Assert memory reparent correctly.
  176. assert_state 0 $(($size * 2))
  177. rm -rf "$MNT"/*
  178. umount "$MNT"
  179. echo Assert memory uncharged correctly.
  180. assert_state 0 0
  181. cleanup
  182. fi
  183. echo
  184. echo
  185. echo "Test child only hugetlb usage"
  186. echo setup
  187. setup
  188. echo write
  189. write_hugetlbfs a/b "$MNT"/test2 $size
  190. echo Assert memory charged correctly for child only use.
  191. assert_state 0 $(($size)) 0 $size
  192. rmdir "$CGROUP_ROOT"/a/b
  193. echo Assert memory reparent correctly.
  194. assert_state 0 $size
  195. rm -rf "$MNT"/*
  196. umount "$MNT"
  197. echo Assert memory uncharged correctly.
  198. assert_state 0 0
  199. cleanup
  200. echo ALL PASS
  201. if [[ $do_umount ]]; then
  202. umount $CGROUP_ROOT
  203. rm -rf $CGROUP_ROOT
  204. fi
  205. echo "$nr_hugepgs" > /proc/sys/vm/nr_hugepages