runtests.sh: Make test bit more generic
PATCH 1/11 runtests.sh: Make test bit more generic
From: Sukadev Bhattiprolu <[email protected]>
Date: Fri, 22 Jan 2010 11:53:01 -0800
Subject: [PATCH 01/11] runtests.sh: Make test bit more generic
Remove hardcoding of test case name so it is a bit more generic (although other test cases can't use this script as is).
--- fileio/runtests.sh | 14 +++++++++----- 1 files changed, 9 insertions(+), 5 deletions(-) mode change 100755 => 100644 fileio/runtests.sh
fileio/runtests.sh +9 -5
@@ -4,21 +4,25 @@ source ../common.sh -dir=`mktemp -p . -d -t cr_fileio_XXXXXXX` || (echo "mktemp failed"; exit 1) +# test_case could be a command-line-arg, but since only one test +# uses this for now, hard code. +test_case="fileio1" + +dir=`mktemp -p . -d -t cr_${test_case}_XXXXXXX` || (echo "mktemp failed"; exit 1) echo "Using output dir $dir" SLOW_DOWN="$dir/slow-down-fileio" -CKPT_FILE="$dir/ckpt-fileio1"; +CKPT_FILE="$dir/checkpoint-${test_case}" CKPT_READY="$dir/checkpoint.ready" COPY_DONE="$dir/copy.done" SRC_FILE="$dir/input-data.1"; DEST_FILE="$dir/output-data.1"; DEST_FILE_SNAP="$dir/output-data.1.snap"; -TEST_LOG="$dir/log.fileio1" -TEST_LOG_SNAP="$dir/log.fileio1.snap" +TEST_LOG="$dir/log.${test_case}" +TEST_LOG_SNAP="$dir/log.${test_case}.snap" LOG_FILE="$dir/f1-loop.log" -TEST_CMD="./fileio1" +TEST_CMD="./$test_case" NS_EXEC="../ns_exec" # Make sure no stray TEST_CMD from another run is still going
Signature · 1 line
1.6.0.4
A message that is not in the archive (sent off-list or not yet received): 20100129202842.GA25490-r/[email protected]
PATCH 2/11 Make runtests.sh a wrapper for fileio tests
From: Sukadev Bhattiprolu <[email protected]>
Date: Fri, 22 Jan 2010 11:55:45 -0800
Subject: [PATCH 02/11] Make runtests.sh a wrapper for fileio tests
Move runtests.sh to run-fileio1.sh and create a runtests.sh that runs both run-fileio1.sh and run-filelock1.sh. It can later be extended to run other, possibly all, fileio tests.
--- fileio/run-fileio1.sh | 148 +++++++++++++++++++++++++++++++++++++++++++++++ fileio/runtests.sh | 153 +++---------------------------------------------- 2 files changed, 156 insertions(+), 145 deletions(-) create mode 100755 fileio/run-fileio1.sh mode change 100644 => 100755 fileio/runtests.sh
fileio/run-fileio1.sh new file +148 -0
@@ -0,0 +1,148 @@ +#!/bin/bash +# Copyright 2009 IBM Corp. +# Author: Sukadev Bhattiprolu <sukadev-r/[email protected]> + +source ../common.sh + +# test_case could be a command-line-arg, but since only one test +# uses this for now, hard code. +test_case="fileio1" + +dir=`mktemp -p . -d -t cr_${test_case}_XXXXXXX` || (echo "mktemp failed"; exit 1) +echo "Using output dir $dir" + +SLOW_DOWN="$dir/slow-down-fileio" +CKPT_FILE="$dir/checkpoint-${test_case}" +CKPT_READY="$dir/checkpoint.ready" +COPY_DONE="$dir/copy.done" +SRC_FILE="$dir/input-data.1"; +DEST_FILE="$dir/output-data.1"; +DEST_FILE_SNAP="$dir/output-data.1.snap"; +TEST_LOG="$dir/log.${test_case}" +TEST_LOG_SNAP="$dir/log.${test_case}.snap" + +LOG_FILE="$dir/f1-loop.log" +TEST_CMD="./$test_case" +NS_EXEC="../ns_exec" + +# Make sure no stray TEST_CMD from another run is still going +killall $TEST_CMD + +#echo > $LOG_FILE + +#Create the SRC_FILE +$TEST_CMD -d $dir -C $SRC_FILE + +cnt=1 +sleep_time=3; + +NUMTESTS=5 +for testnum in `seq 1 $NUMTESTS`; do + echo "----- Iteration $cnt" + + # Copy file slowly, so we can checkpoint + touch $SLOW_DOWN + + # Remove CKPT_READY file, start the application and let app tell + # us when it is ready + rm -f $CKPT_READY; + $NS_EXEC -m $TEST_CMD -d $dir -c $SRC_FILE $DEST_FILE & + while [ ! -f $CKPT_READY ]; do + sleep 1; + done; + + # Let it run for a while before checkpointing + echo "Created $TEST_CMD process, sleep $sleep_time" + sleep $sleep_time + + pid=`pidof $TEST_CMD` + if [ "x$pid" == "x" ]; then + echo "$TEST_CMD is not running! pid is $pid. fail" + ps -ef |grep $TEST_CMD + exit 1 + fi + + freeze_pid $pid + + # Checkpoint + echo $CHECKPOINT $pid > $CKPT_FILE + $CHECKPOINT $pid > $CKPT_FILE + ret=$? + if [ $ret -ne 0 ]; then + echo "===== Checkpoint of $pid failed" + ps aux |grep $TEST_CMD + exit 1; + fi + + # Snapshot the outfile and log file + cp $DEST_FILE $DEST_FILE_SNAP + cp $TEST_LOG $TEST_LOG_SNAP + + ls -l $SRC_FILE $DEST_FILE + + thaw $pid + + kill -9 $pid + + # Restore the snapshot after the main process has been killed + cp ${DEST_FILE}.snap $DEST_FILE + + cp $TEST_LOG_SNAP $TEST_LOG + + # Remove COPY_DONE file. We will wait below for application to + # finish copying and let us know. + rm -f $COPY_DONE; + + # Restart. + $NS_EXEC -m rstrsh $CKPT_FILE & + ret=$? + + if [ $ret -ne 0 ]; then + echo "===== Restart of $pid failed" + ps aux |grep $TEST_CMD + exit 1; + fi + + # Find pid of restarted test cmd... + + sleep 1; + pid=`pidof $TEST_CMD` + if [ "x$pid" == "x" ]; then + echo "Can't find pid of $TEST_CMD" + exit 1 + fi + + nspid=`pidof $NS_EXEC` + if [ "x$nspid" == "x" ]; then + echo "Can't find pid of $NS_EXEC" + exit 1 + fi + + # ...then zip through rest of copy. + rm $SLOW_DOWN + + wait $nspid; + ret=$? + + echo "$nspid exited, status $ret" + + #ls -l $SRC_FILE $DEST_FILE $CKPT_FILE + + /usr/bin/cmp $SRC_FILE $DEST_FILE + if [ $? -ne 0 ]; then + echo "file copy ($SRC_FILE -> $DEST_FILE) failed after restart" + exit 1; + fi + + cnt=$((cnt+1)) + + # Change delay so next checkpoint happens at a different point + sleep_time=$((sleep_time+1)) + if [ $sleep_time -gt 10 ]; then + sleep_time=2; + fi +done + +echo PASS + +exit 0
fileio/runtests.sh +8 -145
156 lines not on this page · raw message
Signature · 1 line
1.6.0.4
PATCH 3/11 Check for failure while waiting for checkpoint-ready
In reply to a message not in the archiveFrom: Sukadev Bhattiprolu <[email protected]>
Date: Mon, 25 Jan 2010 18:09:50 -0800
Subject: [PATCH 03/11] Check for failure while waiting for checkpoint-ready
It is possible that an application has encountered an error before creating the checkpoint-ready file. So while polling for 'checkpoint-ready' to be true, look for errors in the log file.
Also, ensure filelock temp files are cleaned up by 'make clean'.
--- fileio/Makefile | 2 +- fileio/run-filelock1.sh | 24 +++++++++++++++--------- 2 files changed, 16 insertions(+), 10 deletions(-)
fileio/Makefile +1 -1
@@ -9,4 +9,4 @@ all: $(LIBCRTEST) $(targets) clean: rm -f $(targets) - rm -rf cr_fileio* + rm -rf cr_fileio* cr_filelock1*
fileio/run-filelock1.sh +15 -9
@@ -45,11 +45,25 @@ checkpoint() fi } +function check_for_failure() +{ + grep --binary-files=text FAIL $PWD/$TEST_LOG > /dev/null 2>&1 + if [ $? -eq 0 ]; then + $ECHO "\t***** Application FAILED after restart" >> $SCRIPT_LOG + $ECHO "\t***** See $TEST_LOG for details" >> $SCRIPT_LOG + + $ECHO "\t***** Application FAILED after restart" + $ECHO "\tSee $PWD/$TEST_LOG for details" + exit 1; + fi +} + function wait_for_checkpoint_ready() { # Wait for test to finish setup while [ ! -f $CHECKPOINT_READY ]; do $ECHO "\t- Waiting for $CHECKPOINT_READY" + check_for_failure; sleep 1; done; }
@@ -202,15 +216,7 @@ while [ $cnt -lt 20 ]; do wait $nspid; ret=$? - grep --binary-files=text FAIL $PWD/$TEST_LOG > /dev/null 2>&1 - if [ $? -eq 0 ]; then - $ECHO "\t***** Application FAILED after restart" >> $SCRIPT_LOG - $ECHO "\t***** See $TEST_LOG for details" >> $SCRIPT_LOG - - $ECHO "\t***** Application FAILED after restart" - $ECHO "\tSee $PWD/$TEST_LOG for details" - exit 1; - fi + check_for_failure; $ECHO "\t- Container exited, status $ret"
Signature · 1 line
1.6.0.4
PATCH 4/11 Rename run-filelock1 to run-fcntltests.sh
In reply to a message not in the archiveFrom: Sukadev Bhattiprolu <[email protected]>
Date: Mon, 25 Jan 2010 18:26:57 -0800
Subject: [PATCH 04/11] Rename run-filelock1 to run-fcntltests.sh
run-filelock1 wrapper could share lot of code with other fcntl tests. Remove hardcoded names, rename it run-fcntltests.sh and pass in test_case name as an argument.
--- fileio/run-fcntltests.sh | 236 ++++++++++++++++++++++++++++++++++++++++++++++ fileio/run-filelock1.sh | 223 +------------------------------------------- fileio/runtests.sh | 2 +- 3 files changed, 238 insertions(+), 223 deletions(-) create mode 100755 fileio/run-fcntltests.sh
fileio/run-fcntltests.sh new file +236 -0
@@ -0,0 +1,236 @@ +#!/bin/bash + +source ../common.sh + +if [ $# -ne 1 ]; then + echo "Usage: $0 <test-case>"; + exit 1; +fi + +test_case=$1; + +if [ ! -x $test_case ]; then + echo "$0: Test case \'$test_case\' does not exist / not executable ?" + exit 1; +fi + +dir=`mktemp -p . -d -t cr_${test_case}_XXXXXXX` || (echo "mktemp failed"; exit 1) + +# NOTE: As of ckpt-v15-dev, the --container option to 'ckpt' causes this +# test to fail with "container not isolated" message due to the +# log-file being shared between the application threads. +# +CHECKPOINT="`which checkpoint` --container" +RESTART=`which restart` +ECHO="/bin/echo -e" + +TEST_CMD="../$test_case" +TEST_ARGS="" +TEST_LOG="logs.d/log.${test_case}" +SCRIPT_LOG="logs.d/log.run-${test_case}" +TEST_PID_FILE="pid.${test_case}"; + +SNAPSHOT_DIR="snap1.d" + +TEST_DONE="test-done" +CHECKPOINT_FILE="checkpoint-${test_case}"; +CHECKPOINT_READY="checkpoint-ready" +CHECKPOINT_DONE="checkpoint-done" + +LOGS_DIR="logs.d" +DATA_DIR="data.d" + +NS_EXEC="../../ns_exec" +NS_EXEC_ARGS="-cgpuimP $TEST_PID_FILE" + +checkpoint() +{ + local pid=$1 + + $ECHO "\t- Checkpoint: $CHECKPOINT $pid \> $CHECKPOINT_FILE" + $CHECKPOINT $pid > $CHECKPOINT_FILE + ret=$? + if [ $ret -ne 0 ]; then + $ECHO "***** FAIL: Checkpoint of $pid failed" + ps -efL |grep $TEST_CMD >> $SCRIPT_LOG + exit 1; + fi +} + +function check_for_failure() +{ + grep --binary-files=text FAIL $PWD/$TEST_LOG > /dev/null 2>&1 + if [ $? -eq 0 ]; then + $ECHO "\t***** Application FAILED after restart" >> $SCRIPT_LOG + $ECHO "\t***** See $TEST_LOG for details" >> $SCRIPT_LOG + + $ECHO "\t***** Application FAILED after restart" + $ECHO "\tSee $PWD/$TEST_LOG for details" + exit 1; + fi +} + +function wait_for_checkpoint_ready() +{ + # Wait for test to finish setup + while [ ! -f $CHECKPOINT_READY ]; do + $ECHO "\t- Waiting for $CHECKPOINT_READY" + check_for_failure; + sleep 1; + done; +} + +function create_container() +{ + local pid; + + cmdline="$NS_EXEC $NS_EXEC_ARGS -- $TEST_CMD $TEST_ARGS" + + $ECHO "\t- Creating container:" + $ECHO "\t- $cmdline" + + $cmdline & + + wait_for_checkpoint_ready; + + # Find global pid of container-init + pid=`cat $TEST_PID_FILE`; + if [ "x$pid" == "x" ]; then + $ECHO "***** FAIL: Invalid container-init pid $pid" + ps -efL |grep $TEST_CMD >> $SCRIPT_LOG + exit 1 + fi + $ECHO "Created container with pid $pid" >> $SCRIPT_LOG +} + +function restart_container +{ + local ret; + + cmdline="$RESTART --pids --pidns --wait" + $ECHO "\t- $cmdline" + + sleep 1 + + $cmdline < $CHECKPOINT_FILE >> $SCRIPT_LOG 2>&1 & + ret=$? + + if [ $ret -ne 0 ]; then + $ECHO "***** FAIL: Restart of $pid failed" + ps -efL |grep $TEST_CMD >> $SCRIPT_LOG + exit 1; + fi + +} + +function create_fs_snapshot() +{ + # Prepare for snapshot + if [ -d $SNAPSHOT_DIR ]; then + rm -rf ${SNAPSHOT_DIR}.prev + mv $SNAPSHOT_DIR ${SNAPSHOT_DIR}.prev + mkdir $SNAPSHOT_DIR + fi + + # Snapshot the log files + cp ${LOGS_DIR}/* $SNAPSHOT_DIR +} + +function restore_fs_snapshot() +{ + # Restore the snapshot after the main process has been killed + /bin/cp ${SNAPSHOT_DIR}/* $LOGS_DIR +} + +cd $dir +echo "Current directory: `pwd`" + +if [ ! -d $LOGS_DIR ]; then + mkdir $LOGS_DIR +fi + +if [ ! -d $DATA_DIR ]; then + mkdir $DATA_DIR +fi + +if [ ! -d $SNAPSHOT_DIR ]; then + mkdir $SNAPSHOT_DIR +fi + +if [ ! -f $INPUT_DATA ]; then + $FILEIO -C $INPUT_DATA +fi + +# Make sure no stray test-case process from another run is still going +killall $TEST_CMD > $SCRIPT_LOG 2>&1 + +> $SCRIPT_LOG; +cnt=1 +while [ $cnt -lt 20 ]; do + $ECHO "===== Iteration $cnt" + + # Remove any 'state' files, start the app and let it tell us + # when it is ready + rm -f $CHECKPOINT_READY $TEST_DONE $TEST_PID_FILE + + create_container + wait_for_checkpoint_ready + + pid=`cat $TEST_PID_FILE` + + $ECHO "\t- Done creating container, cinit-pid $pid" + + ps -efL |grep $TEST_CMD >> $SCRIPT_LOG + + # override default freezerdir + if [ -d $freezerdir ]; then + rmdir $freezerdir + fi + freezerdir=$freezermountpoint/$pid + freeze_pid $pid + + num_pids1=`ps -efL |grep $TEST_CMD | wc -l` + + create_fs_snapshot + + checkpoint $pid + + touch $CHECKPOINT_DONE + + killall -9 `basename $TEST_CMD` + + thaw + + sleep 3 + + restore_fs_snapshot + + restart_container + + sleep 3; + + num_pids2=`ps -efL |grep $TEST_CMD | wc -l` + ps -efL |grep $TEST_CMD >> $SCRIPT_LOG + $ECHO "\t- num_pids1 $num_pids1, num_pids2 $num_pids2"; + + # ns_exec pid is parent-pid of restarted-container-init + nspid=`pidof restart` + + if [ "x$nspid" == "x" ]; then + $ECHO "***** FAIL: Can't find pid of $RESTART" + exit 1; + fi + + # End test gracefully + touch $TEST_DONE + + $ECHO "\t- Waiting for restarted container to exit (gloabl-pid $nspid)" + wait $nspid; + ret=$? + + check_for_failure; + + $ECHO "\t- Container exited, status $ret" + + cnt=$((cnt+1)) +done
fileio/run-filelock1.sh +1 -222
225 lines not on this page · raw message
fileio/runtests.sh +1 -1
@@ -8,4 +8,4 @@ echo echo echo "****** $0: Running test: filelock1" echo -./run-filelock1.sh +./run-fcntltests.sh filelock1
Signature · 1 line
1.6.0.4
PATCH 5/11 Move event-notifications to libcrtest/common.c
In reply to a message not in the archiveFrom: Sukadev Bhattiprolu <[email protected]>
Date: Tue, 26 Jan 2010 16:46:09 -0800
Subject: [PATCH 05/11] Move event-notifications to libcrtest/common.c
The event notification functions using eventfd can be used by other fcntl tests (and possibly other tests). Move them out of filelock1.c and into libcrtest/common.c
--- fileio/filelock1.c | 53 ------------------------------------------- libcrtest/common.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++ libcrtest/libcrtest.h | 7 +++++ 3 files changed, 67 insertions(+), 53 deletions(-)
fileio/filelock1.c +0 -53
@@ -9,8 +9,6 @@#define TEST_FILE "data.d/data.filelock1"#define LOG_FILE "logs.d/log.filelock1" -typedef unsigned long long u64 ; -extern FILE *logfp;int test_fd;int event_fd1;
@@ -31,57 +29,6 @@ int event_fd2;* held by the other process. */ -setup_notification() -{ -int efd; - - efd =eventfd (0 ,0 ); -if (efd <0 ) { -fprintf (logfp,"ERROR: eventfd(): %s\n" ,strerror (errno)); -do_exit (1 ); - } -return efd; -} - -wait_for_events(int efd, u64 total) -{ - int n; -u64 events; -u64 count = (u64 )0 ; - -do { -fprintf (logfp,"%d: wait_for_events: fd %d, reading for %llu\n" , -getpid (), efd, total); -fflush (logfp); - - n =read (efd, &events,sizeof (events)); -if (n !=sizeof (events)) { -fprintf (logfp,"ERROR: read(event_fd) %s\n" , -strerror (errno)); -do_exit (1 ); - } -fprintf (logfp,"%d: wait_for_events: fd %d read %llu\n" , -getpid (), efd, events); - - count += events; - }while (count < total); -} - -notify_one_event(int efd) -{ -int n; -u64 event = (u64 )1 ; - -fprintf (logfp,"%d: Notifying one event on fd %d\n" ,getpid (), efd); -fflush (logfp); - - n =write (efd, &event,sizeof (event)); -if (n !=sizeof (event)) { -fprintf (logfp,"ERROR: write(event_fd) %s\n" ,strerror (errno)); -do_exit (1 ); - } -} -struct test_arg {int child_idx;int type;
libcrtest/common.c +60 -0
63 lines not on this page · raw message
libcrtest/libcrtest.h +7 -0
@@ -12,6 +12,10 @@ struct record {char data[256 ]; }; +#ifdef __i386__ +typedef unsigned long long u64 ; +#endif +extern void do_exit (int status);extern int test_done (void );extern int test_checkpoint_done ();
@@ -23,4 +27,7 @@ extern char *freezer_mountpoint(void);/* right now, subsys must always be "freezer" */ extern int move_to_cgroup (char *subsys,char *grp,int pid); +extern void notify_one_event (int efd); +extern void wait_for_events (int efd,u64 total); +extern int setup_notification ();#endif /* LIBCRTEST_H */
Signature · 1 line
1.6.0.4
A message that is not in the archive (sent off-list or not yet received): 20100129204228.GD26721-r/[email protected]
Re: [PATCH 05/11] Move event-notifications to libcrtest/common.c
Quoting Sukadev Bhattiprolu ([email protected]):
...
libcrtest/libcrtest.h struct record { · line 18
Quoted 12 lines
libcrtest/libcrtest.h +4
-0@@ -12,6 +12,10 @@ struct record {char data[256 ]; }; +#ifdef __i386__ +typedef unsigned long long u64 ; +#endif +
Why did you make this __i386__ only? I need this on s390 too, but am wondering whether I'll break another arch if I just remove this ifdef? Did you see this break on x86-64 or powerpc or something?
-serge
PATCH 6/11 filelease1: Test restore of file leases
In reply to a message not in the archiveFrom: Sukadev Bhattiprolu <[email protected]>
Date: Thu, 21 Jan 2010 12:36:24 -0800
Subject: [PATCH 06/11] filelease1: Test restore of file leases
Checkpoint an application that has F_RDLCK and F_WRLCK leases on files. Restart the application and ensure that the leases are restored.
--- fileio/Makefile | 4 +- fileio/filelease1.c | 262 ++++++++++++++++++++++++++++++++++++++++++++++ fileio/run-filelease1.sh | 3 + fileio/runtests.sh | 5 + 4 files changed, 272 insertions(+), 2 deletions(-) create mode 100644 fileio/filelease1.c create mode 100755 fileio/run-filelease1.sh
fileio/Makefile +2 -2
@@ -1,4 +1,4 @@ -targets = fileio1 filelock1 +targets = fileio1 filelock1 filelease1 INCLUDE = ../libcrtest LIBCRTEST = ../libcrtest/common.o
@@ -9,4 +9,4 @@ all: $(LIBCRTEST) $(targets) clean: rm -f $(targets) - rm -rf cr_fileio* cr_filelock1* + rm -rf cr_fileio* cr_filelock1* cr_filelease1*
fileio/filelease1.c new file +262 -0
262 lines not on this page · raw message
fileio/run-filelease1.sh new file +3 -0
@@ -0,0 +1,3 @@ +#!/bin/bash + +./run-fcntltests.sh filelease1
fileio/runtests.sh +5 -0
@@ -9,3 +9,8 @@ echo echo "****** $0: Running test: filelock1" echo ./run-fcntltests.sh filelock1 + +echo +echo "****** $0: Running test: filelease1" +echo +./run-fcntltests.sh filelease1
Signature · 1 line
1.6.0.4
PATCH 7/11 fsetown1: Test async I/O notification after restart
In reply to a message not in the archiveFrom: Sukadev Bhattiprolu <[email protected]>
Date: Thu, 21 Jan 2010 23:07:51 -0800
Subject: [PATCH 07/11] fsetown1: Test async I/O notification after restart
Checkpoint a process that is waiting for async notification of data being available on a pipe. When the process is restarted, make data available on the pipe and ensure that the process is notified.
--- fileio/Makefile | 4 +- fileio/fsetown1.c | 268 ++++++++++++++++++++++++++++++++++++++++++++++++ fileio/run-fsetown1.sh | 3 + fileio/runtests.sh | 5 + libcrtest/common.c | 2 +- 5 files changed, 279 insertions(+), 3 deletions(-) create mode 100644 fileio/fsetown1.c create mode 100755 fileio/run-fsetown1.sh
fileio/Makefile +2 -2
@@ -1,4 +1,4 @@ -targets = fileio1 filelock1 filelease1 +targets = fileio1 filelock1 filelease1 fsetown1 INCLUDE = ../libcrtest LIBCRTEST = ../libcrtest/common.o
@@ -9,4 +9,4 @@ all: $(LIBCRTEST) $(targets) clean: rm -f $(targets) - rm -rf cr_fileio* cr_filelock1* cr_filelease1* + rm -rf cr_fileio* cr_filelock1* cr_filelease1* cr_fsetown1*
fileio/fsetown1.c new file +268 -0
268 lines not on this page · raw message
fileio/run-fsetown1.sh new file +3 -0
@@ -0,0 +1,3 @@ +#!/bin/bash + +./run-fcntltests.sh fsetown1
fileio/runtests.sh +5 -0
@@ -14,3 +14,8 @@ echo echo "****** $0: Running test: filelease1" echo ./run-fcntltests.sh filelease1 + +echo +echo "****** $0: Running test: fsetown1" +echo +./run-fcntltests.sh fsetown1
libcrtest/common.c +1 -1
@@ -58,7 +58,7 @@ void set_checkpoint_ready()close (fd); } -static void print_exit_status (int pid,int status) +void print_exit_status (int pid,int status) {fprintf (logfp,"Pid %d unexpected exit - " , pid);if (WIFEXITED (status)) {
Signature · 1 line
1.6.0.4
PATCH 8/11 filelock1: Extend for mandatory locks
In reply to a message not in the archiveFrom: Sukadev Bhattiprolu <[email protected]>
Date: Tue, 26 Jan 2010 19:38:28 -0800
Subject: [PATCH 08/11] filelock1: Extend for mandatory locks
Extend filelock1 to test for mandatory locks, when filelock1 is run with the -m option.
--- fileio/filelock1.c | 67 +++++++++++++++++++++++++++++++++++++++------ fileio/run-fcntltests.sh | 5 ++- fileio/run-filelock1.sh | 2 + 3 files changed, 63 insertions(+), 11 deletions(-)
fileio/filelock1.c +58 -9
@@ -4,6 +4,7 @@#include <string.h> #include <signal.h> #include <errno.h> +#include <sys/stat.h> #include "libcrtest.h" #define TEST_FILE "data.d/data.filelock1"
@@ -13,6 +14,7 @@ extern FILE *logfp;int test_fd;int event_fd1;int event_fd2; +int mandatory_locks =1 ;/* * Description:
@@ -60,6 +62,9 @@ void set_lock(int fd, struct test_arg *tlock)fprintf (logfp,"%d: set_lock(): ERROR [%d, %llu, %llu]: %s\n" ,getpid (), tlock->type, (u64 )tlock->start, (u64 )tlock->len,strerror (errno)); +if (mandatory_locks) +fprintf (logfp,"\n\t***** Is the FS mounted with " +"'-o mand' option ?\n\n" );fflush (logfp);kill (getppid (),SIGUSR1 );do_exit (1 );
@@ -108,6 +113,9 @@ void test_lock(int fd, int locked_by_me, struct test_arg *tlock) }else if (rc <0 ) {fprintf (logfp,"ERROR: fcntl(F_SETLK): %s, error %s\n" , lock_info,strerror (errno)); +if (mandatory_locks) +fprintf (logfp,"\n\t***** Is the FS mounted with " +"'-o mand' option ?\n\n" ); goto error; }
@@ -215,8 +223,12 @@ int do_child1(int idx)void setup_test_file () {char buf[256 ]; +int mode; +int rc; + + mode =S_IRUSR |S_IWUSR |S_IRGRP |S_IWGRP |S_IROTH |S_IWOTH ;/* 0666 */ - test_fd =open (TEST_FILE ,O_RDWR |O_CREAT |O_TRUNC ,0666 ); + test_fd =open (TEST_FILE ,O_RDWR |O_CREAT |O_TRUNC , mode);if (test_fd <0 ) {fprintf (logfp,"ERROR: open(%s): %s\n" ,TEST_FILE ,strerror (errno));
@@ -225,6 +237,23 @@ void setup_test_file()memset (buf,0 ,sizeof (buf));write (test_fd, buf,sizeof (buf)); + +if (!mandatory_locks) +return ; + +/* Enable mandatory file locks (setgid, clear group execute) */ + mode |=S_ISGID ; + mode &= ~S_IXGRP ; + + rc =fchmod (test_fd, mode); +if (rc <0 ) { +fprintf (logfp,"ERROR: fchmod(%s): rc %d, error %s\n" , +TEST_FILE , rc,strerror (errno)); +fprintf (logfp,"Maybe '-o mand' mount option is not set ?\n" ); +do_exit (1 ); + } +fprintf (logfp,"Mandatory locking set on %s, mode 0%o\n" ,TEST_FILE , + mode); }int pid1, pid2;
@@ -238,25 +267,32 @@ void child_handler(int sig)if (sig ==SIGCHLD )do_wait (1 ); +fprintf (logfp,"%d: Test case FAILED\n" ,getpid ());fflush (logfp);/* * Kill (remaining) children and exit. */ -kill (pid1,SIGKILL ); -kill (pid2,SIGKILL ); +if (pid1) +kill (pid1,SIGKILL ); +if (pid2) +kill (pid2,SIGKILL );do_exit (-1 ); } -main(int argc, char *argv[]) +usage(char *argv[]) { - int i, status, rc; +fprintf (logfp,"Usage: %s [-m]\n" , argv[0 ]); +fprintf (logfp,"\tTest POSIX (advisory) file locks (without -m)\n" ); +fprintf (logfp,"\t-m: Test mandatory file locks\n" ); +fprintf (logfp,"Test FAILED\n" ); +do_exit (1 ); +} -if (test_done ()) { -printf ("Remove %s before running test\n" ,TEST_DONE ); -do_exit (1 ); - } +main(int argc, char *argv[]) +{ + int i, c, status, rc; logfp =fopen (LOG_FILE ,"w" );if (!logfp) {
@@ -264,6 +300,19 @@ main(int argc, char *argv[])do_exit (1 ); } + mandatory_locks =0 ; +while ((c =getopt (argc, argv,"m" )) !=EOF ) { +switch (c) { +case 'm' : mandatory_locks =1 ;break ; +default :usage (argv); + } + } + +if (test_done ()) { +printf ("Remove %s before running test\n" ,TEST_DONE ); +do_exit (1 ); + } +printf ("%s: Closing stdio fds and writing messages to %s\n" , argv[0 ],LOG_FILE );
fileio/run-fcntltests.sh +3 -2
@@ -2,12 +2,13 @@ source ../common.sh -if [ $# -ne 1 ]; then +if [ $# -lt 1 ]; then echo "Usage: $0 <test-case>"; exit 1; fi test_case=$1; +shift if [ ! -x $test_case ]; then echo "$0: Test case \'$test_case\' does not exist / not executable ?"
@@ -25,7 +26,7 @@ RESTART=`which restart` ECHO="/bin/echo -e" TEST_CMD="../$test_case" -TEST_ARGS="" +TEST_ARGS=$* TEST_LOG="logs.d/log.${test_case}" SCRIPT_LOG="logs.d/log.run-${test_case}" TEST_PID_FILE="pid.${test_case}";
fileio/run-filelock1.sh +2 -0
@@ -1,3 +1,5 @@ #!/bin/bash ./run-fcntltests.sh filelock1 + +./run-fcntltests.sh filelock1 -m
Signature · 1 line
1.6.0.4
PATCH 9/11 pthread1: Don't close stderr() before opening log
In reply to a message not in the archiveFrom: Sukadev Bhattiprolu <[email protected]>
Date: Tue, 26 Jan 2010 22:47:24 -0800
Subject: [PATCH 09/11] pthread1: Don't close stderr() before opening log
If we encounter an error while opening the log file, we write to stderr. In which case, we need the 'stderr' to remain open at least till the log file is open.
--- process-tree/pthread1.c | 12 +++++++++++- 1 files changed, 11 insertions(+), 1 deletions(-)
process-tree/pthread1.c +11 -1
@@ -9,6 +9,10 @@int num_threads =5 ;FILE *logfp; +/* +* Use LOG_PREFIX with thread index as suffix, if each thread needs a +* separate log file. For now, we use a single log +*/ #define LOG_PREFIX "logs.d/pthread1"static void usage (char *argv[])
@@ -137,7 +141,6 @@ main(int argc, char *argv[])pthread_t *tid_list;char log_file[256 ]; -for (i=0 ; i<100 ; i++)close (i);sprintf (log_file,"%s.log" ,LOG_PREFIX ); logfp =fopen (log_file,"w" );
@@ -148,6 +151,13 @@ main(int argc, char *argv[])do_exit (1 ); } +fprintf (stderr,"Redirecting output to logfile %s\n" , log_file); + +for (i=0 ; i<100 ; i++) { +if (i !=fileno (logfp)) +close (i); + } +if (test_done ()) {printf ("Remove %s before running test\n" ,TEST_DONE );do_exit (1 );
Signature · 1 line
1.6.0.4
PATCH 10/11 filelock2: Test restart of process in F_GETLK
In reply to a message not in the archiveFrom: Sukadev Bhattiprolu <[email protected]>
Date: Wed, 27 Jan 2010 19:31:22 -0800
Subject: [PATCH 10/11] filelock2: Test restart of process in F_GETLK
Checkpoint a process that is waiting on a record lock in fcntl(F_GETLK). Upon restart, ensure that it remains in fcntl(F_GETLK) and when the record is unlocked, ensure that the process correctly gets the record lock.
--- fileio/filelock2.c | 421 +++++++++++++++++++++++++++++++++++++++++++++++ fileio/run-filelock2.sh | 5 + 2 files changed, 426 insertions(+), 0 deletions(-) create mode 100644 fileio/filelock2.c create mode 100755 fileio/run-filelock2.sh
fileio/filelock2.c new file +421 -0
@@ -0,0 +1,421 @@ +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <signal.h> +#include <errno.h> +#include <sys/stat.h> +#include "libcrtest.h" + +#define TEST_FILE "data.d/data.filelock2" +#define LOG_FILE "logs.d/log.filelock2" + +extern FILE *logfp; +int test_fd; +int event_fd1; +int event_fd2; +int mandatory_locks =1 ; + +/* +* Description: +* Ensure that a process waiting for a range lock on a file the time +* of checkpoint is properly notified after restart from the checkpoint. +* +* Implementation: +* Process P1 acquires a F_WRLCK on a range and waits for checkpoint. +* Process P2 waits in F_SETLKW. After the checkpoint, P1 confirms +* that it still has the lock and then unlocks the range. P2 must +* return succesfully from the fcntl() and must acquire the lock. +*/ +struct test_record { +int start; +int len; +}; + +struct test_record test_record = {0 ,17 }; + +void set_lock (int fd,int lock_type,struct test_record *rec) +{ +int rc; +struct flock lock; + + lock.l_type = lock_type; + lock.l_whence =SEEK_SET ; + lock.l_start = (off_t )rec->start; + lock.l_len = (off_t )rec->len; + + rc =fcntl (fd,F_SETLKW , &lock); +if (rc <0 && errno !=EAGAIN ) { +fprintf (logfp,"%d: set_lock(): ERROR [%d, %llu, %llu]: %s\n" , +getpid (), lock_type, (u64 )rec->start, + (u64 )rec->len,strerror (errno)); +if (mandatory_locks) +fprintf (logfp,"\n\t***** Is the FS mounted with " +"'-o mand' option ?\n\n" ); +fflush (logfp); +kill (getppid (),SIGUSR1 ); +do_exit (1 ); + } + +fprintf (logfp,"%d: set_lock(): [%d, %llu, %llu] %s\n" ,getpid (), + lock_type, (u64 )rec->start, (u64 )rec->len, + rc <0 ?strerror (errno) :"done" ); +} +/* +* If @set is TRUE, ensure that the given lock is set. +* If @set is FALSE, ensure that the given lock is NOT set. +*/ +void test_lock (int fd,int lock_type,struct test_record *rec) +{ +int rc; +int conflict; +struct flock lock; +char lock_info[512 ]; + + lock.l_type = lock_type; + lock.l_whence =SEEK_SET ; + lock.l_start = (off_t )rec->start; + lock.l_len = (off_t )rec->len; + lock.l_pid =0 ; + +sprintf (lock_info,"lock [%d, %llu, %llu] " , lock_type, + (u64 )rec->start, (u64 )rec->len); + + conflict =0 ; + rc =fcntl (fd,F_SETLK , &lock); +if (rc <0 && (errno ==EAGAIN || errno ==EACCES )) { + rc =fcntl (fd,F_GETLK , &lock); +if (rc <0 ) { +fprintf (logfp,"ERROR: fcntl(F_GETLK): %s, error %s\n" , + lock_info,strerror (errno)); + goto error; + } + +if (lock.l_type ==F_UNLCK || lock.l_pid ==0 ) { +fprintf (logfp,"%d: ERROR: %s F_SETLK / F_GETLK " +"mismatch !!!\n" ,getpid (), lock_info); + goto error; + } + conflict =1 ; + }else if (rc <0 ) { +fprintf (logfp,"ERROR: fcntl(F_SETLK): %s, error %s\n" , + lock_info,strerror (errno)); +if (mandatory_locks) +fprintf (logfp,"\n\t***** Is the FS mounted with " +"'-o mand' option ?\n\n" ); + goto error; + } + +fprintf (logfp,"%d: %s, conflict %d\n" ,getpid (), lock_info, conflict); + +if (conflict) { +fprintf (logfp,"%d: FAIL: %s is NOT set by me !!!\n" ,getpid (), + lock_info); + goto error; + }else { +fprintf (logfp,"%d: PASS: %s is set by me\n" ,getpid (), + lock_info); +return ; + } + +error: +fflush (logfp); +kill (getppid (),SIGUSR1 ); +do_exit (1 ); +} + +void handler (int sig) +{ +/* +* We completed the test and sibling completed its test. Safe to +* exit. +*/ +fprintf (logfp,"%d: Ok to exit...\n" ,getpid ()); +fflush (logfp); +do_exit (0 ); +} + +/* +* Notify parent that we are done testing and wait for a SIGINT to +* exit cleanly. Parent will wait for sibling to also exit and then +* signal us. This orderly exit will help parent distinguish this +* exit from an unexpected exit by the children. +*/ +exit_cleanly() +{ +notify_one_event (event_fd2); +pause (); +do_exit (0 ); +} + +int do_child1 (int idx) +{ +int rc; +int i; +int num_locks; +int failed; + +fprintf (logfp,"%d: Child %d starting up\n" ,getpid (), idx); +fflush (logfp); + +signal (SIGINT , handler); + +set_lock (test_fd,F_WRLCK , &test_record); + +/* +* Tell parent we are ready for checkpoint... +*/ +notify_one_event (event_fd1); + +/* +* Wait for checkpoint/restart +*/ +fprintf (logfp,"%d: waiting for test-done\n" ,getpid ()); +fflush (logfp); +while (!test_done ()) { +sleep (1 ); + } +fprintf (logfp,"%d: Found test-done\n" ,getpid ()); +fflush (logfp); + +test_lock (test_fd,F_WRLCK , &test_record); + +/* +* Drop our lock and exit. Sibling can then acquire the lock. +*/ +set_lock (test_fd,F_UNLCK , &test_record); + +exit_cleanly (); +} + +int do_child2 (int idx) +{ +int rc; +int i; +int num_locks; +int failed; + +fprintf (logfp,"%d: Child %d starting up\n" ,getpid (), idx); +fflush (logfp); + +signal (SIGINT , handler); + +/* +* Tell parent we are about to get the lock. +* NOTE: There is still a window between now and when we actually +* block in the F_SETLK. But the parent has to guess and sleep() +* before enabling checkpoint. +*/ +notify_one_event (event_fd1); + +/* This should block, until checkpoint/restart is done */ +set_lock (test_fd,F_WRLCK , &test_record); + +/* +* We must got here after checkpoint/restart. If not, something is +* wrong ? +*/ +if (!test_checkpoint_done ()) { +fprintf (logfp,"Child2: ERROR: expected C/R to be done " +"by now, but is not ?\n" ); +do_exit (1 ); + } + +/* +* Since we get here after checkpoint/restart, ensure we have the lock. +*/ +test_lock (test_fd,F_WRLCK , &test_record); + +exit_cleanly (); +} + +/* +* Populate the test file so the children can lock some portions of +* the file +*/ +void setup_test_file () +{ +char buf[256 ]; +int mode; +int rc; + + mode =S_IRUSR |S_IWUSR |S_IRGRP |S_IWGRP |S_IROTH |S_IWOTH ;/* 0666 */ + + test_fd =open (TEST_FILE ,O_RDWR |O_CREAT |O_TRUNC , mode); +if (test_fd <0 ) { +fprintf (logfp,"ERROR: open(%s): %s\n" ,TEST_FILE , +strerror (errno)); +do_exit (1 ); + } + +memset (buf,0 ,sizeof (buf)); +write (test_fd, buf,sizeof (buf)); + +if (!mandatory_locks) +return ; + +/* Enable mandatory file locks (setgid, clear group execute) */ + mode |=S_ISGID ; + mode &= ~S_IXGRP ; + + rc =fchmod (test_fd, mode); +if (rc <0 ) { +fprintf (logfp,"ERROR: fchmod(%s): rc %d, error %s\n" , +TEST_FILE , rc,strerror (errno)); +fprintf (logfp,"Maybe '-o mand' mount option is not set ?\n" ); +do_exit (1 ); + } +fprintf (logfp,"Mandatory locking set on %s, mode 0%o\n" ,TEST_FILE , + mode); +} + +int pid1, pid2; + +kill_children(int sig) +{ +signal (SIGCHLD ,SIG_DFL ); +if (pid1) +kill (pid1, sig); + +if (pid2) +kill (pid2, sig); +do_wait (2 ); +} + +/* +* We get a SIGCHLD if a child exited prematurely. SIGUSR1 if child +* exited due to an error. +*/ +void child_handler (int sig) +{ +fprintf (logfp,"%d: Got signal %d. Test case FAILED\n" ,getpid (), sig); +fflush (logfp); + +/* +* Kill (remaining) children and exit. +*/ +kill_children (SIGKILL ); + +do_exit (-1 ); +} + +usage(char *argv[]) +{ +fprintf (logfp,"Usage: %s [-m]\n" , argv[0 ]); +fprintf (logfp,"\tTest POSIX (advisory) file locks (without -m)\n" ); +fprintf (logfp,"\t-m: Test mandatory file locks\n" ); +fprintf (logfp,"Test FAILED\n" ); +do_exit (1 ); +} + +int create_child (int idx,int (*child_func)(int )) +{ +int rc; + + rc =fork (); +if (rc ==0 ) + (*child_func)(idx); + +if (rc <0 ) { +fprintf (logfp,"%d: fork() failed, error %s\n" ,getpid (), +strerror (errno)); +kill_children (SIGKILL ); + } + +wait_for_events (event_fd1,1 ); + +return rc; +} + +main(int argc, char *argv[]) +{ + int i, c, status, rc; + + logfp =fopen (LOG_FILE ,"w" ); +if (!logfp) { +perror ("open() logfile" ); +do_exit (1 ); + } + +fprintf (logfp,"%d: Parent starting up\n" ,getpid ()); +fflush (logfp); + + mandatory_locks =0 ; +while ((c =getopt (argc, argv,"m" )) !=EOF ) { +switch (c) { +case 'm' : mandatory_locks =1 ;break ; +default :usage (argv); + } + } + +if (test_done ()) { +printf ("Remove %s before running test\n" ,TEST_DONE ); +do_exit (1 ); + } + +printf ("%s: Closing stdio fds and writing messages to %s\n" , + argv[0 ],LOG_FILE ); + +for (i=0 ; i<100 ; i++) { +if (fileno (logfp) != i) +close (i); + } + +setup_test_file (); + event_fd1 =setup_notification (); + event_fd2 =setup_notification (); + +/* +* Before waiting for events below, ensure we will be notified +* if a child encounters an error and/or exits prematurely. +*/ +signal (SIGCHLD , child_handler); +signal (SIGUSR1 , child_handler); + +/* +* Create the first child and wait for it take its record lock. +*/ + pid1 =create_child (0 , do_child1); + +/* +* Create the second child and wait for it to block on the +* record lock. +* +*/ + pid2 =create_child (1 , do_child2); + +/* +* NOTE: We have some guessing to do here. The notification from +* the second child (in create_child()) just tells us that +* the child is _about_ to attempt the lock. Give it extra +* time to actually block before enabling checkpoint. +*/ +sleep (10 ); + +/* +* Now that the test processes are ready, tell any wrapper scripts, +* we are ready for checkpoint. +*/ +set_checkpoint_ready (); + +fprintf (logfp,"***** %d: Ready for checkpoint\n" ,getpid ()); +fflush (logfp); + +/* +* Wait for tests to finish their testing. +*/ +wait_for_events (event_fd2,2 ); + +/* +* Now tell them that it is safe to exit. +* +* NOTE: This orderly exit is needed to: +* +* - ensure we don't get stuck waiting for events, and, +* - enable us to distinguish normal and unexpected exits so +* we can properly report test status to wrapper scripts. +*/ +kill_children (SIGINT ); + +do_exit (0 ); +}
fileio/run-filelock2.sh new file +5 -0
@@ -0,0 +1,5 @@ +#!/bin/bash + +./run-fcntltests.sh filelock2 + +./run-fcntltests.sh filelock2 -m
Signature · 1 line
1.6.0.4
PATCH 11/11 filelease2: Test C/R during lease-break-interval
In reply to a message not in the archiveFrom: Sukadev Bhattiprolu <[email protected]>
Date: Thu, 28 Jan 2010 23:18:50 -0800
Subject: [PATCH 11/11] filelease2: Test C/R during lease-break-interval
When a process, P1 (lease-owner of a file) is notified of an impending lease-break (due to a conflicting open of the file by process P2 (lease- breaker), have P1 "flush" some data to the file. Checkpoint processes P1 and P2 before the kernel forcibly revokes the lease (i.e checkpoint within the lease-break-interval).
Upon restart, verify that the P2's open() of the file completes properly and that the data flushed by P1 is visible to P2.
NOTE:
This test passes even with out support for checkpoint of file-locks. The reason for this is that the kernel terminates the lease of P1 before notifying P1 about the lease-break. Since we checkpoint while P1 is in signal handler, neither P1 nor P2 have a lease and so the C/R passes. Hopefully the data-comparison checks will catch some errors during development. If not, we may need to redesign the test or drop it later.
--- fileio/Makefile | 4 +- fileio/filelease2.c | 400 ++++++++++++++++++++++++++++++++++++++++++++++ fileio/run-filelease2.sh | 3 + 3 files changed, 405 insertions(+), 2 deletions(-) create mode 100644 fileio/filelease2.c create mode 100755 fileio/run-filelease2.sh
fileio/Makefile +2 -2
@@ -1,4 +1,4 @@ -targets = fileio1 filelock1 filelease1 fsetown1 +targets = fileio1 filelock1 fsetown1 filelease1 filelease2 INCLUDE = ../libcrtest LIBCRTEST = ../libcrtest/common.o
@@ -9,4 +9,4 @@ all: $(LIBCRTEST) $(targets) clean: rm -f $(targets) - rm -rf cr_fileio* cr_filelock1* cr_filelease1* cr_fsetown1* + rm -rf cr_fileio* cr_filelock1* cr_filelease[12]* cr_fsetown1*
fileio/filelease2.c new file +400 -0
400 lines not on this page · raw message
fileio/run-filelease2.sh new file +3 -0
@@ -0,0 +1,3 @@ +#!/bin/bash + +./run-fcntltests.sh filelease2
Signature · 1 line
1.6.0.4