* [LTP] [PATCH] containers: added mountns/mountns05.c @ 2014-10-30 15:07 Matus Marhefka 2014-10-30 16:01 ` Cyril Hrubis 2014-11-05 16:49 ` [LTP] [PATCH v2] " Matus Marhefka 0 siblings, 2 replies; 7+ messages in thread From: Matus Marhefka @ 2014-10-30 15:07 UTC (permalink / raw) To: ltp-list Tests a slave-shared mount: slave-shared mount makes a mountpoint both, shared and slave at the same time. Signed-off-by: Matus Marhefka <mmarhefk@redhat.com> --- runtest/containers | 1 + testcases/kernel/containers/.gitignore | 1 + testcases/kernel/containers/mountns/mountns05.c | 375 +++++++++++++++++++++ .../kernel/containers/mountns/mountns_helper.h | 4 + 4 files changed, 381 insertions(+) create mode 100644 testcases/kernel/containers/mountns/mountns05.c diff --git a/runtest/containers b/runtest/containers index 6535628..54b9fd2 100644 --- a/runtest/containers +++ b/runtest/containers @@ -67,3 +67,4 @@ mountns01 mountns01 mountns02 mountns02 mountns03 mountns03 mountns04 mountns04 +mountns05 mountns05 diff --git a/testcases/kernel/containers/.gitignore b/testcases/kernel/containers/.gitignore index 4a98373..386e211 100644 --- a/testcases/kernel/containers/.gitignore +++ b/testcases/kernel/containers/.gitignore @@ -3,3 +3,4 @@ mountns/mountns01 mountns/mountns02 mountns/mountns03 mountns/mountns04 +mountns/mountns05 diff --git a/testcases/kernel/containers/mountns/mountns05.c b/testcases/kernel/containers/mountns/mountns05.c new file mode 100644 index 0000000..d1e61aa --- /dev/null +++ b/testcases/kernel/containers/mountns/mountns05.c @@ -0,0 +1,375 @@ +/* Copyright (c) 2014 Red Hat, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of version 2 the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + *********************************************************************** + * File: mountns05.c + * + * Tests a slave-shared mount: slave-shared mount makes a mountpoint both, + * shared and slave at the same time. + * Description (X is parent namespace, Y and Z are child namespaces): + * 1. Creates directories "A", "B" and files "A/A", "B/B" + * 2. Unshares mount namespace and makes it private (so mounts/umounts + * have no effect on a real system) + * 3. Bind mounts directory "A" to "A" + * 4. Makes directory "A" shared + * 5. Clones a new child process with CLONE_NEWNS flag (creates namespace Y) + * 6. The new child (namespace Y) makes "A" a slave mount (of mount in parent + * namespace X) and also makes "A" shared inside its (Y) namespace + * 7. The new child process (namespace Y) clones a new child with CLONE_NEWNS + * flag (creates namespace Z) + * 6. There are two test cases: + * 1) + * X: bind mounts "B" to "A" + * Y: must see "A/B" + * Z: must see "A/B" + * X: umounts "A" + * 2) + * Y: bind mounts "B" to "A" + * X: must see only "A/A" - slave cannot propagate up + * Z: must see "A/B" - NS Z shares "A" with NS Y + * Y: umounts "A" + * 3) + * Z: bind mounts "B" to "A" + * X: must see only "A/A" - slave cannot propagate up + * Y: must see "A/B" - NS Y shares "A" with NS Z + * Z: umounts "A" + ***********************************************************************/ + +#define _GNU_SOURCE +#include <sys/wait.h> +#include <sys/mount.h> +#include <stdio.h> +#include <errno.h> +#include <sys/msg.h> +#include "test.h" +#include "usctest.h" +#include "libclone.h" +#include "safe_macros.h" +#include "safe_file_ops.h" +#include "mountns_helper.h" + + +#define TC1_MSG "parent: shared mount propagation to slave mount shared between two children" +#define TC2_MSG "child1: slave-shared mount inability to prapagate up to " \ + "master and ability to propagate to shared mount with child2" +#define TC3_MSG "child2: slave-shared mount inability to prapagate up to " \ + "master and ability to propagate to shared mount with child1" + +#define TESTKEY 124426L +#define TC1_OK 0x01 +#define TC2_OK 0x02 +#define TC3_OK 0x04 +#define ERRC 0x10 + +#define REPORT_PARENT_ERROR(errmsg) \ +{ \ + msgctl(id, IPC_RMID, NULL); \ + tst_brkm(TBROK | TERRNO, cleanup, errmsg); \ +} + +#define REPORT_CHLD_ERROR(errmsg) \ +{ \ + perror(errmsg); umount(DIRA); \ + msgctl(id, IPC_RMID, NULL); \ + wait(&status); return ERRC; \ +} + +char *TCID = "mountns05"; +int TST_TOTAL = 3; + + +#if defined(MS_SHARED) && defined(MS_PRIVATE) \ + && defined(MS_REC) && defined(MS_SLAVE) + +int child_func2(void *arg) +{ + int status; + int id, result = TC3_OK; + struct msgbuf m, r; + m.mtype = 3; + + id = msgget(TESTKEY, 0644); + if (id == -1) + REPORT_CHLD_ERROR("msgget"); + + /* TC#1 */ + if (msgrcv(id, &r, sizeof(r.mtext), 1, 0) == -1) + REPORT_CHLD_ERROR("msgrcv"); + + if (access(DIRA"/B", F_OK) == 0) + result |= TC1_OK; + + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) + REPORT_CHLD_ERROR("msgsnd"); + /* END OF TC#1 */ + + /* sync with parent */ + if (msgrcv(id, &r, sizeof(r.mtext), 4, 0) == -1) + REPORT_CHLD_ERROR("msgrcv"); + + /* TC#2 */ + if (msgrcv(id, &r, sizeof(r.mtext), 2, 0) == -1) + REPORT_CHLD_ERROR("msgrcv"); + + if (access(DIRA"/B", F_OK) == 0) + result |= TC2_OK; + + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) + REPORT_CHLD_ERROR("msgsnd"); + /* END OF TC#2 */ + + /* sync with parent */ + if (msgrcv(id, &r, sizeof(r.mtext), 4, 0) == -1) + REPORT_CHLD_ERROR("msgrcv"); + + /* TC#3 */ + /* bind mounts DIRB to DIRA */ + if (mount(DIRB, DIRA, "none", MS_BIND, NULL) == -1) + REPORT_CHLD_ERROR("mount"); + + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) + REPORT_CHLD_ERROR("msgsnd"); + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) + REPORT_CHLD_ERROR("msgsnd"); + + if (msgrcv(id, &r, sizeof(r.mtext), 1, 0) == -1) + REPORT_CHLD_ERROR("msgrcv"); + if (msgrcv(id, &r, sizeof(r.mtext), 2, 0) == -1) + REPORT_CHLD_ERROR("msgrcv"); + + umount(DIRA); + /* END OF TC#3 */ + + return result; +} + +int child_func1(void *arg) +{ + int status, id, result = TC2_OK; + struct msgbuf m, r; + m.mtype = 2; + + id = msgget(TESTKEY, 0644); + if (id == -1) + REPORT_CHLD_ERROR("msgget"); + + /* makes mount DIRA a slave mount (of DIRA in parent NS) */ + if (mount("none", DIRA, "none", MS_SLAVE, NULL) == -1) + REPORT_CHLD_ERROR("mount"); + + /* makes mount DIRA a shared mount inside child NS */ + if (mount("none", DIRA, "none", MS_SHARED, NULL) == -1) + REPORT_CHLD_ERROR("mount"); + + if (do_clone_tests(CLONE_NEWNS, child_func2, NULL, NULL, NULL) == -1) + REPORT_CHLD_ERROR("clone"); + + /* sync with parent*/ + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) + REPORT_CHLD_ERROR("msgsnd"); + + /* TC#1 */ + if (msgrcv(id, &r, sizeof(r.mtext), 1, 0) == -1) + REPORT_CHLD_ERROR("msgrcv"); + + if (access(DIRA"/B", F_OK) == 0) + result |= TC1_OK; + + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) + REPORT_CHLD_ERROR("msgsnd"); + /* END OF TC#1 */ + + /* sync with parent */ + if (msgrcv(id, &r, sizeof(r.mtext), 4, 0) == -1) + REPORT_CHLD_ERROR("msgrcv"); + + /* TC#2 */ + /* bind mounts DIRB to DIRA */ + if (mount(DIRB, DIRA, "none", MS_BIND, NULL) == -1) + REPORT_CHLD_ERROR("mount"); + + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) + REPORT_CHLD_ERROR("msgsnd"); + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) + REPORT_CHLD_ERROR("msgsnd"); + + if (msgrcv(id, &r, sizeof(r.mtext), 1, 0) == -1) + REPORT_CHLD_ERROR("msgrcv"); + if (msgrcv(id, &r, sizeof(r.mtext), 3, 0) == -1) + REPORT_CHLD_ERROR("msgrcv"); + + umount(DIRA); + /* END OF TC#2 */ + + /* sync with parent */ + if (msgrcv(id, &r, sizeof(r.mtext), 4, 0) == -1) + REPORT_CHLD_ERROR("msgrcv"); + + /* TC#3 */ + if (msgrcv(id, &r, sizeof(r.mtext), 3, 0) == -1) + REPORT_CHLD_ERROR("msgrcv"); + + if (access(DIRA"/B", F_OK) == 0) + result |= TC3_OK; + + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) + REPORT_CHLD_ERROR("msgsnd"); + /* END OF TC#3 */ + + wait(&status); + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) & ERRC) + return ERRC; + return (result & WEXITSTATUS(status)); + } else { + return ERRC; + } +} + +static void test(void) +{ + int status, id, result = TC1_OK; + struct msgbuf m, r, sync; + m.mtype = 1; + sync.mtype = 4; + + /* unshares the mount ns */ + if (unshare(CLONE_NEWNS) == -1) + tst_brkm(TBROK | TERRNO, cleanup, "unshare failed"); + /* makes sure parent mounts/umounts have no effect on a real system */ + SAFE_MOUNT(cleanup, "none", "/", "none", MS_REC|MS_PRIVATE, NULL); + + /* bind mounts DIRA to itself */ + SAFE_MOUNT(cleanup, DIRA, DIRA, "none", MS_BIND, NULL); + + /* makes mount DIRA shared */ + SAFE_MOUNT(cleanup, "none", DIRA, "none", MS_SHARED, NULL); + + id = msgget(TESTKEY, IPC_CREAT | 0644); + if (id == -1) + tst_brkm(TBROK | TERRNO, cleanup, "msgget"); + + if (do_clone_tests(CLONE_NEWNS, child_func1, NULL, NULL, NULL) == -1) + tst_brkm(TBROK | TERRNO, cleanup, "clone"); + + /* sync with child1 */ + if (msgrcv(id, &r, sizeof(r.mtext), 2, 0) == -1) + REPORT_PARENT_ERROR("msgrcv"); + + /* TC#1 */ + /* bind mounts DIRB to DIRA */ + SAFE_MOUNT(cleanup, DIRB, DIRA, "none", MS_BIND, NULL); + + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) + REPORT_PARENT_ERROR("msgsnd"); + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) + REPORT_PARENT_ERROR("msgsnd"); + + if (msgrcv(id, &r, sizeof(r.mtext), 2, 0) == -1) + REPORT_PARENT_ERROR("msgrcv"); + if (msgrcv(id, &r, sizeof(r.mtext), 3, 0) == -1) + REPORT_PARENT_ERROR("msgrcv"); + + SAFE_UMOUNT(cleanup, DIRA); + /* END OF TC#1 */ + + /* sync with children */ + if (msgsnd(id, &sync, sizeof(sync.mtext), 0) == -1) + REPORT_PARENT_ERROR("msgsnd"); + if (msgsnd(id, &sync, sizeof(sync.mtext), 0) == -1) + REPORT_PARENT_ERROR("msgsnd"); + + /* TC#2 */ + if (msgrcv(id, &r, sizeof(r.mtext), 2, 0) == -1) + REPORT_PARENT_ERROR("msgrcv"); + + if ((access(DIRA"/A", F_OK) == 0) && (access(DIRA"/B", F_OK) == -1)) + result |= TC2_OK; + + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) + REPORT_PARENT_ERROR("msgsnd"); + /* END OF TC#2 */ + + /* sync with children */ + if (msgsnd(id, &sync, sizeof(sync.mtext), 0) == -1) + REPORT_PARENT_ERROR("msgsnd"); + if (msgsnd(id, &sync, sizeof(sync.mtext), 0) == -1) + REPORT_PARENT_ERROR("msgsnd"); + + /* TC#3 */ + if (msgrcv(id, &r, sizeof(r.mtext), 3, 0) == -1) + REPORT_PARENT_ERROR("msgrcv"); + + if ((access(DIRA"/A", F_OK) == 0) && (access(DIRA"/B", F_OK) == -1)) + result |= TC3_OK; + + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) + REPORT_PARENT_ERROR("msgsnd"); + /* END OF TC#3 */ + + + SAFE_WAIT(cleanup, &status); + if (WIFEXITED(status)) { + result &= WEXITSTATUS(status); + if (result & ERRC) + tst_brkm(TBROK, cleanup, "error in child"); + } + if (WIFSIGNALED(status)) { + tst_resm(TBROK, "child was killed with signal %s", + tst_strsig(WTERMSIG(status))); + return; + } + + msgctl(id, IPC_RMID, NULL); + SAFE_UMOUNT(cleanup, DIRA); + + if ((result & TC1_OK) == TC1_OK) + tst_resm(TPASS, TC1_MSG); + else + tst_resm(TFAIL, TC1_MSG); + + if ((result & TC2_OK) == TC2_OK) + tst_resm(TPASS, TC2_MSG); + else + tst_resm(TFAIL, TC2_MSG); + + if ((result & TC3_OK) == TC3_OK) + tst_resm(TPASS, TC3_MSG); + else + tst_resm(TFAIL, TC3_MSG); +} + +int main(int argc, char *argv[]) +{ + const char *msg; + int lc; + + msg = parse_opts(argc, argv, NULL, NULL); + if (msg != NULL) + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); + + setup(); + + for (lc = 0; TEST_LOOPING(lc); lc++) + test(); + + cleanup(); + tst_exit(); +} + +#else +int main(void) +{ + tst_brkm(TCONF, NULL, "needed mountflags are not defined"); +} +#endif diff --git a/testcases/kernel/containers/mountns/mountns_helper.h b/testcases/kernel/containers/mountns/mountns_helper.h index d4a6a91..d82c837 100644 --- a/testcases/kernel/containers/mountns/mountns_helper.h +++ b/testcases/kernel/containers/mountns/mountns_helper.h @@ -47,6 +47,10 @@ static int check_newns(void) static void cleanup(void) { + int status; + + wait(&status); + umount(DIRA); umount(DIRA); umount(DIRB); tst_rmdir(); -- 1.8.3.1 ------------------------------------------------------------------------------ _______________________________________________ Ltp-list mailing list Ltp-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ltp-list ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [LTP] [PATCH] containers: added mountns/mountns05.c 2014-10-30 15:07 [LTP] [PATCH] containers: added mountns/mountns05.c Matus Marhefka @ 2014-10-30 16:01 ` Cyril Hrubis 2014-11-05 16:49 ` [LTP] [PATCH v2] " Matus Marhefka 1 sibling, 0 replies; 7+ messages in thread From: Cyril Hrubis @ 2014-10-30 16:01 UTC (permalink / raw) To: Matus Marhefka; +Cc: ltp-list Hi! I do not like these macros. > +#define REPORT_PARENT_ERROR(errmsg) \ > +{ \ > + msgctl(id, IPC_RMID, NULL); \ ^ This should be removed from the test cleanup. If you want to call the default cleanup defined in the header you can define second cleanup function that does specific cleanup and then calls the generic cleanup pass the right function pointers to tst_brmk() > + tst_brkm(TBROK | TERRNO, cleanup, errmsg); \ > +} > + > +#define REPORT_CHLD_ERROR(errmsg) \ > +{ \ > + perror(errmsg); umount(DIRA); \ > + msgctl(id, IPC_RMID, NULL); \ > + wait(&status); return ERRC; \ > +} Can't we do the cleanup the kenel style? i.e. if (something_failed()) { errmsg = "message"; goto err; } ... return result; err: perror(errmsg); umout(DIRA); msgclt(id, IPC_RMID, NULL); wait(&status); return ERRC; ... > diff --git a/testcases/kernel/containers/mountns/mountns_helper.h b/testcases/kernel/containers/mountns/mountns_helper.h > index d4a6a91..d82c837 100644 > --- a/testcases/kernel/containers/mountns/mountns_helper.h > +++ b/testcases/kernel/containers/mountns/mountns_helper.h > @@ -47,6 +47,10 @@ static int check_newns(void) > > static void cleanup(void) > { > + int status; > + > + wait(&status); > + umount(DIRA); > umount(DIRA); > umount(DIRB); > tst_rmdir(); This changes function called from several testcases, I guess that this is missing cleanup being added there. Maybe it should deserve to be pushed as a separate patch with description in commit message. -- Cyril Hrubis chrubis@suse.cz ------------------------------------------------------------------------------ _______________________________________________ Ltp-list mailing list Ltp-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ltp-list ^ permalink raw reply [flat|nested] 7+ messages in thread
* [LTP] [PATCH v2] containers: added mountns/mountns05.c 2014-10-30 15:07 [LTP] [PATCH] containers: added mountns/mountns05.c Matus Marhefka 2014-10-30 16:01 ` Cyril Hrubis @ 2014-11-05 16:49 ` Matus Marhefka 2014-12-02 16:42 ` Cyril Hrubis 1 sibling, 1 reply; 7+ messages in thread From: Matus Marhefka @ 2014-11-05 16:49 UTC (permalink / raw) To: ltp-list Tests a slave-shared mount: slave-shared mount makes a mountpoint both, shared and slave at the same time. Signed-off-by: Matus Marhefka <mmarhefk@redhat.com> --- runtest/containers | 1 + testcases/kernel/containers/.gitignore | 1 + testcases/kernel/containers/mountns/mountns05.c | 448 ++++++++++++++++++++++++ 3 files changed, 450 insertions(+) create mode 100644 testcases/kernel/containers/mountns/mountns05.c diff --git a/runtest/containers b/runtest/containers index 6535628..54b9fd2 100644 --- a/runtest/containers +++ b/runtest/containers @@ -67,3 +67,4 @@ mountns01 mountns01 mountns02 mountns02 mountns03 mountns03 mountns04 mountns04 +mountns05 mountns05 diff --git a/testcases/kernel/containers/.gitignore b/testcases/kernel/containers/.gitignore index 4a98373..386e211 100644 --- a/testcases/kernel/containers/.gitignore +++ b/testcases/kernel/containers/.gitignore @@ -3,3 +3,4 @@ mountns/mountns01 mountns/mountns02 mountns/mountns03 mountns/mountns04 +mountns/mountns05 diff --git a/testcases/kernel/containers/mountns/mountns05.c b/testcases/kernel/containers/mountns/mountns05.c new file mode 100644 index 0000000..a75f1bc --- /dev/null +++ b/testcases/kernel/containers/mountns/mountns05.c @@ -0,0 +1,448 @@ +/* Copyright (c) 2014 Red Hat, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of version 2 the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + *********************************************************************** + * File: mountns05.c + * + * Tests a slave-shared mount: slave-shared mount makes a mountpoint both, + * shared and slave at the same time. + * Description (X is parent namespace, Y and Z are child namespaces): + * 1. Creates directories "A", "B" and files "A/A", "B/B" + * 2. Unshares mount namespace and makes it private (so mounts/umounts + * have no effect on a real system) + * 3. Bind mounts directory "A" to "A" + * 4. Makes directory "A" shared + * 5. Clones a new child process with CLONE_NEWNS flag (creates namespace Y) + * 6. The new child (namespace Y) makes "A" a slave mount (of mount in parent + * namespace X) and also makes "A" shared inside its (Y) namespace + * 7. The new child process (namespace Y) clones a new child with CLONE_NEWNS + * flag (creates namespace Z) + * 6. There are three test cases: + * 1) + * X: bind mounts "B" to "A" + * Y: must see "A/B" + * Z: must see "A/B" + * X: umounts "A" + * 2) + * Y: bind mounts "B" to "A" + * X: must see only "A/A" - slave cannot propagate up + * Z: must see "A/B" - NS Z shares "A" with NS Y + * Y: umounts "A" + * 3) + * Z: bind mounts "B" to "A" + * X: must see only "A/A" - slave cannot propagate up + * Y: must see "A/B" - NS Y shares "A" with NS Z + * Z: umounts "A" + ***********************************************************************/ + +#define _GNU_SOURCE +#include <sys/wait.h> +#include <sys/mount.h> +#include <stdio.h> +#include <errno.h> +#include <sys/msg.h> +#include "test.h" +#include "usctest.h" +#include "libclone.h" +#include "safe_macros.h" +#include "safe_file_ops.h" +#include "mountns_helper.h" + + +#define TC1_MSG "parent: shared mount propagation to slave mount shared " \ + " between two children" +#define TC2_MSG "child1: slave-shared mount inability to prapagate up to " \ + "master and ability to propagate to shared mount with child2" +#define TC3_MSG "child2: slave-shared mount inability to prapagate up to " \ + "master and ability to propagate to shared mount with child1" + +#define TESTKEY 124426L +#define TC1_OK 0x01 +#define TC2_OK 0x02 +#define TC3_OK 0x04 +#define ERRC 0x10 + + +char *TCID = "mountns05"; +int TST_TOTAL = 3; +int id; + + +#if defined(MS_SHARED) && defined(MS_PRIVATE) \ + && defined(MS_REC) && defined(MS_SLAVE) + +int child_func2(void *arg) +{ + int result = TC3_OK; + char *errmsg; + struct msgbuf m, r; + + m.mtype = 3; + + id = msgget(TESTKEY, 0644); + if (id == -1) { + errmsg = "msgget"; + goto err; + } + + /* TC#1 */ + if (msgrcv(id, &r, sizeof(r.mtext), 1, 0) == -1) { + errmsg = "msgrcv"; + goto err; + } + + if (access(DIRA"/B", F_OK) == 0) + result |= TC1_OK; + + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) { + errmsg = "msgsnd"; + goto err; + } + /* END OF TC#1 */ + + /* sync with parent */ + if (msgrcv(id, &r, sizeof(r.mtext), 4, 0) == -1) { + errmsg = "msgrcv"; + goto err; + } + + /* TC#2 */ + if (msgrcv(id, &r, sizeof(r.mtext), 2, 0) == -1) { + errmsg = "msgrcv"; + goto err; + } + + if (access(DIRA"/B", F_OK) == 0) + result |= TC2_OK; + + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) { + errmsg = "msgsnd"; + goto err; + } + /* END OF TC#2 */ + + /* sync with parent */ + if (msgrcv(id, &r, sizeof(r.mtext), 4, 0) == -1) { + errmsg = "msgrcv"; + goto err; + } + + /* TC#3 */ + /* bind mounts DIRB to DIRA */ + if (mount(DIRB, DIRA, "none", MS_BIND, NULL) == -1) { + errmsg = "mount"; + goto err; + } + + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) { + errmsg = "msgsnd"; + goto err; + } + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) { + errmsg = "msgsnd"; + goto err; + } + + if (msgrcv(id, &r, sizeof(r.mtext), 1, 0) == -1) { + errmsg = "msgrcv"; + goto err; + } + if (msgrcv(id, &r, sizeof(r.mtext), 2, 0) == -1) { + errmsg = "msgrcv"; + goto err; + } + + umount(DIRA); + /* END OF TC#3 */ + + return result; + +err: + perror(errmsg); + umount(DIRA); + msgctl(id, IPC_RMID, NULL); + return ERRC; +} + +int child_func1(void *arg) +{ + int status, result = TC2_OK; + char *errmsg; + struct msgbuf m, r; + + m.mtype = 2; + + id = msgget(TESTKEY, 0644); + if (id == -1) { + errmsg = "msgget"; + goto err; + } + + /* makes mount DIRA a slave mount (of DIRA in parent NS) */ + if (mount("none", DIRA, "none", MS_SLAVE, NULL) == -1) { + errmsg = "mount"; + goto err; + } + + /* makes mount DIRA a shared mount inside child NS */ + if (mount("none", DIRA, "none", MS_SHARED, NULL) == -1) { + errmsg = "mount"; + goto err; + } + + if (do_clone_tests(CLONE_NEWNS, child_func2, NULL, NULL, NULL) == -1) { + errmsg = "clone"; + goto err; + } + + /* sync with parent*/ + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) { + errmsg = "msgsnd"; + goto err; + } + + /* TC#1 */ + if (msgrcv(id, &r, sizeof(r.mtext), 1, 0) == -1) { + errmsg = "msgrcv"; + goto err; + } + + if (access(DIRA"/B", F_OK) == 0) + result |= TC1_OK; + + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) { + errmsg = "msgsnd"; + goto err; + } + /* END OF TC#1 */ + + /* sync with parent */ + if (msgrcv(id, &r, sizeof(r.mtext), 4, 0) == -1) { + errmsg = "msgrcv"; + goto err; + } + + /* TC#2 */ + /* bind mounts DIRB to DIRA */ + if (mount(DIRB, DIRA, "none", MS_BIND, NULL) == -1) { + errmsg = "mount"; + goto err; + } + + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) { + errmsg = "msgsnd"; + goto err; + } + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) { + errmsg = "msgsnd"; + goto err; + } + + if (msgrcv(id, &r, sizeof(r.mtext), 1, 0) == -1) { + errmsg = "msgrcv"; + goto err; + } + if (msgrcv(id, &r, sizeof(r.mtext), 3, 0) == -1) { + errmsg = "msgrcv"; + goto err; + } + + umount(DIRA); + /* END OF TC#2 */ + + /* sync with parent */ + if (msgrcv(id, &r, sizeof(r.mtext), 4, 0) == -1) { + errmsg = "msgrcv"; + goto err; + } + + /* TC#3 */ + if (msgrcv(id, &r, sizeof(r.mtext), 3, 0) == -1) { + errmsg = "msgrcv"; + goto err; + } + + if (access(DIRA"/B", F_OK) == 0) + result |= TC3_OK; + + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) { + errmsg = "msgsnd"; + goto err; + } + /* END OF TC#3 */ + + wait(&status); + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) & ERRC) + return ERRC; + return (result & WEXITSTATUS(status)); + } else { + return ERRC; + } + +err: + perror(errmsg); + umount(DIRA); + msgctl(id, IPC_RMID, NULL); + wait(&status); + return ERRC; +} + +static void cleanup2(void) +{ + int status; + + msgctl(id, IPC_RMID, NULL); + wait(&status); + umount(DIRA); + cleanup(); +} + +static void test(void) +{ + int status, result = TC1_OK; + struct msgbuf m, r, sync; + + m.mtype = 1; + sync.mtype = 4; + + /* unshares the mount ns */ + if (unshare(CLONE_NEWNS) == -1) + tst_brkm(TBROK | TERRNO, cleanup, "unshare failed"); + /* makes sure parent mounts/umounts have no effect on a real system */ + SAFE_MOUNT(cleanup, "none", "/", "none", MS_REC|MS_PRIVATE, NULL); + + /* bind mounts DIRA to itself */ + SAFE_MOUNT(cleanup, DIRA, DIRA, "none", MS_BIND, NULL); + + /* makes mount DIRA shared */ + SAFE_MOUNT(cleanup, "none", DIRA, "none", MS_SHARED, NULL); + + id = msgget(TESTKEY, IPC_CREAT | 0644); + if (id == -1) + tst_brkm(TBROK | TERRNO, cleanup, "msgget"); + + if (do_clone_tests(CLONE_NEWNS, child_func1, NULL, NULL, NULL) == -1) + tst_brkm(TBROK | TERRNO, cleanup, "clone"); + + /* sync with child1 */ + if (msgrcv(id, &r, sizeof(r.mtext), 2, 0) == -1) + tst_brkm(TBROK | TERRNO, cleanup2, "msgrcv"); + + /* TC#1 */ + /* bind mounts DIRB to DIRA */ + SAFE_MOUNT(cleanup2, DIRB, DIRA, "none", MS_BIND, NULL); + + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) + tst_brkm(TBROK | TERRNO, cleanup2, "msgsnd"); + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) + tst_brkm(TBROK | TERRNO, cleanup2, "msgsnd"); + + if (msgrcv(id, &r, sizeof(r.mtext), 2, 0) == -1) + tst_brkm(TBROK | TERRNO, cleanup2, "msgrcv"); + if (msgrcv(id, &r, sizeof(r.mtext), 3, 0) == -1) + tst_brkm(TBROK | TERRNO, cleanup2, "msgrcv"); + + SAFE_UMOUNT(cleanup2, DIRA); + /* END OF TC#1 */ + + /* sync with children */ + if (msgsnd(id, &sync, sizeof(sync.mtext), 0) == -1) + tst_brkm(TBROK | TERRNO, cleanup2, "msgsnd"); + if (msgsnd(id, &sync, sizeof(sync.mtext), 0) == -1) + tst_brkm(TBROK | TERRNO, cleanup2, "msgsnd"); + + /* TC#2 */ + if (msgrcv(id, &r, sizeof(r.mtext), 2, 0) == -1) + tst_brkm(TBROK | TERRNO, cleanup2, "msgrcv"); + + if ((access(DIRA"/A", F_OK) == 0) && (access(DIRA"/B", F_OK) == -1)) + result |= TC2_OK; + + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) + tst_brkm(TBROK | TERRNO, cleanup2, "msgsnd"); + /* END OF TC#2 */ + + /* sync with children */ + if (msgsnd(id, &sync, sizeof(sync.mtext), 0) == -1) + tst_brkm(TBROK | TERRNO, cleanup2, "msgsnd"); + if (msgsnd(id, &sync, sizeof(sync.mtext), 0) == -1) + tst_brkm(TBROK | TERRNO, cleanup2, "msgsnd"); + + /* TC#3 */ + if (msgrcv(id, &r, sizeof(r.mtext), 3, 0) == -1) + tst_brkm(TBROK | TERRNO, cleanup2, "msgrcv"); + + if ((access(DIRA"/A", F_OK) == 0) && (access(DIRA"/B", F_OK) == -1)) + result |= TC3_OK; + + if (msgsnd(id, &m, sizeof(m.mtext), 0) == -1) + tst_brkm(TBROK | TERRNO, cleanup2, "msgsnd"); + /* END OF TC#3 */ + + + SAFE_WAIT(cleanup2, &status); + if (WIFEXITED(status)) { + result &= WEXITSTATUS(status); + if (result & ERRC) + tst_brkm(TBROK, cleanup2, "error in child"); + } + if (WIFSIGNALED(status)) { + tst_resm(TBROK, "child was killed with signal %s", + tst_strsig(WTERMSIG(status))); + return; + } + + msgctl(id, IPC_RMID, NULL); + SAFE_UMOUNT(cleanup, DIRA); + + if ((result & TC1_OK) == TC1_OK) + tst_resm(TPASS, TC1_MSG); + else + tst_resm(TFAIL, TC1_MSG); + + if ((result & TC2_OK) == TC2_OK) + tst_resm(TPASS, TC2_MSG); + else + tst_resm(TFAIL, TC2_MSG); + + if ((result & TC3_OK) == TC3_OK) + tst_resm(TPASS, TC3_MSG); + else + tst_resm(TFAIL, TC3_MSG); +} + +int main(int argc, char *argv[]) +{ + const char *msg; + int lc; + + msg = parse_opts(argc, argv, NULL, NULL); + if (msg != NULL) + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); + + setup(); + + for (lc = 0; TEST_LOOPING(lc); lc++) + test(); + + cleanup(); + tst_exit(); +} + +#else +int main(void) +{ + tst_brkm(TCONF, NULL, "needed mountflags are not defined"); +} +#endif -- 1.8.3.1 ------------------------------------------------------------------------------ _______________________________________________ Ltp-list mailing list Ltp-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ltp-list ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [LTP] [PATCH v2] containers: added mountns/mountns05.c 2014-11-05 16:49 ` [LTP] [PATCH v2] " Matus Marhefka @ 2014-12-02 16:42 ` Cyril Hrubis [not found] ` <1962544618.7994595.1417604885928.JavaMail.zimbra@redhat.com> 0 siblings, 1 reply; 7+ messages in thread From: Cyril Hrubis @ 2014-12-02 16:42 UTC (permalink / raw) To: Matus Marhefka; +Cc: ltp-list Hi! > Tests a slave-shared mount: slave-shared mount makes > a mountpoint both, shared and slave at the same time. Looking at the code I wonder why msg IPC was choosen for parent-child synchronization over the checkpoint interface? -- Cyril Hrubis chrubis@suse.cz ------------------------------------------------------------------------------ Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server from Actuate! Instantly Supercharge Your Business Reports and Dashboards with Interactivity, Sharing, Native Excel Exports, App Integration & more Get technology previously reserved for billion-dollar corporations, FREE http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk _______________________________________________ Ltp-list mailing list Ltp-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ltp-list ^ permalink raw reply [flat|nested] 7+ messages in thread
[parent not found: <1962544618.7994595.1417604885928.JavaMail.zimbra@redhat.com>]
* Re: [LTP] [PATCH v2] containers: added mountns/mountns05.c [not found] ` <1962544618.7994595.1417604885928.JavaMail.zimbra@redhat.com> @ 2014-12-17 14:10 ` Cyril Hrubis [not found] ` <5495D100.8000107@redhat.com> [not found] ` <939621071.8375320.1423670135099.JavaMail.zimbra@redhat.com> 0 siblings, 2 replies; 7+ messages in thread From: Cyril Hrubis @ 2014-12-17 14:10 UTC (permalink / raw) To: Matus Marhefka; +Cc: ltp-list Hi! > I used msg IPC because this test needs to synchronize 3 processes (parent > and 2 children) and in this case at least 6 named pipes would be needed. > So instead 6 named pipes I used only one message queue where each process > has its own message type. There are a few things I do not like about this solution: * There is a static IPC key compiled in the source - we cannot run two instances of the test at once - it may interfere with the rest of the system * There are no timeouts, if something fails the parent may end up waiting forever * The code could be shorter, it takes more than three lines to just send the notification. I guess that one of the problems is that the child processes need to signal each other, which is something that the checkpoint code wasn't written for. I think that it would be better to adapth the library so that it fits the needs that has emerged. Or write better one that fits all needs. Looking at the checkpoint code, we would need a two more functions that could be used synchronize between child processes. What about: tst_checkpoint_signal_sibling(const char *file, const int lineno, struct tst_checkpoint *checkpoint); tst_checkopint_sibling_wait(const char *file, const int lineno, struct tst_checkpoint *checkpoint); Internally we can just reuse the tst_checkpoint_child_wait() and tst_checkpoint_signal_parent() code (move it to separate static functions and add a parameter with the character to be send/received). Would that solve the problem here or are there any other obstacles? -- Cyril Hrubis chrubis@suse.cz ------------------------------------------------------------------------------ Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server from Actuate! Instantly Supercharge Your Business Reports and Dashboards with Interactivity, Sharing, Native Excel Exports, App Integration & more Get technology previously reserved for billion-dollar corporations, FREE http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk _______________________________________________ Ltp-list mailing list Ltp-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ltp-list ^ permalink raw reply [flat|nested] 7+ messages in thread
[parent not found: <5495D100.8000107@redhat.com>]
* Re: [LTP] [PATCH v2] containers: added mountns/mountns05.c [not found] ` <5495D100.8000107@redhat.com> @ 2015-01-05 12:38 ` Cyril Hrubis 0 siblings, 0 replies; 7+ messages in thread From: Cyril Hrubis @ 2015-01-05 12:38 UTC (permalink / raw) To: Jiri Jaburek; +Cc: ltp-list Hi! > May I ask why there needs to be a distinction between "parent" and > "child" embedded into the checkpoint implementation, going as far as > checking 'p' or 'c' read from FIFO? Why does it matter? > I guess it adds a little to "code safety", but also severely limits > the use cases for checkpointing. Why not simply have a "regular" mutex > lock, like ie. pthread mutexes? The distinction is unfortunately mandated by the differencies between the parent (main test process) and child (forked process). The parent is expected to prepare the testing environment and also do a cleanup and therefore uses the tst_* interface, passes the cleanup function pointer to the calls etc. The parent also includes timeout logic which ensures that the parent does not hang while waiting for children to come up. The child processes does only the some test related task and does not use the tst_ interface, exit with plain exit(), etc. The letter that is send around is different in order to enforce that the right function is called, no more no less. What this avoids, for example, is calling cleanup callback from the child process that is common mistake which leads to ugly race conditions. Note also that before commit 8c1e0b3afe4f1c4da32fe7d1b5fa9738aacacab4 any usage of tst_* interface in child processes was strongly discouraged. Maybe we can rethink the API a bit now... > Going a bit further - wouldn't it be easier to simply let the test(s) > use sysv ipc, with tstlib-created objects (IPC_PRIVATE), providing > semi-safe macros for svipc(7) functions (permitting ie. EAGAIN)? > > (or even use sysv ipc for the mutex implementation, think semtimedop(2) > instead of open_wronly_timed) I've considered that. There are a few downsides to this approach. Apart from these being global system resources the reason why I've choosen fifos over these is that they can be compiled out of kernel and there are minimal systems out there run fine without them. And while I do not care much that sysvipc tests are broken on such configuration I certainly do not want to break rest of the testcases. -- Cyril Hrubis chrubis@suse.cz ------------------------------------------------------------------------------ Dive into the World of Parallel Programming! The Go Parallel Website, sponsored by Intel and developed in partnership with Slashdot Media, is your hub for all things parallel software development, from weekly thought leadership blogs to news, videos, case studies, tutorials and more. Take a look and join the conversation now. http://goparallel.sourceforge.net _______________________________________________ Ltp-list mailing list Ltp-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ltp-list ^ permalink raw reply [flat|nested] 7+ messages in thread
[parent not found: <939621071.8375320.1423670135099.JavaMail.zimbra@redhat.com>]
* Re: [LTP] [PATCH v2] containers: added mountns/mountns05.c [not found] ` <939621071.8375320.1423670135099.JavaMail.zimbra@redhat.com> @ 2015-02-12 15:04 ` Cyril Hrubis 0 siblings, 0 replies; 7+ messages in thread From: Cyril Hrubis @ 2015-02-12 15:04 UTC (permalink / raw) To: Matus Marhefka; +Cc: ltp-list Hi! > >There are a few things I do not like about this solution: > > > >* There is a static IPC key compiled in the source > > - we cannot run two instances of the test at once > > - it may interfere with the rest of the system > > Agree on that, I should rewrite it to use ftok() to get a key. ftok() on a a path under tst_tmpdir() should be reasonably random, but still it's a global resource... > > > >* There are no timeouts, if something fails the parent may end up > > waiting forever > > > > This shouldn't happen as whole code contains error checking. If something > fails it also removes the message queue and according to the man page removing > the message queue also does "awakening all waiting reader and writer processes > (with an error return and errno set to EIDRM)". Missed that. This should work fine in this case. > >Internally we can just reuse the tst_checkpoint_child_wait() and > >tst_checkpoint_signal_parent() code (move it to separate static > >functions and add a parameter with the character to be send/received). > > > >Would that solve the problem here or are there any other obstacles? > > > > In this case 3 pipes would have to be used anyway. The solution > with only one sysv message queue seems just better at least for me > plus it's just for this one specific test case. I've sumarized my points in: https://sourceforge.net/p/ltp/mailman/message/33204261/ The major point is to avoid sysv ipc in testcases that does not test sysv ipc. But we may be able to build something better than fifos with POSIX shared memory (shm_open()) and futexes. I've looked into this recently. The code would be quite easy to write as all we need is a page of shared memory that would provide space for 128 futexes and implementing timeouts is as easy as passing struct timespec to the FUTEX_WAIT function. So we will have one init function to create shared memory page and then a pair of wait and wake functions with an offset to the page (selects which futex to wait for). The only scenario that would be a bit more complicated is the case where code that waits is needed after exec(). For this case we need to open and map the same shared memory segment, i.e. need to know the name to pass to the shm_open() but we can pass it to the child as a parameter. I will try to prototype the code and test it on older distributions hopefully soon enough. -- Cyril Hrubis chrubis@suse.cz ------------------------------------------------------------------------------ Dive into the World of Parallel Programming. The Go Parallel Website, sponsored by Intel and developed in partnership with Slashdot Media, is your hub for all things parallel software development, from weekly thought leadership blogs to news, videos, case studies, tutorials and more. Take a look and join the conversation now. http://goparallel.sourceforge.net/ _______________________________________________ Ltp-list mailing list Ltp-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ltp-list ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2015-02-12 15:04 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-10-30 15:07 [LTP] [PATCH] containers: added mountns/mountns05.c Matus Marhefka
2014-10-30 16:01 ` Cyril Hrubis
2014-11-05 16:49 ` [LTP] [PATCH v2] " Matus Marhefka
2014-12-02 16:42 ` Cyril Hrubis
[not found] ` <1962544618.7994595.1417604885928.JavaMail.zimbra@redhat.com>
2014-12-17 14:10 ` Cyril Hrubis
[not found] ` <5495D100.8000107@redhat.com>
2015-01-05 12:38 ` Cyril Hrubis
[not found] ` <939621071.8375320.1423670135099.JavaMail.zimbra@redhat.com>
2015-02-12 15:04 ` Cyril Hrubis
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox