: eclone-1: Test basic functionality
PATCH 1/1 : eclone-1: Test basic functionality
From: Sukadev Bhattiprolu <[email protected]>
Date: Sat, 30 Jan 2010 12:49:30 -0800
Subject: [PATCH 1/6] eclone-1: Test basic functionality
Verify that a child process gets the expected pid and arguments on stack when it is created with eclone() system call.
NOTE: The myclone() function in eclone-lib.c supports just x86 for now.
Needs to be ported to other architectures.
--- Makefile | 2 +- eclone/Makefile | 16 +++++++ eclone/clone_args.h | 37 ++++++++++++++++ eclone/eclone-1.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++ eclone/eclone-lib.c | 85 ++++++++++++++++++++++++++++++++++++ 5 files changed, 260 insertions(+), 1 deletions(-) create mode 100644 eclone/Makefile create mode 100644 eclone/clone_args.h create mode 100644 eclone/eclone-1.c create mode 100644 eclone/eclone-lib.c
Makefile +1 -1
@@ -1,5 +1,5 @@ SUBDIRS = libcrtest counterloop fileio simple userns ipc sleep \ - process-tree futex epoll taskfs + process-tree futex epoll taskfs eclone targets = ns_exec mysu
eclone/Makefile new file +16 -0
@@ -0,0 +1,16 @@ + +CFLAGS = -Wall + +LDFLAGS = + +PROGS = eclone-1 + +all: $(PROGS) + +eclone-lib.o: eclone-lib.c clone_args.h + +$(PROGS): %: %.c eclone-lib.o + $(CC) $(CFLAGS) -o $@ $< eclone-lib.o $(LDFLAGS) + +clean: + rm -f $(PROGS) eclone-lib.o
eclone/clone_args.h new file +37 -0
@@ -0,0 +1,37 @@ +#include <errno.h> + +#define __NR_clone_with_pids 337 +#define __NR_clone3 337 +#define __NR_eclone 337 +#define __NR_clone 120 +#define __NR_exit 1 +#define __NR_getpid 20 + +#define CLONE_NEWPID 0x20000000 +#define CLONE_CHILD_SETTID 0x01000000 +#define CLONE_PARENT_SETTID 0x00100000 +#define CLONE_UNUSED 0x00001000 + +#define STACKSIZE 8192 + +typedef unsigned long long u64 ; +typedef unsigned int u32 ; +typedef int pid_t ; +struct clone_args { +u64 clone_flags_high; + +u64 child_stack_base; +u64 child_stack_size; + +u64 parent_tid_ptr; +u64 child_tid_ptr; + +u32 nr_pids; + +u32 reserved0; +}; + +void *setup_stack (int (*child_fn)(void *),void *child_arg,int stack_size); +int eclone (int flags_low,struct clone_args *clone_args,int args_size, +int *pids); +int gettid ();
eclone/eclone-1.c new file +121 -0
121 lines not on this page · raw message
eclone/eclone-lib.c new file +85 -0
85 lines not on this page · raw message
Signature · 1 line
1.6.6.1
A message that is not in the archive (sent off-list or not yet received): 20100202193508.GA8542-r/[email protected]
PATCH 2/6 : eclone-2: Fail if selected pid is in use
From: Sukadev Bhattiprolu <[email protected]>
Date: Sat, 30 Jan 2010 12:51:23 -0800
Subject: [PATCH 2/6]: eclone-2: Fail if selected pid is in use
Ensure that eclone() system call fails with -EBUSY if selected pid is in use.
--- eclone/Makefile | 2 +- eclone/eclone-2.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 1 deletions(-) create mode 100644 eclone/eclone-2.c
eclone/Makefile +1 -1
@@ -3,7 +3,7 @@ CFLAGS = -Wall LDFLAGS = -PROGS = eclone-1 +PROGS = eclone-1 eclone-2 all: $(PROGS)
eclone/eclone-2.c new file +117 -0
117 lines not on this page · raw message
Signature · 1 line
1.6.6.1
A message that is not in the archive (sent off-list or not yet received): 20100202193720.GA8793-r/[email protected]
Re: [PATCH 2/6][cr-tests]: eclone-2: Fail if selected pid is in use
Quoted 20 lines · Sukadev Bhattiprolu
From: Sukadev Bhattiprolu <[email protected]>
Date: Sat, 30 Jan 2010 12:51:23 -0800
Subject: [PATCH 2/6]: eclone-2: Fail if selected pid is in useEnsure that
eclone()system call fails with-EBUSYif selected pid is in use.Signed-off-by Sukadev Bhattiprolu <[email protected]>--- eclone/Makefile | 2 +- eclone/eclone-2.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 1 deletions(-) create mode 100644 eclone/eclone-2.ceclone/Makefile +0
-0
eclone/Makefile CFLAGS = -Wall · line 6
Quoted 5 lines
eclone/Makefile +1
-1@@ -3,7 +3,7 @@ CFLAGS = -Wall LDFLAGS = -PROGS = eclone-1 +PROGS = eclone-1 eclone-2
Just a few nits. I don't see any real problems with this, but like I said I'd like the whole set re-sent along with a user-cr patch to make a libeclone.a or .so that these tests can link against.
Quoted 83 lines
eclone/Makefile +0
-0all: $(PROGS)eclone/eclone-2.c new file +75
-0@@ -0,0 +1,117 @@ +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#include <signal.h> +#include <string.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/syscall.h> +#include "clone_args.h" + +/* +* Verify that eclone() fails if the selected pid is in use. +* We try to assign parent's pid which should already be in use. +*/ +int verbose =0 ; +int child_tid, parent_tid; +#define CHILD_ARG (void *)0x979797 + +pid_t pids_list[2 ]; + +int do_child (void *arg) +{ +printf ("FAIL: Child created with [%d, %d], but we expected child " +"creation to fail since pid is in use\n" ,gettid (), +getpid ()); +exit (2 ); +} + +static int myclone (int (*child_fn)(void *),void *child_arg, +unsigned int flags_low,int nr_pids,pid_t *pids_list) +{ +int rc; +void *stack; +struct clone_args ca; +int args_size; + + stack =setup_stack (child_fn, child_arg,STACKSIZE ); +if (!stack) { +printf ("ERROR: setup_stack returns NULL for size %d\n" , +STACKSIZE ); +exit (1 ); + } + +memset (&ca,0 ,sizeof (ca)); + ca.child_stack_base = (u64 )(int )stack; + ca.child_stack_size = (u64 )0 ; + ca.parent_tid_ptr = (u64)((int )&parent_tid); + ca.child_tid_ptr = (u64)((int )&child_tid); + ca.nr_pids = nr_pids; + +if (verbose) { +printf ("[%d, %d]: Parent:\n\t child_stack 0x%p, ptidp %llx, " +"ctidp %llx, pids %p\n" ,getpid (),gettid (), + stack, ca.parent_tid_ptr, ca.child_tid_ptr, + pids_list); + } + + args_size =sizeof (struct clone_args ); + rc =eclone (flags_low, &ca, args_size, pids_list); + +if (verbose) { +printf ("[%d, %d]: eclone() returned %d, error %d\n" ,getpid (), +gettid (), rc, errno); +fflush (stdout); + } + +if (rc <0 && errno ==EAGAIN ) { +printf ("PASS: Unable to create a process with a pid that is " +"in use\n" ); +exit (0 ); + }else { +printf ("ERROR: " ); +return rc; + }
eclone/eclone-2.c line 85
Quoted 10 lines
eclone/eclone-2.c new file +10
-0+} + +int main () +{ +int rc, pid, status; +unsigned long flags; +int nr_pids =1 ; + + flags =SIGCHLD |CLONE_PARENT_SETTID |CLONE_CHILD_SETTID ; + flags =SIGCHLD ;
Did you want to delete that first line?
eclone/eclone-2.c line 90
Quoted 5 lines
eclone/eclone-2.c new file +5
-0+ +/* +* Try to create a process with same pid as parent ! +*/ + pids_list[0 ] = pids_list[1 ] =getpid ();
Any reason you're setting pids_list[1]? Shouldn't be used, right?
eclone/eclone-2.c line 92
Quoted 1 line
eclone/eclone-2.c new file +1
-0+ pid =myclone (do_child, (void *)CHILD_ARG , flags, nr_pids, pids_list);
CHILD_ARG is already cast btw
Quoted 27 lines
eclone/eclone-2.c new file +25
-0+ +if (verbose) { +printf ("[%d, %d]: Parent waiting for %d\n" ,getpid (), +gettid (), pid); + } + + rc =waitpid (pid, &status, __WALL); +if (rc <0 ) { +printf ("ERROR: " ); + verbose =1 ; + } + +if (verbose) { +printf ("\twaitpid(): child %d, rc %d, error %d, status 0x%x\n" , +getpid (), rc, errno, status); +if (rc >=0 ) { +if (WIFEXITED (status)) { +printf ("\t EXITED, %d\n" ,WEXITSTATUS (status)); + }else if (WIFSIGNALED (status)) { +printf ("\t SIGNALED, %d\n" ,WTERMSIG (status)); + } + } + } +return 0 ; +}Signature · 1 line
1.6.6.1
PATCH 3/6 : eclone-3: Fail if reserved fields are not 0
In reply to a message not in the archiveFrom: Sukadev Bhattiprolu <[email protected]>
Date: Sat, 30 Jan 2010 12:53:04 -0800
Subject: [PATCH 3/6][cr-tests]: eclone-3: Fail if reserved fields are not 0.
To ensure future extendability, we want the unused fields to be 0. Ensure eclone() fails if ->reserved0 field is non-0.
--- eclone/Makefile | 2 +- eclone/eclone-3.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 1 deletions(-) create mode 100644 eclone/eclone-3.c
eclone/Makefile +1 -1
@@ -3,7 +3,7 @@ CFLAGS = -Wall LDFLAGS = -PROGS = eclone-1 eclone-2 +PROGS = eclone-1 eclone-2 eclone-3 all: $(PROGS)
eclone/eclone-3.c new file +117 -0
117 lines not on this page · raw message
Signature · 1 line
1.6.6.1
A message that is not in the archive (sent off-list or not yet received): 20100202193822.GB8793-r/[email protected]
Serge E. Hallyn
Acked-byRe: [PATCH 3/6][cr-tests]: eclone-3: Fail if reserved fields are not 0
Quoted 9 lines · Sukadev Bhattiprolu
From: Sukadev Bhattiprolu <[email protected]>
Date: Sat, 30 Jan 2010 12:53:04 -0800
Subject: [PATCH 3/6][cr-tests]: eclone-3: Fail if reserved fields are not 0.To ensure future extendability, we want the unused fields to be 0. Ensure
eclone()fails if ->reserved0 field is non-0.Signed-off-by Sukadev Bhattiprolu <[email protected]>
Quoted 144 lines
--- eclone/Makefile | 2 +- eclone/eclone-3.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 1 deletions(-) create mode 100644 eclone/eclone-3.ceclone/Makefile +1
-1@@ -3,7 +3,7 @@ CFLAGS = -Wall LDFLAGS = -PROGS = eclone-1 eclone-2 +PROGS = eclone-1 eclone-2 eclone-3 all: $(PROGS)eclone/eclone-3.c new file +117
-0@@ -0,0 +1,117 @@ +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#include <signal.h> +#include <string.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/syscall.h> +#include "clone_args.h" + +/* +* Verify that eclone() fails if ->reserved0 field is non-zero. +*/ +int verbose =0 ; +int child_tid, parent_tid; + +#define CHILD_TID1 377 +#define CHILD_TID2 399 +#define CHILD_ARG (void *)0x979797 + +pid_t pids_list[] = {CHILD_TID1 ,CHILD_TID2 }; + +int do_child (void *arg) +{ +printf ("FAIL: Child created with [%d, %d]. We expected eclone() to " +"fail with EINVAL since ->reserved0 is non-zero\n" , +gettid (),getpid ()); +exit (2 ); +} + +static int myclone (int (*child_fn)(void *),void *child_arg, +unsigned int flags_low,int nr_pids,pid_t *pids_list) +{ +int rc; +void *stack; +struct clone_args ca; +int args_size; + + stack =setup_stack (child_fn, child_arg,STACKSIZE ); +if (!stack) { +printf ("ERROR: setup_stack returns NULL for size %d\n" , +STACKSIZE ); +exit (1 ); + } + +memset (&ca,0 ,sizeof (ca)); + ca.child_stack_base = (u64 )(int )stack; + ca.child_stack_size = (u64 )0 ; + ca.parent_tid_ptr = (u64)((int )&parent_tid); + ca.child_tid_ptr = (u64)((int )&child_tid); + ca.reserved0 =0xdeadbeef ; + ca.nr_pids = nr_pids; + +if (verbose) { +printf ("[%d, %d]: Parent:\n\t child_stack 0x%p, ptidp %llx, " +"ctidp %llx, pids %p\n" ,getpid (),gettid (), + stack, ca.parent_tid_ptr, ca.child_tid_ptr, + pids_list); + } + + args_size =sizeof (struct clone_args ); + rc =eclone (flags_low, &ca, args_size, pids_list); + +if (verbose) { +printf ("[%d, %d]: eclone() returned %d, error %d\n" ,getpid (), +gettid (), rc, errno); +fflush (stdout); + } + +if (rc <0 && errno ==EINVAL ) { +printf ("PASS: eclone() failed (->reserved0 is not 0)\n" ); +exit (0 ); + }else { +printf ("FAIL: Expected eclone() to fail with EINVAL" ); +exit (1 ); + } + +return rc; +} + +int main () +{ +int rc, pid, status; +unsigned long flags; +int nr_pids =1 ; + + flags =SIGCHLD |CLONE_PARENT_SETTID |CLONE_CHILD_SETTID ; + flags =SIGCHLD ; + + pid =myclone (do_child, (void *)CHILD_ARG , flags, nr_pids, pids_list); + +if (verbose) { +printf ("[%d, %d]: Parent waiting for %d\n" ,getpid (), +gettid (), pid); + } + + rc =waitpid (pid, &status, __WALL); +if (rc <0 ) { +printf ("ERROR: " ); + verbose =1 ; + } + +if (verbose) { +printf ("\twaitpid(): child %d, rc %d, error %d, status 0x%x\n" , +getpid (), rc, errno, status); +if (rc >=0 ) { +if (WIFEXITED (status)) { +printf ("\t EXITED, %d\n" ,WEXITSTATUS (status)); + }else if (WIFSIGNALED (status)) { +printf ("\t SIGNALED, %d\n" ,WTERMSIG (status)); + } + } + } + +return 0 ; +}Signature · 1 line
1.6.6.1
PATCH 4/6 : eclone-4: Fail if clone_flags_high is non-zero
In reply to a message not in the archiveFrom: Sukadev Bhattiprolu <[email protected]>
Date: Mon, 1 Feb 2010 18:10:32 -0800
Subject: [PATCH 4/6][cr-tests]: eclone-4: Fail if clone_flags_high is non-zero
To ensure future extendability, we want the unused fields to be 0. Ensure eclone() fails if ->clone_flags_high field is non-0.
--- eclone/Makefile | 2 +- eclone/eclone-4.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 1 deletions(-) create mode 100644 eclone/eclone-4.c
eclone/Makefile +1 -1
@@ -3,7 +3,7 @@ CFLAGS = -Wall LDFLAGS = -PROGS = eclone-1 eclone-2 eclone-3 +PROGS = eclone-1 eclone-2 eclone-3 eclone-4 all: $(PROGS)
eclone/eclone-4.c new file +116 -0
116 lines not on this page · raw message
Signature · 1 line
1.6.6.1
A message that is not in the archive (sent off-list or not yet received): 20100202193931.GC8793-r/[email protected]
Re: [PATCH 4/6][cr-tests]: eclone-4: Fail if clone_flags_high is non-zero
eclone/eclone-4.c line 48
Quoted 11 lines · Sukadev Bhattiprolu
From: Sukadev Bhattiprolu <[email protected]>
Date: Mon, 1 Feb 2010 18:10:32 -0800
Subject: [PATCH 4/6][cr-tests]: eclone-4: Fail ifclone_flags_highis non-zeroTo ensure future extendability, we want the unused fields to be 0. Ensure
eclone()fails if ->clone_flags_high field is non-0.Signed-off-by Sukadev Bhattiprolu <[email protected]>eclone/eclone-4.c new file +1
-0+ ca.clone_flags_high = (u64 )1 <<33 ;
So have you tested this on x86-32? does it pass?
-serge
PATCH 5/6 : eclone-5: nr_pids must not exceed nesting level
In reply to a message not in the archiveFrom: Sukadev Bhattiprolu <[email protected]>
Date: Mon, 1 Feb 2010 18:13:51 -0800
Subject: [PATCH 5/6][cr-tests]: eclone-5: nr_pids must not exceed nesting level
Verify that eclone() fails if nr_pids exceeds the current nesting level of pid namespaces. Also verify that eclone() succeeds in choosing a pid for a process in a descendant pid namespace.
--- eclone/Makefile | 2 +- eclone/eclone-5.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 175 insertions(+), 1 deletions(-) create mode 100644 eclone/eclone-5.c
eclone/Makefile +1 -1
@@ -3,7 +3,7 @@ CFLAGS = -Wall LDFLAGS = -PROGS = eclone-1 eclone-2 eclone-3 eclone-4 +PROGS = eclone-1 eclone-2 eclone-3 eclone-4 eclone-5 all: $(PROGS)
eclone/eclone-5.c new file +174 -0
174 lines not on this page · raw message
Signature · 1 line
1.6.6.1
A message that is not in the archive (sent off-list or not yet received): 20100202194106.GD8793-r/[email protected]
Serge E. Hallyn
Acked-byRe: [PATCH 5/6][cr-tests]: eclone-5: nr_pids must not exceed nesting level
Quoted 10 lines · Sukadev Bhattiprolu
From: Sukadev Bhattiprolu <[email protected]>
Date: Mon, 1 Feb 2010 18:13:51 -0800
Subject: [PATCH 5/6][cr-tests]: eclone-5:nr_pidsmust not exceed nesting levelVerify that
eclone()fails ifnr_pidsexceeds the current nesting level of pid namespaces. Also verify thateclone()succeeds in choosing a pid for a process in a descendant pid namespace.Signed-off-by Sukadev Bhattiprolu <[email protected]>
Quoted 201 lines
--- eclone/Makefile | 2 +- eclone/eclone-5.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 175 insertions(+), 1 deletions(-) create mode 100644 eclone/eclone-5.ceclone/Makefile +1
-1@@ -3,7 +3,7 @@ CFLAGS = -Wall LDFLAGS = -PROGS = eclone-1 eclone-2 eclone-3 eclone-4 +PROGS = eclone-1 eclone-2 eclone-3 eclone-4 eclone-5 all: $(PROGS)eclone/eclone-5.c new file +174
-0@@ -0,0 +1,174 @@ +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#include <signal.h> +#include <string.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/syscall.h> +#define _GNU_SOURCE +#include <sched.h> +#include "clone_args.h" + +/* +* Verify that eclone() fails if nr_pids exceeds the current nesting level +* of pid namespaces +*/ +int verbose =0 ; + +#define CHILD_TID1 377 +#define CHILD_TID2 399 +#define CHILD_ARG (void *)0x979797 + +pid_t pids_list[] = {CHILD_TID1 ,CHILD_TID2 }; +int parent_tid; +int child_tid; + +int do_child (void *arg) +{ +if (verbose) +printf ("Child created with [%d, %d]\n" ,gettid (),getpid ()); + +sleep (2 ); +exit (0 ); +} + +static int myclone (int (*child_fn)(void *),void *child_arg, +unsigned int flags_low,int nr_pids,pid_t *pids_list) +{ +int rc; +void *stack; +struct clone_args ca; +int args_size; + + stack =setup_stack (child_fn, child_arg,STACKSIZE ); +if (!stack) { +printf ("ERROR: setup_stack returns NULL for size %d\n" , +STACKSIZE ); +exit (1 ); + } + +memset (&ca,0 ,sizeof (ca)); + ca.child_stack_base = (u64 )(int )stack; + ca.child_stack_size = (u64 )0 ; + ca.parent_tid_ptr = (u64)((int )&parent_tid); + ca.child_tid_ptr = (u64)((int )&child_tid); + ca.nr_pids = nr_pids; + +if (verbose) { +printf ("[%d, %d]: Parent:\n\t child_stack 0x%p, ptidp %llx, " +"ctidp %llx, pids %p\n" ,getpid (),gettid (), + stack, ca.parent_tid_ptr, ca.child_tid_ptr, + pids_list); + } + + errno =0 ; + args_size =sizeof (struct clone_args ); + rc =eclone (flags_low, &ca, args_size, pids_list); + +if (verbose) { +printf ("[%d, %d]: eclone() returned %d, error %d\n" ,getpid (), +gettid (), rc, errno); +fflush (stdout); + } + +return rc; +} + +int do_test (void *arg) +{ +int rc, pid, status; +unsigned long flags; +int nested_ns; +int nr_pids; +int error; + + nested_ns = *(int *)arg; + nr_pids =2 ; + + flags =SIGCHLD |CLONE_PARENT_SETTID |CLONE_CHILD_SETTID ; + + pid =myclone (do_child, (void *)CHILD_ARG , flags, nr_pids, pids_list); + + error =0 ; +if (pid <0 ) + error = errno; + +/* If we did create a child, wait for it to exit */ +if (pid >0 ) { + rc =waitpid (pid, &status, __WALL); +if (rc <0 ) { +printf ("%d: ERROR: waitpid() rc %d, error %d\n" , +getpid (), rc, errno); + verbose =1 ; + } + } + +if (verbose) { +printf ("%d: nested_ns %d, pid %d, error %d\n" ,getpid (), + nested_ns, pid, error); + } + +/* +* We set nr_pids to 2 above. If we cloned from current pid ns, +* eclone() must fail with EINVAL. If we eclone() from a nested pid +* ns, eclone() must succeed. In all other cases, test has failed. +*/ + rc =0 ; +if (!nested_ns && (pid <0 ) && (error ==EINVAL )) { +printf ("%d: PASSED: Got EINVAL when nr_pids > nesting-depth\n" , +getpid ()); + }else if (nested_ns && (pid >0 )) { +printf ("%d: PASSED: eclone() succeeded in nested pid-ns\n" , +getpid ()); + }else { +printf ("%d: FAILED: nested_ns %d, pid %d, error %d\n" ,getpid (), + nested_ns, pid, error); + rc =1 ; + } + +fflush (stdout); +return rc; +} + +int main () +{ +int rc, pid, status; +int nested_ns; +unsigned long flags; +void *stack; + +/* First test in current pid namespace */ + nested_ns =0 ; + rc =do_test (&nested_ns); +if (rc) +exit (rc); + +/* Then test in a nested pid-namespace - use normal clone() */ + stack =malloc (STACKSIZE ); +if (!stack) { +printf ("ERROR: setup_stack returns NULL for size %d\n" , +STACKSIZE ); +exit (1 ); + } + stack += (STACKSIZE -1 ); + + nested_ns =1 ; + flags =SIGCHLD |CLONE_NEWPID |CLONE_NEWNS ; + pid =clone (do_test, stack, flags, (void *)&nested_ns,NULL ,NULL ,NULL ); +if (pid <0 ) { +printf ("ERROR: clone() failed, pid %d, error %s\n" , pid, +strerror (errno)); +exit (1 ); + } + + rc =waitpid (pid, &status, __WALL); +if (rc <0 ) { +printf ("ERROR: waitpid() failed, rc %d, error %s\n" , rc, +strerror (errno)); +fflush (stdout); +exit (1 ); + } +return 0 ; +}Signature · 1 line
1.6.6.1
PATCH 6/6 : eclone/runtests.sh: Wrapper script for eclone tests
In reply to a message not in the archiveFrom: Sukadev Bhattiprolu <[email protected]>
Date: Tue, 2 Feb 2010 11:21:07 -0800
Subject: [PATCH 6/6][cr-tests]: eclone/runtests.sh: Wrapper script for eclone tests
A simple wrapper script to run all eclone tests in this directory.
--- eclone/runtests.sh | 23 +++++++++++++++++++++++ 1 files changed, 23 insertions(+), 0 deletions(-) create mode 100755 eclone/runtests.sh
eclone/runtests.sh new file +23 -0
@@ -0,0 +1,23 @@ +#!/bin/bash + +TEST_LOG=`mktemp -p . runtests-XXXXXXX`.log + +echo Logfile: $TEST_LOG + +> $TEST_LOG + +TESTS="eclone-1 eclone-2 eclone-3 eclone-4 eclone-5" +#TESTS="eclone-5" + +for t in $TESTS +do + echo "===== Test: $t" >> $TEST_LOG + ./$t >> $TEST_LOG 2>&1 + if [ $? -eq 0 ]; then + echo "Test '$t' PASSED" >> $TEST_LOG + else + echo "Test '$t' FAILED" >> $TEST_LOG + fi +done + +cat $TEST_LOG
Signature · 1 line
1.6.6.1
Quoted 10 lines · Sukadev Bhattiprolu
From: Sukadev Bhattiprolu <[email protected]>
Date: Sat, 30 Jan 2010 12:49:30 -0800
Subject: [PATCH 1/6] eclone-1: Test basic functionalityVerify that a child process gets the expected pid and arguments on stack when it is created with
eclone()system call.NOTE: The
myclone()function ineclone-lib.csupports just x86 for now.
Needs to be ported to other architectures.
Thanks, but
I'd prefer to see a libeclone patch for user-cr, and cr_tests programs compiled against that. user-cr already has done the ugliness required to do eclone per-arch right now.
Would it be a lot of work to do so? (I shouldn't think so)
thanks,
-serge
Quoted 309 lines
Signed-off-by Sukadev Bhattiprolu <[email protected]>--- Makefile | 2 +- eclone/Makefile | 16 +++++++ eclone/clone_args.h | 37 ++++++++++++++++ eclone/eclone-1.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++ eclone/eclone-lib.c | 85 ++++++++++++++++++++++++++++++++++++ 5 files changed, 260 insertions(+), 1 deletions(-) create mode 100644 eclone/Makefile create mode 100644 eclone/clone_args.h create mode 100644 eclone/eclone-1.c create mode 100644 eclone/eclone-lib.cMakefile +1
-1@@ -1,5 +1,5 @@ SUBDIRS = libcrtest counterloop fileio simple userns ipc sleep \ - process-tree futex epoll taskfs + process-tree futex epoll taskfs eclone targets = ns_exec mysueclone/Makefile new file +16
-0@@ -0,0 +1,16 @@ + +CFLAGS = -Wall + +LDFLAGS = + +PROGS = eclone-1 + +all: $(PROGS) + +eclone-lib.o: eclone-lib.c clone_args.h + +$(PROGS): %: %.c eclone-lib.o + $(CC) $(CFLAGS) -o $@ $< eclone-lib.o $(LDFLAGS) + +clean: + rm -f $(PROGS) eclone-lib.oeclone/clone_args.h new file +37
-0@@ -0,0 +1,37 @@ +#include <errno.h> + +#define __NR_clone_with_pids 337 +#define __NR_clone3 337 +#define __NR_eclone 337 +#define __NR_clone 120 +#define __NR_exit 1 +#define __NR_getpid 20 + +#define CLONE_NEWPID 0x20000000 +#define CLONE_CHILD_SETTID 0x01000000 +#define CLONE_PARENT_SETTID 0x00100000 +#define CLONE_UNUSED 0x00001000 + +#define STACKSIZE 8192 + +typedef unsigned long long u64 ; +typedef unsigned int u32 ; +typedef int pid_t ; +struct clone_args { +u64 clone_flags_high; + +u64 child_stack_base; +u64 child_stack_size; + +u64 parent_tid_ptr; +u64 child_tid_ptr; + +u32 nr_pids; + +u32 reserved0; +}; + +void *setup_stack (int (*child_fn)(void *),void *child_arg,int stack_size); +int eclone (int flags_low,struct clone_args *clone_args,int args_size, +int *pids); +int gettid ();eclone/eclone-1.c new file +121
-0@@ -0,0 +1,121 @@ +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#include <signal.h> +#include <string.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/syscall.h> +#include "clone_args.h" + +int verbose =0 ; +int child_tid, parent_tid; + +#define CHILD_TID1 377 +#define CHILD_TID2 399 +#define CHILD_ARG (void *)0x979797 + +pid_t pids_list[] = {CHILD_TID1 ,CHILD_TID2 }; + +int do_child (void *arg) +{ +sleep (3 ); + +if (arg !=CHILD_ARG ) { +printf ("ERROR: Expected arg %p, actual %p\n" ,CHILD_ARG , arg); +exit (1 ); + } + +if (gettid () !=CHILD_TID1 ) { +printf ("FAIL: Child expected pid %d, actual %d\n" ,CHILD_TID1 , +getpid ()); +exit (2 ); + }else { +printf ("PASS: Child got expected pid %d\n" ,CHILD_TID1 ); +exit (0 ); + } + +} + +static int myclone (int (*child_fn)(void *),void *child_arg, +unsigned int flags_low,int nr_pids,pid_t *pids_list) +{ +int rc; +void *stack; +struct clone_args ca; +int args_size; + + stack =setup_stack (child_fn, child_arg,STACKSIZE ); +if (!stack) { +printf ("ERROR: setup_stack returns NULL for size %d\n" , +STACKSIZE ); +exit (1 ); + } + +memset (&ca,0 ,sizeof (ca)); + ca.child_stack_base = (u64 )(int )stack; + ca.child_stack_size = (u64 )0 ; + ca.parent_tid_ptr = (u64)((int )&parent_tid); + ca.child_tid_ptr = (u64)((int )&child_tid); + ca.nr_pids = nr_pids; + +if (verbose) { +printf ("[%d, %d]: Parent:\n\t child_stack 0x%p, ptidp %llx, " +"ctidp %llx, pids %p\n" ,getpid (),gettid (), + stack, ca.parent_tid_ptr, ca.child_tid_ptr, + pids_list); + } + + args_size =sizeof (struct clone_args ); + rc =eclone (flags_low, &ca, args_size, pids_list); + +if (verbose) { +printf ("[%d, %d]: eclone() returned %d, error %d\n" ,getpid (), +gettid (), rc, errno); +fflush (stdout); + } + +if (rc <0 ) { +printf ("ERROR: " ); +exit (1 ); + } + +return rc; +} + +int main () +{ +int rc, pid, status; +unsigned long flags; +int nr_pids =1 ; + + flags =SIGCHLD |CLONE_PARENT_SETTID |CLONE_CHILD_SETTID ; + + pid =myclone (do_child, (void *)CHILD_ARG , flags, nr_pids, pids_list); + +if (verbose) { +printf ("[%d, %d]: Parent waiting for %d\n" ,getpid (), +gettid (), pid); + } + + rc =waitpid (pid, &status, __WALL); +if (rc <0 ) { +printf ("ERROR: " ); + verbose =1 ; + } + +if (verbose) { +printf ("\twaitpid(): child %d, rc %d, error %d, status 0x%x\n" , +getpid (), rc, errno, status); +if (rc >=0 ) { +if (WIFEXITED (status)) { +printf ("\t EXITED, %d\n" ,WEXITSTATUS (status)); + }else if (WIFSIGNALED (status)) { +printf ("\t SIGNALED, %d\n" ,WTERMSIG (status)); + } + } + } + +return 0 ; +}eclone/eclone-lib.c new file +85
-0@@ -0,0 +1,85 @@ +#define _GNU_SOURCE +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/syscall.h> +#include "clone_args.h" + +/* From Oren Laadan */ + +#if defined(__i386__) && defined(__NR_eclone) +/* +* libc doesn't support eclone() yet... +* (see: http://lkml.indiana.edu/hypermail/linux/kernel/9604.3/0204.html) +*/ + +int eclone (int flags_low,struct clone_args *clone_args,int args_size, +int *pids) +{ +long retval; + + __asm__ __volatile__( +"movl %3, %%ebx\n\t" /* flags_low -> 1st (ebx) */ +"movl %4, %%ecx\n\t" /* clone_args -> 2nd (ecx) */ +"movl %5, %%edx\n\t" /* args_size -> 3rd (edx) */ +"movl %6, %%esi\n\t" /* pids -> 4th (esi) */ + +"pushl %%ebp\n\t" /* save value of ebp */ +"int $0x80\n\t" /* Linux/i386 system call */ +"testl %0,%0\n\t" /* check return value */ +"jne 1f\n\t" /* jump if parent */ +"popl %%esi\n\t" /* get subthread function */ +"call *%%esi\n\t" /* start subthread function */ +"movl %2,%0\n\t" +"int $0x80\n" /* exit system call: exit subthread */ +"1:\n\t" +"popl %%ebp\t" /* restore parent's ebp */ + + :"=a" (retval) + + :"0" (__NR_clone3), +"i" (__NR_exit), +"b" (flags_low), +"c" (clone_args), +"d" (args_size), +"D" (pids) + ); + +if (retval <0 ) { + errno = -retval; + retval =-1 ; + } +return retval; +} + +void *setup_stack (int (*child_fn)(void *),void *child_arg,int size) +{ +void *stack_base; +void **stack_top; + + stack_base =malloc (size); +if (!stack_base) +return NULL ; + + stack_top = (void **)((char *)stack_base + (size -4 )); + *--stack_top = child_arg; + *--stack_top = child_fn; + +return stack_top; +} + +#endif + +/* gettid() is a bit more useful than getpid() when messing with clone() */ +int gettid () +{ +int rc; + + rc =syscall (__NR_gettid,0 ,0 ,0 ); +if (rc <0 ) { +printf ("rc %d, errno %d\n" , rc, errno); +exit (1 ); + } +return rc; +}Signature · 1 line
1.6.6.1