@@ -80,6 +80,37 @@ check_kernel_bug()
return 0
}
+setup_cgroupv2()
+{
+ cgroup_mount_point=$(grep -w cgroup2 /proc/mounts | cut -f 2 | cut -d " " -f2)
+ if ! grep -q memory "$cgroup_mount_point"/cgroup.controllers; then
+ tst_res TINFO "memory controller not supported on cgroup v2."
+ return
+ fi
+
+ ROD mkdir -p $mount_point
+ ROD mount -t cgroup2 none $mount_point
+
+ task_list="cgroup.procs"
+ memory_limit="memory.max"
+ cgroup_v="v2"
+}
+
+setup_cgroupv1()
+{
+ exist=$(grep -w memory /proc/cgroups | cut -f1);
+ if [ "$exist" = "" ]; then
+ tst_brk TCONF NULL "memory controller not supported"
+ fi
+
+ ROD mkdir -p $mount_point
+ ROD mount -t cgroup -o memory none $mount_point
+
+ task_list="tasks"
+ memory_limit="memory.limit_in_bytes"
+ cgroup_v="v1"
+}
+
setup()
{
mount_point="/dev/memcg"
@@ -89,13 +120,15 @@ setup()
tst_brk TBROK "Test should be run with kernel 2.6.30 or newer"
fi
- exist=$(grep -w memory /proc/cgroups | cut -f1);
- if [ "$exist" = "" ]; then
- tst_brk TCONF "memory controller not supported"
+ if grep -q cgroup2 /proc/mounts; then
+ setup_cgroupv2
fi
- ROD mkdir -p $mount_point
- ROD mount -t cgroup -o memory none $mount_point
+ if [ -z "$cgroup_v" ]; then
+ setup_cgroupv1
+ fi
+
+ tst_res TINFO "test starts with cgroup $cgroup_v"
}
cleanup()
@@ -115,7 +148,7 @@ cleanup()
test_1()
{
ROD mkdir -p "$test_path"
- ROD echo 0 > "$test_path"/memory.limit_in_bytes
+ ROD echo 0 > "$test_path/$memory_limit"
./memcg_test_1
@@ -136,6 +169,14 @@ test_1()
#---------------------------------------------------------------------------
test_2()
{
+ # for cgroup2 writing to memory.max first checks the new limit against the
+ # current usage and will start killing processes if oom, therefore we do not
+ # expect EBUSY to be returned by the shrink operation.
+ if [ "$cgroup_v" = "v2" ]; then
+ tst_res TCONF "Cgroup v2 found, skipping test"
+ return
+ fi
+
./memcg_test_2 &
pid1=$!
sleep 1
@@ -188,12 +229,12 @@ test_2()
test_3()
{
ROD mkdir -p "$test_path"
- for pid in $(cat "$mount_point"/tasks); do
- echo $pid > "$test_path"/tasks 2> /dev/null
+ for pid in $(cat "$mount_point/$task_list"); do
+ echo $pid > "$test_path/$task_list" 2> /dev/null
done
- for pid in $(cat "$test_path"/tasks); do
- echo $pid > "$mount_point"/tasks 2> /dev/null
+ for pid in $(cat "$test_path/$task_list"); do
+ echo $pid > "$mount_point/$task_list" 2> /dev/null
done
rmdir "$test_path"
@@ -212,7 +253,7 @@ test_3()
test_4()
{
ROD mkdir -p "$test_path"
- ./memcg_test_4.sh
+ ./memcg_test_4.sh "$cgroup_v"
check_kernel_bug
if [ $? -eq 1 ]; then
@@ -33,6 +33,16 @@
#define FORKED_PROC_COUNT 10
+static int open_cgroup_tasklist(void)
+{
+ int fd = open("/dev/memcg/0/tasks", O_WRONLY);
+ if (fd >= 0)
+ return fd;
+
+ fd = open("/dev/memcg/0/cgroup.procs", O_WRONLY);
+ return fd;
+}
+
int main(void)
{
char buf[10];
@@ -40,7 +50,7 @@ int main(void)
int loop;
int pid;
int size = getpagesize();
- int fd = open("/dev/memcg/0/tasks", O_WRONLY);
+ int fd = open_cgroup_tasklist();
if (fd < 0)
return 1;
@@ -17,12 +17,12 @@
#include <sys/types.h>
#include <sys/mount.h>
#include "tst_test.h"
+#include "tst_cgroup.h"
-#define MNTPOINT "memcg"
-#define SUBDIR "memcg/testdir"
-static int mount_flag;
static volatile int sigcounter;
+static const struct tst_cgroup_group *cg;
+static struct tst_cgroup_group *test_cg;
static void sighandler(int sig LTP_ATTRIBUTE_UNUSED)
{
@@ -48,9 +48,10 @@ static void do_test(void)
do_child();
while (sigcounter < 50000) {
- if (access(SUBDIR, F_OK))
- SAFE_MKDIR(SUBDIR, 0644);
- rmdir(SUBDIR);
+ test_cg = tst_cgroup_group_mk(cg, "test");
+
+ if (test_cg)
+ test_cg = tst_cgroup_group_rm(test_cg);
}
SAFE_KILL(cpid, SIGKILL);
@@ -61,32 +62,24 @@ static void do_test(void)
static void setup(void)
{
- int ret;
-
- SAFE_MKDIR(MNTPOINT, 0644);
+ tst_cgroup_require("memory", NULL);
- ret = mount("memcg", MNTPOINT, "cgroup", 0, "memory");
- if (ret) {
- if (errno == ENOENT)
- tst_brk(TCONF | TERRNO, "memcg not supported");
+ cg = tst_cgroup_get_test_group();
- tst_brk(TCONF | TERRNO, "mounting memcg failed");
- }
- mount_flag = 1;
+ if (TST_CGROUP_VER(cg, "memory") != TST_CGROUP_V1)
+ SAFE_CGROUP_PRINT(cg, "cgroup.subtree_control", "+memory");
}
static void cleanup(void)
{
- if (!access(SUBDIR, F_OK))
- SAFE_RMDIR(SUBDIR);
+ if (test_cg)
+ test_cg = tst_cgroup_group_rm(test_cg);
- if (mount_flag)
- tst_umount(MNTPOINT);
+ tst_cgroup_cleanup();
}
static struct tst_test test = {
.needs_root = 1,
- .needs_tmpdir = 1,
.forks_child = 1,
.min_kver = "2.6.24",
.setup = setup,
@@ -22,10 +22,19 @@
## ##
################################################################################
+cgroup_v=$1
mount_point="/dev/memcg"
test_path="$mount_point"/0
-echo $$ > "$test_path"/tasks
+if [ $cgroup_v = "v2" ]; then
+ task_list="cgroup.procs"
+ memory_limit="memory.max"
+else
+ task_list="tasks"
+ memory_limit="memory.limit_in_bytes"
+fi
+
+echo $$ > "$test_path/$memory_limit"
./memcg_test_4 &
pid=$!
@@ -36,13 +45,13 @@ sleep 1
sleep 1
# shrink memory, and then 80M will be swapped
-echo 40M > "$test_path"/memory.limit_in_bytes
+echo 40M > "$test_path/$memory_limit"
# turn off swap, and swapoff will be killed
swapoff -a
sleep 1
-echo $pid > "$mount_point"/tasks 2> /dev/null
-echo $$ > "$mount_point"/tasks 2> /dev/null
+echo $pid > "$mount_point/$task_list" 2> /dev/null
+echo $$ > "$mount_point/$task_list" 2> /dev/null
# now remove the cgroup
rmdir "$test_path"
Add support for regression tests when memory controller is mounted on cgroup2 hierarchy. Most of the tests are still useful and require changing some parameters to match the cgroup2 memory interface. Signed-off-by: Luke Nowakowski-Krijger <luke.nowakowskikrijger@canonical.com> --- .../memcg/regression/memcg_regression_test.sh | 63 +++++++++++++++---- .../memcg/regression/memcg_test_1.c | 12 +++- .../memcg/regression/memcg_test_3.c | 35 +++++------ .../memcg/regression/memcg_test_4.sh | 17 +++-- 4 files changed, 90 insertions(+), 37 deletions(-)