* [LTP] [PATCH 1/2] lib: Add library functions to check specified cgroup subsystem
@ 2019-01-28 5:54 Xiao Yang
2019-01-28 5:54 ` [LTP] [PATCH 2/2] syscalls/madvise09.c: Use " Xiao Yang
2019-01-28 16:12 ` [LTP] [PATCH 1/2] lib: Add " Cyril Hrubis
0 siblings, 2 replies; 3+ messages in thread
From: Xiao Yang @ 2019-01-28 5:54 UTC (permalink / raw)
To: ltp
1) Check if specified cgroup subsystem is supported.
2) Check if specified cgroup subsystem is mounted by default, and use
custom mountpoint as the cgroup subsystem's mountpoint properly.
3) Add doc for these library functions.
Signed-off-by: Xiao Yang <yangx.jy@cn.fujitsu.com>
---
doc/test-writing-guidelines.txt | 45 +++++++++++++++++
include/tst_cgroups.h | 13 +++++
lib/tst_cgroups.c | 107 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 165 insertions(+)
create mode 100644 include/tst_cgroups.h
create mode 100644 lib/tst_cgroups.c
diff --git a/doc/test-writing-guidelines.txt b/doc/test-writing-guidelines.txt
index 731be76..57ae6aa 100644
--- a/doc/test-writing-guidelines.txt
+++ b/doc/test-writing-guidelines.txt
@@ -1539,6 +1539,51 @@ static struct tst_test test = {
};
-------------------------------------------------------------------------------
+2.2.29 Parsing specified cgroup subsystem
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+void tst_set_cgroup_mntpoint(char *subsys_name, char *spec_mntpoint);
+void tst_umount_cgroup(char *spec_mntpoint);
+
+The 'tst_set_cgroup_mntpoint()' function checks if 'subsys_name' (i.e. specified
+cgroup subsystem) is supported and mounted by default, and uses 'spec_mntpoint'
+(custom mountpoint) as 'subsys_name' mountpoint to test. For details:
+1) It exits with TCONF if 'subsys_name' is not supported.
+2) If 'subsys_name' is already mounted to a mountpoint, it creates a symlink
+ named by 'spec_mntpoint' to the pre-existent mountpoint.
+3) If 'subsys_name' is not mounted, it mounts 'subsys_name' to 'spec_mntpoint'.
+
+The 'tst_umount_cgroup()' function unmounts and removes 'spec_mntpoint'.
+
+Note:
+We should set .needs_tmpdir flag because we create 'spec_mntpoint' in tmpdir.
+
+[source,c]
+-------------------------------------------------------------------------------
+#include "tst_test.h"
+#include "tst_cgroups.h"
+
+static void setup(void)
+{
+ ...
+ tst_set_cgroups_mntpoint("memory", "mntpoint");
+ ...
+}
+
+static void cleanup(void)
+{
+ ...
+ tst_umount_cgroup("mntpoint");
+ ...
+}
+
+sturct tst_test test = {
+ ...
+ .setup = setup,
+ .cleanup = cleanup,
+ ...
+};
+-------------------------------------------------------------------------------
2.3 Writing a testcase in shell
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/include/tst_cgroups.h b/include/tst_cgroups.h
new file mode 100644
index 0000000..70f5d18
--- /dev/null
+++ b/include/tst_cgroups.h
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2019 FUJITSU LIMITED. All rights reserved.
+ * Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
+ */
+
+#ifndef TST_CGROUPS_H__
+#define TST_CGROUPS_H__
+
+void tst_set_cgroup_mntpoint(char *subsys_name, char *spec_mntpoint);
+void tst_umount_cgroup(char *spec_mntpoint);
+
+#endif /* TST_CGROUPS_H__ */
diff --git a/lib/tst_cgroups.c b/lib/tst_cgroups.c
new file mode 100644
index 0000000..dd027c5
--- /dev/null
+++ b/lib/tst_cgroups.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2019 FUJITSU LIMITED. All rights reserved.
+ * Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <mntent.h>
+
+#define TST_NO_DEFAULT_MAIN
+#include "tst_test.h"
+#include "tst_safe_stdio.h"
+
+#define CGROUPS_PATH "/proc/cgroups"
+#define MOUNTS_PATH "/proc/mounts"
+
+static char *cgroup_mntpoint;
+static int cgroup_mounted;
+
+void tst_umount_cgroup(char *spec_mntpoint)
+{
+ char buf[1024];
+
+ if (cgroup_mntpoint) {
+ if (!access(spec_mntpoint, F_OK))
+ SAFE_UNLINK(spec_mntpoint);
+ return;
+ }
+
+ if (cgroup_mounted) {
+ /* 'spec_mntpoint' may be treated as source instead
+ * of target, so append '/' to 'spec_mntpoint'. See
+ * ltp commit 4617249 for details.
+ */
+ sprintf(buf, "%s/", spec_mntpoint);
+ SAFE_UMOUNT(buf);
+ cgroup_mounted = 0;
+ }
+
+ if (!access(spec_mntpoint, F_OK))
+ SAFE_RMDIR(spec_mntpoint);
+}
+
+void tst_set_cgroup_mntpoint(char *subsys_name, char *spec_mntpoint)
+{
+ FILE *fp = NULL, *mp = NULL;
+ struct mntent *mnt;
+ char buf[1024], name[64];
+ int enabled = 0, supported = 0;
+
+ if (access(CGROUPS_PATH, F_OK))
+ tst_brk(TCONF, "Kernel didn't support for control groups");
+
+ fp = SAFE_FOPEN(CGROUPS_PATH, "r");
+
+ while (fgets(buf, 1024, fp)) {
+ if (sscanf(buf, "%s %*d %*d %d", name, &enabled) == -1) {
+ SAFE_FCLOSE(fp);
+ tst_brk(TBROK | TERRNO,
+ "sscanf() failed to read %s info",
+ subsys_name);
+ }
+
+ if (!strcmp(name, subsys_name)) {
+ supported++;
+ break;
+ }
+ }
+
+ SAFE_FCLOSE(fp);
+
+ if (!supported || !enabled) {
+ tst_brk(TCONF,
+ "%s wasn't supported by kernel or it wasn't enabled",
+ subsys_name);
+ }
+
+ mp = setmntent(MOUNTS_PATH, "r");
+ if (mp == NULL) {
+ tst_brk(TBROK | TERRNO,
+ "setmntent() failed to open /proc/mounts");
+ }
+
+ while ((mnt = getmntent(mp))) {
+ if (hasmntopt(mnt, subsys_name)) {
+ cgroup_mntpoint = mnt->mnt_dir;
+ break;
+ }
+ }
+
+ endmntent(mp);
+
+ if (cgroup_mntpoint) {
+ /* Use pre-existent subsys mountpoint and creat a symlink
+ * named by spec_mntpoint to it.
+ */
+ SAFE_SYMLINK(cgroup_mntpoint, spec_mntpoint);
+ } else {
+ /* Mount subsys to spec_mntpoint. */
+ SAFE_MKDIR(spec_mntpoint, 0777);
+ SAFE_MOUNT("none", spec_mntpoint, "cgroup", 0, subsys_name);
+ cgroup_mounted = 1;
+ }
+}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [LTP] [PATCH 2/2] syscalls/madvise09.c: Use library functions to check specified cgroup subsystem
2019-01-28 5:54 [LTP] [PATCH 1/2] lib: Add library functions to check specified cgroup subsystem Xiao Yang
@ 2019-01-28 5:54 ` Xiao Yang
2019-01-28 16:12 ` [LTP] [PATCH 1/2] lib: Add " Cyril Hrubis
1 sibling, 0 replies; 3+ messages in thread
From: Xiao Yang @ 2019-01-28 5:54 UTC (permalink / raw)
To: ltp
1) Apply tst_set_cgroup_mntpoint() and tst_umount_cgroup().
2) Remove redundant '/'.
3) Add and use dir_cleanup() in run().
Signed-off-by: Xiao Yang <yangx.jy@cn.fujitsu.com>
---
testcases/kernel/syscalls/madvise/madvise09.c | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/testcases/kernel/syscalls/madvise/madvise09.c b/testcases/kernel/syscalls/madvise/madvise09.c
index f744405..4aaf1db 100644
--- a/testcases/kernel/syscalls/madvise/madvise09.c
+++ b/testcases/kernel/syscalls/madvise/madvise09.c
@@ -56,8 +56,9 @@
#include "tst_test.h"
#include "lapi/mmap.h"
+#include "tst_cgroups.h"
-#define MEMCG_PATH "/sys/fs/cgroup/memory/"
+#define MEMCG_PATH "test_memcg"
static char cgroup_path[PATH_MAX];
static char tasks_path[PATH_MAX];
@@ -105,7 +106,7 @@ static void memory_pressure_child(void)
static void setup_cgroup_paths(int pid)
{
snprintf(cgroup_path, sizeof(cgroup_path),
- MEMCG_PATH "ltp_madvise09_%i/", pid);
+ MEMCG_PATH "/ltp_madvise09_%i", pid);
snprintf(tasks_path, sizeof(tasks_path), "%s/tasks", cgroup_path);
snprintf(limit_in_bytes_path, sizeof(limit_in_bytes_path),
"%s/memory.limit_in_bytes", cgroup_path);
@@ -273,12 +274,19 @@ static void child(void)
exit(0);
}
-static void cleanup(void)
+static void dir_cleanup(void)
{
if (cgroup_path[0] && !access(cgroup_path, F_OK))
rmdir(cgroup_path);
}
+static void cleanup(void)
+{
+ dir_cleanup();
+
+ tst_umount_cgroup(MEMCG_PATH);
+}
+
static void run(void)
{
pid_t pid;
@@ -294,7 +302,7 @@ retry:
setup_cgroup_paths(pid);
SAFE_WAIT(&status);
- cleanup();
+ dir_cleanup();
/*
* Rarely cgroup OOM kills both children not only the one that allocates
@@ -316,10 +324,7 @@ static void setup(void)
{
long int swap_total;
- if (access(MEMCG_PATH, F_OK)) {
- tst_brk(TCONF, "'" MEMCG_PATH
- "' not present, CONFIG_MEMCG missing?");
- }
+ tst_set_cgroup_mntpoint("memory", MEMCG_PATH);
if (!access(MEMCG_PATH "memory.memsw.limit_in_bytes", F_OK))
swap_accounting_enabled = 1;
@@ -339,4 +344,5 @@ static struct tst_test test = {
.test_all = run,
.needs_root = 1,
.forks_child = 1,
+ .needs_tmpdir = 1,
};
--
1.8.3.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [LTP] [PATCH 1/2] lib: Add library functions to check specified cgroup subsystem
2019-01-28 5:54 [LTP] [PATCH 1/2] lib: Add library functions to check specified cgroup subsystem Xiao Yang
2019-01-28 5:54 ` [LTP] [PATCH 2/2] syscalls/madvise09.c: Use " Xiao Yang
@ 2019-01-28 16:12 ` Cyril Hrubis
1 sibling, 0 replies; 3+ messages in thread
From: Cyril Hrubis @ 2019-01-28 16:12 UTC (permalink / raw)
To: ltp
Hi!
> 1) Check if specified cgroup subsystem is supported.
> 2) Check if specified cgroup subsystem is mounted by default, and use
> custom mountpoint as the cgroup subsystem's mountpoint properly.
> 3) Add doc for these library functions.
>
> Signed-off-by: Xiao Yang <yangx.jy@cn.fujitsu.com>
> ---
> doc/test-writing-guidelines.txt | 45 +++++++++++++++++
> include/tst_cgroups.h | 13 +++++
> lib/tst_cgroups.c | 107 ++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 165 insertions(+)
> create mode 100644 include/tst_cgroups.h
> create mode 100644 lib/tst_cgroups.c
>
> diff --git a/doc/test-writing-guidelines.txt b/doc/test-writing-guidelines.txt
> index 731be76..57ae6aa 100644
> --- a/doc/test-writing-guidelines.txt
> +++ b/doc/test-writing-guidelines.txt
> @@ -1539,6 +1539,51 @@ static struct tst_test test = {
> };
> -------------------------------------------------------------------------------
>
> +2.2.29 Parsing specified cgroup subsystem
> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> +
> +void tst_set_cgroup_mntpoint(char *subsys_name, char *spec_mntpoint);
This function name is a bit misleading as it actually mounts the cgroup.
> +void tst_umount_cgroup(char *spec_mntpoint);
> +
> +The 'tst_set_cgroup_mntpoint()' function checks if 'subsys_name' (i.e. specified
> +cgroup subsystem) is supported and mounted by default, and uses 'spec_mntpoint'
> +(custom mountpoint) as 'subsys_name' mountpoint to test. For details:
> +1) It exits with TCONF if 'subsys_name' is not supported.
> +2) If 'subsys_name' is already mounted to a mountpoint, it creates a symlink
> + named by 'spec_mntpoint' to the pre-existent mountpoint.
> +3) If 'subsys_name' is not mounted, it mounts 'subsys_name' to 'spec_mntpoint'.
> +
> +The 'tst_umount_cgroup()' function unmounts and removes 'spec_mntpoint'.
> +
> +Note:
> +We should set .needs_tmpdir flag because we create 'spec_mntpoint' in tmpdir.
Generally this is a great step forward but what this is missing:
* Automatic cleanup, if tests creates any subdirectories in the cgroup
filesystem these will stay there until the machine is rebooted
I guess that it will be much easier to create the interface so that it
returns a path to a newly created subdirectory in the cgroup
filesystem tree so that we can remove it recursively later on
* Interface in tst_test structure. I suppose that we may add something
as const char *needs_cgroup; to the tst_test structure which would
be set to subsystem name such as:
static struct tst_test test = {
...
.needs_cgroup = "memory",
...
};
And the test will then set const char *tst_cgroup_path pointer to the
actuall path to the cgroup.
* I do wonder if we will nedd support for more than one cgroup type
later on, but so far I do not see that need so keeping it as an
interface for a single subsytem type will suffice.
> +[source,c]
> +-------------------------------------------------------------------------------
> +#include "tst_test.h"
> +#include "tst_cgroups.h"
> +
> +static void setup(void)
> +{
> + ...
> + tst_set_cgroups_mntpoint("memory", "mntpoint");
> + ...
> +}
> +
> +static void cleanup(void)
> +{
> + ...
> + tst_umount_cgroup("mntpoint");
> + ...
> +}
> +
> +sturct tst_test test = {
> + ...
> + .setup = setup,
> + .cleanup = cleanup,
> + ...
> +};
> +-------------------------------------------------------------------------------
>
> 2.3 Writing a testcase in shell
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> diff --git a/include/tst_cgroups.h b/include/tst_cgroups.h
> new file mode 100644
> index 0000000..70f5d18
> --- /dev/null
> +++ b/include/tst_cgroups.h
> @@ -0,0 +1,13 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2019 FUJITSU LIMITED. All rights reserved.
> + * Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
> + */
> +
> +#ifndef TST_CGROUPS_H__
> +#define TST_CGROUPS_H__
> +
> +void tst_set_cgroup_mntpoint(char *subsys_name, char *spec_mntpoint);
> +void tst_umount_cgroup(char *spec_mntpoint);
> +
> +#endif /* TST_CGROUPS_H__ */
> diff --git a/lib/tst_cgroups.c b/lib/tst_cgroups.c
> new file mode 100644
> index 0000000..dd027c5
> --- /dev/null
> +++ b/lib/tst_cgroups.c
> @@ -0,0 +1,107 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2019 FUJITSU LIMITED. All rights reserved.
> + * Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
> + */
> +
> +#include <errno.h>
> +#include <unistd.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <mntent.h>
> +
> +#define TST_NO_DEFAULT_MAIN
> +#include "tst_test.h"
> +#include "tst_safe_stdio.h"
> +
> +#define CGROUPS_PATH "/proc/cgroups"
> +#define MOUNTS_PATH "/proc/mounts"
> +
> +static char *cgroup_mntpoint;
> +static int cgroup_mounted;
> +
> +void tst_umount_cgroup(char *spec_mntpoint)
> +{
> + char buf[1024];
> +
> + if (cgroup_mntpoint) {
> + if (!access(spec_mntpoint, F_OK))
> + SAFE_UNLINK(spec_mntpoint);
> + return;
> + }
> +
> + if (cgroup_mounted) {
> + /* 'spec_mntpoint' may be treated as source instead
> + * of target, so append '/' to 'spec_mntpoint'. See
> + * ltp commit 4617249 for details.
> + */
> + sprintf(buf, "%s/", spec_mntpoint);
> + SAFE_UMOUNT(buf);
> + cgroup_mounted = 0;
> + }
> +
> + if (!access(spec_mntpoint, F_OK))
> + SAFE_RMDIR(spec_mntpoint);
> +}
> +
> +void tst_set_cgroup_mntpoint(char *subsys_name, char *spec_mntpoint)
> +{
> + FILE *fp = NULL, *mp = NULL;
> + struct mntent *mnt;
> + char buf[1024], name[64];
> + int enabled = 0, supported = 0;
> +
> + if (access(CGROUPS_PATH, F_OK))
> + tst_brk(TCONF, "Kernel didn't support for control groups");
> +
> + fp = SAFE_FOPEN(CGROUPS_PATH, "r");
> +
> + while (fgets(buf, 1024, fp)) {
> + if (sscanf(buf, "%s %*d %*d %d", name, &enabled) == -1) {
> + SAFE_FCLOSE(fp);
> + tst_brk(TBROK | TERRNO,
> + "sscanf() failed to read %s info",
> + subsys_name);
> + }
> +
> + if (!strcmp(name, subsys_name)) {
> + supported++;
> + break;
> + }
> + }
> +
> + SAFE_FCLOSE(fp);
> +
> + if (!supported || !enabled) {
> + tst_brk(TCONF,
> + "%s wasn't supported by kernel or it wasn't enabled",
> + subsys_name);
> + }
> +
> + mp = setmntent(MOUNTS_PATH, "r");
> + if (mp == NULL) {
> + tst_brk(TBROK | TERRNO,
> + "setmntent() failed to open /proc/mounts");
> + }
> +
> + while ((mnt = getmntent(mp))) {
> + if (hasmntopt(mnt, subsys_name)) {
> + cgroup_mntpoint = mnt->mnt_dir;
> + break;
> + }
> + }
> +
> + endmntent(mp);
> +
> + if (cgroup_mntpoint) {
> + /* Use pre-existent subsys mountpoint and creat a symlink
> + * named by spec_mntpoint to it.
> + */
> + SAFE_SYMLINK(cgroup_mntpoint, spec_mntpoint);
> + } else {
> + /* Mount subsys to spec_mntpoint. */
> + SAFE_MKDIR(spec_mntpoint, 0777);
> + SAFE_MOUNT("none", spec_mntpoint, "cgroup", 0, subsys_name);
> + cgroup_mounted = 1;
> + }
> +}
> --
> 1.8.3.1
>
>
>
--
Cyril Hrubis
chrubis@suse.cz
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2019-01-28 16:12 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-01-28 5:54 [LTP] [PATCH 1/2] lib: Add library functions to check specified cgroup subsystem Xiao Yang
2019-01-28 5:54 ` [LTP] [PATCH 2/2] syscalls/madvise09.c: Use " Xiao Yang
2019-01-28 16:12 ` [LTP] [PATCH 1/2] lib: Add " Cyril Hrubis
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox