pipeio/pipeio.c: cleanup and add it to run default
Delete some useless comments and fix some.
Use SAFE_* macros.
Make a re-arrangement on original code: let parent process
work in do_parent(), child process work in do_child(), and
arguments parse and initialization work in setup().
Delete several useless or pointless options:
Option C: this option is not supported and has no effect to this test.
Option B: if this option is specified, the parent process will always
return 0, which won't reflect the correct test results. I think it does
not make much sense and remove it.
Option d: this option is used to specify a directory, where named pipe
is created, other than the current directory. Since tst_tmpdir() will
create a temporary directory, so I think "-d" option can be removed.
printf() is not async-signal-safe, so use write(2) in signal handler directly.
Some cleanup.
Signed-off-by: Xiaoguang Wang <wangxg.fnst@cn.fujitsu.com>
Acked-by: Jan Stancek <jstancek@redhat.com>
Signed-off-by: Wanlong Gao <gaowanlong@cn.fujitsu.com>
diff --git a/scenario_groups/default b/scenario_groups/default
index 196e636..bf7ab79 100644
--- a/scenario_groups/default
+++ b/scenario_groups/default
@@ -27,3 +27,4 @@
kernel_misc
modules
fs_ext4
+pipes
diff --git a/testcases/kernel/ipc/pipeio/pipeio.c b/testcases/kernel/ipc/pipeio/pipeio.c
index 7dfbe44..479d5c8 100644
--- a/testcases/kernel/ipc/pipeio/pipeio.c
+++ b/testcases/kernel/ipc/pipeio/pipeio.c
@@ -52,28 +52,18 @@
#include "tlibio.h"
#include "test.h"
+#include "usctest.h"
+#include "safe_macros.h"
-char *TCID = "pipeio"; /* Test program identifier. */
-int TST_TOTAL = 1; /* Total number of test cases. */
+char *TCID = "pipeio";
+int TST_TOTAL = 1;
#define SAFE_FREE(p) { if (p) { free(p); (p)=NULL; } }
-/* To avoid extensive modifications to the code, use this bodge */
-#define exit(x) myexit(x)
-void myexit(int x)
-{
- if (x)
- tst_resm(TFAIL, "Test failed");
- else
- tst_resm(TPASS, "Test passed");
- tst_exit();
-}
-
#if defined(__linux__)
#define NBPW sizeof(int)
#endif
-#define PPATH "tpipe"
#define OCTAL 'o'
#define HEX 'x'
#define DECIMAL 'd'
@@ -90,130 +80,145 @@
#define MAX_ERRS 16
#define MAX_EMPTY 256
-void sig_handler(), help(), usage(), prt_buf(), prt_examples();
-void sig_child();
+static int parse_options(int argc, char *argv[]);
+static void setup(int argc, char *argv[]);
+static void cleanup(void);
-int count = 0;
-int Nchildcomplete = 0;
+static void do_child(void);
+static void do_parent(void);
-/*
- * Ensure PATH_MAX is define
- */
-#ifndef PATH_MAX
-#ifdef MAXPATHLEN
-#define PATH_MAX MAXPATHLEN
-#else
-#define PATH_MAX 1024
-#endif /* ! MAXPATHLEN */
-#endif /* PATH_MAX */
+static void help(void), usage(void), prt_examples(void);
+static void prt_buf(char **addr, char *buf, int length, int format);
+static void sig_child(int sig);
+static int check_rw_buf(void);
-int main(ac, av)
-int ac;
-char *av[];
+static volatile sig_atomic_t nchildcompleted;
+
+/* variables may be modified in setup() */
+static int num_writers = 1; /* number of writers */
+static int num_writes = 1; /* number of writes per child */
+static int loop; /* loop indefinitely */
+static int exit_error = 1; /* exit on error #, zero means no exit */
+static int size = 327; /* default size */
+static int unpipe; /* un-named pipe if non-zero */
+static int verbose; /* verbose mode if set */
+static int quiet; /* quiet mode if set */
+static int num_rpt; /* ping number, how often to print message */
+static int chld_wait; /* max time to wait between writes, 1 == no wait */
+static int parent_wait; /* max time to wait between reads, 1 == no wait */
+static int ndelay = O_NDELAY; /* additional flag to open */
+static char *writebuf;
+static char *readbuf;
+static char pname[PATH_MAX]; /* contains the name of the named pipe */
+static char *blk_type = NON_BLOCKING_IO; /* blocking i/o or not */
+static char *pipe_type; /* type of pipe under test */
+static int format = HEX;
+static int format_size = -1;
+static int iotype; /* sync io */
+
+/* variables will be modified in running */
+static int error;
+static int count;
+static int read_fd;
+static int write_fd;
+static int empty_read;
+static int sem_id;
+
+static union semun {
+ int val;
+ struct semid_ds *buf;
+ unsigned short int *array;
+} u;
+
+int main(int ac, char *av[])
{
- int i, j, c, error = 0;
- int n;
- int nb; /* number of bytes read */
- int num_wrters = 1; /* number of writers */
- int num_writes = 1; /* number of writes per child */
- int loop = 0; /* loop indefinitely */
- int exit_error = 1; /* exit on error #, zero means no exit */
- int size = 327; /* default size */
- int unpipe = 0; /* un-named pipe if non-zero */
- int verbose = 0; /* verbose mode if set */
- int quiet = 0; /* quiet mode if set */
- int num_rpt = 0; /* ping number, how often to print message */
- int chld_wait = 0; /* max time to wait between writes, 1 == no wait */
- int parent_wait = 0; /* max time to wait between reads, 1 == no wait */
- int ndelay = O_NDELAY; /* additional flag to open */
- long clock;
- char *writebuf = NULL;
- char *readbuf = NULL;
- double d;
- char *cp;
- extern char *optarg;
- char pname[PATH_MAX]; /* contains the name of the unamed pipe */
- char dir[PATH_MAX]; /* directory to create pipe in */
- char *blk_type; /* blocking i/o or not */
- char *pipe_type; /* type of pipe under test */
- int fds[2]; /* un-named pipe fds */
- int read_fd = 0;
- int write_fd = 0;
- int empty_read = 0;
- time_t start_time, current_time, diff_time; /* start time, current time, diff of times */
- int *count_word; /* holds address where to write writers count */
- int *pid_word; /* holds address where to write writers pid */
- int format;
- int format_size = -1;
- int background = 0; /* if set, put process in background */
- struct stat stbuf;
- int iotype = 0; /* sync io */
- char *toutput; /* for getenv() */
- int sem_id;
- struct sembuf sem_op;
- union semun { /* for semctl() */
- int val;
- struct semid_ds *buf;
- unsigned short int *array;
- } u;
- unsigned int uwait_iter = 1000;
- unsigned int uwait_total = 5000000;
+ int i;
+ unsigned int j;
+ unsigned int uwait_iter = 1000, uwait_total = 5000000;
+ pid_t child;
- u.val = 0;
- format = HEX;
- blk_type = NON_BLOCKING_IO;
- dir[0] = '\0';
- sprintf(pname, "%s.%d", PPATH, getpid());
+ setup(ac, av);
- if ((toutput = getenv("TOUTPUT")) != NULL) {
- if (strcmp(toutput, "NOPASS") == 0) {
- quiet = 1;
+ for (i = num_writers; i > 0; --i) {
+
+ child = tst_fork();
+ switch (child) {
+ case -1:
+ tst_brkm(TBROK | TERRNO, cleanup, "fork() failed");
+ case 0:
+ do_child();
+ exit(0);
+ default:
+ break;
}
}
- while ((c =
- getopt(ac, av,
- "T:BbCc:D:d:he:Ef:i:I:ln:p:qs:uvW:w:P:")) != EOF) {
+ do_parent();
+
+ if (empty_read)
+ tst_resm(TWARN, "%d empty reads", empty_read);
+
+ if (error) {
+ tst_resm(TFAIL, "%d data errors on pipe, read size = %d, %s %s",
+ error, size, pipe_type, blk_type);
+ } else if (!quiet) {
+ tst_resm(TPASS, "%d pipe reads complete, read size = %d, %s %s",
+ count + 1, size, pipe_type, blk_type);
+ }
+
+ /*
+ * wait for all children to finish, timeout after uwait_total
+ * semtimedop might not be available everywhere
+ */
+ for (j = 0; j < uwait_total; j += uwait_iter) {
+ if (semctl(sem_id, 1, GETVAL) == 0)
+ break;
+ usleep(uwait_iter);
+ }
+
+ if (j >= uwait_total) {
+ tst_resm(TWARN,
+ "Timed out waiting for child processes to exit");
+ }
+
+ cleanup();
+ tst_exit();
+}
+
+static int parse_options(int argc, char *argv[])
+{
+ char *cp;
+ int c;
+ int ret = 0;
+ static double d;
+
+ while ((c = getopt(argc, argv, "T:bc:D:he:Ef:i:I:ln:p:qs:uvW:w:"))
+ != -1) {
switch (c) {
case 'T':
TCID = optarg;
break;
case 'h':
help();
- exit(0);
- break;
- case 'd': /* dir name */
- strcpy(dir, optarg);
+ ret = 1;
break;
case 'D': /* pipe name */
strcpy(pname, optarg);
break;
- case 'B': /* background */
- background = 1;
- break;
case 'b': /* blocked */
ndelay = 0;
blk_type = BLOCKING_IO;
break;
- case 'C':
- fprintf(stderr,
- "%s: --C option not supported on this architecture\n",
- TCID);
- exit(1);
- break;
case 'c': /* number childern */
- if (sscanf(optarg, "%d", &num_wrters) != 1) {
+ if (sscanf(optarg, "%d", &num_writers) != 1) {
fprintf(stderr,
"%s: --c option invalid arg '%s'.\n",
TCID, optarg);
- usage();
- exit(1);
- } else if (num_wrters <= 0) {
- fprintf(stderr,
- "%s: --c option must be greater than zero.\n",
- TCID);
- usage();
- exit(1);
+ ret = 1;
+ } else if (num_writers <= 0) {
+ fprintf(stderr, "%s: --c option must be "
+ "greater than zero.\n", TCID);
+ ret = 1;
}
break;
case 'e': /* exit on error # */
@@ -221,20 +226,16 @@
fprintf(stderr,
"%s: --e option invalid arg '%s'.\n",
TCID, optarg);
- usage();
- exit(1);
+ ret = 1;
} else if (exit_error < 0) {
- fprintf(stderr,
- "%s: --e option must be greater than zero.\n",
- TCID);
- usage();
- exit(1);
+ fprintf(stderr, "%s: --e option must be "
+ "greater than zero.\n", TCID);
+ ret = 1;
}
break;
-
case 'E':
prt_examples();
- exit(0);
+ ret = 1;
break;
case 'f': /* format of buffer on error */
switch (optarg[0]) {
@@ -263,32 +264,34 @@
fprintf(stderr,
"%s: --f option invalid arg '%s'.\n",
TCID, optarg);
- fprintf(stderr,
- "\tIt must be x(hex), o(octal), d(decimal), a(ascii) or n(none) with opt sz\n");
- exit(1);
+ fprintf(stderr, "\tIt must be x(hex), o(octal),"
+ "d(decimal), a(ascii) or n(none) with "
+ "opt sz\n");
+ ret = 1;
break;
}
cp = optarg;
cp++;
if (*cp) {
if (sscanf(cp, "%i", &format_size) != 1) {
- fprintf(stderr,
- "%s: --f option invalid arg '%s'.\n",
- TCID, optarg);
- fprintf(stderr,
- "\tIt must be x(hex), o(octal), d(decimal), a(ascii) or n(none) with opt sz\n");
- exit(1);
+ fprintf(stderr, "%s: --f option invalid"
+ "arg '%s'.\n", TCID, optarg);
+ fprintf(stderr, "\tIt must be x(hex),"
+ "o(octal), d(decimal), a(ascii)"
+ " or n(none) with opt sz\n");
+ ret = 1;
break;
}
}
break;
case 'I':
- if ((iotype = lio_parse_io_arg1(optarg)) == -1) {
- fprintf(stderr,
- "%s: --I arg is invalid, must be s, p, f, a, l, L or r.\n",
+ iotype = lio_parse_io_arg1(optarg);
+ if (iotype == -1) {
+ fprintf(stderr, "%s: --I arg is invalid, "
+ "must be s, p, f, a, l, L or r.\n",
TCID);
- exit(1);
+ ret = 1;
}
break;
@@ -299,42 +302,29 @@
case 'i':
case 'n': /* number writes per child */
if (sscanf(optarg, "%d", &num_writes) != 1) {
- fprintf(stderr,
- "%s: --i/n option invalid arg '%s'.\n",
- TCID, optarg);
- usage();
- exit(1);
+ fprintf(stderr, "%s: --i/n option invalid "
+ "arg '%s'.\n", TCID, optarg);
+ ret = 1;
} else if (num_writes < 0) {
- fprintf(stderr,
- "%s: --i/n option must be greater than equal to zero.\n",
+ fprintf(stderr, "%s: --i/n option must be "
+ "greater than equal to zero.\n",
TCID);
- usage();
- exit(1);
+ ret = 1;
}
if (num_writes == 0) /* loop forever */
++loop;
-
- break;
- case 'P': /* panic flag */
- fprintf(stderr,
- "%s: --P not supported on this architecture\n",
- TCID);
- exit(1);
break;
case 'p': /* ping */
if (sscanf(optarg, "%d", &num_rpt) != 1) {
fprintf(stderr,
"%s: --p option invalid arg '%s'.\n",
TCID, optarg);
- usage();
- exit(1);
+ ret = 1;
} else if (num_rpt < 0) {
- fprintf(stderr,
- "%s: --p option must be greater than equal to zero.\n",
- TCID);
- usage();
- exit(1);
+ fprintf(stderr, "%s: --p option must be greater"
+ " than equal to zero.\n", TCID);
+ ret = 1;
}
break;
case 'q': /* Quiet - NOPASS */
@@ -345,14 +335,11 @@
fprintf(stderr,
"%s: --s option invalid arg '%s'.\n",
TCID, optarg);
- usage();
- exit(1);
+ ret = 1;
} else if (size <= 0) {
- fprintf(stderr,
- "%s: --s option must be greater than zero.\n",
- TCID);
- usage();
- exit(1);
+ fprintf(stderr, "%s: --s option must be greater"
+ " than zero.\n", TCID);
+ ret = 1;
}
break;
case 'u':
@@ -361,20 +348,17 @@
case 'v': /* verbose */
verbose = 1;
break;
- case 'W': /* max wait time between writes */
+ case 'W': /* max wait time between reads */
d = strtod(optarg, &cp);
if (*cp != '\0') {
fprintf(stderr,
"%s: --w option invalid arg '%s'.\n",
TCID, optarg);
- usage();
- exit(1);
+ ret = 1;
} else if (d < 0) {
- fprintf(stderr,
- "%s: --w option must be greater than zero.\n",
- TCID);
- usage();
- exit(1);
+ fprintf(stderr, "%s: --w option must be greater"
+ " than zero.\n", TCID);
+ ret = 1;
}
parent_wait = (int)(d * 1000000.0);
break;
@@ -384,29 +368,59 @@
fprintf(stderr,
"%s: --w option invalid arg '%s'.\n",
TCID, optarg);
- usage();
- exit(1);
+ ret = 1;
} else if (d < 0) {
- fprintf(stderr,
- "%s: --w option must be greater than zero.\n",
- TCID);
- usage();
- exit(1);
+ fprintf(stderr, "%s: --w option must be greater"
+ " than zero.\n", TCID);
+ ret = 1;
}
chld_wait = (int)(d * 1000000.0);
break;
case '?':
- usage();
- exit(1);
+ ret = 1;
break;
}
+
+ if (ret == 1) {
+ usage();
+ return ret;
+ }
}
+ return ret;
+}
+
+static void setup(int argc, char *argv[])
+{
+ int ret;
+ char *toutput;
+ int fds[2];
+
+ tst_sig(FORK, DEF_HANDLER, cleanup);
+
+ TEST_PAUSE;
+
+ tst_tmpdir();
+
+ if (signal(SIGCHLD, sig_child) == SIG_ERR) {
+ tst_brkm(TBROK | TERRNO, cleanup,
+ "set signal handler for SIGCHLD failed");
+ }
+
+ toutput = getenv("TOUTPUT");
+ if (toutput != NULL && strcmp(toutput, "NOPASS") == 0)
+ quiet = 1;
+
+ sprintf(pname, "%s", "tpipe");
+
+ ret = parse_options(argc, argv);
+ if (ret == 1)
+ tst_brkm(TBROK, cleanup, "options parse error");
+
if (format_size == -1)
format_size = size;
/*
- *
* If there is more than one writer, all writes and reads
* must be the same size. Only writes of a size <= PIPE_BUF
* are atomic. T
@@ -422,376 +436,306 @@
* bytes will be written.) This is the same as:
* pipeio -s 4096 -n 13 -c 5
*/
- if (size > PIPE_BUF && num_wrters > 1) {
+ if (size > PIPE_BUF && num_writers > 1) {
if (!loop) {
- /* we must set num_writes s.t. num_writes*num_wrters doesn't overflow later */
- num_writes =
- MIN(((long long)num_writes * size + PIPE_BUF -
- 1) / PIPE_BUF, INT_MAX / num_wrters);
- tst_resm(TINFO,
- "adjusting i/o size to %d, and # of writes to %d",
- PIPE_BUF, num_writes);
+ /*
+ * we must set num_writes*num_writers
+ * doesn't overflow later
+ */
+ num_writes = MIN(((long long)num_writes * size +
+ PIPE_BUF - 1) / PIPE_BUF,
+ INT_MAX / num_writers);
+ tst_resm(TINFO, "adjusting i/o size to %d, and # of "
+ "writes to %d", PIPE_BUF, num_writes);
} else {
tst_resm(TINFO, "adjusting i/o size to %d", PIPE_BUF);
}
size = PIPE_BUF;
-
}
- if ((writebuf = (char *)malloc(size)) == NULL ||
- (readbuf = (char *)malloc(size)) == NULL) {
- tst_resm(TFAIL | TERRNO, "malloc() failed");
- SAFE_FREE(writebuf);
- SAFE_FREE(readbuf);
- exit(1);
- }
+ writebuf = SAFE_MALLOC(cleanup, size);
+ readbuf = SAFE_MALLOC(cleanup, size);
memset(writebuf, 'Z', size);
+ writebuf[size - 1] = 'A';
- writebuf[size - 1] = 'A'; /* to detect partial read/write problem */
-
- if ((sem_id = semget(IPC_PRIVATE, 2, IPC_CREAT | S_IRWXU)) == -1) {
- tst_brkm(TBROK | TERRNO, NULL, "Couldn't allocate semaphore");
+ sem_id = semget(IPC_PRIVATE, 2, IPC_CREAT | S_IRWXU);
+ if (sem_id == -1) {
+ tst_brkm(TBROK | TERRNO, cleanup,
+ "Couldn't allocate semaphore");
}
- if (semctl(sem_id, 0, SETVAL, u) == -1)
- tst_brkm(TBROK | TERRNO, NULL,
+ if (semctl(sem_id, 0, SETVAL, u) == -1) {
+ tst_brkm(TBROK | TERRNO, cleanup,
"Couldn't initialize semaphore 0 value");
+ }
- /* semaphore to hold off children from exiting until open() completes */
- if (semctl(sem_id, 1, SETVAL, u) == -1)
- tst_brkm(TBROK | TERRNO, NULL,
+ if (semctl(sem_id, 1, SETVAL, u) == -1) {
+ tst_brkm(TBROK | TERRNO, cleanup,
"Couldn't initialize semaphore 1 value");
-
- if (background) {
- if ((n = fork()) == -1) {
- tst_resm(TFAIL | TERRNO, "fork() failed");
- exit(1);
- } else if (n != 0) /* parent */
- exit(0);
}
if (unpipe) {
- if (pipe(fds) == -1) {
- tst_resm(TFAIL | TERRNO,
- "pipe() failed to create un-named pipe");
- exit(1);
- }
+ SAFE_PIPE(cleanup, fds);
read_fd = fds[0];
write_fd = fds[1];
pipe_type = PIPE_UNNAMED;
blk_type = UNNAMED_IO;
} else {
- if (strlen(dir) && chdir(dir) == -1) {
- tst_resm(TFAIL | TERRNO, "chdir(%s) failed", dir);
- exit(1);
- }
-
- if (stat(pname, &stbuf) == -1) {
-
- if (mkfifo(pname, 0777) == -1) {
- tst_resm(TFAIL | TERRNO,
- "mkfifo(%s,0777) failed", pname);
- exit(1);
- }
+ if (mkfifo(pname, 0777) == -1) {
+ tst_brkm(TBROK | TERRNO, cleanup,
+ "mkfifo(%s, 0777) failed", pname);
}
pipe_type = PIPE_NAMED;
}
+}
- start_time = time(0);
-
-#if DEBUG
- printf("num_wrters = %d\n", num_wrters);
-#endif
-
-#ifdef linux
- signal(SIGCHLD, sig_child);
- signal(SIGHUP, sig_handler);
- signal(SIGINT, sig_handler);
- signal(SIGQUIT, sig_handler);
-#ifdef SIGRECOVERY
- signal(SIGRECOVERY, sig_handler);
-#endif /* SIGRECOVERY */
-#else
- sigset(SIGCHLD, sig_child);
- sigset(SIGHUP, sig_handler);
- sigset(SIGINT, sig_handler);
- sigset(SIGQUIT, sig_handler);
-#ifdef SIGRECOVERY
- sigset(SIGRECOVERY, sig_handler);
-#endif /* SIGRECOVERY */
-#endif /* linux */
-
- for (i = num_wrters; i > 0; --i) {
- if ((c = fork()) < 0) {
- tst_resm(TFAIL | TERRNO, "fork() failed");
- exit(1);
- }
- if (c == 0)
- break; /* stop child from forking */
- }
- if (c == 0) { /***** if child *****/
-#if DEBUG
- printf("child after fork pid = %d\n", getpid());
-#endif
- if (!unpipe) {
- if ((write_fd = open(pname, O_WRONLY)) == -1) {
- tst_resm(TFAIL | TERRNO,
- "child pipe open(%s, %#o) failed",
- pname, O_WRONLY | ndelay);
- exit(1);
- }
- if (ndelay
- && fcntl(write_fd, F_SETFL, O_NONBLOCK) == -1) {
- tst_brkm(TBROK | TERRNO, NULL,
- "Failed setting the pipe to nonblocking mode");
- }
- } else {
- close(read_fd);
- }
-
- sem_op = (struct sembuf) {
- .sem_num = 0,.sem_op = 1,.sem_flg = 0};
-
- if (semop(sem_id, &sem_op, 1) == -1)
- tst_brkm(TBROK | TERRNO, NULL,
- "Couldn't raise the semaphore 0");
-
- pid_word = (int *)&writebuf[0];
- count_word = (int *)&writebuf[NBPW];
-
- for (j = 0; j < num_writes || loop; ++j) {
-
- /* writes are only in one unit when the size of the write
- * is <= PIPE_BUF.
- * Therefore, if size is greater than PIPE_BUF, we will break
- * the writes into PIPE_BUF chunks.
- * All writes and read need to be same size.
- */
-
- /*
- * write pid and count in first two
- * words of buffer
- */
-
- *count_word = j;
- *pid_word = getpid();
-
- if ((nb =
- lio_write_buffer(write_fd, iotype, writebuf, size,
- SIGUSR1, &cp, 0)) < 0) {
- /*
- * If lio_write_buffer returns a negative number,
- * the return will be -errno.
- */
- tst_resm(TFAIL,
- "pass %d: lio_write_buffer(%s) failed; it returned %d: %s",
- j, cp, nb, strerror(-nb));
- exit(1);
- } else if (nb != size) {
- tst_resm(TFAIL,
- "pass %d: lio_write_buffer(%s) failed, write count %d, but expected to write %d",
- j, cp, nb, size);
- }
- if (verbose)
- tst_resm(TINFO,
- "pass %d: pid %d: wrote %d bytes, expected %d bytes",
- j, getpid(), nb, size);
-
- if (chld_wait) {
- clock = time(0);
- srand48(clock);
- n = lrand48() % chld_wait;
- usleep(n);
- }
- fflush(stderr);
- }
-
- /* child waits until parent completes open() */
- sem_op = (struct sembuf) {
- .sem_num = 1,.sem_op = -1,.sem_flg = 0};
- if (semop(sem_id, &sem_op, 1) == -1)
- tst_brkm(TBROK | TERRNO, NULL,
- "Couldn't lower the semaphore 1");
- }
- if (c > 0) { /***** if parent *****/
-
- if (!unpipe) {
- if ((read_fd = open(pname, O_RDONLY)) == -1) {
- tst_resm(TFAIL | TERRNO,
- "parent pipe open(%s, %#o) failed",
- pname, O_RDONLY);
- exit(1);
- }
- if (ndelay && fcntl(read_fd, F_SETFL, O_NONBLOCK) == -1) {
- tst_brkm(TBROK | TERRNO, NULL,
- "Failed setting the pipe to nonblocking mode");
- }
- } else {
- close(write_fd);
- }
-
- /* raise semaphore so children can exit */
- sem_op = (struct sembuf) {
- .sem_num = 1,.sem_op = num_wrters,.sem_flg = 0};
- if (semop(sem_id, &sem_op, 1) == -1)
- tst_brkm(TBROK | TERRNO, NULL,
- "Couldn't raise the semaphore 1");
-
- sem_op = (struct sembuf) {
- .sem_num = 0,.sem_op = -num_wrters,.sem_flg = 0};
-
- while (Nchildcomplete < num_wrters
- && semop(sem_id, &sem_op, 1) == -1) {
- if (errno == EINTR) {
- continue;
- }
- tst_brkm(TBROK | TERRNO, NULL,
- "Couldn't wait on semaphore 0");
- }
-
- for (i = num_wrters * num_writes; i > 0 || loop; --i) {
- if (error >= MAX_ERRS || empty_read >= MAX_EMPTY)
- break;
- if (parent_wait) {
- clock = time(0);
- srand48(clock);
- n = lrand48() % parent_wait;
- usleep(n);
- }
- ++count;
- if ((nb =
- lio_read_buffer(read_fd, iotype, readbuf, size,
- SIGUSR1, &cp, 0)) < 0) {
- /*
- * If lio_read_buffer returns a negative number,
- * the return will be -errno.
- */
- tst_resm(TFAIL,
- "pass %d: lio_read_buffer(%s) failed; it returned %d: %s",
- i, cp, nb, strerror(-nb));
- ++i;
- count--;
- error++;
- continue;
-
- } else {
- if (nb == 0) {
- if (Nchildcomplete >= num_wrters) {
- if (!loop)
- tst_resm(TWARN,
- "The children have died prematurely");
- break; /* All children have died */
- }
- empty_read++;
-/*
- fprintf(stdout,
- "%s: Nothing on the pipe (%d),read count %d (read not counted)\n",
- TCID,empty_read,count);
- fflush(stdout);
- */
- ++i;
- count--;
- continue;
- } else if (nb < size && size <= PIPE_BUF) {
- tst_resm(TFAIL,
- "pass %d: partial read from the pipe: read %d bytes, expected %d, read count %d",
- i, nb, size, count);
- ++error;
- } else if (nb == size) {
- for (j = 2 * NBPW; j < size; ++j) {
- if (writebuf[j] != readbuf[j]) {
- ++error;
- tst_resm(TFAIL,
- "1 FAIL data error on byte %d; rd# %d, sz= %d, %s %s empty_reads= %d, err= %d",
- j, count, size,
- pipe_type,
- blk_type,
- empty_read,
- error);
- prt_buf(&readbuf,
- readbuf,
- format_size,
- format);
- fflush(stdout);
- if (exit_error
- && exit_error ==
- error)
- goto output;
-
- else
- break;
- }
- }
- }
- if (verbose || (num_rpt && !(count % num_rpt))) {
- current_time = time(0);
- diff_time = current_time - start_time; /* elapsed time */
- tst_resm(TFAIL,
- "(%d) rd# %d, sz= %d, %s %s empty_reads= %d, err= %d\n",
- (int)diff_time, count, size,
- pipe_type, blk_type,
- empty_read, error);
- fflush(stdout);
- }
- }
- }
- if (empty_read)
- tst_resm(TWARN, "%d empty reads", empty_read);
-output:
- if (error)
- tst_resm(TFAIL,
- "1 FAIL %d data errors on pipe, read size = %d, %s %s",
- error, size, pipe_type, blk_type);
- else if (!quiet)
- tst_resm(TPASS,
- "1 PASS %d pipe reads complete, read size = %d, %s %s",
- count + 1, size, pipe_type, blk_type);
-
- /* wait for all children to finish, timeout after uwait_total
- semtimedop might not be available everywhere */
- for (i = 0; i < uwait_total; i += uwait_iter) {
- if (semctl(sem_id, 1, GETVAL) == 0) {
- break;
- }
- usleep(uwait_iter);
- }
-
- if (i > uwait_total) {
- tst_resm(TWARN,
- "Timed out waiting for child processes to exit");
- }
-
- semctl(sem_id, 0, IPC_RMID);
-
- if (!unpipe)
- unlink(pname);
- }
+static void cleanup(void)
+{
+ TEST_CLEANUP;
SAFE_FREE(writebuf);
SAFE_FREE(readbuf);
- return (error);
+
+ semctl(sem_id, 0, IPC_RMID);
+
+ if (!unpipe)
+ SAFE_UNLINK(NULL, pname);
+
+ tst_rmdir();
}
-void usage()
+static void do_child(void)
{
- fprintf(stderr,
- "Usage: %s [-BbCEv][-c #writers][-D pname][-d dir][-h][-e exit_num][-f fmt][-l][-i #writes][-n #writes][-p num_rpt]\n\t[-s size][-W max_wait][-w max_wait][-u]\n",
- TCID);
- fflush(stderr);
+ int *count_word; /* holds address where to write writers count */
+ int *pid_word; /* holds address where to write writers pid */
+ int nb, j;
+ long clock;
+ char *cp;
+ long int n;
+ struct sembuf sem_op;
+ pid_t self_pid = getpid();
+ if (!unpipe) {
+ write_fd = open(pname, O_WRONLY);
+ if (write_fd == -1) {
+ fprintf(stderr, "child pipe open(%s, %#o) failed",
+ pname, O_WRONLY | ndelay);
+ exit(1);
+ }
+ if (ndelay && fcntl(write_fd, F_SETFL, O_NONBLOCK) == -1) {
+ fprintf(stderr, "Failed setting the pipe to "
+ "nonblocking mode");
+ exit(1);
+ }
+ } else {
+ close(read_fd);
+ }
+
+ sem_op = (struct sembuf) {
+ .sem_num = 0, .sem_op = 1, .sem_flg = 0};
+
+ if (semop(sem_id, &sem_op, 1) == -1) {
+ fprintf(stderr, "child: %d couldn't raise the semaphore 0",
+ self_pid);
+ exit(1);
+ }
+
+ pid_word = (int *)&writebuf[0];
+ count_word = (int *)&writebuf[NBPW];
+
+ for (j = 0; j < num_writes || loop; ++j) {
+ /*
+ * writes are only in one unit when the size of the write
+ * is <= PIPE_BUF.
+ * Therefore, if size is greater than PIPE_BUF, we will break
+ * the writes into PIPE_BUF chunks.
+ * All writes and read need to be same size.
+ */
+
+ /*
+ * write pid and count in first two
+ * words of buffer
+ */
+ *count_word = j;
+ *pid_word = self_pid;
+
+ nb = lio_write_buffer(write_fd, iotype, writebuf, size,
+ SIGUSR1, &cp, 0);
+ if (nb < 0) {
+ /*
+ * If lio_write_buffer returns a negative number,
+ * the return will be -errno.
+ */
+ fprintf(stderr, "pass %d: lio_write_buffer(%s) failed;"
+ " it returned %d: %s",
+ j, cp, nb, strerror(-nb));
+ exit(1);
+ } else if (nb != size) {
+ fprintf(stderr, "pass %d: lio_write_buffer(%s) failed,"
+ " write count %d, but expected to write %d",
+ j, cp, nb, size);
+ }
+ if (verbose) {
+ fprintf(stderr, "pass %d: pid %d: wrote %d bytes,"
+ "expected %d bytes",
+ j, self_pid, nb, size);
+ }
+
+ if (chld_wait) {
+ clock = time(0);
+ srand48(clock);
+ n = lrand48() % chld_wait;
+ usleep(n);
+ }
+ fflush(stderr);
+ }
+
+ /* child waits until parent completes open() */
+ sem_op = (struct sembuf) {
+ .sem_num = 1, .sem_op = -1, .sem_flg = 0};
+ if (semop(sem_id, &sem_op, 1) == -1)
+ fprintf(stderr, "Couldn't lower the semaphore 1");
+
+ exit(0);
}
-void help()
+static int check_rw_buf(void)
+{
+ int i;
+
+ for (i = 2 * NBPW; i < size; ++i) {
+ if (writebuf[i] != readbuf[i]) {
+ ++error;
+ tst_resm(TFAIL,
+ "FAIL data error on byte %d; rd# %d, sz= %d, "
+ "%s %s empty_reads= %d, err= %d",
+ i, count, size, pipe_type, blk_type,
+ empty_read, error);
+ prt_buf(&readbuf, readbuf, format_size, format);
+ fflush(stdout);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void do_parent(void)
+{
+ int i, nb;
+ long clock;
+ time_t start_time, current_time, diff_time;
+ char *cp;
+ long int n;
+ struct sembuf sem_op;
+
+ start_time = time(0);
+ if (!unpipe) {
+ read_fd = SAFE_OPEN(cleanup, pname, O_RDONLY);
+ if (ndelay && fcntl(read_fd, F_SETFL, O_NONBLOCK) == -1) {
+ tst_brkm(TBROK | TERRNO, cleanup,
+ "Failed setting the pipe to nonblocking mode");
+ }
+ } else {
+ SAFE_CLOSE(cleanup, write_fd);
+ }
+
+ /* raise semaphore so children can exit */
+ sem_op = (struct sembuf) {
+ .sem_num = 1, .sem_op = num_writers, .sem_flg = 0};
+ if (semop(sem_id, &sem_op, 1) == -1) {
+ tst_brkm(TBROK | TERRNO, cleanup,
+ "Couldn't raise the semaphore 1");
+ }
+
+ sem_op = (struct sembuf) {
+ .sem_num = 0, .sem_op = -num_writers, .sem_flg = 0};
+
+ while (nchildcompleted < num_writers
+ && semop(sem_id, &sem_op, 1) == -1) {
+ if (errno == EINTR)
+ continue;
+ tst_brkm(TBROK | TERRNO, cleanup,
+ "Couldn't wait on semaphore 0");
+ }
+
+ /* parent start to read pipe */
+ for (i = num_writers * num_writes; i > 0 || loop; --i) {
+ if (error >= MAX_ERRS || empty_read >= MAX_EMPTY)
+ break;
+ if (parent_wait) {
+ clock = time(0);
+ srand48(clock);
+ n = lrand48() % parent_wait;
+ usleep(n);
+ }
+ ++count;
+ nb = lio_read_buffer(read_fd, iotype, readbuf, size,
+ SIGUSR1, &cp, 0);
+ if (nb < 0) {
+ /*
+ * If lio_read_buffer returns a negative number,
+ * the return will be -errno.
+ */
+ tst_resm(TFAIL, "pass %d: lio_read_buffer(%s) failed; "
+ "returned %d: %s", i, cp, nb, strerror(-nb));
+ ++i;
+ count--;
+ error++;
+ continue;
+ } else {
+ if (nb == 0) {
+ if (nchildcompleted >= num_writers && !loop) {
+ tst_resm(TWARN, "The children have "
+ "died prematurely");
+ break; /* All children have died */
+ }
+ empty_read++;
+ ++i;
+ count--;
+ continue;
+ } else if (nb < size && size <= PIPE_BUF) {
+ tst_resm(TFAIL, "pass %d: partial read from the"
+ " pipe: read %d bytes, expected %d, "
+ "read count %d", i, nb, size, count);
+ ++error;
+ } else if (nb == size) {
+ check_rw_buf();
+ if (exit_error && exit_error == error)
+ return;
+ }
+
+ if (verbose || (num_rpt && !(count % num_rpt))) {
+ current_time = time(0);
+ diff_time = current_time - start_time;
+ tst_resm(TFAIL,
+ "(%d) rd# %d, sz= %d, %s %s "
+ "empty_reads= %d, err= %d\n",
+ (int)diff_time, count, size,
+ pipe_type, blk_type,
+ empty_read, error);
+ fflush(stdout);
+ }
+ }
+ }
+}
+
+static void usage(void)
+{
+ fprintf(stderr, "Usage: %s [-bEv][-c #writers][-D pname][-h]"
+ "[-e exit_num][-f fmt][-l][-i #writes][-n #writes][-p num_rpt]"
+ "\n\t[-s size][-W max_wait][-w max_wait][-u]\n", TCID);
+ fflush(stderr);
+}
+
+static void help(void)
{
usage();
- printf(" -B - execute actions in background\n\
- -b - blocking reads and writes. default non-block\n\
+ printf(" -b - blocking reads and writes. default non-block\n\
-c #writers - number of writers (childern)\n\
-D pname - name of fifo (def tpipe<pid>)\n\
- -d dir - cd to dir before creating named pipe\n\
- - (silently ignored if used with -u)\n\
-h - print this help message\n\
-e exit_num - exit on error exit_num, 0 is ignore errors, 1 is default.\n\
-E - print cmd line examples and exit\n\
@@ -815,12 +759,10 @@
-v - verbose mode, all writes/reads resutlts printed\n");
fflush(stdout);
-
}
-void prt_buf(long addr, char *buf, int length, int format)
+static void prt_buf(char **addr, char *buf, int length, int format)
{
-
int i;
int num_words = length / NBPW; /* given length in bytes, get length in words */
int width; /* number of columns */
@@ -856,13 +798,13 @@
* get the last 2 words printed
*/
memcpy(c, a - (width * NBPW), width * NBPW);
- for (p = c; (p - c) < width * NBPW; ++p) {
+ for (p = c; (p - c) < (int)(width*NBPW); ++p) {
if (*p < '!' || *p > '~')
*p = '.';
}
printf("\t%16.16s", c);
}
- printf("\n%7lo: ", addr);
+ printf("\n%p: ", addr);
/***printf("\n%7o (%d): ",addr,i);***/
}
@@ -875,7 +817,7 @@
break;
case ASCII:
memcpy(b, a, NBPW);
- for (p = b; (p - b) < NBPW; ++p) {
+ for (p = b; (p - b) < (int)NBPW; ++p) {
if (*p < '!' || *p > '~')
*p = '.';
}
@@ -895,7 +837,7 @@
if (extra_words)
width = extra_words; /* odd number of words */
memcpy(c, a - (width * NBPW), width * NBPW);
- for (p = c; (p - c) < width * NBPW; ++p) {
+ for (p = c; (p - c) < (int)(width * NBPW); ++p) {
if (*p < '!' || *p > '~')
*p = '.';
}
@@ -908,46 +850,21 @@
fflush(stdout);
}
-void prt_examples()
+static void prt_examples(void)
{
printf("%s -c 5 -i 0 -s 4090 -b\n", TCID);
printf("%s -c 5 -i 0 -s 4090 -b -u \n", TCID);
printf("%s -c 5 -i 0 -s 4090 -b -W 3 -w 3 \n", TCID);
-
}
-void sig_child(int sig)
+static void sig_child(int sig)
{
int status;
- Nchildcomplete++;
+ nchildcompleted++;
#if DEBUG
- printf("parent: received SIGCHLD\n");
+ #define STR "parent: received SIGCHLD\n"
+ write(STDOUT_FILENO, str, strlen(STR));
#endif
waitpid(-1, &status, WNOHANG);
-#if linux
- signal(SIGCHLD, sig_child);
-#else
- sigset(SIGCHLD, sig_child);
-#endif
-}
-
-void sig_handler(int sig)
-{
-#ifdef SIGRECOVERY
- if (sig == SIGRECOVERY) {
- printf("%s: received SIGRECOVERY, count = %d\n", TCID, count);
- fflush(stdout);
-#ifdef linux
- signal(sig, sig_handler);
-#else
- sigset(sig, sig_handler);
-#endif
- return;
- }
-#endif
- printf("%s: received unexpected signal: %d\n", TCID, sig);
- fflush(stdout);
- exit(3);
-
}