All of lore.kernel.org
 help / color / mirror / Atom feed
From: Richard Palethorpe <rpalethorpe@suse.de>
To: Cyril Hrubis <chrubis@suse.cz>
Cc: ltp@lists.linux.it
Subject: Re: [LTP] [PATCH v3 5/5] cgroup: Add memcontrol02
Date: Tue, 04 Jan 2022 15:26:02 +0000	[thread overview]
Message-ID: <871r1no5kd.fsf@suse.de> (raw)
In-Reply-To: <YdRhmxXqDNAV2sva@yuki>

Hello,

Cyril Hrubis <chrubis@suse.cz> writes:

>> + *
>> + * [Description]
>> + *
>> + * Conversion of second kself test in cgroup/test_memcontrol.c.
>> + *
>> + * Original description:
>> + * "This test creates a memory cgroup, allocates some anonymous memory
>> + * and some pagecache and check memory.current and some memory.stat
>> + * values."
>> + *
>> + * Note that the V1 rss and cache counters were renamed to anon and
>> + * file in V2. Besides error reporting, this test differs from the
>> + * kselftest in the following ways:
>> + *
>> + * . It supports V1.
>> + * . It writes instead of reads to fill the page cache. Because no
>> + *   pages were allocated on tmpfs.
>
> Shouldn't we actually run the test both for read/write and skip the read
> part of tmpfs?
>
> Well I guess that the pages are put into the page cache the same way
> regardless if they came from userspace write or as a request for data to
> be read from the disk, so probably not I guess.

I reckon there are a lot of ways to fill the page cache from
userland. mmap and madvise also come to mind. I don't know how many ways
there are to get/allocate a page from the page cache internally. I guess
it's possible to circumvent the accountancy.

I think for now just writing is good enough. This doesn't appear to be
the only test which measures the page cache. So I think we should look
at what the other tests do first. 

>
>> + * . It runs on most filesystems available
>> + * . On EXFAT and extN we change the margine of error between all and file
>                                            ^
> 					   margin
>> + *   memory to 50%. Because these allocate non-page-cache memory during writes.
>> + */
>> +#define _GNU_SOURCE
>> +
>> +#include <stdlib.h>
>> +#include <stdio.h>
>
> Do we really need stdio here?

Sorry, nope.

>
>> +#include "tst_test.h"
>> +#include "tst_cgroup.h"
>> +
>> +#define TMPDIR "mntdir"
>> +#define MB(x) (x << 20)
>> +
>> +static size_t page_size;
>> +static const struct tst_cgroup_group *cg_test;
>> +static int is_v1_memcg;
>> +static struct tst_cgroup_group *cg_child;
>> +static int fd;
>> +static int file_to_all_error = 10;
>> +
>> +/*
>> + * Checks if two given values differ by less than err% of their sum.
>> + */
>> +static inline int values_close(const ssize_t a,
>> +			       const ssize_t b,
>> +			       const ssize_t err)
>> +{
>> +	return labs(a - b) <= (a + b) / 100 * err;
>> +}
>
> I guess that this crude integer version works only since we allocate
> reasonable large memory sizes.

I suppose I could multiply both sides of the inequality by
100... perhaps we could even use the FPU, I hear it's quite usable in
userland. :-p

>
>> +static void alloc_anon_50M_check(void)
>> +{
>> +	const ssize_t size = MB(50);
>> +	char *buf, *ptr;
>> +	ssize_t anon, current;
>> +	const char *const anon_key_fmt = is_v1_memcg ? "rss %zd" : "anon %zd";
>> +
>> +	buf = SAFE_MALLOC(size);
>> +	for (ptr = buf; ptr < buf + size; ptr += page_size)
>> +		*ptr = 0;
>> +
>> +	SAFE_CGROUP_SCANF(cg_child, "memory.current", "%zd", &current);
>> +	TST_EXP_EXPR(current >= size,
>> +		     "(memory.current=%zd) >= (size=%zd)", current, size);
>> +
>> +	SAFE_CGROUP_LINES_SCANF(cg_child, "memory.stat", anon_key_fmt, &anon);
>> +
>> +	TST_EXP_EXPR(anon > 0, "(memory.stat.anon=%zd) > 0", anon);
>> +	TST_EXP_EXPR(values_close(size, current, 3),
>> +		     "(size=%zd) ~= (memory.stat.anon=%zd)", size, current);
>> +	TST_EXP_EXPR(values_close(anon, current, 3),
>> +		     "(memory.current=%zd) ~= (memory.stat.anon=%zd)",
>> +		     current, anon);
>> +}
>> +
>> +static void alloc_pagecache(const int fd, size_t size)
>> +{
>> +	char buf[BUFSIZ];
>> +	size_t i;
>
> We may as well fill the buffer with something so that this function will
> not trigger static analyzers.

+1
>
>> +	for (i = 0; i < size; i += sizeof(buf))
>> +		SAFE_WRITE(1, fd, buf, sizeof(buf));
>> +}
>> +
>> +static void alloc_pagecache_50M_check(void)
>> +{
>> +	const size_t size = MB(50);
>> +	size_t current, file;
>> +	const char *const file_key_fmt = is_v1_memcg ? "cache %zd" : "file %zd";
>
> This may be a global initialized in the test setup.

Is it not easier to read when set in the context it is used? Otherwise
the key name is hidden in setup.

>
>> +	TEST(open(TMPDIR"/tmpfile", O_RDWR | O_CREAT, 0600));
>> +
>> +	if (TST_RET < 0) {
>> +		if (TST_ERR == EOPNOTSUPP)
>> +			tst_brk(TCONF, "O_TMPFILE not supported by FS");
>> +
>> +		tst_brk(TBROK | TTERRNO,
>> +			"open(%s, O_TMPFILE | O_RDWR | O_EXCL", TMPDIR"/.");
>> +	}
>> +	fd = TST_RET;
>> +
>> +	SAFE_CGROUP_SCANF(cg_child, "memory.current", "%zu", &current);
>> +	tst_res(TINFO, "Created temp file: memory.current=%zu", current);
>> +
>> +	alloc_pagecache(fd, size);
>> +
>> +	SAFE_CGROUP_SCANF(cg_child, "memory.current", "%zu", &current);
>> +	TST_EXP_EXPR(current >= size,
>> +			 "(memory.current=%zu) >= (size=%zu)", current, size);
>> +
>> +	SAFE_CGROUP_LINES_SCANF(cg_child, "memory.stat", file_key_fmt, &file);
>> +	TST_EXP_EXPR(file > 0, "(memory.stat.file=%zd) > 0", file);
>> +
>> +	TST_EXP_EXPR(values_close(file, current, file_to_all_error),
>> +			 "(memory.current=%zd) ~= (memory.stat.file=%zd)",
>> +			 current, file);
>> +
>> +	SAFE_CLOSE(fd);
>> +}
>> +
>> +static void test_memcg_current(unsigned int n)
>> +{
>> +	size_t current;
>> +
>> +	cg_child = tst_cgroup_group_mk(cg_test, "child");
>> +	SAFE_CGROUP_SCANF(cg_child, "memory.current", "%zu", &current);
>> +	TST_EXP_EXPR(current == 0, "(current=%zu) == 0", current);
>> +
>> +	if (!SAFE_FORK()) {
>> +		SAFE_CGROUP_PRINTF(cg_child, "cgroup.procs", "%d", getpid());
>> +
>> +		SAFE_CGROUP_SCANF(cg_child, "memory.current", "%zu", &current);
>> +		tst_res(TINFO, "Added proc to memcg: memory.current=%zu",
>> +			current);
>> +
>> +		if (!n)
>> +			alloc_anon_50M_check();
>> +		else
>> +			alloc_pagecache_50M_check();
>> +	} else {
>> +		tst_reap_children();
>> +		cg_child = tst_cgroup_group_rm(cg_child);
>> +	}
>> +}
>> +
>> +static void setup(void)
>> +{
>> +	page_size = SAFE_SYSCONF(_SC_PAGESIZE);
>> +
>> +	tst_cgroup_require("memory", NULL);
>> +	cg_test = tst_cgroup_get_test_group();
>> +
>> +	is_v1_memcg = TST_CGROUP_VER(cg_test, "memory") == TST_CGROUP_V1;
>
> I find this statement a bit confusing, maybe TST_CGGROUP_IS_V1() and
> TST_CGROUP_IS_V2() macros in the library would make it slightly
> better.

Yeah, I suppose this is proving to be tiresome.

>
>> +	switch (tst_fs_type(TMPDIR)) {
>> +	case TST_EXFAT_MAGIC:
>> +	case TST_EXT234_MAGIC:
>> +		file_to_all_error = 50;
>> +		break;
>> +	}
>> +}
>> +
>> +static void cleanup(void)
>> +{
>> +	if (cg_child)
>> +		cg_child = tst_cgroup_group_rm(cg_child);
>> +
>> +	tst_cgroup_cleanup();
>> +}
>> +
>> +static struct tst_test test = {
>> +	.setup = setup,
>> +	.cleanup = cleanup,
>> +	.tcnt = 2,
>> +	.test = test_memcg_current,
>> +	.mount_device = 1,
>> +	.dev_min_size = 256,
>> +	.mntpoint = TMPDIR,
>> +	.all_filesystems = 1,
>> +	.forks_child = 1,
>> +	.needs_root = 1,
>> +};
>
> Generally minus typos and minor things it looks good, I guess that it
> can as well go in if you fix the typos as it is.
>
> Reviewed-by: Cyril Hrubis <chrubis@susec.cz>


-- 
Thank you,
Richard.

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

  reply	other threads:[~2022-01-04 15:59 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-04 12:20 [LTP] [PATCH v3 1/5] API/cgroup: Add safe_cgroup_lines_scanf Richard Palethorpe via ltp
2022-01-04 12:20 ` [LTP] [PATCH v3 2/5] API/cgroup: Add memory.stat Richard Palethorpe via ltp
2022-01-04 12:20 ` [LTP] [PATCH v3 3/5] API/fs: Add exfat magic Richard Palethorpe via ltp
2022-01-04 14:20   ` Cyril Hrubis
2022-01-04 12:20 ` [LTP] [PATCH v3 4/5] API: Add TST_EXP_EXPR macro Richard Palethorpe via ltp
2022-01-04 14:25   ` Cyril Hrubis
2022-01-04 12:20 ` [LTP] [PATCH v3 5/5] cgroup: Add memcontrol02 Richard Palethorpe via ltp
2022-01-04 15:02   ` Cyril Hrubis
2022-01-04 15:26     ` Richard Palethorpe [this message]
2022-01-05  5:12       ` Richard Palethorpe

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=871r1no5kd.fsf@suse.de \
    --to=rpalethorpe@suse.de \
    --cc=chrubis@suse.cz \
    --cc=ltp@lists.linux.it \
    /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.