mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-19 16:24:21 +00:00
Currently if the filesystem for the cgroups version it wants to use is not
mounted charge_reserved_hugetlb.sh and hugetlb_reparenting_test.sh tests
will attempt to mount it on the hard coded path /dev/cgroup/memory,
deleting that directory when the test finishes. This will fail if there
is not a preexisting directory at that path, and since the directory is
deleted subsequent runs of the test will fail. Instead of relying on this
hard coded directory name use mktemp to generate a temporary directory to
use as a mountpoint, fixing both the assumption and the disruption caused
by deleting a preexisting directory.
This means that if the relevant cgroup filesystem is not already mounted
then we rely on having coreutils (which provides mktemp) installed. I
suspect that many current users are relying on having things automounted
by default, and given that the script relies on bash it's probably not an
unreasonable requirement.
Link: https://lkml.kernel.org/r/20250404-kselftest-mm-cgroup2-detection-v1-1-3dba6d32ba8c@kernel.org
Fixes: 209376ed2a ("selftests/vm: make charge_reserved_hugetlb.sh work with existing cgroup setting")
Signed-off-by: Mark Brown <broonie@kernel.org>
Cc: Aishwarya TCV <aishwarya.tcv@arm.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Mina Almasry <almasrymina@google.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Waiman Long <longman@redhat.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
258 lines
5.6 KiB
Bash
Executable File
258 lines
5.6 KiB
Bash
Executable File
#!/bin/bash
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
|
|
# Kselftest framework requirement - SKIP code is 4.
|
|
ksft_skip=4
|
|
|
|
set -e
|
|
|
|
if [[ $(id -u) -ne 0 ]]; then
|
|
echo "This test must be run as root. Skipping..."
|
|
exit $ksft_skip
|
|
fi
|
|
|
|
nr_hugepgs=$(cat /proc/sys/vm/nr_hugepages)
|
|
usage_file=usage_in_bytes
|
|
|
|
if [[ "$1" == "-cgroup-v2" ]]; then
|
|
cgroup2=1
|
|
usage_file=current
|
|
fi
|
|
|
|
|
|
if [[ $cgroup2 ]]; then
|
|
CGROUP_ROOT=$(mount -t cgroup2 | head -1 | awk '{print $3}')
|
|
if [[ -z "$CGROUP_ROOT" ]]; then
|
|
CGROUP_ROOT=$(mktemp -d)
|
|
mount -t cgroup2 none $CGROUP_ROOT
|
|
do_umount=1
|
|
fi
|
|
echo "+hugetlb +memory" >$CGROUP_ROOT/cgroup.subtree_control
|
|
else
|
|
CGROUP_ROOT=$(mount -t cgroup | grep ",hugetlb" | awk '{print $3}')
|
|
if [[ -z "$CGROUP_ROOT" ]]; then
|
|
CGROUP_ROOT=/dev/cgroup/memory
|
|
mount -t cgroup memory,hugetlb $CGROUP_ROOT
|
|
do_umount=1
|
|
fi
|
|
fi
|
|
MNT='/mnt/huge/'
|
|
|
|
function get_machine_hugepage_size() {
|
|
hpz=$(grep -i hugepagesize /proc/meminfo)
|
|
kb=${hpz:14:-3}
|
|
mb=$(($kb / 1024))
|
|
echo $mb
|
|
}
|
|
|
|
MB=$(get_machine_hugepage_size)
|
|
|
|
function cleanup() {
|
|
echo cleanup
|
|
set +e
|
|
rm -rf "$MNT"/* 2>/dev/null
|
|
umount "$MNT" 2>/dev/null
|
|
rmdir "$MNT" 2>/dev/null
|
|
rmdir "$CGROUP_ROOT"/a/b 2>/dev/null
|
|
rmdir "$CGROUP_ROOT"/a 2>/dev/null
|
|
rmdir "$CGROUP_ROOT"/test1 2>/dev/null
|
|
echo 0 >/proc/sys/vm/nr_hugepages
|
|
set -e
|
|
}
|
|
|
|
function assert_state() {
|
|
local expected_a="$1"
|
|
local expected_a_hugetlb="$2"
|
|
local expected_b=""
|
|
local expected_b_hugetlb=""
|
|
|
|
if [ ! -z ${3:-} ] && [ ! -z ${4:-} ]; then
|
|
expected_b="$3"
|
|
expected_b_hugetlb="$4"
|
|
fi
|
|
local tolerance=$((5 * 1024 * 1024))
|
|
|
|
local actual_a
|
|
actual_a="$(cat "$CGROUP_ROOT"/a/memory.$usage_file)"
|
|
if [[ $actual_a -lt $(($expected_a - $tolerance)) ]] ||
|
|
[[ $actual_a -gt $(($expected_a + $tolerance)) ]]; then
|
|
echo actual a = $((${actual_a%% *} / 1024 / 1024)) MB
|
|
echo expected a = $((${expected_a%% *} / 1024 / 1024)) MB
|
|
echo fail
|
|
|
|
cleanup
|
|
exit 1
|
|
fi
|
|
|
|
local actual_a_hugetlb
|
|
actual_a_hugetlb="$(cat "$CGROUP_ROOT"/a/hugetlb.${MB}MB.$usage_file)"
|
|
if [[ $actual_a_hugetlb -lt $(($expected_a_hugetlb - $tolerance)) ]] ||
|
|
[[ $actual_a_hugetlb -gt $(($expected_a_hugetlb + $tolerance)) ]]; then
|
|
echo actual a hugetlb = $((${actual_a_hugetlb%% *} / 1024 / 1024)) MB
|
|
echo expected a hugetlb = $((${expected_a_hugetlb%% *} / 1024 / 1024)) MB
|
|
echo fail
|
|
|
|
cleanup
|
|
exit 1
|
|
fi
|
|
|
|
if [[ -z "$expected_b" || -z "$expected_b_hugetlb" ]]; then
|
|
return
|
|
fi
|
|
|
|
local actual_b
|
|
actual_b="$(cat "$CGROUP_ROOT"/a/b/memory.$usage_file)"
|
|
if [[ $actual_b -lt $(($expected_b - $tolerance)) ]] ||
|
|
[[ $actual_b -gt $(($expected_b + $tolerance)) ]]; then
|
|
echo actual b = $((${actual_b%% *} / 1024 / 1024)) MB
|
|
echo expected b = $((${expected_b%% *} / 1024 / 1024)) MB
|
|
echo fail
|
|
|
|
cleanup
|
|
exit 1
|
|
fi
|
|
|
|
local actual_b_hugetlb
|
|
actual_b_hugetlb="$(cat "$CGROUP_ROOT"/a/b/hugetlb.${MB}MB.$usage_file)"
|
|
if [[ $actual_b_hugetlb -lt $(($expected_b_hugetlb - $tolerance)) ]] ||
|
|
[[ $actual_b_hugetlb -gt $(($expected_b_hugetlb + $tolerance)) ]]; then
|
|
echo actual b hugetlb = $((${actual_b_hugetlb%% *} / 1024 / 1024)) MB
|
|
echo expected b hugetlb = $((${expected_b_hugetlb%% *} / 1024 / 1024)) MB
|
|
echo fail
|
|
|
|
cleanup
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
function setup() {
|
|
echo 100 >/proc/sys/vm/nr_hugepages
|
|
mkdir "$CGROUP_ROOT"/a
|
|
sleep 1
|
|
if [[ $cgroup2 ]]; then
|
|
echo "+hugetlb +memory" >$CGROUP_ROOT/a/cgroup.subtree_control
|
|
else
|
|
echo 0 >$CGROUP_ROOT/a/cpuset.mems
|
|
echo 0 >$CGROUP_ROOT/a/cpuset.cpus
|
|
fi
|
|
|
|
mkdir "$CGROUP_ROOT"/a/b
|
|
|
|
if [[ ! $cgroup2 ]]; then
|
|
echo 0 >$CGROUP_ROOT/a/b/cpuset.mems
|
|
echo 0 >$CGROUP_ROOT/a/b/cpuset.cpus
|
|
fi
|
|
|
|
mkdir -p "$MNT"
|
|
mount -t hugetlbfs none "$MNT"
|
|
}
|
|
|
|
write_hugetlbfs() {
|
|
local cgroup="$1"
|
|
local path="$2"
|
|
local size="$3"
|
|
|
|
if [[ $cgroup2 ]]; then
|
|
echo $$ >$CGROUP_ROOT/$cgroup/cgroup.procs
|
|
else
|
|
echo 0 >$CGROUP_ROOT/$cgroup/cpuset.mems
|
|
echo 0 >$CGROUP_ROOT/$cgroup/cpuset.cpus
|
|
echo $$ >"$CGROUP_ROOT/$cgroup/tasks"
|
|
fi
|
|
./write_to_hugetlbfs -p "$path" -s "$size" -m 0 -o
|
|
if [[ $cgroup2 ]]; then
|
|
echo $$ >$CGROUP_ROOT/cgroup.procs
|
|
else
|
|
echo $$ >"$CGROUP_ROOT/tasks"
|
|
fi
|
|
echo
|
|
}
|
|
|
|
set -e
|
|
|
|
size=$((${MB} * 1024 * 1024 * 25)) # 50MB = 25 * 2MB hugepages.
|
|
|
|
cleanup
|
|
|
|
echo
|
|
echo
|
|
echo Test charge, rmdir, uncharge
|
|
setup
|
|
echo mkdir
|
|
mkdir $CGROUP_ROOT/test1
|
|
|
|
echo write
|
|
write_hugetlbfs test1 "$MNT"/test $size
|
|
|
|
echo rmdir
|
|
rmdir $CGROUP_ROOT/test1
|
|
mkdir $CGROUP_ROOT/test1
|
|
|
|
echo uncharge
|
|
rm -rf /mnt/huge/*
|
|
|
|
cleanup
|
|
|
|
echo done
|
|
echo
|
|
echo
|
|
if [[ ! $cgroup2 ]]; then
|
|
echo "Test parent and child hugetlb usage"
|
|
setup
|
|
|
|
echo write
|
|
write_hugetlbfs a "$MNT"/test $size
|
|
|
|
echo Assert memory charged correctly for parent use.
|
|
assert_state 0 $size 0 0
|
|
|
|
write_hugetlbfs a/b "$MNT"/test2 $size
|
|
|
|
echo Assert memory charged correctly for child use.
|
|
assert_state 0 $(($size * 2)) 0 $size
|
|
|
|
rmdir "$CGROUP_ROOT"/a/b
|
|
sleep 5
|
|
echo Assert memory reparent correctly.
|
|
assert_state 0 $(($size * 2))
|
|
|
|
rm -rf "$MNT"/*
|
|
umount "$MNT"
|
|
echo Assert memory uncharged correctly.
|
|
assert_state 0 0
|
|
|
|
cleanup
|
|
fi
|
|
|
|
echo
|
|
echo
|
|
echo "Test child only hugetlb usage"
|
|
echo setup
|
|
setup
|
|
|
|
echo write
|
|
write_hugetlbfs a/b "$MNT"/test2 $size
|
|
|
|
echo Assert memory charged correctly for child only use.
|
|
assert_state 0 $(($size)) 0 $size
|
|
|
|
rmdir "$CGROUP_ROOT"/a/b
|
|
echo Assert memory reparent correctly.
|
|
assert_state 0 $size
|
|
|
|
rm -rf "$MNT"/*
|
|
umount "$MNT"
|
|
echo Assert memory uncharged correctly.
|
|
assert_state 0 0
|
|
|
|
cleanup
|
|
|
|
echo ALL PASS
|
|
|
|
if [[ $do_umount ]]; then
|
|
umount $CGROUP_ROOT
|
|
rm -rf $CGROUP_ROOT
|
|
fi
|
|
|
|
echo "$nr_hugepgs" > /proc/sys/vm/nr_hugepages
|