From: Cyril Hrubis <chrubis@suse.cz>
To: Richard Palethorpe <rpalethorpe@suse.com>
Cc: ltp@lists.linux.it
Subject: Re: [LTP] [PATCH v2 5/5] memcontrol03: Copy from kselftest
Date: Thu, 3 Feb 2022 14:52:19 +0100 [thread overview]
Message-ID: <YfveE3QtrfAQvTac@yuki> (raw)
In-Reply-To: <20220203081820.29521-7-rpalethorpe@suse.com>
Hi!
> Note that the tolerances had to be increased slightly otherwise the
> test only passed on ext4 in upstream 5.16 on x86_64. In all cases it
> seems more memory is evicted from C than expected and not enough from
> D. This may indicate some tuning is possible, but does not look like a
> serious regression.
>
> Signed-off-by: Richard Palethorpe <rpalethorpe@suse.com>
> ---
> runtest/controllers | 1 +
> testcases/kernel/controllers/memcg/.gitignore | 1 +
> .../kernel/controllers/memcg/memcontrol03.c | 255 ++++++++++++++++++
> 3 files changed, 257 insertions(+)
> create mode 100644 testcases/kernel/controllers/memcg/memcontrol03.c
>
> diff --git a/runtest/controllers b/runtest/controllers
> index 09e0107e4..4a6f919af 100644
> --- a/runtest/controllers
> +++ b/runtest/controllers
> @@ -19,6 +19,7 @@ memcg_control memcg_control_test.sh
> # kselftest ports
> memcontrol01 memcontrol01
> memcontrol02 memcontrol02
> +memcontrol03 memcontrol03
>
> cgroup_fj_function_debug cgroup_fj_function.sh debug
> cgroup_fj_function_cpuset cgroup_fj_function.sh cpuset
> diff --git a/testcases/kernel/controllers/memcg/.gitignore b/testcases/kernel/controllers/memcg/.gitignore
> index f7de40d53..49df1582c 100644
> --- a/testcases/kernel/controllers/memcg/.gitignore
> +++ b/testcases/kernel/controllers/memcg/.gitignore
> @@ -7,3 +7,4 @@
> /stress/memcg_process_stress
> memcontrol01
> memcontrol02
> +memcontrol03
> diff --git a/testcases/kernel/controllers/memcg/memcontrol03.c b/testcases/kernel/controllers/memcg/memcontrol03.c
> new file mode 100644
> index 000000000..8f1d7f8c1
> --- /dev/null
> +++ b/testcases/kernel/controllers/memcg/memcontrol03.c
> @@ -0,0 +1,255 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*\
> + *
> + * [Description]
> + *
> + * Conversion of the third kself test in cgroup/test_memcontrol.c.
> + *
> + * Original description:
> + * "First, this test creates the following hierarchy:
> + * A memory.min = 50M, memory.max = 200M
> + * A/B memory.min = 50M, memory.current = 50M
> + * A/B/C memory.min = 75M, memory.current = 50M
> + * A/B/D memory.min = 25M, memory.current = 50M
> + * A/B/E memory.min = 500M, memory.current = 0
> + * A/B/F memory.min = 0, memory.current = 50M
> + *
> + * Usages are pagecache, but the test keeps a running
> + * process in every leaf cgroup.
> + * Then it creates A/G and creates a significant
> + * memory pressure in it.
> + *
> + * A/B memory.current ~= 50M
> + * A/B/C memory.current ~= 33M
> + * A/B/D memory.current ~= 17M
> + * A/B/E memory.current ~= 0
> + *
> + * After that it tries to allocate more than there is unprotected
> + * memory in A available, and checks that memory.min protects
> + * pagecache even in this case."
> + *
> + * memory.min doesn't appear to exist on V1 so we only test on V2 like
> + * the selftest. We do test on more file systems, but not tempfs
> + * becaue it can't evict the page cache without swap. Also we avoid
> + * filesystems which allocate extra memory for buffer heads.
> + *
> + * The tolerances have been increased from the self tests.
> + */
> +
> +#define _GNU_SOURCE
> +
> +#include <inttypes.h>
> +
> +#include "memcontrol_common.h"
> +
> +#define TMPDIR "mntdir"
> +
> +static struct tst_cgroup_group *trunk_cg[3];
> +static struct tst_cgroup_group *leaf_cg[4];
> +static int fd = -1;
> +
> +enum checkpoints {
> + CHILD_IDLE,
> + TEST_DONE,
> +};
> +
> +enum trunk_cg {
> + A,
> + B,
> + G
> +};
> +
> +enum leaf_cg {
> + C,
> + D,
> + E,
> + F
> +};
> +
> +static void cleanup_sub_groups(void)
> +{
> + size_t i;
> +
> + for (i = ARRAY_SIZE(leaf_cg); i > 0; i--) {
> + if (!leaf_cg[i - 1])
> + continue;
> +
> + TST_CHECKPOINT_WAKE2(TEST_DONE,
> + ARRAY_SIZE(leaf_cg) - 1);
> + tst_reap_children();
> + break;
> + }
> +
> + for (i = ARRAY_SIZE(leaf_cg); i > 0; i--) {
> + if (!leaf_cg[i - 1])
> + continue;
> +
> + leaf_cg[i - 1] = tst_cgroup_group_rm(leaf_cg[i - 1]);
> + }
> +
> + for (i = ARRAY_SIZE(trunk_cg); i > 0; i--) {
> + if (!trunk_cg[i - 1])
> + continue;
> +
> + trunk_cg[i - 1] = tst_cgroup_group_rm(trunk_cg[i - 1]);
> + }
> +}
> +
> +static void alloc_anon_in_child(const struct tst_cgroup_group *const cg,
> + const size_t size, const int expect_oom)
> +{
> + int status;
> + const pid_t pid = SAFE_FORK();
> +
> + if (!pid) {
> + SAFE_CGROUP_PRINTF(cg, "cgroup.procs", "%d", getpid());
> +
> + tst_res(TINFO, "%d in %s: Allocating anon: %"PRIdPTR,
> + getpid(), tst_cgroup_group_name(cg), size);
> + alloc_anon(size);
> + exit(0);
> + }
> +
> + SAFE_WAITPID(pid, &status, 0);
> +
> + if (!expect_oom) {
> + if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
> + return;
> + } else {
> + if (WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL)
> + return;
> + }
Maybe we should print TPASS in these as well to complement the TFAIL
below. Also the negation in !expect_oom is kind of useless since we
handle both cases anyways.
> + tst_res(TFAIL,
> + "Expected child %d to %s, but instead %s",
> + pid,
> + expect_oom ? "be killed" : "exit(0)",
> + tst_strstatus(status));
> +}
> +
> +static void alloc_pagecache_in_child(const struct tst_cgroup_group *const cg,
> + const size_t size)
> +{
> + const pid_t pid = SAFE_FORK();
> +
> + if (pid) {
> + TST_CHECKPOINT_WAIT(CHILD_IDLE);
> + return;
> + }
> +
> + SAFE_CGROUP_PRINTF(cg, "cgroup.procs", "%d", getpid());
> +
> + tst_res(TINFO, "PID %d in %s: Allocating pagecache: %"PRIdPTR,
> + getpid(), tst_cgroup_group_name(cg), size);
> + alloc_pagecache(fd, size);
> +
> + TST_CHECKPOINT_WAKE(CHILD_IDLE);
> + TST_CHECKPOINT_WAIT(TEST_DONE);
> + exit(0);
> +}
> +
> +static void test_memcg_min(void)
> +{
> + long c[4];
> + unsigned int i;
> + size_t attempts;
> +
> + fd = SAFE_OPEN(TMPDIR"/tmpfile", O_RDWR | O_CREAT, 0600);
> + trunk_cg[A] = tst_cgroup_group_mk(tst_cgroup, "trunk_A");
> +
> + SAFE_CGROUP_SCANF(trunk_cg[A], "memory.min", "%ld", c);
> + if (c[0]) {
> + tst_brk(TCONF,
> + "memory.min already set to %ld on parent group", c[0]);
> + }
> +
> + if (!TST_CGROUP_VER_IS_V1(trunk_cg[A], "memory")) {
> + SAFE_CGROUP_PRINT(trunk_cg[A], "cgroup.subtree_control",
> + "+memory");
> + }
> + SAFE_CGROUP_PRINT(trunk_cg[A], "memory.max", "200M");
> + SAFE_CGROUP_PRINT(trunk_cg[A], "memory.swap.max", "0");
> +
> + trunk_cg[B] = tst_cgroup_group_mk(trunk_cg[A], "trunk_B");
> + if (!TST_CGROUP_VER_IS_V1(trunk_cg[A], "memory")) {
> + SAFE_CGROUP_PRINT(trunk_cg[B], "cgroup.subtree_control",
> + "+memory");
> + }
Don't we require V2 for the whole test anyways?
Also I think I asked if this si really needed in v1, don't we enable the
required subgroups in group_mk() anyways?
> + trunk_cg[G] = tst_cgroup_group_mk(trunk_cg[A], "trunk_G");
> +
> + for (i = 0; i < ARRAY_SIZE(leaf_cg); i++) {
> + leaf_cg[i] = tst_cgroup_group_mk(trunk_cg[B],
> + "leaf_%c", 'C' + i);
> +
> + if (i == E)
> + continue;
> +
> + alloc_pagecache_in_child(leaf_cg[i], MB(50));
> + }
> +
> + SAFE_CGROUP_PRINT(trunk_cg[A], "memory.min", "50M");
> + SAFE_CGROUP_PRINT(trunk_cg[B], "memory.min", "50M");
> + SAFE_CGROUP_PRINT(leaf_cg[C], "memory.min", "75M");
> + SAFE_CGROUP_PRINT(leaf_cg[D], "memory.min", "25M");
> + SAFE_CGROUP_PRINT(leaf_cg[E], "memory.min", "500M");
> + SAFE_CGROUP_PRINT(leaf_cg[F], "memory.min", "0");
> +
> + for (attempts = 0; attempts < 5; attempts++) {
> + SAFE_CGROUP_SCANF(trunk_cg[B], "memory.current", "%ld", c);
> + if (values_close(c[0], MB(150), 3))
> + break;
> +
> + sleep(1);
> + }
> +
> + alloc_anon_in_child(trunk_cg[G], MB(148), 0);
> +
> + SAFE_CGROUP_SCANF(trunk_cg[B], "memory.current", "%ld", c);
> + TST_EXP_EXPR(values_close(c[0], MB(50), 5),
> + "(A/B memory.current=%ld) ~= %d", c[0], MB(50));
> +
> + for (i = 0; i < ARRAY_SIZE(leaf_cg); i++)
> + SAFE_CGROUP_SCANF(leaf_cg[i], "memory.current", "%ld", c + i);
> +
> + TST_EXP_EXPR(values_close(c[0], MB(33), 20),
> + "(A/B/C memory.current=%ld) ~= %d", c[0], MB(33));
> + TST_EXP_EXPR(values_close(c[1], MB(17), 20),
> + "(A/B/D memory.current=%ld) ~= %d", c[1], MB(17));
> + TST_EXP_EXPR(values_close(c[2], 0, 1),
> + "(A/B/E memory.current=%ld) ~= 0", c[2]);
> +
> + alloc_anon_in_child(trunk_cg[G], MB(170), 1);
> +
> + SAFE_CGROUP_SCANF(trunk_cg[B], "memory.current", "%ld", c);
> + TST_EXP_EXPR(values_close(c[0], MB(50), 5),
> + "(A/B memory.current=%ld) ~= %d", c[0], MB(50));
> +
> + cleanup_sub_groups();
> + SAFE_CLOSE(fd);
> + SAFE_UNLINK(TMPDIR"/tmpfile");
> +}
> +
> +static void cleanup(void)
> +{
> + cleanup_sub_groups();
> + if (fd > -1)
> + SAFE_CLOSE(fd);
> +}
> +
> +static struct tst_test test = {
> + .cleanup = cleanup,
> + .test_all = test_memcg_min,
> + .mount_device = 1,
> + .dev_min_size = 256,
> + .mntpoint = TMPDIR,
> + .all_filesystems = 1,
> + .skip_filesystems = (const char *const[]){
> + "exfat", "vfat", "fuse", "ntfs", "tmpfs", NULL
> + },
> + .forks_child = 1,
> + .needs_root = 1,
> + .needs_checkpoints = 1,
> + .needs_cgroup_ver = TST_CGROUP_V2,
> + .needs_cgroup_controllers = (const char *const[]){ "memory", NULL },
> +};
> --
> 2.34.1
>
>
> --
> Mailing list info: https://lists.linux.it/listinfo/ltp
--
Cyril Hrubis
chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
next prev parent reply other threads:[~2022-02-03 13:50 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-02-03 8:18 [LTP] [PATCH v2 0/5] Add memcontrol03 and declarative CG API Richard Palethorpe via ltp
2022-02-03 8:18 ` [LTP] [PATCH v2 1/5] memcontrol: Lift out some common definitions into a shared header Richard Palethorpe via ltp
2022-02-03 13:04 ` Cyril Hrubis
2022-02-04 7:42 ` Li Wang
2022-02-03 8:18 ` [LTP] [PATCH v2 2/5] API/cgroup: Declare required controllers and version in test struct Richard Palethorpe via ltp
2022-02-03 13:03 ` Cyril Hrubis
2022-02-04 7:37 ` Li Wang
2022-02-07 13:18 ` Richard Palethorpe
2022-02-03 8:18 ` [LTP] [PATCH v2 3/5] API/cgroup: Add memory.min Richard Palethorpe via ltp
2022-02-03 13:13 ` Cyril Hrubis
2022-02-07 11:36 ` Richard Palethorpe
2022-02-03 8:18 ` [LTP] [PATCH v2 4/5] API/cgroup: Allow formatting of new cg names Richard Palethorpe via ltp
2022-02-03 8:18 ` [LTP] [PATCH v2 4/5] API/cgroup: Make tst_cgroup_group_mk sprintf like Richard Palethorpe via ltp
2022-02-03 13:20 ` Cyril Hrubis
2022-02-04 6:41 ` Li Wang
2022-02-04 10:01 ` Cyril Hrubis
2022-02-07 8:44 ` Richard Palethorpe
2022-02-03 8:18 ` [LTP] [PATCH v2 5/5] memcontrol03: Copy from kselftest Richard Palethorpe via ltp
2022-02-03 13:52 ` Cyril Hrubis [this message]
2022-02-07 9:46 ` Richard Palethorpe
2022-02-08 8:03 ` Li Wang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=YfveE3QtrfAQvTac@yuki \
--to=chrubis@suse.cz \
--cc=ltp@lists.linux.it \
--cc=rpalethorpe@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.