diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile index fb856d55b4..548cefac28 100644 --- a/test/zdtm/static/Makefile +++ b/test/zdtm/static/Makefile @@ -402,6 +402,7 @@ TST_DIR = \ cgroup_ignore \ cgroup_stray \ cgroup_yard \ + cgroup_threads \ unlink_fstat04 \ unlink_fstat041 \ mntns_remap \ @@ -684,6 +685,8 @@ s390x_gs_threads: LDFLAGS += -pthread thread_different_uid_gid: LDLIBS += -pthread -lcap +cgroup_threads: LDFLAGS += -pthread + bpf_hash: LDLIBS += -lbpf bpf_array: LDLIBS += -lbpf diff --git a/test/zdtm/static/cgroup_threads.c b/test/zdtm/static/cgroup_threads.c new file mode 100644 index 0000000000..6bfe049003 --- /dev/null +++ b/test/zdtm/static/cgroup_threads.c @@ -0,0 +1,157 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "zdtmtst.h" + +const char *test_doc = "Check that cgroup layout of threads is preserved"; +const char *test_author = "Michał Cłapiński "; + +char *dirname; +TEST_OPTION(dirname, string, "cgroup directory name", 1); +static const char *cgname = "zdtmtst"; +#define SUBNAME "subcg_threads" +#define SUBNAME2 SUBNAME "/subsubcg" + +static int cg_move(char *name) +{ + int cgfd, l; + char paux[256]; + + sprintf(paux, "%s/%s", dirname, name); + mkdir(paux, 0600); + + sprintf(paux, "%s/%s/tasks", dirname, name); + + cgfd = open(paux, O_WRONLY); + if (cgfd < 0) { + pr_perror("Can't open tasks"); + return -1; + } + + l = write(cgfd, "0", 2); + close(cgfd); + + if (l < 0) { + pr_perror("Can't move self to subcg"); + return -1; + } + + return 0; +} + +static int cg_check(char *name) +{ + int found = 0; + FILE *cgf; + char paux[256], aux[128]; + + cgf = fopen("/proc/thread-self/cgroup", "r"); + if (cgf == NULL) + return -1; + + sprintf(aux, "name=%s:/%s", cgname, name); + while (fgets(paux, sizeof(paux), cgf)) { + char *s; + + s = strchr(paux, ':') + 1; + s[strlen(s) - 1] = '\0'; + test_msg("CMP [%s] vs [%s]\n", s, aux); + if (!strcmp(s, aux)) { + found = 1; + break; + } + } + + fclose(cgf); + + return found ? 0 : -1; +} + +int p1[2], pr[2]; + +void *child(void *args) +{ + int status = cg_move(SUBNAME2); + write(p1[1], &status, sizeof(status)); + + if (status == 0) { + read(pr[0], &status, sizeof(status)); + + status = cg_check(SUBNAME2); + write(p1[1], &status, sizeof(status)); + } + + pthread_exit(0); +} + +int main(int argc, char **argv) +{ + char aux[64]; + int status; + pthread_t thread; + + test_init(argc, argv); + + /* + * Pipe to talk to the kid. + * First, it reports that it's ready (int), + * then it reports the restore status (int). + */ + + pipe(p1); + + /* "Restore happened" pipe */ + pipe(pr); + + if (mkdir(dirname, 0700) < 0) { + pr_perror("Can't make dir"); + goto out; + } + + sprintf(aux, "none,name=%s", cgname); + if (mount("none", dirname, "cgroup", 0, aux)) { + pr_perror("Can't mount cgroups"); + goto out_rd; + } + + if (cg_move(SUBNAME)) + goto out_rs; + + pthread_create(&thread, NULL, child, NULL); + + status = -1; + read(p1[0], &status, sizeof(status)); + if (status != 0) + goto out_ks; + + test_daemon(); + test_waitsig(); + + close(pr[1]); + + status = -1; + read(p1[0], &status, sizeof(status)); + if (status != 0) { + fail("child cg changed"); + goto out_rs; + } + + pass(); + +out_rs: + umount(dirname); +out_rd: + rmdir(dirname); +out: + return 0; + +out_ks: + pr_perror("Error moving into cgroups"); + close(pr[0]); + goto out_rs; +} diff --git a/test/zdtm/static/cgroup_threads.desc b/test/zdtm/static/cgroup_threads.desc new file mode 100644 index 0000000000..3c6c4a7e22 --- /dev/null +++ b/test/zdtm/static/cgroup_threads.desc @@ -0,0 +1 @@ +{'flavor': 'h', 'flags': 'suid', 'opts': '--manage-cgroups'} diff --git a/test/zdtm/static/cgroup_threads.hook b/test/zdtm/static/cgroup_threads.hook new file mode 100644 index 0000000000..4acfd63d98 --- /dev/null +++ b/test/zdtm/static/cgroup_threads.hook @@ -0,0 +1,20 @@ +#!/bin/bash + +[ "$1" == "--clean" -o "$1" == "--pre-restore" ] || exit 0 + +set -e + +tname=$(mktemp -d cgclean.XXXXXX) +mount -t cgroup none $tname -o "none,name=zdtmtst" + +echo "Cleaning $tname" + +set +e +rmdir "$tname/subcg_threads/subsubcg/" +rmdir "$tname/subcg_threads/" +set -e + +echo "Left there is:" +ls "$tname" +umount "$tname" +rmdir "$tname"