Linux Test Project
 help / color / mirror / Atom feed
From: Cyril Hrubis <chrubis@suse.cz>
To: Pavithra <pavrampu@linux.ibm.com>
Cc: "Michal Koutný" <mkoutny@suse.com>, ltp@lists.linux.it
Subject: Re: [LTP] [PATCH v7] memcg/memcontrol05: add cgroup v2 task migration charge accounting test
Date: Fri, 30 Oct 2026 16:29:37 +0100	[thread overview]
Message-ID: <auS34aeU5tMadFsg@yuki.lan> (raw)
In-Reply-To: <20260830173408.261946-1-pavrampu@linux.ibm.com>

Hi!
> Verify that in cgroup v2, memory charges remain pinned to the cgroup
> that allocated them when a task migrates, and that new allocations after
> migration are charged to the destination cgroup.
> 
> Signed-off-by: Pavithra <pavrampu@linux.ibm.com>
> ---
> v6 -> v7:
> - Replace named checkpoint enum with single index 0
> - Collapse wake/wait pairs into TST_CHECKPOINT_WAKE_AND_WAIT(0)
> - Drop worker_stage tracking
> - Replace manual pass/fail blocks with TST_EXP_LE_LU()
> - Remove MB(4) factor from migration charge check
> - Kill worker with SAFE_KILL/SAFE_WAITPID instead of checkpoint-based exit handshake
> link to v6: https://lore.kernel.org/ltp/20260817155701.943752-1-pavrampu@linux.ibm.com/
> ---
>  runtest/controllers                           |   1 +
>  testcases/kernel/controllers/memcg/.gitignore |   1 +
>  .../kernel/controllers/memcg/memcontrol05.c   | 160 ++++++++++++++++++
>  3 files changed, 162 insertions(+)
>  create mode 100644 testcases/kernel/controllers/memcg/memcontrol05.c
> 
> diff --git a/runtest/controllers b/runtest/controllers
> index 93c52c439..a9050ef0e 100644
> --- a/runtest/controllers
> +++ b/runtest/controllers
> @@ -24,6 +24,7 @@ memcontrol01 memcontrol01
>  memcontrol02 memcontrol02
>  memcontrol03 memcontrol03
>  memcontrol04 memcontrol04
> +memcontrol05 memcontrol05
>  
>  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 3883cede6..8b9f6005c 100644
> --- a/testcases/kernel/controllers/memcg/.gitignore
> +++ b/testcases/kernel/controllers/memcg/.gitignore
> @@ -9,3 +9,4 @@ memcontrol01
>  memcontrol02
>  memcontrol03
>  memcontrol04
> +memcontrol05
> diff --git a/testcases/kernel/controllers/memcg/memcontrol05.c b/testcases/kernel/controllers/memcg/memcontrol05.c
> new file mode 100644
> index 000000000..d452039e6
> --- /dev/null
> +++ b/testcases/kernel/controllers/memcg/memcontrol05.c
> @@ -0,0 +1,160 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2026 IBM
> + * Author : Pavithra <pavrampu@linux.ibm.com>
> + */
> +
> +/*\
> + * Origin: ``testcases/kernel/controllers/memctl/memctl_testplan.txt``
> + * Verify memory controller charge accounting during task migration.
> + *
> + * Two child cgroups (``group_a``, ``group_b``) are created under the test cgroup.
> + * A worker process is placed in ``group_a`` and allocates a known amount of
> + * anonymous memory, touching every page to ensure physical allocation.
> + * Root is required to create cgroup subdirectories and to write a PID
> + * into ``cgroup.procs`` to migrate the worker between cgroups.
> + *
> + * Test 1 - No charge transfer on migration:
> + *   The worker is migrated to ``group_b`` by writing its PID to
> + *   ``group_b/cgroup.procs``. In cgroup v2 memory charges are never
> + *   transferred on task migration; they remain pinned to the cgroup
> + *   that allocated them. ``group_b/memory.current`` must not increase
> + *   beyond its baseline after the migration.
> + *
> + * Test 2 - New allocations charged to destination cgroup:
> + *   After migration the worker allocates an additional chunk of memory.
> + *   This new allocation must be charged to ``group_b``, so
> + *   ``group_b/memory.current`` must increase from the post-migration
> + *   baseline.
> + */
> +
> +#define _GNU_SOURCE
> +
> +#include <stdlib.h>
> +#include <sys/types.h>
> +#include <sys/wait.h>
> +#include "tst_test.h"
> +#include "memcontrol_common.h"
> +
> +#define ALLOC_SIZE	MB(60)
> +#define ALLOC_SIZE2	MB(20)
> +#define MIN_MEM_AVAIL	128
> +
> +static struct tst_cg_group *group_a;
> +static struct tst_cg_group *group_b;
> +static pid_t worker_pid;
> +
> +static void touch_pages(char *buf, size_t size)
> +{
> +	size_t i;
> +
> +	for (i = 0; i < size; i += getpagesize())
> +		buf[i] = 1;
> +}
> +
> +static void worker(void)
> +{
> +	char *buf1, *buf2;
> +
> +	SAFE_CG_PRINTF(group_a, "cgroup.procs", "%d", getpid());
> +
> +	buf1 = SAFE_MMAP(NULL, ALLOC_SIZE, PROT_READ | PROT_WRITE,
> +			 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
> +	touch_pages(buf1, ALLOC_SIZE);
> +
> +	TST_CHECKPOINT_WAKE_AND_WAIT(0);
> +
> +	buf2 = SAFE_MMAP(NULL, ALLOC_SIZE2, PROT_READ | PROT_WRITE,
> +			 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
> +	touch_pages(buf2, ALLOC_SIZE2);
> +
> +	TST_CHECKPOINT_WAKE(0);
> +
> +	pause();
> +}
> +
> +static void test_memcg_task_migration(void)
> +{
> +	long baseline_b, after_migrate, after_migrate_a, after_alloc2, current_a;
> +
> +	worker_pid = 0;
> +
> +	group_a = tst_cg_group_mk(tst_cg, "group_a");
> +	group_b = tst_cg_group_mk(tst_cg, "group_b");
> +
> +	if (SAFE_CG_HAS(tst_cg, "memory.swap.max")) {
> +		SAFE_CG_PRINT(group_a, "memory.swap.max", "0");
> +		SAFE_CG_PRINT(group_b, "memory.swap.max", "0");
> +	}
> +
> +	SAFE_CG_SCANF(group_b, "memory.current", "%ld", &baseline_b);
> +	tst_res(TINFO, "group_b baseline memory.current=%ld", baseline_b);
> +
> +	worker_pid = SAFE_FORK();
> +	if (!worker_pid) {
> +		worker();
> +		exit(0);
> +	}
> +
> +	TST_CHECKPOINT_WAIT(0);
> +
> +	SAFE_CG_SCANF(group_a, "memory.current", "%ld", &current_a);
> +	TST_EXP_LE_LU(ALLOC_SIZE, current_a);
> +
> +	SAFE_CG_PRINTF(group_b, "cgroup.procs", "%d", worker_pid);
> +	tst_res(TINFO, "Migrated worker PID %d to group_b", worker_pid);
> +
> +	SAFE_CG_SCANF(group_b, "memory.current", "%ld", &after_migrate);
> +	tst_res(TINFO,
> +		"group_b memory.current=%ld after migration (baseline=%ld)",
> +		after_migrate, baseline_b);
> +
> +	TST_EXP_LE_LU(after_migrate, baseline_b);

I do not think that it's actually guaranteed that nothing is charged in
the cgroup_b after the migration. I guess that we can use values_close()
function here.

> +	SAFE_CG_SCANF(group_a, "memory.current", "%ld", &after_migrate_a);
> +	tst_res(TINFO, "group_a memory.current=%ld after migration", after_migrate_a);
> +	TST_EXP_EXPR(after_migrate_a >= (long)ALLOC_SIZE,
> +		     "group_a memory.current (%ld) still holds pre-migration charges (>= ALLOC_SIZE %ld)",
> +		     after_migrate_a, (long)ALLOC_SIZE);
> +
> +	TST_CHECKPOINT_WAKE_AND_WAIT(0);
> +
> +	SAFE_CG_SCANF(group_b, "memory.current", "%ld", &after_alloc2);
> +	tst_res(TINFO, "group_b memory.current=%ld after second alloc (baseline=%ld)",
> +		after_alloc2, after_migrate);
> +
> +	TST_EXP_EXPR(after_alloc2 >= after_migrate + (long)ALLOC_SIZE2,
> +		     "group_b memory.current (%ld) increased by >= ALLOC_SIZE2 (%ld)",
> +		     after_alloc2, (long)ALLOC_SIZE2);

And here as well, I suppose that we can only assert that the
after_alloc2 >= ALLOC_SIZE2.

Also CCing Michal Koutny, our cgroup expert.

-- 
Cyril Hrubis
chrubis@suse.cz

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

      parent reply	other threads:[~2026-10-30 15:29 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-30 17:34 [LTP] [PATCH v7] memcg/memcontrol05: add cgroup v2 task migration charge accounting test Pavithra
2026-08-30 17:59 ` [LTP] " linuxtestproject.agent
2026-10-30 15:29 ` Cyril Hrubis [this message]

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=auS34aeU5tMadFsg@yuki.lan \
    --to=chrubis@suse.cz \
    --cc=ltp@lists.linux.it \
    --cc=mkoutny@suse.com \
    --cc=pavrampu@linux.ibm.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox