linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Michal Koutný" <mkoutny@suse.com>
To: cgroups@vger.kernel.org
Cc: alex.shi@linux.alibaba.com, guro@fb.com, hannes@cmpxchg.org,
	kernel-team@android.com, linger.lee@mediatek.com,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org,
	linux-mediatek@lists.infradead.org, lizefan@huawei.com,
	matthias.bgg@gmail.com, shuah@kernel.org, surenb@google.com,
	tj@kernel.org, tomcherry@google.com
Subject: [PATCH v2 3/3] kselftest/cgroup: add cgroup destruction test
Date: Fri, 24 Jan 2020 12:40:17 +0100	[thread overview]
Message-ID: <20200124114017.8363-4-mkoutny@suse.com> (raw)
In-Reply-To: <20200124114017.8363-1-mkoutny@suse.com>

From: Suren Baghdasaryan <surenb@google.com>

Add new test to verify that a cgroup with dead processes can be destroyed.
The test spawns a child process which allocates and touches 100MB of RAM
to ensure prolonged exit. Subsequently it kills the child, waits until
the cgroup containing the child is empty and destroys the cgroup.

Signed-off-by: Suren Baghdasaryan <surenb@google.com>
[mkoutny@suse.com: Fix typo in test_cgcore_destroy comment]
Acked-by: Michal Koutný <mkoutny@suse.com>
Signed-off-by: Michal Koutný <mkoutny@suse.com>
---
 tools/testing/selftests/cgroup/test_core.c | 113 +++++++++++++++++++++
 1 file changed, 113 insertions(+)

diff --git a/tools/testing/selftests/cgroup/test_core.c b/tools/testing/selftests/cgroup/test_core.c
index c5ca669feb2b..76c9dd578ba5 100644
--- a/tools/testing/selftests/cgroup/test_core.c
+++ b/tools/testing/selftests/cgroup/test_core.c
@@ -2,7 +2,10 @@
 
 #include <linux/limits.h>
 #include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
 #include <unistd.h>
+#include <fcntl.h>
 #include <stdio.h>
 #include <errno.h>
 #include <signal.h>
@@ -12,6 +15,115 @@
 #include "../kselftest.h"
 #include "cgroup_util.h"
 
+static int touch_anon(char *buf, size_t size)
+{
+	int fd;
+	char *pos = buf;
+
+	fd = open("/dev/urandom", O_RDONLY);
+	if (fd < 0)
+		return -1;
+
+	while (size > 0) {
+		ssize_t ret = read(fd, pos, size);
+
+		if (ret < 0) {
+			if (errno != EINTR) {
+				close(fd);
+				return -1;
+			}
+		} else {
+			pos += ret;
+			size -= ret;
+		}
+	}
+	close(fd);
+
+	return 0;
+}
+
+static int alloc_and_touch_anon_noexit(const char *cgroup, void *arg)
+{
+	int ppid = getppid();
+	size_t size = (size_t)arg;
+	void *buf;
+
+	buf = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON,
+		   0, 0);
+	if (buf == MAP_FAILED)
+		return -1;
+
+	if (touch_anon((char *)buf, size)) {
+		munmap(buf, size);
+		return -1;
+	}
+
+	while (getppid() == ppid)
+		sleep(1);
+
+	munmap(buf, size);
+	return 0;
+}
+
+/*
+ * Create a child process that allocates and touches 100MB, then waits to be
+ * killed. Wait until the child is attached to the cgroup, kill all processes
+ * in that cgroup and wait until "cgroup.procs" is empty. At this point try to
+ * destroy the empty cgroup. The test helps detect race conditions between
+ * dying processes leaving the cgroup and cgroup destruction path.
+ */
+static int test_cgcore_destroy(const char *root)
+{
+	int ret = KSFT_FAIL;
+	char *cg_test = NULL;
+	int child_pid;
+	char buf[PAGE_SIZE];
+
+	cg_test = cg_name(root, "cg_test");
+
+	if (!cg_test)
+		goto cleanup;
+
+	for (int i = 0; i < 10; i++) {
+		if (cg_create(cg_test))
+			goto cleanup;
+
+		child_pid = cg_run_nowait(cg_test, alloc_and_touch_anon_noexit,
+					  (void *) MB(100));
+
+		if (child_pid < 0)
+			goto cleanup;
+
+		/* wait for the child to enter cgroup */
+		if (cg_wait_for_proc_count(cg_test, 1))
+			goto cleanup;
+
+		if (cg_killall(cg_test))
+			goto cleanup;
+
+		/* wait for cgroup to be empty */
+		while (1) {
+			if (cg_read(cg_test, "cgroup.procs", buf, sizeof(buf)))
+				goto cleanup;
+			if (buf[0] == '\0')
+				break;
+			usleep(1000);
+		}
+
+		if (rmdir(cg_test))
+			goto cleanup;
+
+		if (waitpid(child_pid, NULL, 0) < 0)
+			goto cleanup;
+	}
+	ret = KSFT_PASS;
+cleanup:
+	if (cg_test)
+		cg_destroy(cg_test);
+	free(cg_test);
+	return ret;
+}
+
 /*
  * A(0) - B(0) - C(1)
  *        \ D(0)
@@ -512,6 +624,7 @@ struct corecg_test {
 	T(test_cgcore_populated),
 	T(test_cgcore_proc_migration),
 	T(test_cgcore_thread_migration),
+	T(test_cgcore_destroy),
 };
 #undef T
 
-- 
2.24.1


  parent reply	other threads:[~2020-01-24 11:40 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-16  4:36 [PATCH 1/2] cgroup: allow deletion of cgroups containing only dying processes Suren Baghdasaryan
2020-01-16  4:36 ` [PATCH 2/2] kselftest/cgroup: add cgroup destruction test Suren Baghdasaryan
2020-01-17 15:15 ` [PATCH 0/3] cgroup: Iterate tasks that did not finish do_exit() Michal Koutný
2020-01-17 15:15   ` [PATCH 1/3] cgroup: Unify css_set task lists Michal Koutný
2020-01-17 16:59     ` Tejun Heo
2020-01-17 15:15   ` [PATCH 2/3] cgroup: Iterate tasks that did not finish do_exit() Michal Koutný
2020-01-17 17:28     ` Tejun Heo
2020-01-17 18:41       ` Suren Baghdasaryan
2020-01-20 14:56         ` Michal Koutný
2020-01-24 11:40           ` [PATCH v2 0/3] " Michal Koutný
2020-01-24 11:40             ` [PATCH v2 1/3] " Michal Koutný
2020-01-24 22:56               ` Suren Baghdasaryan
2020-02-05 17:27                 ` Suren Baghdasaryan
2020-02-12 22:03               ` Tejun Heo
2020-01-24 11:40             ` [PATCH v2 2/3] cgroup: Clean up css_set task traversal Michal Koutný
2020-01-24 11:40             ` Michal Koutný [this message]
2020-02-12 22:10               ` [PATCH v2 3/3] kselftest/cgroup: add cgroup destruction test Tejun Heo
2020-01-17 15:15   ` [PATCH " Michal Koutný
2020-01-17 17:30   ` [PATCH 0/3] cgroup: Iterate tasks that did not finish do_exit() Suren Baghdasaryan

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=20200124114017.8363-4-mkoutny@suse.com \
    --to=mkoutny@suse.com \
    --cc=alex.shi@linux.alibaba.com \
    --cc=cgroups@vger.kernel.org \
    --cc=guro@fb.com \
    --cc=hannes@cmpxchg.org \
    --cc=kernel-team@android.com \
    --cc=linger.lee@mediatek.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-mediatek@lists.infradead.org \
    --cc=lizefan@huawei.com \
    --cc=matthias.bgg@gmail.com \
    --cc=shuah@kernel.org \
    --cc=surenb@google.com \
    --cc=tj@kernel.org \
    --cc=tomcherry@google.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;
as well as URLs for NNTP newsgroup(s).