blob: 5ec4e1811cacd4d898e799686b78252490ad7053 [file] [log] [blame]
robbiewbfb98f92002-06-13 05:26:55 +00001/*
2 *
3 * Copyright (c) International Business Machines Corp., 2002
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
robbiewbfb98f92002-06-13 05:26:55 +000018 */
19
robbiewbfb98f92002-06-13 05:26:55 +000020/*
21 * NAME
22 * diotest3.c
23 *
24 * DESCRIPTION
25 * Fork given number of children. Each child opens the same file, but
26 * uses its own file descriptiors. The child does writes and reads from
27 * its segment in the file. The segment to which the child writes is
28 * determined by childnumber * bufsize. There is no need to use any locks.
subrata_modak4bb656a2009-02-26 12:02:09 +000029 * Program tests the combinations of buffered/buffered read(), write()
robbiewbfb98f92002-06-13 05:26:55 +000030 * calls.
31 * Test blocks:
32 * [1] Direct Read, Buffered write
33 * [2] Direct Write, Buffered read
34 * [3] Direct Read, Direct Write
35 *
36 * USAGE
37 * diotest3 [-b bufsize] [-o offset] [-n numchild]
38 * [-i iterations [-f filename]
subrata_modak4bb656a2009-02-26 12:02:09 +000039 *
robbiewbfb98f92002-06-13 05:26:55 +000040 * History
41 * 04/22/2002 Narasimha Sharoff nsharoff@us.ibm.com
42 *
43 * RESTRICTIONS
44 * None
45*/
46
47#include <stdio.h>
48#include <stdlib.h>
49#include <unistd.h>
50#include <string.h>
51#include <sys/file.h>
52#include <sys/fcntl.h>
mridgeb48651d2004-05-18 17:05:51 +000053#include <sys/syscall.h>
robbiewbfb98f92002-06-13 05:26:55 +000054#include <errno.h>
55
robbiewf7dc1be2003-03-14 16:20:37 +000056#include "diotest_routines.h"
57
robbiew96f4bb32003-03-13 15:39:53 +000058#include "test.h"
robbiew96f4bb32003-03-13 15:39:53 +000059
Wanlong Gao354ebb42012-12-07 10:10:04 +080060char *TCID = "diotest03"; /* Test program identifier. */
61int TST_TOTAL = 3; /* Total number of test conditions */
robbiew8680e9b2003-11-19 15:29:01 +000062
robbiew96f4bb32003-03-13 15:39:53 +000063#ifdef O_DIRECT
64
robbiewbfb98f92002-06-13 05:26:55 +000065#define BUFSIZE 4096
66#define TRUE 1
67#define LEN 30
68#define READ_DIRECT 1
69#define WRITE_DIRECT 2
70#define RDWR_DIRECT 3
71
Wanlong Gao354ebb42012-12-07 10:10:04 +080072static int iter = 100; /* Iterations. Default 100 */
73static int bufsize = BUFSIZE; /* Buffersize. Default 4k */
74static int offset = 0; /* Offset. Default 0 */
75static char filename[LEN];
robbiewbfb98f92002-06-13 05:26:55 +000076
robbiewbfb98f92002-06-13 05:26:55 +000077/*
78 * prg_usage: display the program usage
79*/
Wanlong Gao354ebb42012-12-07 10:10:04 +080080void prg_usage()
robbiewbfb98f92002-06-13 05:26:55 +000081{
Wanlong Gao354ebb42012-12-07 10:10:04 +080082 fprintf(stderr,
83 "Usage: diotest3 [-b bufsize] [-o offset] [-n numchild] [-i iterations] [-f filename]\n");
robbiewbfb98f92002-06-13 05:26:55 +000084 exit(1);
85}
86
87/*
robbiew8c64d1b2003-03-24 22:20:47 +000088 * runtest: write the data to the file. Read the data from the file and compare.
subrata_modak4bb656a2009-02-26 12:02:09 +000089 * For each iteration, write data starting at offse+iter*bufsize
robbiew8c64d1b2003-03-24 22:20:47 +000090 * location in the file and read from there.
Garrett Cooper8dca4222010-12-18 03:57:35 -080091 *
92 * XXX (garrcoop): shouldn't use libltp APIs because it runs forked.
93 */
Wanlong Gao354ebb42012-12-07 10:10:04 +080094int runtest(int fd_r, int fd_w, int childnum, int action)
robbiew8c64d1b2003-03-24 22:20:47 +000095{
Wanlong Gao354ebb42012-12-07 10:10:04 +080096 char *buf1;
97 char *buf2;
98 off_t seekoff;
99 int bufsize = BUFSIZE;
100 int i;
robbiew8c64d1b2003-03-24 22:20:47 +0000101
102 /* Allocate for buffers */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800103 seekoff = offset + bufsize * childnum;
robbiew8c64d1b2003-03-24 22:20:47 +0000104 if ((buf1 = valloc(bufsize)) == 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800105 tst_resm(TFAIL | TERRNO, "valloc for buf1 failed");
106 return (-1);
robbiew8c64d1b2003-03-24 22:20:47 +0000107 }
108 if ((buf2 = valloc(bufsize)) == 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800109 tst_resm(TFAIL | TERRNO, "valloc for buf2 failed");
110 return (-1);
robbiew8c64d1b2003-03-24 22:20:47 +0000111 }
112
113 /* seek, write, read and verify */
114 for (i = 0; i < iter; i++) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800115 fillbuf(buf1, bufsize, childnum + i);
robbiew8c64d1b2003-03-24 22:20:47 +0000116 if (lseek(fd_w, seekoff, SEEK_SET) < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800117 tst_resm(TFAIL | TERRNO, "lseek (fd_w, ..) failed");
118 return (-1);
robbiew8c64d1b2003-03-24 22:20:47 +0000119 }
120 if (write(fd_w, buf1, bufsize) < bufsize) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800121 tst_resm(TFAIL | TERRNO, "write failed");
122 return (-1);
robbiew8c64d1b2003-03-24 22:20:47 +0000123 }
124 if (action == READ_DIRECT) {
125 /* Make sure data is on to disk before read */
126 if (fsync(fd_w) < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800127 tst_resm(TFAIL | TERRNO, "fsync failed");
128 return (-1);
robbiew8c64d1b2003-03-24 22:20:47 +0000129 }
130 }
131 if (lseek(fd_r, seekoff, SEEK_SET) < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800132 tst_resm(TFAIL | TERRNO, "lseek(fd_r, ..) failed");
133 return (-1);
robbiew8c64d1b2003-03-24 22:20:47 +0000134 }
135 if (read(fd_r, buf2, bufsize) < bufsize) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800136 tst_resm(TFAIL | TERRNO, "read failed");
137 return (-1);
robbiew8c64d1b2003-03-24 22:20:47 +0000138 }
139 if (bufcmp(buf1, buf2, bufsize) != 0) {
Garrett Cooper8dca4222010-12-18 03:57:35 -0800140 tst_resm(TFAIL,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800141 "comparsion failed; child=%d offset=%d",
142 childnum, (int)seekoff);
143 return (-1);
robbiew8c64d1b2003-03-24 22:20:47 +0000144 }
145 }
Garrett Cooper8dca4222010-12-18 03:57:35 -0800146 tst_exit();
robbiew8c64d1b2003-03-24 22:20:47 +0000147}
148
149/*
robbiewbfb98f92002-06-13 05:26:55 +0000150 * child_function: open the file for read and write. Call the runtest routine.
151*/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800152int child_function(int childnum, int action)
robbiewbfb98f92002-06-13 05:26:55 +0000153{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800154 int fd_w, fd_r;
robbiewbfb98f92002-06-13 05:26:55 +0000155
Wanlong Gao354ebb42012-12-07 10:10:04 +0800156 switch (action) {
Garrett Cooper8dca4222010-12-18 03:57:35 -0800157 case READ_DIRECT:
Wanlong Gao354ebb42012-12-07 10:10:04 +0800158 if ((fd_w = open(filename, O_WRONLY | O_CREAT, 0666)) < 0) {
159 tst_resm(TFAIL | TERRNO,
160 "open(%s, O_WRONLY|O_CREAT, ..) failed",
161 filename);
162 return (-1);
robbiewbfb98f92002-06-13 05:26:55 +0000163 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800164 if ((fd_r = open(filename, O_DIRECT | O_RDONLY, 0666)) < 0) {
165 tst_resm(TFAIL | TERRNO,
166 "open(%s, O_DIRECT|O_RDONLY, ..) failed",
167 filename);
robbiewbfb98f92002-06-13 05:26:55 +0000168 close(fd_w);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800169 return (-1);
robbiewbfb98f92002-06-13 05:26:55 +0000170 }
171 if (runtest(fd_r, fd_w, childnum, action) == -1) {
vapier0bdbaa32006-02-12 10:56:55 +0000172 tst_resm(TFAIL, "Read Direct-child %d failed",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800173 childnum);
robbiewbfb98f92002-06-13 05:26:55 +0000174 close(fd_w);
175 close(fd_r);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800176 return (-1);
robbiewbfb98f92002-06-13 05:26:55 +0000177 }
178 break;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800179 case WRITE_DIRECT:
180 if ((fd_w =
181 open(filename, O_DIRECT | O_WRONLY | O_CREAT, 0666)) < 0) {
182 tst_resm(TFAIL, "fd_w open failed for %s: %s", filename,
183 strerror(errno));
184 return (-1);
robbiewbfb98f92002-06-13 05:26:55 +0000185 }
186 if ((fd_r = open(filename, O_RDONLY, 0666)) < 0) {
vapier0bdbaa32006-02-12 10:56:55 +0000187 tst_resm(TFAIL, "fd_r open failed for %s: %s",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800188 filename, strerror(errno));
robbiewbfb98f92002-06-13 05:26:55 +0000189 close(fd_w);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800190 return (-1);
robbiewbfb98f92002-06-13 05:26:55 +0000191 }
192 if (runtest(fd_r, fd_w, childnum, action) == -1) {
vapier0bdbaa32006-02-12 10:56:55 +0000193 tst_resm(TFAIL, "Write Direct-child %d failed",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800194 childnum);
robbiewbfb98f92002-06-13 05:26:55 +0000195 close(fd_w);
196 close(fd_r);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800197 return (-1);
robbiewbfb98f92002-06-13 05:26:55 +0000198 }
199 break;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800200 case RDWR_DIRECT:
201 if ((fd_w =
202 open(filename, O_DIRECT | O_WRONLY | O_CREAT, 0666)) < 0) {
203 tst_resm(TFAIL, "fd_w open failed for %s: %s", filename,
204 strerror(errno));
205 return (-1);
robbiewbfb98f92002-06-13 05:26:55 +0000206 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800207 if ((fd_r = open(filename, O_DIRECT | O_RDONLY, 0666)) < 0) {
vapier0bdbaa32006-02-12 10:56:55 +0000208 tst_resm(TFAIL, "fd_r open failed for %s: %s",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800209 filename, strerror(errno));
robbiewbfb98f92002-06-13 05:26:55 +0000210 close(fd_w);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800211 return (-1);
robbiewbfb98f92002-06-13 05:26:55 +0000212 }
213 if (runtest(fd_r, fd_w, childnum, action) == -1) {
vapier0bdbaa32006-02-12 10:56:55 +0000214 tst_resm(TFAIL, "RDWR Direct-child %d failed",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800215 childnum);
robbiewbfb98f92002-06-13 05:26:55 +0000216 close(fd_w);
217 close(fd_r);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800218 return (-1);
robbiewbfb98f92002-06-13 05:26:55 +0000219 }
220 break;
Garrett Cooper8dca4222010-12-18 03:57:35 -0800221 default:
Wanlong Gao354ebb42012-12-07 10:10:04 +0800222 fprintf(stderr, "Invalid Action Value\n");
223 return (-1);
robbiewbfb98f92002-06-13 05:26:55 +0000224 }
225 close(fd_w);
226 close(fd_r);
227 exit(0);
228}
229
subrata_modak04e0bfa2009-06-23 14:11:03 +0000230static void setup(void);
231static void cleanup(void);
232static int fd1 = -1;
robbiewbfb98f92002-06-13 05:26:55 +0000233
Wanlong Gao354ebb42012-12-07 10:10:04 +0800234int main(int argc, char *argv[])
robbiewbfb98f92002-06-13 05:26:55 +0000235{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800236 int *pidlst;
237 int numchild = 1; /* Number of children. Default 5 */
238 int i, fail_count = 0, failed = 0, total = 0;
robbiewbfb98f92002-06-13 05:26:55 +0000239
240 /* Options */
Jeff Laytond97f51d2013-11-06 11:39:11 -0500241 sprintf(filename, "testdata-3.%ld", syscall(__NR_gettid));
robbiewbfb98f92002-06-13 05:26:55 +0000242 while ((i = getopt(argc, argv, "b:o:i:n:f:")) != -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800243 switch (i) {
robbiewbfb98f92002-06-13 05:26:55 +0000244 case 'b':
245 if ((bufsize = atoi(optarg)) <= 0) {
246 fprintf(stderr, "bufsize must be > 0\n");
247 prg_usage();
248 }
249 if (bufsize % 4096 != 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800250 fprintf(stderr,
251 "bufsize must be multiple of 4k\n");
robbiewbfb98f92002-06-13 05:26:55 +0000252 prg_usage();
253 }
254 break;
255 case 'o':
256 if ((offset = atoi(optarg)) <= 0) {
257 fprintf(stderr, "offset must be > 0\n");
258 prg_usage();
259 }
260 break;
261 case 'i':
262 if ((iter = atoi(optarg)) <= 0) {
263 fprintf(stderr, "iterations must be > 0\n");
264 prg_usage();
265 }
266 break;
267 case 'n':
268 if ((numchild = atoi(optarg)) <= 0) {
269 fprintf(stderr, "no of children must be > 0\n");
270 prg_usage();
271 }
272 break;
273 case 'f':
274 strcpy(filename, optarg);
275 break;
276 default:
277 prg_usage();
278 }
279 }
robbiewbfb98f92002-06-13 05:26:55 +0000280
subrata_modak04e0bfa2009-06-23 14:11:03 +0000281 setup();
robbiew8680e9b2003-11-19 15:29:01 +0000282
robbiewbfb98f92002-06-13 05:26:55 +0000283 /* Testblock-1: Read with Direct IO, Write without */
Garrett Cooper8fb1cdb2010-11-28 22:56:35 -0800284 if (forkchldrn(&pidlst, numchild, READ_DIRECT, child_function) < 0) {
robbiewbfb98f92002-06-13 05:26:55 +0000285 failed = TRUE;
286 fail_count++;
Garrett Cooper8dca4222010-12-18 03:57:35 -0800287 tst_resm(TFAIL, "Read with Direct IO, Write without");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800288 } else {
robbiewbfb98f92002-06-13 05:26:55 +0000289 if (waitchldrn(&pidlst, numchild) < 0) {
290 failed = TRUE;
291 fail_count++;
Garrett Cooper8dca4222010-12-18 03:57:35 -0800292 tst_resm(TFAIL, "Read with Direct IO, Write without");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800293 } else
Garrett Cooper8dca4222010-12-18 03:57:35 -0800294 tst_resm(TPASS, "Read with Direct IO, Write without");
robbiew92b688b2004-03-01 22:36:38 +0000295
robbiewbfb98f92002-06-13 05:26:55 +0000296 }
297 unlink(filename);
298 free(pidlst);
299 total++;
300
301 /* Testblock-2: Write with Direct IO, Read without */
302 if (forkchldrn(&pidlst, numchild, WRITE_DIRECT, child_function) < 0) {
303 failed = TRUE;
304 fail_count++;
Garrett Cooper8dca4222010-12-18 03:57:35 -0800305 tst_resm(TFAIL, "Write with Direct IO, Read without");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800306 } else {
robbiewbfb98f92002-06-13 05:26:55 +0000307 if (waitchldrn(&pidlst, numchild) < 0) {
308 failed = TRUE;
309 fail_count++;
Garrett Cooper8dca4222010-12-18 03:57:35 -0800310 tst_resm(TFAIL, "Write with Direct IO, Read without");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800311 } else
Garrett Cooper8dca4222010-12-18 03:57:35 -0800312 tst_resm(TPASS, "Write with Direct IO, Read without");
robbiewbfb98f92002-06-13 05:26:55 +0000313 }
314 unlink(filename);
315 free(pidlst);
316 total++;
317
318 /* Testblock-3: Read, Write with Direct IO. */
319 if (forkchldrn(&pidlst, numchild, RDWR_DIRECT, child_function) < 0) {
320 failed = TRUE;
321 fail_count++;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800322 tst_resm(TFAIL, "Read, Write with Direct IO");
323 } else {
robbiewbfb98f92002-06-13 05:26:55 +0000324 if (waitchldrn(&pidlst, numchild) < 0) {
325 failed = TRUE;
326 fail_count++;
Garrett Cooper8dca4222010-12-18 03:57:35 -0800327 tst_resm(TFAIL, "Read, Write with Direct IO");
328 } else
329 tst_resm(TPASS, "Read, Write with Direct IO");
robbiewbfb98f92002-06-13 05:26:55 +0000330 }
331 unlink(filename);
332 free(pidlst);
333 total++;
334
Garrett Cooper8dca4222010-12-18 03:57:35 -0800335 if (failed)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800336 tst_resm(TINFO, "%d/%d testblocks failed", fail_count, total);
subrata_modak04e0bfa2009-06-23 14:11:03 +0000337 else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800338 tst_resm(TINFO,
339 "%d testblocks %d iterations with %d children completed",
340 total, iter, numchild);
subrata_modak04e0bfa2009-06-23 14:11:03 +0000341 cleanup();
Garrett Cooper2c282152010-12-16 00:55:50 -0800342
Garrett Cooper8dca4222010-12-18 03:57:35 -0800343 tst_exit();
344
robbiewbfb98f92002-06-13 05:26:55 +0000345}
346
subrata_modak04e0bfa2009-06-23 14:11:03 +0000347static void setup(void)
348{
349 tst_tmpdir();
robbiew96f4bb32003-03-13 15:39:53 +0000350
Wanlong Gao354ebb42012-12-07 10:10:04 +0800351 if ((fd1 = open(filename, O_CREAT | O_EXCL, 0600)) < 0)
352 tst_brkm(TBROK | TERRNO, cleanup,
353 "open(%s, O_CREAT|O_EXCL, ..) failed", filename);
subrata_modak04e0bfa2009-06-23 14:11:03 +0000354 close(fd1);
355
356 /* Test for filesystem support of O_DIRECT */
Garrett Cooper8dca4222010-12-18 03:57:35 -0800357 if ((fd1 = open(filename, O_DIRECT, 0600)) < 0)
Garrett Cooper72521cf2010-12-18 06:31:47 -0800358 tst_brkm(TCONF, cleanup, "open(%s, O_DIRECT, ..) failed",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800359 filename);
Subrata Modak76a720a2010-07-03 21:08:18 +0530360 close(fd1);
subrata_modak04e0bfa2009-06-23 14:11:03 +0000361}
362
363static void cleanup(void)
364{
Garrett Cooperdf3eb162010-11-28 22:44:32 -0800365 if (fd1 != -1)
subrata_modak04e0bfa2009-06-23 14:11:03 +0000366 unlink(filename);
367
368 tst_rmdir();
369
subrata_modak04e0bfa2009-06-23 14:11:03 +0000370}
robbiew96f4bb32003-03-13 15:39:53 +0000371#else /* O_DIRECT */
372
Wanlong Gao354ebb42012-12-07 10:10:04 +0800373int main()
Garrett Cooper8dca4222010-12-18 03:57:35 -0800374{
375 tst_brkm(TCONF, NULL, "O_DIRECT is not defined.");
robbiew96f4bb32003-03-13 15:39:53 +0000376}
Chris Dearmanec6edca2012-10-17 19:54:01 -0700377#endif /* O_DIRECT */