1*49cdfc7eSAndroid Build Coastguard Worker /*
2*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
3*49cdfc7eSAndroid Build Coastguard Worker *
4*49cdfc7eSAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or modify it
5*49cdfc7eSAndroid Build Coastguard Worker * under the terms of version 2 of the GNU General Public License as
6*49cdfc7eSAndroid Build Coastguard Worker * published by the Free Software Foundation.
7*49cdfc7eSAndroid Build Coastguard Worker *
8*49cdfc7eSAndroid Build Coastguard Worker * This program is distributed in the hope that it would be useful, but
9*49cdfc7eSAndroid Build Coastguard Worker * WITHOUT ANY WARRANTY; without even the implied warranty of
10*49cdfc7eSAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11*49cdfc7eSAndroid Build Coastguard Worker *
12*49cdfc7eSAndroid Build Coastguard Worker * Further, this software is distributed without any warranty that it is
13*49cdfc7eSAndroid Build Coastguard Worker * free of the rightful claim of any third person regarding infringement
14*49cdfc7eSAndroid Build Coastguard Worker * or the like. Any license provided herein, whether implied or
15*49cdfc7eSAndroid Build Coastguard Worker * otherwise, applies only to this software file. Patent licenses, if
16*49cdfc7eSAndroid Build Coastguard Worker * any, provided herein do not apply to combinations of this program with
17*49cdfc7eSAndroid Build Coastguard Worker * other software, or any other product whatsoever.
18*49cdfc7eSAndroid Build Coastguard Worker *
19*49cdfc7eSAndroid Build Coastguard Worker * You should have received a copy of the GNU General Public License along
20*49cdfc7eSAndroid Build Coastguard Worker * with this program; if not, write the Free Software Foundation, Inc.,
21*49cdfc7eSAndroid Build Coastguard Worker * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22*49cdfc7eSAndroid Build Coastguard Worker *
23*49cdfc7eSAndroid Build Coastguard Worker * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24*49cdfc7eSAndroid Build Coastguard Worker * Mountain View, CA 94043, or:
25*49cdfc7eSAndroid Build Coastguard Worker *
26*49cdfc7eSAndroid Build Coastguard Worker * http://www.sgi.com
27*49cdfc7eSAndroid Build Coastguard Worker *
28*49cdfc7eSAndroid Build Coastguard Worker * For further information regarding this notice, see:
29*49cdfc7eSAndroid Build Coastguard Worker *
30*49cdfc7eSAndroid Build Coastguard Worker * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
31*49cdfc7eSAndroid Build Coastguard Worker *
32*49cdfc7eSAndroid Build Coastguard Worker */
33*49cdfc7eSAndroid Build Coastguard Worker /* $Header: /cvsroot/ltp/ltp/testcases/kernel/ipc/pipeio/pipeio.c,v 1.18 2009/03/19 07:10:02 subrata_modak Exp $ */
34*49cdfc7eSAndroid Build Coastguard Worker /*
35*49cdfc7eSAndroid Build Coastguard Worker * This tool can be used to beat on system or named pipes.
36*49cdfc7eSAndroid Build Coastguard Worker * See the help() function below for user information.
37*49cdfc7eSAndroid Build Coastguard Worker */
38*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
39*49cdfc7eSAndroid Build Coastguard Worker #include <fcntl.h>
40*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
41*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
42*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
43*49cdfc7eSAndroid Build Coastguard Worker #include <sys/param.h>
44*49cdfc7eSAndroid Build Coastguard Worker #include <sys/wait.h>
45*49cdfc7eSAndroid Build Coastguard Worker #include <time.h>
46*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
47*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
48*49cdfc7eSAndroid Build Coastguard Worker #include <signal.h>
49*49cdfc7eSAndroid Build Coastguard Worker #include <sys/stat.h>
50*49cdfc7eSAndroid Build Coastguard Worker
51*49cdfc7eSAndroid Build Coastguard Worker #include "tlibio.h"
52*49cdfc7eSAndroid Build Coastguard Worker
53*49cdfc7eSAndroid Build Coastguard Worker #include "test.h"
54*49cdfc7eSAndroid Build Coastguard Worker #include "safe_macros.h"
55*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/sem.h"
56*49cdfc7eSAndroid Build Coastguard Worker
57*49cdfc7eSAndroid Build Coastguard Worker char *TCID = "pipeio";
58*49cdfc7eSAndroid Build Coastguard Worker int TST_TOTAL = 1;
59*49cdfc7eSAndroid Build Coastguard Worker
60*49cdfc7eSAndroid Build Coastguard Worker #define SAFE_FREE(p) { if (p) { free(p); (p)=NULL; } }
61*49cdfc7eSAndroid Build Coastguard Worker
62*49cdfc7eSAndroid Build Coastguard Worker #if defined(__linux__)
63*49cdfc7eSAndroid Build Coastguard Worker #define NBPW sizeof(int)
64*49cdfc7eSAndroid Build Coastguard Worker #endif
65*49cdfc7eSAndroid Build Coastguard Worker
66*49cdfc7eSAndroid Build Coastguard Worker #define OCTAL 'o'
67*49cdfc7eSAndroid Build Coastguard Worker #define HEX 'x'
68*49cdfc7eSAndroid Build Coastguard Worker #define DECIMAL 'd'
69*49cdfc7eSAndroid Build Coastguard Worker #define ASCII 'a'
70*49cdfc7eSAndroid Build Coastguard Worker #define NO_OUT 'n'
71*49cdfc7eSAndroid Build Coastguard Worker
72*49cdfc7eSAndroid Build Coastguard Worker #define PIPE_NAMED "named pipe,"
73*49cdfc7eSAndroid Build Coastguard Worker #define PIPE_UNNAMED "sys pipe,"
74*49cdfc7eSAndroid Build Coastguard Worker
75*49cdfc7eSAndroid Build Coastguard Worker #define BLOCKING_IO "blking,"
76*49cdfc7eSAndroid Build Coastguard Worker #define NON_BLOCKING_IO "non-blking,"
77*49cdfc7eSAndroid Build Coastguard Worker #define UNNAMED_IO ""
78*49cdfc7eSAndroid Build Coastguard Worker
79*49cdfc7eSAndroid Build Coastguard Worker #define MAX_ERRS 16
80*49cdfc7eSAndroid Build Coastguard Worker #define MAX_EMPTY 256
81*49cdfc7eSAndroid Build Coastguard Worker
82*49cdfc7eSAndroid Build Coastguard Worker static int parse_options(int argc, char *argv[]);
83*49cdfc7eSAndroid Build Coastguard Worker static void setup(int argc, char *argv[]);
84*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void);
85*49cdfc7eSAndroid Build Coastguard Worker
86*49cdfc7eSAndroid Build Coastguard Worker static void do_child(void);
87*49cdfc7eSAndroid Build Coastguard Worker static void do_parent(void);
88*49cdfc7eSAndroid Build Coastguard Worker
89*49cdfc7eSAndroid Build Coastguard Worker static void help(void), usage(void), prt_examples(void);
90*49cdfc7eSAndroid Build Coastguard Worker static void prt_buf(char **addr, char *buf, int length, int format);
91*49cdfc7eSAndroid Build Coastguard Worker static void sig_child(int sig);
92*49cdfc7eSAndroid Build Coastguard Worker static int check_rw_buf(void);
93*49cdfc7eSAndroid Build Coastguard Worker
94*49cdfc7eSAndroid Build Coastguard Worker static volatile sig_atomic_t nchildcompleted;
95*49cdfc7eSAndroid Build Coastguard Worker
96*49cdfc7eSAndroid Build Coastguard Worker /* variables may be modified in setup() */
97*49cdfc7eSAndroid Build Coastguard Worker static int num_writers = 1; /* number of writers */
98*49cdfc7eSAndroid Build Coastguard Worker static int num_writes = 1; /* number of writes per child */
99*49cdfc7eSAndroid Build Coastguard Worker static int loop; /* loop indefinitely */
100*49cdfc7eSAndroid Build Coastguard Worker static int exit_error = 1; /* exit on error #, zero means no exit */
101*49cdfc7eSAndroid Build Coastguard Worker static int size = 327; /* default size */
102*49cdfc7eSAndroid Build Coastguard Worker static int unpipe; /* un-named pipe if non-zero */
103*49cdfc7eSAndroid Build Coastguard Worker static int verbose; /* verbose mode if set */
104*49cdfc7eSAndroid Build Coastguard Worker static int quiet; /* quiet mode if set */
105*49cdfc7eSAndroid Build Coastguard Worker static int num_rpt; /* ping number, how often to print message */
106*49cdfc7eSAndroid Build Coastguard Worker static int chld_wait; /* max time to wait between writes, 1 == no wait */
107*49cdfc7eSAndroid Build Coastguard Worker static int parent_wait; /* max time to wait between reads, 1 == no wait */
108*49cdfc7eSAndroid Build Coastguard Worker static int ndelay = O_NDELAY; /* additional flag to open */
109*49cdfc7eSAndroid Build Coastguard Worker static char *writebuf;
110*49cdfc7eSAndroid Build Coastguard Worker static char *readbuf;
111*49cdfc7eSAndroid Build Coastguard Worker static char pname[PATH_MAX]; /* contains the name of the named pipe */
112*49cdfc7eSAndroid Build Coastguard Worker static char *blk_type = NON_BLOCKING_IO; /* blocking i/o or not */
113*49cdfc7eSAndroid Build Coastguard Worker static char *pipe_type; /* type of pipe under test */
114*49cdfc7eSAndroid Build Coastguard Worker static int format = HEX;
115*49cdfc7eSAndroid Build Coastguard Worker static int format_size = -1;
116*49cdfc7eSAndroid Build Coastguard Worker static int iotype; /* sync io */
117*49cdfc7eSAndroid Build Coastguard Worker
118*49cdfc7eSAndroid Build Coastguard Worker /* variables will be modified in running */
119*49cdfc7eSAndroid Build Coastguard Worker static int error;
120*49cdfc7eSAndroid Build Coastguard Worker static int count;
121*49cdfc7eSAndroid Build Coastguard Worker static int read_fd;
122*49cdfc7eSAndroid Build Coastguard Worker static int write_fd;
123*49cdfc7eSAndroid Build Coastguard Worker static int empty_read;
124*49cdfc7eSAndroid Build Coastguard Worker static int sem_id;
125*49cdfc7eSAndroid Build Coastguard Worker
126*49cdfc7eSAndroid Build Coastguard Worker static union semun u;
127*49cdfc7eSAndroid Build Coastguard Worker
main(int ac,char * av[])128*49cdfc7eSAndroid Build Coastguard Worker int main(int ac, char *av[])
129*49cdfc7eSAndroid Build Coastguard Worker {
130*49cdfc7eSAndroid Build Coastguard Worker int i;
131*49cdfc7eSAndroid Build Coastguard Worker unsigned int j;
132*49cdfc7eSAndroid Build Coastguard Worker unsigned int uwait_iter = 1000, uwait_total = 5000000;
133*49cdfc7eSAndroid Build Coastguard Worker pid_t child;
134*49cdfc7eSAndroid Build Coastguard Worker
135*49cdfc7eSAndroid Build Coastguard Worker setup(ac, av);
136*49cdfc7eSAndroid Build Coastguard Worker
137*49cdfc7eSAndroid Build Coastguard Worker for (i = num_writers; i > 0; --i) {
138*49cdfc7eSAndroid Build Coastguard Worker
139*49cdfc7eSAndroid Build Coastguard Worker child = tst_fork();
140*49cdfc7eSAndroid Build Coastguard Worker switch (child) {
141*49cdfc7eSAndroid Build Coastguard Worker case -1:
142*49cdfc7eSAndroid Build Coastguard Worker tst_brkm(TBROK | TERRNO, cleanup, "fork() failed");
143*49cdfc7eSAndroid Build Coastguard Worker case 0:
144*49cdfc7eSAndroid Build Coastguard Worker do_child();
145*49cdfc7eSAndroid Build Coastguard Worker exit(0);
146*49cdfc7eSAndroid Build Coastguard Worker default:
147*49cdfc7eSAndroid Build Coastguard Worker break;
148*49cdfc7eSAndroid Build Coastguard Worker }
149*49cdfc7eSAndroid Build Coastguard Worker }
150*49cdfc7eSAndroid Build Coastguard Worker
151*49cdfc7eSAndroid Build Coastguard Worker do_parent();
152*49cdfc7eSAndroid Build Coastguard Worker
153*49cdfc7eSAndroid Build Coastguard Worker if (empty_read)
154*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TWARN, "%d empty reads", empty_read);
155*49cdfc7eSAndroid Build Coastguard Worker
156*49cdfc7eSAndroid Build Coastguard Worker if (error) {
157*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TFAIL, "%d data errors on pipe, read size = %d, %s %s",
158*49cdfc7eSAndroid Build Coastguard Worker error, size, pipe_type, blk_type);
159*49cdfc7eSAndroid Build Coastguard Worker } else if (!quiet) {
160*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TPASS, "%d pipe reads complete, read size = %d, %s %s",
161*49cdfc7eSAndroid Build Coastguard Worker count + 1, size, pipe_type, blk_type);
162*49cdfc7eSAndroid Build Coastguard Worker }
163*49cdfc7eSAndroid Build Coastguard Worker
164*49cdfc7eSAndroid Build Coastguard Worker /*
165*49cdfc7eSAndroid Build Coastguard Worker * wait for all children to finish, timeout after uwait_total
166*49cdfc7eSAndroid Build Coastguard Worker * semtimedop might not be available everywhere
167*49cdfc7eSAndroid Build Coastguard Worker */
168*49cdfc7eSAndroid Build Coastguard Worker for (j = 0; j < uwait_total; j += uwait_iter) {
169*49cdfc7eSAndroid Build Coastguard Worker if (semctl(sem_id, 1, GETVAL) == 0)
170*49cdfc7eSAndroid Build Coastguard Worker break;
171*49cdfc7eSAndroid Build Coastguard Worker usleep(uwait_iter);
172*49cdfc7eSAndroid Build Coastguard Worker }
173*49cdfc7eSAndroid Build Coastguard Worker
174*49cdfc7eSAndroid Build Coastguard Worker if (j >= uwait_total) {
175*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TWARN,
176*49cdfc7eSAndroid Build Coastguard Worker "Timed out waiting for child processes to exit");
177*49cdfc7eSAndroid Build Coastguard Worker }
178*49cdfc7eSAndroid Build Coastguard Worker
179*49cdfc7eSAndroid Build Coastguard Worker cleanup();
180*49cdfc7eSAndroid Build Coastguard Worker tst_exit();
181*49cdfc7eSAndroid Build Coastguard Worker }
182*49cdfc7eSAndroid Build Coastguard Worker
parse_options(int argc,char * argv[])183*49cdfc7eSAndroid Build Coastguard Worker static int parse_options(int argc, char *argv[])
184*49cdfc7eSAndroid Build Coastguard Worker {
185*49cdfc7eSAndroid Build Coastguard Worker char *cp;
186*49cdfc7eSAndroid Build Coastguard Worker int c;
187*49cdfc7eSAndroid Build Coastguard Worker int ret = 0;
188*49cdfc7eSAndroid Build Coastguard Worker static double d;
189*49cdfc7eSAndroid Build Coastguard Worker
190*49cdfc7eSAndroid Build Coastguard Worker while ((c = getopt(argc, argv, "T:bc:D:he:Ef:i:I:ln:p:qs:uvW:w:"))
191*49cdfc7eSAndroid Build Coastguard Worker != -1) {
192*49cdfc7eSAndroid Build Coastguard Worker switch (c) {
193*49cdfc7eSAndroid Build Coastguard Worker case 'T':
194*49cdfc7eSAndroid Build Coastguard Worker TCID = optarg;
195*49cdfc7eSAndroid Build Coastguard Worker break;
196*49cdfc7eSAndroid Build Coastguard Worker case 'h':
197*49cdfc7eSAndroid Build Coastguard Worker help();
198*49cdfc7eSAndroid Build Coastguard Worker ret = 1;
199*49cdfc7eSAndroid Build Coastguard Worker break;
200*49cdfc7eSAndroid Build Coastguard Worker case 'D': /* pipe name */
201*49cdfc7eSAndroid Build Coastguard Worker strcpy(pname, optarg);
202*49cdfc7eSAndroid Build Coastguard Worker break;
203*49cdfc7eSAndroid Build Coastguard Worker case 'b': /* blocked */
204*49cdfc7eSAndroid Build Coastguard Worker ndelay = 0;
205*49cdfc7eSAndroid Build Coastguard Worker blk_type = BLOCKING_IO;
206*49cdfc7eSAndroid Build Coastguard Worker break;
207*49cdfc7eSAndroid Build Coastguard Worker case 'c': /* number childern */
208*49cdfc7eSAndroid Build Coastguard Worker if (sscanf(optarg, "%d", &num_writers) != 1) {
209*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr,
210*49cdfc7eSAndroid Build Coastguard Worker "%s: --c option invalid arg '%s'.\n",
211*49cdfc7eSAndroid Build Coastguard Worker TCID, optarg);
212*49cdfc7eSAndroid Build Coastguard Worker ret = 1;
213*49cdfc7eSAndroid Build Coastguard Worker } else if (num_writers <= 0) {
214*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "%s: --c option must be "
215*49cdfc7eSAndroid Build Coastguard Worker "greater than zero.\n", TCID);
216*49cdfc7eSAndroid Build Coastguard Worker ret = 1;
217*49cdfc7eSAndroid Build Coastguard Worker }
218*49cdfc7eSAndroid Build Coastguard Worker break;
219*49cdfc7eSAndroid Build Coastguard Worker case 'e': /* exit on error # */
220*49cdfc7eSAndroid Build Coastguard Worker if (sscanf(optarg, "%d", &exit_error) != 1) {
221*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr,
222*49cdfc7eSAndroid Build Coastguard Worker "%s: --e option invalid arg '%s'.\n",
223*49cdfc7eSAndroid Build Coastguard Worker TCID, optarg);
224*49cdfc7eSAndroid Build Coastguard Worker ret = 1;
225*49cdfc7eSAndroid Build Coastguard Worker } else if (exit_error < 0) {
226*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "%s: --e option must be "
227*49cdfc7eSAndroid Build Coastguard Worker "greater than zero.\n", TCID);
228*49cdfc7eSAndroid Build Coastguard Worker ret = 1;
229*49cdfc7eSAndroid Build Coastguard Worker }
230*49cdfc7eSAndroid Build Coastguard Worker break;
231*49cdfc7eSAndroid Build Coastguard Worker case 'E':
232*49cdfc7eSAndroid Build Coastguard Worker prt_examples();
233*49cdfc7eSAndroid Build Coastguard Worker ret = 1;
234*49cdfc7eSAndroid Build Coastguard Worker break;
235*49cdfc7eSAndroid Build Coastguard Worker case 'f': /* format of buffer on error */
236*49cdfc7eSAndroid Build Coastguard Worker switch (optarg[0]) {
237*49cdfc7eSAndroid Build Coastguard Worker case 'x':
238*49cdfc7eSAndroid Build Coastguard Worker case 'X':
239*49cdfc7eSAndroid Build Coastguard Worker format = HEX;
240*49cdfc7eSAndroid Build Coastguard Worker break;
241*49cdfc7eSAndroid Build Coastguard Worker case 'o':
242*49cdfc7eSAndroid Build Coastguard Worker case 'O':
243*49cdfc7eSAndroid Build Coastguard Worker format = OCTAL;
244*49cdfc7eSAndroid Build Coastguard Worker break;
245*49cdfc7eSAndroid Build Coastguard Worker case 'd':
246*49cdfc7eSAndroid Build Coastguard Worker case 'D':
247*49cdfc7eSAndroid Build Coastguard Worker format = DECIMAL;
248*49cdfc7eSAndroid Build Coastguard Worker break;
249*49cdfc7eSAndroid Build Coastguard Worker case 'a':
250*49cdfc7eSAndroid Build Coastguard Worker case 'A':
251*49cdfc7eSAndroid Build Coastguard Worker format = ASCII;
252*49cdfc7eSAndroid Build Coastguard Worker break;
253*49cdfc7eSAndroid Build Coastguard Worker case 'n': /* not output */
254*49cdfc7eSAndroid Build Coastguard Worker case 'N':
255*49cdfc7eSAndroid Build Coastguard Worker format = NO_OUT;
256*49cdfc7eSAndroid Build Coastguard Worker break;
257*49cdfc7eSAndroid Build Coastguard Worker
258*49cdfc7eSAndroid Build Coastguard Worker default:
259*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr,
260*49cdfc7eSAndroid Build Coastguard Worker "%s: --f option invalid arg '%s'.\n",
261*49cdfc7eSAndroid Build Coastguard Worker TCID, optarg);
262*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "\tIt must be x(hex), o(octal),"
263*49cdfc7eSAndroid Build Coastguard Worker "d(decimal), a(ascii) or n(none) with "
264*49cdfc7eSAndroid Build Coastguard Worker "opt sz\n");
265*49cdfc7eSAndroid Build Coastguard Worker ret = 1;
266*49cdfc7eSAndroid Build Coastguard Worker break;
267*49cdfc7eSAndroid Build Coastguard Worker }
268*49cdfc7eSAndroid Build Coastguard Worker cp = optarg;
269*49cdfc7eSAndroid Build Coastguard Worker cp++;
270*49cdfc7eSAndroid Build Coastguard Worker if (*cp) {
271*49cdfc7eSAndroid Build Coastguard Worker if (sscanf(cp, "%i", &format_size) != 1) {
272*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "%s: --f option invalid"
273*49cdfc7eSAndroid Build Coastguard Worker "arg '%s'.\n", TCID, optarg);
274*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "\tIt must be x(hex),"
275*49cdfc7eSAndroid Build Coastguard Worker "o(octal), d(decimal), a(ascii)"
276*49cdfc7eSAndroid Build Coastguard Worker " or n(none) with opt sz\n");
277*49cdfc7eSAndroid Build Coastguard Worker ret = 1;
278*49cdfc7eSAndroid Build Coastguard Worker break;
279*49cdfc7eSAndroid Build Coastguard Worker }
280*49cdfc7eSAndroid Build Coastguard Worker }
281*49cdfc7eSAndroid Build Coastguard Worker break;
282*49cdfc7eSAndroid Build Coastguard Worker
283*49cdfc7eSAndroid Build Coastguard Worker case 'I':
284*49cdfc7eSAndroid Build Coastguard Worker iotype = lio_parse_io_arg1(optarg);
285*49cdfc7eSAndroid Build Coastguard Worker if (iotype == -1) {
286*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "%s: --I arg is invalid, "
287*49cdfc7eSAndroid Build Coastguard Worker "must be s, p, f, a, l, L or r.\n",
288*49cdfc7eSAndroid Build Coastguard Worker TCID);
289*49cdfc7eSAndroid Build Coastguard Worker ret = 1;
290*49cdfc7eSAndroid Build Coastguard Worker }
291*49cdfc7eSAndroid Build Coastguard Worker break;
292*49cdfc7eSAndroid Build Coastguard Worker
293*49cdfc7eSAndroid Build Coastguard Worker case 'l': /* loop forever */
294*49cdfc7eSAndroid Build Coastguard Worker ++loop;
295*49cdfc7eSAndroid Build Coastguard Worker break;
296*49cdfc7eSAndroid Build Coastguard Worker
297*49cdfc7eSAndroid Build Coastguard Worker case 'i':
298*49cdfc7eSAndroid Build Coastguard Worker case 'n': /* number writes per child */
299*49cdfc7eSAndroid Build Coastguard Worker if (sscanf(optarg, "%d", &num_writes) != 1) {
300*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "%s: --i/n option invalid "
301*49cdfc7eSAndroid Build Coastguard Worker "arg '%s'.\n", TCID, optarg);
302*49cdfc7eSAndroid Build Coastguard Worker ret = 1;
303*49cdfc7eSAndroid Build Coastguard Worker } else if (num_writes < 0) {
304*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "%s: --i/n option must be "
305*49cdfc7eSAndroid Build Coastguard Worker "greater than equal to zero.\n",
306*49cdfc7eSAndroid Build Coastguard Worker TCID);
307*49cdfc7eSAndroid Build Coastguard Worker ret = 1;
308*49cdfc7eSAndroid Build Coastguard Worker }
309*49cdfc7eSAndroid Build Coastguard Worker
310*49cdfc7eSAndroid Build Coastguard Worker if (num_writes == 0) /* loop forever */
311*49cdfc7eSAndroid Build Coastguard Worker ++loop;
312*49cdfc7eSAndroid Build Coastguard Worker break;
313*49cdfc7eSAndroid Build Coastguard Worker case 'p': /* ping */
314*49cdfc7eSAndroid Build Coastguard Worker if (sscanf(optarg, "%d", &num_rpt) != 1) {
315*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr,
316*49cdfc7eSAndroid Build Coastguard Worker "%s: --p option invalid arg '%s'.\n",
317*49cdfc7eSAndroid Build Coastguard Worker TCID, optarg);
318*49cdfc7eSAndroid Build Coastguard Worker ret = 1;
319*49cdfc7eSAndroid Build Coastguard Worker } else if (num_rpt < 0) {
320*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "%s: --p option must be greater"
321*49cdfc7eSAndroid Build Coastguard Worker " than equal to zero.\n", TCID);
322*49cdfc7eSAndroid Build Coastguard Worker ret = 1;
323*49cdfc7eSAndroid Build Coastguard Worker }
324*49cdfc7eSAndroid Build Coastguard Worker break;
325*49cdfc7eSAndroid Build Coastguard Worker case 'q': /* Quiet - NOPASS */
326*49cdfc7eSAndroid Build Coastguard Worker quiet = 1;
327*49cdfc7eSAndroid Build Coastguard Worker break;
328*49cdfc7eSAndroid Build Coastguard Worker case 's': /* size */
329*49cdfc7eSAndroid Build Coastguard Worker if (sscanf(optarg, "%d", &size) != 1) {
330*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr,
331*49cdfc7eSAndroid Build Coastguard Worker "%s: --s option invalid arg '%s'.\n",
332*49cdfc7eSAndroid Build Coastguard Worker TCID, optarg);
333*49cdfc7eSAndroid Build Coastguard Worker ret = 1;
334*49cdfc7eSAndroid Build Coastguard Worker } else if (size <= 0) {
335*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "%s: --s option must be greater"
336*49cdfc7eSAndroid Build Coastguard Worker " than zero.\n", TCID);
337*49cdfc7eSAndroid Build Coastguard Worker ret = 1;
338*49cdfc7eSAndroid Build Coastguard Worker }
339*49cdfc7eSAndroid Build Coastguard Worker break;
340*49cdfc7eSAndroid Build Coastguard Worker case 'u':
341*49cdfc7eSAndroid Build Coastguard Worker unpipe = 1; /* un-named pipe */
342*49cdfc7eSAndroid Build Coastguard Worker break;
343*49cdfc7eSAndroid Build Coastguard Worker case 'v': /* verbose */
344*49cdfc7eSAndroid Build Coastguard Worker verbose = 1;
345*49cdfc7eSAndroid Build Coastguard Worker break;
346*49cdfc7eSAndroid Build Coastguard Worker case 'W': /* max wait time between reads */
347*49cdfc7eSAndroid Build Coastguard Worker d = strtod(optarg, &cp);
348*49cdfc7eSAndroid Build Coastguard Worker if (*cp != '\0') {
349*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr,
350*49cdfc7eSAndroid Build Coastguard Worker "%s: --w option invalid arg '%s'.\n",
351*49cdfc7eSAndroid Build Coastguard Worker TCID, optarg);
352*49cdfc7eSAndroid Build Coastguard Worker ret = 1;
353*49cdfc7eSAndroid Build Coastguard Worker } else if (d < 0) {
354*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "%s: --w option must be greater"
355*49cdfc7eSAndroid Build Coastguard Worker " than zero.\n", TCID);
356*49cdfc7eSAndroid Build Coastguard Worker ret = 1;
357*49cdfc7eSAndroid Build Coastguard Worker }
358*49cdfc7eSAndroid Build Coastguard Worker parent_wait = (int)(d * 1000000.0);
359*49cdfc7eSAndroid Build Coastguard Worker break;
360*49cdfc7eSAndroid Build Coastguard Worker case 'w': /* max wait time between writes */
361*49cdfc7eSAndroid Build Coastguard Worker d = strtod(optarg, &cp);
362*49cdfc7eSAndroid Build Coastguard Worker if (*cp != '\0') {
363*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr,
364*49cdfc7eSAndroid Build Coastguard Worker "%s: --w option invalid arg '%s'.\n",
365*49cdfc7eSAndroid Build Coastguard Worker TCID, optarg);
366*49cdfc7eSAndroid Build Coastguard Worker ret = 1;
367*49cdfc7eSAndroid Build Coastguard Worker } else if (d < 0) {
368*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "%s: --w option must be greater"
369*49cdfc7eSAndroid Build Coastguard Worker " than zero.\n", TCID);
370*49cdfc7eSAndroid Build Coastguard Worker ret = 1;
371*49cdfc7eSAndroid Build Coastguard Worker }
372*49cdfc7eSAndroid Build Coastguard Worker chld_wait = (int)(d * 1000000.0);
373*49cdfc7eSAndroid Build Coastguard Worker break;
374*49cdfc7eSAndroid Build Coastguard Worker case '?':
375*49cdfc7eSAndroid Build Coastguard Worker ret = 1;
376*49cdfc7eSAndroid Build Coastguard Worker break;
377*49cdfc7eSAndroid Build Coastguard Worker }
378*49cdfc7eSAndroid Build Coastguard Worker
379*49cdfc7eSAndroid Build Coastguard Worker if (ret == 1) {
380*49cdfc7eSAndroid Build Coastguard Worker usage();
381*49cdfc7eSAndroid Build Coastguard Worker return ret;
382*49cdfc7eSAndroid Build Coastguard Worker }
383*49cdfc7eSAndroid Build Coastguard Worker }
384*49cdfc7eSAndroid Build Coastguard Worker
385*49cdfc7eSAndroid Build Coastguard Worker return ret;
386*49cdfc7eSAndroid Build Coastguard Worker }
387*49cdfc7eSAndroid Build Coastguard Worker
setup(int argc,char * argv[])388*49cdfc7eSAndroid Build Coastguard Worker static void setup(int argc, char *argv[])
389*49cdfc7eSAndroid Build Coastguard Worker {
390*49cdfc7eSAndroid Build Coastguard Worker int ret;
391*49cdfc7eSAndroid Build Coastguard Worker char *toutput;
392*49cdfc7eSAndroid Build Coastguard Worker int fds[2];
393*49cdfc7eSAndroid Build Coastguard Worker
394*49cdfc7eSAndroid Build Coastguard Worker tst_sig(FORK, DEF_HANDLER, cleanup);
395*49cdfc7eSAndroid Build Coastguard Worker
396*49cdfc7eSAndroid Build Coastguard Worker TEST_PAUSE;
397*49cdfc7eSAndroid Build Coastguard Worker
398*49cdfc7eSAndroid Build Coastguard Worker tst_tmpdir();
399*49cdfc7eSAndroid Build Coastguard Worker
400*49cdfc7eSAndroid Build Coastguard Worker if (signal(SIGCHLD, sig_child) == SIG_ERR) {
401*49cdfc7eSAndroid Build Coastguard Worker tst_brkm(TBROK | TERRNO, cleanup,
402*49cdfc7eSAndroid Build Coastguard Worker "set signal handler for SIGCHLD failed");
403*49cdfc7eSAndroid Build Coastguard Worker }
404*49cdfc7eSAndroid Build Coastguard Worker
405*49cdfc7eSAndroid Build Coastguard Worker toutput = getenv("TOUTPUT");
406*49cdfc7eSAndroid Build Coastguard Worker if (toutput != NULL && strcmp(toutput, "NOPASS") == 0)
407*49cdfc7eSAndroid Build Coastguard Worker quiet = 1;
408*49cdfc7eSAndroid Build Coastguard Worker
409*49cdfc7eSAndroid Build Coastguard Worker sprintf(pname, "%s", "tpipe");
410*49cdfc7eSAndroid Build Coastguard Worker
411*49cdfc7eSAndroid Build Coastguard Worker ret = parse_options(argc, argv);
412*49cdfc7eSAndroid Build Coastguard Worker if (ret == 1)
413*49cdfc7eSAndroid Build Coastguard Worker tst_brkm(TBROK, cleanup, "options parse error");
414*49cdfc7eSAndroid Build Coastguard Worker
415*49cdfc7eSAndroid Build Coastguard Worker if (format_size == -1)
416*49cdfc7eSAndroid Build Coastguard Worker format_size = size;
417*49cdfc7eSAndroid Build Coastguard Worker
418*49cdfc7eSAndroid Build Coastguard Worker /*
419*49cdfc7eSAndroid Build Coastguard Worker * If there is more than one writer, all writes and reads
420*49cdfc7eSAndroid Build Coastguard Worker * must be the same size. Only writes of a size <= PIPE_BUF
421*49cdfc7eSAndroid Build Coastguard Worker * are atomic. T
422*49cdfc7eSAndroid Build Coastguard Worker * Therefore, if size is greater than PIPE_BUF, we will break
423*49cdfc7eSAndroid Build Coastguard Worker * the writes into PIPE_BUF chunks. We will also increase the
424*49cdfc7eSAndroid Build Coastguard Worker * number of writes to ensure the same (or more) amount of
425*49cdfc7eSAndroid Build Coastguard Worker * data is written. This is the same as erroring and telling
426*49cdfc7eSAndroid Build Coastguard Worker * the user the new cmd line to do the same thing.
427*49cdfc7eSAndroid Build Coastguard Worker * Example:
428*49cdfc7eSAndroid Build Coastguard Worker * pipeio -s 5000 -n 10 -c 5
429*49cdfc7eSAndroid Build Coastguard Worker * (each child will write at least 50000 bytes, since all
430*49cdfc7eSAndroid Build Coastguard Worker * writes have to be in 4096 chuncks or 13*4096 (53248)
431*49cdfc7eSAndroid Build Coastguard Worker * bytes will be written.) This is the same as:
432*49cdfc7eSAndroid Build Coastguard Worker * pipeio -s 4096 -n 13 -c 5
433*49cdfc7eSAndroid Build Coastguard Worker */
434*49cdfc7eSAndroid Build Coastguard Worker if (size > PIPE_BUF && num_writers > 1) {
435*49cdfc7eSAndroid Build Coastguard Worker if (!loop) {
436*49cdfc7eSAndroid Build Coastguard Worker /*
437*49cdfc7eSAndroid Build Coastguard Worker * we must set num_writes*num_writers
438*49cdfc7eSAndroid Build Coastguard Worker * doesn't overflow later
439*49cdfc7eSAndroid Build Coastguard Worker */
440*49cdfc7eSAndroid Build Coastguard Worker num_writes = MIN(((long long)num_writes * size +
441*49cdfc7eSAndroid Build Coastguard Worker PIPE_BUF - 1) / PIPE_BUF,
442*49cdfc7eSAndroid Build Coastguard Worker INT_MAX / num_writers);
443*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TINFO, "adjusting i/o size to %d, and # of "
444*49cdfc7eSAndroid Build Coastguard Worker "writes to %d", PIPE_BUF, num_writes);
445*49cdfc7eSAndroid Build Coastguard Worker } else {
446*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TINFO, "adjusting i/o size to %d", PIPE_BUF);
447*49cdfc7eSAndroid Build Coastguard Worker }
448*49cdfc7eSAndroid Build Coastguard Worker size = PIPE_BUF;
449*49cdfc7eSAndroid Build Coastguard Worker }
450*49cdfc7eSAndroid Build Coastguard Worker
451*49cdfc7eSAndroid Build Coastguard Worker writebuf = SAFE_MALLOC(cleanup, size);
452*49cdfc7eSAndroid Build Coastguard Worker readbuf = SAFE_MALLOC(cleanup, size);
453*49cdfc7eSAndroid Build Coastguard Worker
454*49cdfc7eSAndroid Build Coastguard Worker memset(writebuf, 'Z', size);
455*49cdfc7eSAndroid Build Coastguard Worker writebuf[size - 1] = 'A';
456*49cdfc7eSAndroid Build Coastguard Worker
457*49cdfc7eSAndroid Build Coastguard Worker sem_id = semget(IPC_PRIVATE, 2, IPC_CREAT | S_IRWXU);
458*49cdfc7eSAndroid Build Coastguard Worker if (sem_id == -1) {
459*49cdfc7eSAndroid Build Coastguard Worker tst_brkm(TBROK | TERRNO, cleanup,
460*49cdfc7eSAndroid Build Coastguard Worker "Couldn't allocate semaphore");
461*49cdfc7eSAndroid Build Coastguard Worker }
462*49cdfc7eSAndroid Build Coastguard Worker
463*49cdfc7eSAndroid Build Coastguard Worker if (semctl(sem_id, 0, SETVAL, u) == -1) {
464*49cdfc7eSAndroid Build Coastguard Worker tst_brkm(TBROK | TERRNO, cleanup,
465*49cdfc7eSAndroid Build Coastguard Worker "Couldn't initialize semaphore 0 value");
466*49cdfc7eSAndroid Build Coastguard Worker }
467*49cdfc7eSAndroid Build Coastguard Worker
468*49cdfc7eSAndroid Build Coastguard Worker if (semctl(sem_id, 1, SETVAL, u) == -1) {
469*49cdfc7eSAndroid Build Coastguard Worker tst_brkm(TBROK | TERRNO, cleanup,
470*49cdfc7eSAndroid Build Coastguard Worker "Couldn't initialize semaphore 1 value");
471*49cdfc7eSAndroid Build Coastguard Worker }
472*49cdfc7eSAndroid Build Coastguard Worker
473*49cdfc7eSAndroid Build Coastguard Worker if (unpipe) {
474*49cdfc7eSAndroid Build Coastguard Worker SAFE_PIPE(cleanup, fds);
475*49cdfc7eSAndroid Build Coastguard Worker read_fd = fds[0];
476*49cdfc7eSAndroid Build Coastguard Worker write_fd = fds[1];
477*49cdfc7eSAndroid Build Coastguard Worker pipe_type = PIPE_UNNAMED;
478*49cdfc7eSAndroid Build Coastguard Worker blk_type = UNNAMED_IO;
479*49cdfc7eSAndroid Build Coastguard Worker } else {
480*49cdfc7eSAndroid Build Coastguard Worker SAFE_MKFIFO(cleanup, pname, 0777);
481*49cdfc7eSAndroid Build Coastguard Worker pipe_type = PIPE_NAMED;
482*49cdfc7eSAndroid Build Coastguard Worker }
483*49cdfc7eSAndroid Build Coastguard Worker }
484*49cdfc7eSAndroid Build Coastguard Worker
cleanup(void)485*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
486*49cdfc7eSAndroid Build Coastguard Worker {
487*49cdfc7eSAndroid Build Coastguard Worker SAFE_FREE(writebuf);
488*49cdfc7eSAndroid Build Coastguard Worker SAFE_FREE(readbuf);
489*49cdfc7eSAndroid Build Coastguard Worker
490*49cdfc7eSAndroid Build Coastguard Worker semctl(sem_id, 0, IPC_RMID);
491*49cdfc7eSAndroid Build Coastguard Worker
492*49cdfc7eSAndroid Build Coastguard Worker if (!unpipe)
493*49cdfc7eSAndroid Build Coastguard Worker unlink(pname);
494*49cdfc7eSAndroid Build Coastguard Worker
495*49cdfc7eSAndroid Build Coastguard Worker tst_rmdir();
496*49cdfc7eSAndroid Build Coastguard Worker }
497*49cdfc7eSAndroid Build Coastguard Worker
do_child(void)498*49cdfc7eSAndroid Build Coastguard Worker static void do_child(void)
499*49cdfc7eSAndroid Build Coastguard Worker {
500*49cdfc7eSAndroid Build Coastguard Worker int *count_word; /* holds address where to write writers count */
501*49cdfc7eSAndroid Build Coastguard Worker int *pid_word; /* holds address where to write writers pid */
502*49cdfc7eSAndroid Build Coastguard Worker int nb, j;
503*49cdfc7eSAndroid Build Coastguard Worker long clock;
504*49cdfc7eSAndroid Build Coastguard Worker char *cp;
505*49cdfc7eSAndroid Build Coastguard Worker long int n;
506*49cdfc7eSAndroid Build Coastguard Worker struct sembuf sem_op;
507*49cdfc7eSAndroid Build Coastguard Worker pid_t self_pid = getpid();
508*49cdfc7eSAndroid Build Coastguard Worker
509*49cdfc7eSAndroid Build Coastguard Worker if (!unpipe) {
510*49cdfc7eSAndroid Build Coastguard Worker write_fd = open(pname, O_WRONLY);
511*49cdfc7eSAndroid Build Coastguard Worker if (write_fd == -1) {
512*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "child pipe open(%s, %#o) failed",
513*49cdfc7eSAndroid Build Coastguard Worker pname, O_WRONLY | ndelay);
514*49cdfc7eSAndroid Build Coastguard Worker exit(1);
515*49cdfc7eSAndroid Build Coastguard Worker }
516*49cdfc7eSAndroid Build Coastguard Worker if (ndelay && fcntl(write_fd, F_SETFL, O_NONBLOCK) == -1) {
517*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Failed setting the pipe to "
518*49cdfc7eSAndroid Build Coastguard Worker "nonblocking mode");
519*49cdfc7eSAndroid Build Coastguard Worker exit(1);
520*49cdfc7eSAndroid Build Coastguard Worker }
521*49cdfc7eSAndroid Build Coastguard Worker } else {
522*49cdfc7eSAndroid Build Coastguard Worker close(read_fd);
523*49cdfc7eSAndroid Build Coastguard Worker }
524*49cdfc7eSAndroid Build Coastguard Worker
525*49cdfc7eSAndroid Build Coastguard Worker sem_op = (struct sembuf) {
526*49cdfc7eSAndroid Build Coastguard Worker .sem_num = 0, .sem_op = 1, .sem_flg = 0};
527*49cdfc7eSAndroid Build Coastguard Worker
528*49cdfc7eSAndroid Build Coastguard Worker if (semop(sem_id, &sem_op, 1) == -1) {
529*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "child: %d couldn't raise the semaphore 0",
530*49cdfc7eSAndroid Build Coastguard Worker self_pid);
531*49cdfc7eSAndroid Build Coastguard Worker exit(1);
532*49cdfc7eSAndroid Build Coastguard Worker }
533*49cdfc7eSAndroid Build Coastguard Worker
534*49cdfc7eSAndroid Build Coastguard Worker pid_word = (int *)&writebuf[0];
535*49cdfc7eSAndroid Build Coastguard Worker count_word = (int *)&writebuf[NBPW];
536*49cdfc7eSAndroid Build Coastguard Worker
537*49cdfc7eSAndroid Build Coastguard Worker for (j = 0; j < num_writes || loop; ++j) {
538*49cdfc7eSAndroid Build Coastguard Worker /*
539*49cdfc7eSAndroid Build Coastguard Worker * writes are only in one unit when the size of the write
540*49cdfc7eSAndroid Build Coastguard Worker * is <= PIPE_BUF.
541*49cdfc7eSAndroid Build Coastguard Worker * Therefore, if size is greater than PIPE_BUF, we will break
542*49cdfc7eSAndroid Build Coastguard Worker * the writes into PIPE_BUF chunks.
543*49cdfc7eSAndroid Build Coastguard Worker * All writes and read need to be same size.
544*49cdfc7eSAndroid Build Coastguard Worker */
545*49cdfc7eSAndroid Build Coastguard Worker
546*49cdfc7eSAndroid Build Coastguard Worker /*
547*49cdfc7eSAndroid Build Coastguard Worker * write pid and count in first two
548*49cdfc7eSAndroid Build Coastguard Worker * words of buffer
549*49cdfc7eSAndroid Build Coastguard Worker */
550*49cdfc7eSAndroid Build Coastguard Worker *count_word = j;
551*49cdfc7eSAndroid Build Coastguard Worker *pid_word = self_pid;
552*49cdfc7eSAndroid Build Coastguard Worker
553*49cdfc7eSAndroid Build Coastguard Worker nb = lio_write_buffer(write_fd, iotype, writebuf, size,
554*49cdfc7eSAndroid Build Coastguard Worker SIGUSR1, &cp, 0);
555*49cdfc7eSAndroid Build Coastguard Worker if (nb < 0) {
556*49cdfc7eSAndroid Build Coastguard Worker /*
557*49cdfc7eSAndroid Build Coastguard Worker * If lio_write_buffer returns a negative number,
558*49cdfc7eSAndroid Build Coastguard Worker * the return will be -errno.
559*49cdfc7eSAndroid Build Coastguard Worker */
560*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "pass %d: lio_write_buffer(%s) failed;"
561*49cdfc7eSAndroid Build Coastguard Worker " it returned %d: %s",
562*49cdfc7eSAndroid Build Coastguard Worker j, cp, nb, strerror(-nb));
563*49cdfc7eSAndroid Build Coastguard Worker exit(1);
564*49cdfc7eSAndroid Build Coastguard Worker } else if (nb != size) {
565*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "pass %d: lio_write_buffer(%s) failed,"
566*49cdfc7eSAndroid Build Coastguard Worker " write count %d, but expected to write %d",
567*49cdfc7eSAndroid Build Coastguard Worker j, cp, nb, size);
568*49cdfc7eSAndroid Build Coastguard Worker }
569*49cdfc7eSAndroid Build Coastguard Worker if (verbose) {
570*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "pass %d: pid %d: wrote %d bytes,"
571*49cdfc7eSAndroid Build Coastguard Worker "expected %d bytes",
572*49cdfc7eSAndroid Build Coastguard Worker j, self_pid, nb, size);
573*49cdfc7eSAndroid Build Coastguard Worker }
574*49cdfc7eSAndroid Build Coastguard Worker
575*49cdfc7eSAndroid Build Coastguard Worker if (chld_wait) {
576*49cdfc7eSAndroid Build Coastguard Worker clock = time(0);
577*49cdfc7eSAndroid Build Coastguard Worker srand48(clock);
578*49cdfc7eSAndroid Build Coastguard Worker n = lrand48() % chld_wait;
579*49cdfc7eSAndroid Build Coastguard Worker usleep(n);
580*49cdfc7eSAndroid Build Coastguard Worker }
581*49cdfc7eSAndroid Build Coastguard Worker fflush(stderr);
582*49cdfc7eSAndroid Build Coastguard Worker }
583*49cdfc7eSAndroid Build Coastguard Worker
584*49cdfc7eSAndroid Build Coastguard Worker /* child waits until parent completes open() */
585*49cdfc7eSAndroid Build Coastguard Worker sem_op = (struct sembuf) {
586*49cdfc7eSAndroid Build Coastguard Worker .sem_num = 1, .sem_op = -1, .sem_flg = 0};
587*49cdfc7eSAndroid Build Coastguard Worker if (semop(sem_id, &sem_op, 1) == -1)
588*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Couldn't lower the semaphore 1");
589*49cdfc7eSAndroid Build Coastguard Worker
590*49cdfc7eSAndroid Build Coastguard Worker exit(0);
591*49cdfc7eSAndroid Build Coastguard Worker }
592*49cdfc7eSAndroid Build Coastguard Worker
check_rw_buf(void)593*49cdfc7eSAndroid Build Coastguard Worker static int check_rw_buf(void)
594*49cdfc7eSAndroid Build Coastguard Worker {
595*49cdfc7eSAndroid Build Coastguard Worker int i;
596*49cdfc7eSAndroid Build Coastguard Worker
597*49cdfc7eSAndroid Build Coastguard Worker for (i = 2 * NBPW; i < size; ++i) {
598*49cdfc7eSAndroid Build Coastguard Worker if (writebuf[i] != readbuf[i]) {
599*49cdfc7eSAndroid Build Coastguard Worker ++error;
600*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TFAIL,
601*49cdfc7eSAndroid Build Coastguard Worker "FAIL data error on byte %d; rd# %d, sz= %d, "
602*49cdfc7eSAndroid Build Coastguard Worker "%s %s empty_reads= %d, err= %d",
603*49cdfc7eSAndroid Build Coastguard Worker i, count, size, pipe_type, blk_type,
604*49cdfc7eSAndroid Build Coastguard Worker empty_read, error);
605*49cdfc7eSAndroid Build Coastguard Worker prt_buf(&readbuf, readbuf, format_size, format);
606*49cdfc7eSAndroid Build Coastguard Worker fflush(stdout);
607*49cdfc7eSAndroid Build Coastguard Worker return 1;
608*49cdfc7eSAndroid Build Coastguard Worker }
609*49cdfc7eSAndroid Build Coastguard Worker }
610*49cdfc7eSAndroid Build Coastguard Worker
611*49cdfc7eSAndroid Build Coastguard Worker return 0;
612*49cdfc7eSAndroid Build Coastguard Worker }
613*49cdfc7eSAndroid Build Coastguard Worker
do_parent(void)614*49cdfc7eSAndroid Build Coastguard Worker static void do_parent(void)
615*49cdfc7eSAndroid Build Coastguard Worker {
616*49cdfc7eSAndroid Build Coastguard Worker int i, nb;
617*49cdfc7eSAndroid Build Coastguard Worker long clock;
618*49cdfc7eSAndroid Build Coastguard Worker time_t start_time, current_time, diff_time;
619*49cdfc7eSAndroid Build Coastguard Worker char *cp;
620*49cdfc7eSAndroid Build Coastguard Worker long int n;
621*49cdfc7eSAndroid Build Coastguard Worker struct sembuf sem_op;
622*49cdfc7eSAndroid Build Coastguard Worker
623*49cdfc7eSAndroid Build Coastguard Worker start_time = time(0);
624*49cdfc7eSAndroid Build Coastguard Worker if (!unpipe) {
625*49cdfc7eSAndroid Build Coastguard Worker read_fd = SAFE_OPEN(cleanup, pname, O_RDONLY);
626*49cdfc7eSAndroid Build Coastguard Worker if (ndelay && fcntl(read_fd, F_SETFL, O_NONBLOCK) == -1) {
627*49cdfc7eSAndroid Build Coastguard Worker tst_brkm(TBROK | TERRNO, cleanup,
628*49cdfc7eSAndroid Build Coastguard Worker "Failed setting the pipe to nonblocking mode");
629*49cdfc7eSAndroid Build Coastguard Worker }
630*49cdfc7eSAndroid Build Coastguard Worker } else {
631*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(cleanup, write_fd);
632*49cdfc7eSAndroid Build Coastguard Worker }
633*49cdfc7eSAndroid Build Coastguard Worker
634*49cdfc7eSAndroid Build Coastguard Worker /* raise semaphore so children can exit */
635*49cdfc7eSAndroid Build Coastguard Worker sem_op = (struct sembuf) {
636*49cdfc7eSAndroid Build Coastguard Worker .sem_num = 1, .sem_op = num_writers, .sem_flg = 0};
637*49cdfc7eSAndroid Build Coastguard Worker if (semop(sem_id, &sem_op, 1) == -1) {
638*49cdfc7eSAndroid Build Coastguard Worker tst_brkm(TBROK | TERRNO, cleanup,
639*49cdfc7eSAndroid Build Coastguard Worker "Couldn't raise the semaphore 1");
640*49cdfc7eSAndroid Build Coastguard Worker }
641*49cdfc7eSAndroid Build Coastguard Worker
642*49cdfc7eSAndroid Build Coastguard Worker sem_op = (struct sembuf) {
643*49cdfc7eSAndroid Build Coastguard Worker .sem_num = 0, .sem_op = -num_writers, .sem_flg = 0};
644*49cdfc7eSAndroid Build Coastguard Worker
645*49cdfc7eSAndroid Build Coastguard Worker while (nchildcompleted < num_writers
646*49cdfc7eSAndroid Build Coastguard Worker && semop(sem_id, &sem_op, 1) == -1) {
647*49cdfc7eSAndroid Build Coastguard Worker if (errno == EINTR)
648*49cdfc7eSAndroid Build Coastguard Worker continue;
649*49cdfc7eSAndroid Build Coastguard Worker tst_brkm(TBROK | TERRNO, cleanup,
650*49cdfc7eSAndroid Build Coastguard Worker "Couldn't wait on semaphore 0");
651*49cdfc7eSAndroid Build Coastguard Worker }
652*49cdfc7eSAndroid Build Coastguard Worker
653*49cdfc7eSAndroid Build Coastguard Worker /* parent start to read pipe */
654*49cdfc7eSAndroid Build Coastguard Worker for (i = num_writers * num_writes; i > 0 || loop; --i) {
655*49cdfc7eSAndroid Build Coastguard Worker if (error >= MAX_ERRS || empty_read >= MAX_EMPTY)
656*49cdfc7eSAndroid Build Coastguard Worker break;
657*49cdfc7eSAndroid Build Coastguard Worker if (parent_wait) {
658*49cdfc7eSAndroid Build Coastguard Worker clock = time(0);
659*49cdfc7eSAndroid Build Coastguard Worker srand48(clock);
660*49cdfc7eSAndroid Build Coastguard Worker n = lrand48() % parent_wait;
661*49cdfc7eSAndroid Build Coastguard Worker usleep(n);
662*49cdfc7eSAndroid Build Coastguard Worker }
663*49cdfc7eSAndroid Build Coastguard Worker ++count;
664*49cdfc7eSAndroid Build Coastguard Worker nb = lio_read_buffer(read_fd, iotype, readbuf, size,
665*49cdfc7eSAndroid Build Coastguard Worker SIGUSR1, &cp, 0);
666*49cdfc7eSAndroid Build Coastguard Worker if (nb < 0) {
667*49cdfc7eSAndroid Build Coastguard Worker /*
668*49cdfc7eSAndroid Build Coastguard Worker * If lio_read_buffer returns a negative number,
669*49cdfc7eSAndroid Build Coastguard Worker * the return will be -errno.
670*49cdfc7eSAndroid Build Coastguard Worker */
671*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TFAIL, "pass %d: lio_read_buffer(%s) failed; "
672*49cdfc7eSAndroid Build Coastguard Worker "returned %d: %s", i, cp, nb, strerror(-nb));
673*49cdfc7eSAndroid Build Coastguard Worker ++i;
674*49cdfc7eSAndroid Build Coastguard Worker count--;
675*49cdfc7eSAndroid Build Coastguard Worker error++;
676*49cdfc7eSAndroid Build Coastguard Worker continue;
677*49cdfc7eSAndroid Build Coastguard Worker } else {
678*49cdfc7eSAndroid Build Coastguard Worker if (nb == 0) {
679*49cdfc7eSAndroid Build Coastguard Worker if (nchildcompleted >= num_writers && !loop) {
680*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TWARN, "The children have "
681*49cdfc7eSAndroid Build Coastguard Worker "died prematurely");
682*49cdfc7eSAndroid Build Coastguard Worker break; /* All children have died */
683*49cdfc7eSAndroid Build Coastguard Worker }
684*49cdfc7eSAndroid Build Coastguard Worker empty_read++;
685*49cdfc7eSAndroid Build Coastguard Worker ++i;
686*49cdfc7eSAndroid Build Coastguard Worker count--;
687*49cdfc7eSAndroid Build Coastguard Worker continue;
688*49cdfc7eSAndroid Build Coastguard Worker } else if (nb < size && size <= PIPE_BUF) {
689*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TFAIL, "pass %d: partial read from the"
690*49cdfc7eSAndroid Build Coastguard Worker " pipe: read %d bytes, expected %d, "
691*49cdfc7eSAndroid Build Coastguard Worker "read count %d", i, nb, size, count);
692*49cdfc7eSAndroid Build Coastguard Worker ++error;
693*49cdfc7eSAndroid Build Coastguard Worker } else if (nb == size) {
694*49cdfc7eSAndroid Build Coastguard Worker check_rw_buf();
695*49cdfc7eSAndroid Build Coastguard Worker if (exit_error && exit_error == error)
696*49cdfc7eSAndroid Build Coastguard Worker return;
697*49cdfc7eSAndroid Build Coastguard Worker }
698*49cdfc7eSAndroid Build Coastguard Worker
699*49cdfc7eSAndroid Build Coastguard Worker if (verbose || (num_rpt && !(count % num_rpt))) {
700*49cdfc7eSAndroid Build Coastguard Worker current_time = time(0);
701*49cdfc7eSAndroid Build Coastguard Worker diff_time = current_time - start_time;
702*49cdfc7eSAndroid Build Coastguard Worker tst_resm(TFAIL,
703*49cdfc7eSAndroid Build Coastguard Worker "(%d) rd# %d, sz= %d, %s %s "
704*49cdfc7eSAndroid Build Coastguard Worker "empty_reads= %d, err= %d\n",
705*49cdfc7eSAndroid Build Coastguard Worker (int)diff_time, count, size,
706*49cdfc7eSAndroid Build Coastguard Worker pipe_type, blk_type,
707*49cdfc7eSAndroid Build Coastguard Worker empty_read, error);
708*49cdfc7eSAndroid Build Coastguard Worker fflush(stdout);
709*49cdfc7eSAndroid Build Coastguard Worker }
710*49cdfc7eSAndroid Build Coastguard Worker }
711*49cdfc7eSAndroid Build Coastguard Worker }
712*49cdfc7eSAndroid Build Coastguard Worker
713*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(cleanup, read_fd);
714*49cdfc7eSAndroid Build Coastguard Worker }
715*49cdfc7eSAndroid Build Coastguard Worker
usage(void)716*49cdfc7eSAndroid Build Coastguard Worker static void usage(void)
717*49cdfc7eSAndroid Build Coastguard Worker {
718*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "Usage: %s [-bEv][-c #writers][-D pname][-h]"
719*49cdfc7eSAndroid Build Coastguard Worker "[-e exit_num][-f fmt][-l][-i #writes][-n #writes][-p num_rpt]"
720*49cdfc7eSAndroid Build Coastguard Worker "\n\t[-s size][-W max_wait][-w max_wait][-u]\n", TCID);
721*49cdfc7eSAndroid Build Coastguard Worker fflush(stderr);
722*49cdfc7eSAndroid Build Coastguard Worker }
723*49cdfc7eSAndroid Build Coastguard Worker
help(void)724*49cdfc7eSAndroid Build Coastguard Worker static void help(void)
725*49cdfc7eSAndroid Build Coastguard Worker {
726*49cdfc7eSAndroid Build Coastguard Worker usage();
727*49cdfc7eSAndroid Build Coastguard Worker
728*49cdfc7eSAndroid Build Coastguard Worker printf(" -b - blocking reads and writes. default non-block\n\
729*49cdfc7eSAndroid Build Coastguard Worker -c #writers - number of writers (childern)\n\
730*49cdfc7eSAndroid Build Coastguard Worker -D pname - name of fifo (def tpipe<pid>)\n\
731*49cdfc7eSAndroid Build Coastguard Worker -h - print this help message\n\
732*49cdfc7eSAndroid Build Coastguard Worker -e exit_num - exit on error exit_num, 0 is ignore errors, 1 is default.\n\
733*49cdfc7eSAndroid Build Coastguard Worker -E - print cmd line examples and exit\n\
734*49cdfc7eSAndroid Build Coastguard Worker -f format - define format of bad buffer: h(hex), o(octal)\n\
735*49cdfc7eSAndroid Build Coastguard Worker d(decimal), a(ascii), n (none). hex is default\n\
736*49cdfc7eSAndroid Build Coastguard Worker option size can be added to control output\n\
737*49cdfc7eSAndroid Build Coastguard Worker -i #writes - number write per child, zero means forever.\n\
738*49cdfc7eSAndroid Build Coastguard Worker -I io_type - Specifies io type: s - sync, p - polled async, a - async (def s)\n\
739*49cdfc7eSAndroid Build Coastguard Worker l - listio sync, L - listio async, r - random\n\
740*49cdfc7eSAndroid Build Coastguard Worker -l - loop forever (implied by -n 0).\n\
741*49cdfc7eSAndroid Build Coastguard Worker -n #writes - same as -i (for compatability).\n\
742*49cdfc7eSAndroid Build Coastguard Worker -p num_rpt - number of reads before a report\n\
743*49cdfc7eSAndroid Build Coastguard Worker -q - quiet mode, no PASS results are printed\n\
744*49cdfc7eSAndroid Build Coastguard Worker -s size - size of read and write (def 327)\n\
745*49cdfc7eSAndroid Build Coastguard Worker if size >= 4096, i/o will be in 4096 chuncks\n\
746*49cdfc7eSAndroid Build Coastguard Worker -w max_wait - max time (seconds) for sleep between writes.\n\
747*49cdfc7eSAndroid Build Coastguard Worker max_wait is interpreted as a double with ms accuracy.\n\
748*49cdfc7eSAndroid Build Coastguard Worker -W max_wait - max time (seconds) for sleep between reads\n\
749*49cdfc7eSAndroid Build Coastguard Worker max_wait is interpreted as a double with ms accuracy.\n\
750*49cdfc7eSAndroid Build Coastguard Worker -u - un-named pipe instead of named pipe\n\
751*49cdfc7eSAndroid Build Coastguard Worker -v - verbose mode, all writes/reads resutlts printed\n");
752*49cdfc7eSAndroid Build Coastguard Worker
753*49cdfc7eSAndroid Build Coastguard Worker fflush(stdout);
754*49cdfc7eSAndroid Build Coastguard Worker }
755*49cdfc7eSAndroid Build Coastguard Worker
prt_buf(char ** addr,char * buf,int length,int format)756*49cdfc7eSAndroid Build Coastguard Worker static void prt_buf(char **addr, char *buf, int length, int format)
757*49cdfc7eSAndroid Build Coastguard Worker {
758*49cdfc7eSAndroid Build Coastguard Worker int i;
759*49cdfc7eSAndroid Build Coastguard Worker int num_words = length / NBPW; /* given length in bytes, get length in words */
760*49cdfc7eSAndroid Build Coastguard Worker int width; /* number of columns */
761*49cdfc7eSAndroid Build Coastguard Worker int extra_words = 0; /* odd or even number of words */
762*49cdfc7eSAndroid Build Coastguard Worker char *a = buf;
763*49cdfc7eSAndroid Build Coastguard Worker char b[NBPW];
764*49cdfc7eSAndroid Build Coastguard Worker char c[NBPW * 2];
765*49cdfc7eSAndroid Build Coastguard Worker char *p;
766*49cdfc7eSAndroid Build Coastguard Worker long *word;
767*49cdfc7eSAndroid Build Coastguard Worker
768*49cdfc7eSAndroid Build Coastguard Worker if (format == NO_OUT) /* if no output wanted, return */
769*49cdfc7eSAndroid Build Coastguard Worker return;
770*49cdfc7eSAndroid Build Coastguard Worker
771*49cdfc7eSAndroid Build Coastguard Worker if (length % NBPW)
772*49cdfc7eSAndroid Build Coastguard Worker ++num_words; /* is length in full words? */
773*49cdfc7eSAndroid Build Coastguard Worker if (format == ASCII) {
774*49cdfc7eSAndroid Build Coastguard Worker width = 3;
775*49cdfc7eSAndroid Build Coastguard Worker } else {
776*49cdfc7eSAndroid Build Coastguard Worker width = 2;
777*49cdfc7eSAndroid Build Coastguard Worker /* do we have an odd number of words? */
778*49cdfc7eSAndroid Build Coastguard Worker extra_words = num_words % width;
779*49cdfc7eSAndroid Build Coastguard Worker }
780*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < num_words; ++i, a += NBPW, addr++) {
781*49cdfc7eSAndroid Build Coastguard Worker word = (long *)a;
782*49cdfc7eSAndroid Build Coastguard Worker if (!(i % width)) {
783*49cdfc7eSAndroid Build Coastguard Worker if (i > 0 && format != ASCII) {
784*49cdfc7eSAndroid Build Coastguard Worker /*
785*49cdfc7eSAndroid Build Coastguard Worker * print the ascii equivalent of the data
786*49cdfc7eSAndroid Build Coastguard Worker * before beginning the next line of output.
787*49cdfc7eSAndroid Build Coastguard Worker */
788*49cdfc7eSAndroid Build Coastguard Worker memset(c, 0x00, width * NBPW);
789*49cdfc7eSAndroid Build Coastguard Worker /*
790*49cdfc7eSAndroid Build Coastguard Worker * get the last 2 words printed
791*49cdfc7eSAndroid Build Coastguard Worker */
792*49cdfc7eSAndroid Build Coastguard Worker memcpy(c, a - (width * NBPW), width * NBPW);
793*49cdfc7eSAndroid Build Coastguard Worker for (p = c; (p - c) < (int)(width*NBPW); ++p) {
794*49cdfc7eSAndroid Build Coastguard Worker if (*p < '!' || *p > '~')
795*49cdfc7eSAndroid Build Coastguard Worker *p = '.';
796*49cdfc7eSAndroid Build Coastguard Worker }
797*49cdfc7eSAndroid Build Coastguard Worker printf("\t%16.16s", c);
798*49cdfc7eSAndroid Build Coastguard Worker }
799*49cdfc7eSAndroid Build Coastguard Worker printf("\n%p: ", addr);
800*49cdfc7eSAndroid Build Coastguard Worker /***printf("\n%7o (%d): ",addr,i);***/
801*49cdfc7eSAndroid Build Coastguard Worker }
802*49cdfc7eSAndroid Build Coastguard Worker
803*49cdfc7eSAndroid Build Coastguard Worker switch (format) {
804*49cdfc7eSAndroid Build Coastguard Worker case HEX:
805*49cdfc7eSAndroid Build Coastguard Worker printf("%16.16lx ", *word);
806*49cdfc7eSAndroid Build Coastguard Worker break;
807*49cdfc7eSAndroid Build Coastguard Worker case DECIMAL:
808*49cdfc7eSAndroid Build Coastguard Worker printf("%10.10ld ", *word);
809*49cdfc7eSAndroid Build Coastguard Worker break;
810*49cdfc7eSAndroid Build Coastguard Worker case ASCII:
811*49cdfc7eSAndroid Build Coastguard Worker memcpy(b, a, NBPW);
812*49cdfc7eSAndroid Build Coastguard Worker for (p = b; (p - b) < (int)NBPW; ++p) {
813*49cdfc7eSAndroid Build Coastguard Worker if (*p < '!' || *p > '~')
814*49cdfc7eSAndroid Build Coastguard Worker *p = '.';
815*49cdfc7eSAndroid Build Coastguard Worker }
816*49cdfc7eSAndroid Build Coastguard Worker printf("%8.8s ", b);
817*49cdfc7eSAndroid Build Coastguard Worker break;
818*49cdfc7eSAndroid Build Coastguard Worker default:
819*49cdfc7eSAndroid Build Coastguard Worker printf("%22.22lo ", *word);
820*49cdfc7eSAndroid Build Coastguard Worker break;
821*49cdfc7eSAndroid Build Coastguard Worker }
822*49cdfc7eSAndroid Build Coastguard Worker }
823*49cdfc7eSAndroid Build Coastguard Worker if (format != ASCII) {
824*49cdfc7eSAndroid Build Coastguard Worker /*
825*49cdfc7eSAndroid Build Coastguard Worker * print the ascii equivalent of the last words in the buffer
826*49cdfc7eSAndroid Build Coastguard Worker * before returning.
827*49cdfc7eSAndroid Build Coastguard Worker */
828*49cdfc7eSAndroid Build Coastguard Worker memset(c, 0x00, width * NBPW);
829*49cdfc7eSAndroid Build Coastguard Worker if (extra_words)
830*49cdfc7eSAndroid Build Coastguard Worker width = extra_words; /* odd number of words */
831*49cdfc7eSAndroid Build Coastguard Worker memcpy(c, a - (width * NBPW), width * NBPW);
832*49cdfc7eSAndroid Build Coastguard Worker for (p = c; (p - c) < (int)(width * NBPW); ++p) {
833*49cdfc7eSAndroid Build Coastguard Worker if (*p < '!' || *p > '~')
834*49cdfc7eSAndroid Build Coastguard Worker *p = '.';
835*49cdfc7eSAndroid Build Coastguard Worker }
836*49cdfc7eSAndroid Build Coastguard Worker if (width == 2)
837*49cdfc7eSAndroid Build Coastguard Worker printf("\t%16.16s", c);
838*49cdfc7eSAndroid Build Coastguard Worker else
839*49cdfc7eSAndroid Build Coastguard Worker printf("\t\t%16.8s", c);
840*49cdfc7eSAndroid Build Coastguard Worker }
841*49cdfc7eSAndroid Build Coastguard Worker printf("\n");
842*49cdfc7eSAndroid Build Coastguard Worker fflush(stdout);
843*49cdfc7eSAndroid Build Coastguard Worker }
844*49cdfc7eSAndroid Build Coastguard Worker
prt_examples(void)845*49cdfc7eSAndroid Build Coastguard Worker static void prt_examples(void)
846*49cdfc7eSAndroid Build Coastguard Worker {
847*49cdfc7eSAndroid Build Coastguard Worker printf("%s -c 5 -i 0 -s 4090 -b\n", TCID);
848*49cdfc7eSAndroid Build Coastguard Worker printf("%s -c 5 -i 0 -s 4090 -b -u \n", TCID);
849*49cdfc7eSAndroid Build Coastguard Worker printf("%s -c 5 -i 0 -s 4090 -b -W 3 -w 3 \n", TCID);
850*49cdfc7eSAndroid Build Coastguard Worker }
851*49cdfc7eSAndroid Build Coastguard Worker
sig_child(int sig)852*49cdfc7eSAndroid Build Coastguard Worker static void sig_child(int sig)
853*49cdfc7eSAndroid Build Coastguard Worker {
854*49cdfc7eSAndroid Build Coastguard Worker int status;
855*49cdfc7eSAndroid Build Coastguard Worker
856*49cdfc7eSAndroid Build Coastguard Worker nchildcompleted++;
857*49cdfc7eSAndroid Build Coastguard Worker #if DEBUG
858*49cdfc7eSAndroid Build Coastguard Worker #define STR "parent: received SIGCHLD\n"
859*49cdfc7eSAndroid Build Coastguard Worker write(STDOUT_FILENO, str, strlen(STR));
860*49cdfc7eSAndroid Build Coastguard Worker #endif
861*49cdfc7eSAndroid Build Coastguard Worker waitpid(-1, &status, WNOHANG);
862*49cdfc7eSAndroid Build Coastguard Worker }
863