blob: 584197742ba78d065b222099bec2c1cca269653c [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 * diotest6.c
23 *
24 * DESCRIPTION
25 * Fork given number of children. Each child opens the same file, but
26 * uses its own file descriptior. 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.
29 * Tests the combinations of buffered/direct readv(), writev() calls.
30 * Test program contains the following test blocks:
31 * [1] Direct Read, Buffered write
32 * [2] Direct Write, Buffered read
33 * [3] Direct Read, Direct Write
34 *
35 * USAGE
36 * diotest6 [-b bufsize] [-o offset] [-n numchild] [-i iterations]
37 * [-v nvector] [-f fileaname]
subrata_modak4bb656a2009-02-26 12:02:09 +000038 *
robbiewbfb98f92002-06-13 05:26:55 +000039 * History
40 * 04/30/2002 Narasimha Sharoff nsharoff@us.ibm.com
41 *
42 * RESTRICTIONS
43 * None
44*/
45
46#include <stdio.h>
47#include <stdlib.h>
48#include <unistd.h>
49#include <string.h>
50#include <sys/file.h>
51#include <sys/fcntl.h>
mridgeb48651d2004-05-18 17:05:51 +000052#include <sys/syscall.h>
robbiewbfb98f92002-06-13 05:26:55 +000053#include <sys/uio.h>
54#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 = "diotest06"; /* 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 off64_t offset = 0; /* Offset. Default 0 */
75static int nvector = 20; /* Vector array. Default 20 */
76static char filename[LEN]; /* Test data file */
subrata_modak04e0bfa2009-06-23 14:11:03 +000077static int fd1 = -1;
78
79static void setup(void);
80static void cleanup(void);
robbiewbfb98f92002-06-13 05:26:55 +000081
robbiewbfb98f92002-06-13 05:26:55 +000082/*
83 * prg_usage: display the program usage
84*/
Wanlong Gao354ebb42012-12-07 10:10:04 +080085void prg_usage()
robbiewbfb98f92002-06-13 05:26:55 +000086{
Wanlong Gao354ebb42012-12-07 10:10:04 +080087 fprintf(stderr,
88 "Usage: diotest6 [-b bufsize] [-o offset] [-n numchild] [-i iterations] [-v nvector] [-f filename]\n");
robbiewbfb98f92002-06-13 05:26:55 +000089 exit(1);
90}
91
92/*
robbiew8c64d1b2003-03-24 22:20:47 +000093 * runtest: write the data to the file. Read the data from the file and compare.
subrata_modak4bb656a2009-02-26 12:02:09 +000094 * For each iteration, write data starting at offse+iter*bufsize
robbiew8c64d1b2003-03-24 22:20:47 +000095 * location in the file and read from there.
96*/
Wanlong Gao354ebb42012-12-07 10:10:04 +080097int runtest(int fd_r, int fd_w, int childnum, int action)
robbiew8c64d1b2003-03-24 22:20:47 +000098{
Wanlong Gao354ebb42012-12-07 10:10:04 +080099 off64_t seekoff;
100 int i, bufsize = BUFSIZE;
101 struct iovec *iov1, *iov2, *iovp;
robbiew8c64d1b2003-03-24 22:20:47 +0000102
103 /* Allocate for buffers and data pointers */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800104 seekoff = offset + bufsize * childnum;
105 if ((iov1 =
106 (struct iovec *)valloc(sizeof(struct iovec) * nvector)) == NULL) {
vapier0bdbaa32006-02-12 10:56:55 +0000107 tst_resm(TFAIL, "valloc buf1 failed: %s", strerror(errno));
Wanlong Gao354ebb42012-12-07 10:10:04 +0800108 return (-1);
robbiew8c64d1b2003-03-24 22:20:47 +0000109 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800110 if ((iov2 =
111 (struct iovec *)valloc(sizeof(struct iovec) * nvector)) == NULL) {
vapier0bdbaa32006-02-12 10:56:55 +0000112 tst_resm(TFAIL, "valloc buf2 failed: %s", strerror(errno));
Wanlong Gao354ebb42012-12-07 10:10:04 +0800113 return (-1);
robbiew8c64d1b2003-03-24 22:20:47 +0000114 }
115 for (i = 0, iovp = iov1; i < nvector; iovp++, i++) {
116 if ((iovp->iov_base = valloc(bufsize)) == NULL) {
vapier0bdbaa32006-02-12 10:56:55 +0000117 tst_resm(TFAIL, "valloc for iovp->iov_base: %s",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800118 strerror(errno));
119 return (-1);
robbiew8c64d1b2003-03-24 22:20:47 +0000120 }
121 iovp->iov_len = bufsize;
122 }
123 for (i = 0, iovp = iov2; i < nvector; iovp++, i++) {
124 if ((iovp->iov_base = valloc(bufsize)) == NULL) {
vapier0bdbaa32006-02-12 10:56:55 +0000125 tst_resm(TFAIL, "valloc, iov2 for iovp->iov_base: %s",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800126 strerror(errno));
127 return (-1);
robbiew8c64d1b2003-03-24 22:20:47 +0000128 }
129 iovp->iov_len = bufsize;
130 }
131
132 /* seek, write, read and verify */
133 for (i = 0; i < iter; i++) {
134 /*
Wanlong Gao354ebb42012-12-07 10:10:04 +0800135 fillbuf(buf1, bufsize, childnum+i);
136 */
137 vfillbuf(iov1, nvector, childnum + i);
robbiew8c64d1b2003-03-24 22:20:47 +0000138 if (lseek(fd_w, seekoff, SEEK_SET) < 0) {
subrata_modak4bb656a2009-02-26 12:02:09 +0000139 tst_resm(TFAIL, "lseek before write failed: %s",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800140 strerror(errno));
141 return (-1);
robbiew8c64d1b2003-03-24 22:20:47 +0000142 }
143 if (write(fd_w, iov1, bufsize) < bufsize) {
vapier0bdbaa32006-02-12 10:56:55 +0000144 tst_resm(TFAIL, "write failed: %s", strerror(errno));
Wanlong Gao354ebb42012-12-07 10:10:04 +0800145 return (-1);
robbiew8c64d1b2003-03-24 22:20:47 +0000146 }
147 if (action == READ_DIRECT) {
148 /* Make sure data is on to disk before read */
149 if (fsync(fd_w) < 0) {
vapier0bdbaa32006-02-12 10:56:55 +0000150 tst_resm(TFAIL, "fsync failed: %s",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800151 strerror(errno));
152 return (-1);
robbiew8c64d1b2003-03-24 22:20:47 +0000153 }
154 }
155 if (lseek(fd_r, seekoff, SEEK_SET) < 0) {
subrata_modak4bb656a2009-02-26 12:02:09 +0000156 tst_resm(TFAIL, "lseek before read failed: %s",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800157 strerror(errno));
158 return (-1);
robbiew8c64d1b2003-03-24 22:20:47 +0000159 }
160 if (read(fd_r, iov2, bufsize) < bufsize) {
vapier0bdbaa32006-02-12 10:56:55 +0000161 tst_resm(TFAIL, "read failed: %s", strerror(errno));
Wanlong Gao354ebb42012-12-07 10:10:04 +0800162 return (-1);
robbiew8c64d1b2003-03-24 22:20:47 +0000163 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800164 if (bufcmp((char *)iov1, (char *)iov2, bufsize) != 0) {
subrata_modak4bb656a2009-02-26 12:02:09 +0000165 tst_resm(TFAIL, "comparsion failed. Child=%d offset=%d",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800166 childnum, (int)seekoff);
167 return (-1);
robbiew8c64d1b2003-03-24 22:20:47 +0000168 }
169 }
subrata_modak43337a32009-02-26 11:43:51 +0000170 return 0;
robbiew8c64d1b2003-03-24 22:20:47 +0000171}
Wanlong Gao354ebb42012-12-07 10:10:04 +0800172
robbiew8c64d1b2003-03-24 22:20:47 +0000173/*
robbiewbfb98f92002-06-13 05:26:55 +0000174 * child_function: open the file for read and write. Call the runtest routine.
175*/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800176int child_function(int childnum, int action)
robbiewbfb98f92002-06-13 05:26:55 +0000177{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800178 int fd_w, fd_r;
robbiewbfb98f92002-06-13 05:26:55 +0000179
Wanlong Gao354ebb42012-12-07 10:10:04 +0800180 switch (action) {
181 case READ_DIRECT:
182 if ((fd_w = open(filename, O_WRONLY | O_CREAT, 0666)) < 0) {
vapier0bdbaa32006-02-12 10:56:55 +0000183 tst_resm(TFAIL, "fd_w open failed for %s: %s",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800184 filename, strerror(errno));
185 return (-1);
robbiewbfb98f92002-06-13 05:26:55 +0000186 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800187 if ((fd_r = open(filename, O_DIRECT | O_RDONLY, 0666)) < 0) {
vapier0bdbaa32006-02-12 10:56:55 +0000188 tst_resm(TFAIL, "fd_r open failed for %s: %s",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800189 filename, strerror(errno));
robbiewbfb98f92002-06-13 05:26:55 +0000190 close(fd_w);
subrata_modak04e0bfa2009-06-23 14:11:03 +0000191 unlink(filename);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800192 return (-1);
robbiewbfb98f92002-06-13 05:26:55 +0000193 }
194 if (runtest(fd_r, fd_w, childnum, action) == -1) {
vapier0bdbaa32006-02-12 10:56:55 +0000195 tst_resm(TFAIL, "Read Direct-child %d failed",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800196 childnum);
robbiewbfb98f92002-06-13 05:26:55 +0000197 close(fd_w);
198 close(fd_r);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800199 return (-1);
robbiewbfb98f92002-06-13 05:26:55 +0000200 }
201 break;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800202 case WRITE_DIRECT:
203 if ((fd_w =
204 open(filename, O_DIRECT | O_WRONLY | O_CREAT, 0666)) < 0) {
205 tst_resm(TFAIL, "fd_w open failed for %s: %s", filename,
206 strerror(errno));
207 return (-1);
robbiewbfb98f92002-06-13 05:26:55 +0000208 }
209 if ((fd_r = open(filename, O_RDONLY, 0666)) < 0) {
vapier0bdbaa32006-02-12 10:56:55 +0000210 tst_resm(TFAIL, "fd_r open failed for %s: %s",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800211 filename, strerror(errno));
robbiewbfb98f92002-06-13 05:26:55 +0000212 close(fd_w);
subrata_modak04e0bfa2009-06-23 14:11:03 +0000213 unlink(filename);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800214 return (-1);
robbiewbfb98f92002-06-13 05:26:55 +0000215 }
216 if (runtest(fd_r, fd_w, childnum, action) == -1) {
vapier0bdbaa32006-02-12 10:56:55 +0000217 tst_resm(TFAIL, "Write Direct-child %d failed",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800218 childnum);
robbiewbfb98f92002-06-13 05:26:55 +0000219 close(fd_w);
220 close(fd_r);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800221 return (-1);
robbiewbfb98f92002-06-13 05:26:55 +0000222 }
223 break;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800224 case RDWR_DIRECT:
225 if ((fd_w =
226 open(filename, O_DIRECT | O_WRONLY | O_CREAT, 0666)) < 0) {
227 tst_resm(TFAIL, "fd_w open failed for %s: %s", filename,
228 strerror(errno));
229 return (-1);
robbiewbfb98f92002-06-13 05:26:55 +0000230 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800231 if ((fd_r = open(filename, O_DIRECT | O_RDONLY, 0666)) < 0) {
vapier0bdbaa32006-02-12 10:56:55 +0000232 tst_resm(TFAIL, "fd_r open failed for %s: %s",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800233 filename, strerror(errno));
robbiewbfb98f92002-06-13 05:26:55 +0000234 close(fd_w);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800235 return (-1);
robbiewbfb98f92002-06-13 05:26:55 +0000236 }
237 if (runtest(fd_r, fd_w, childnum, action) == -1) {
vapier0bdbaa32006-02-12 10:56:55 +0000238 tst_resm(TFAIL, "RDWR Direct-child %d failed",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800239 childnum);
robbiewbfb98f92002-06-13 05:26:55 +0000240 close(fd_w);
241 close(fd_r);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800242 return (-1);
robbiewbfb98f92002-06-13 05:26:55 +0000243 }
244 break;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800245 default:
246 fprintf(stderr, "Invalid Action Value\n");
247 return (-1);
robbiewbfb98f92002-06-13 05:26:55 +0000248 }
249 close(fd_w);
250 close(fd_r);
251 exit(0);
252}
253
Wanlong Gao354ebb42012-12-07 10:10:04 +0800254int main(int argc, char *argv[])
robbiewbfb98f92002-06-13 05:26:55 +0000255{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800256 int *pidlst;
257 int numchild = 1; /* Number of children. Default 5 */
258 int i, fail_count = 0, failed = 0, total = 0;
robbiewbfb98f92002-06-13 05:26:55 +0000259
260 /* Options */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800261 sprintf(filename, "testdata-6.%ld", syscall(__NR_gettid));
robbiewbfb98f92002-06-13 05:26:55 +0000262 while ((i = getopt(argc, argv, "b:o:i:n:v:f:")) != -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800263 switch (i) {
robbiewbfb98f92002-06-13 05:26:55 +0000264 case 'b':
265 if ((bufsize = atoi(optarg)) <= 0) {
266 fprintf(stderr, "bufsize must be > 0\n");
267 prg_usage();
268 }
269 if (bufsize % 4096 != 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800270 fprintf(stderr,
271 "bufsize must be multiple of 4k\n");
robbiewbfb98f92002-06-13 05:26:55 +0000272 prg_usage();
273 }
274 break;
275 case 'o':
276 if ((offset = atoi(optarg)) <= 0) {
277 fprintf(stderr, "offset must be > 0\n");
278 prg_usage();
279 }
280 break;
281 case 'i':
282 if ((iter = atoi(optarg)) <= 0) {
283 fprintf(stderr, "iterations must be > 0\n");
284 prg_usage();
285 }
286 break;
287 case 'n':
288 if ((numchild = atoi(optarg)) <= 0) {
289 fprintf(stderr, "no of children must be > 0\n");
290 prg_usage();
291 }
292 break;
293 case 'v':
294 if ((nvector = atoi(optarg)) <= 0) {
295 fprintf(stderr, "vectory array must be > 0\n");
296 prg_usage();
297 }
298 break;
299 case 'f':
300 strcpy(filename, optarg);
301 break;
302 default:
303 prg_usage();
304 }
305 }
306
subrata_modak04e0bfa2009-06-23 14:11:03 +0000307 setup();
robbiew8680e9b2003-11-19 15:29:01 +0000308
robbiewbfb98f92002-06-13 05:26:55 +0000309 /* Testblock-1: Read with Direct IO, Write without */
Garrett Cooper8fb1cdb2010-11-28 22:56:35 -0800310 if (forkchldrn(&pidlst, numchild, READ_DIRECT, child_function) < 0) {
robbiewbfb98f92002-06-13 05:26:55 +0000311 failed = TRUE;
312 fail_count++;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800313 tst_resm(TFAIL, "Read with Direct IO, Write without");
314 } else {
robbiewbfb98f92002-06-13 05:26:55 +0000315 if (waitchldrn(&pidlst, numchild) < 0) {
316 failed = TRUE;
317 fail_count++;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800318 tst_resm(TFAIL, "Read with Direct IO, Write without");
319 } else
320 tst_resm(TPASS, "Read with Direct IO, Write without");
robbiew92b688b2004-03-01 22:36:38 +0000321
robbiewbfb98f92002-06-13 05:26:55 +0000322 }
323 unlink(filename);
324 free(pidlst);
325 total++;
326
327 /* Testblock-2: Write with Direct IO, Read without */
328 if (forkchldrn(&pidlst, numchild, WRITE_DIRECT, child_function) < 0) {
329 failed = TRUE;
330 fail_count++;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800331 tst_resm(TFAIL, "Write with Direct IO, Read without");
332 } else {
robbiewbfb98f92002-06-13 05:26:55 +0000333 if (waitchldrn(&pidlst, numchild) < 0) {
334 failed = TRUE;
335 fail_count++;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800336 tst_resm(TFAIL, "Write with Direct IO, Read without");
337 } else
338 tst_resm(TPASS, "Write with Direct IO, Read without");
robbiewbfb98f92002-06-13 05:26:55 +0000339 }
340 unlink(filename);
341 free(pidlst);
342 total++;
343
344 /* Testblock-3: Read, Write with Direct IO. */
345 if (forkchldrn(&pidlst, numchild, RDWR_DIRECT, child_function) < 0) {
346 failed = TRUE;
347 fail_count++;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800348 tst_resm(TFAIL, "Read, Write with Direct IO");
349 } else {
robbiewbfb98f92002-06-13 05:26:55 +0000350 if (waitchldrn(&pidlst, numchild) < 0) {
351 failed = TRUE;
352 fail_count++;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800353 tst_resm(TFAIL, "Read, Write with Direct IO");
354 } else
355 tst_resm(TPASS, "Read, Write with Direct IO");
robbiewbfb98f92002-06-13 05:26:55 +0000356 }
357 unlink(filename);
358 free(pidlst);
359 total++;
360
robbiew92b688b2004-03-01 22:36:38 +0000361 if (failed)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800362 tst_resm(TINFO, "%d/%d testblocks failed", fail_count, total);
robbiew92b688b2004-03-01 22:36:38 +0000363 else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800364 tst_resm(TINFO,
365 "%d testblocks %d iterations with %d children completed",
366 total, iter, numchild);
subrata_modak04e0bfa2009-06-23 14:11:03 +0000367 cleanup();
Garrett Cooper2c282152010-12-16 00:55:50 -0800368 tst_exit();
robbiewbfb98f92002-06-13 05:26:55 +0000369}
370
subrata_modak04e0bfa2009-06-23 14:11:03 +0000371static void setup(void)
372{
373 tst_tmpdir();
374
Wanlong Gao354ebb42012-12-07 10:10:04 +0800375 if ((fd1 = open(filename, O_CREAT | O_EXCL, 0600)) < 0) {
376 tst_brkm(TBROK, cleanup, "Couldn't create test file %s: %s",
377 filename, strerror(errno));
subrata_modak04e0bfa2009-06-23 14:11:03 +0000378 }
379 close(fd1);
380
381 /* Test for filesystem support of O_DIRECT */
382 if ((fd1 = open(filename, O_DIRECT, 0600)) < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800383 tst_brkm(TCONF, cleanup,
384 "O_DIRECT is not supported by this filesystem. %s",
385 strerror(errno));
subrata_modak04e0bfa2009-06-23 14:11:03 +0000386 }
Subrata Modak76a720a2010-07-03 21:08:18 +0530387 close(fd1);
subrata_modak04e0bfa2009-06-23 14:11:03 +0000388}
389
390static void cleanup(void)
391{
Garrett Cooperdf3eb162010-11-28 22:44:32 -0800392 if (fd1 != -1)
subrata_modak04e0bfa2009-06-23 14:11:03 +0000393 unlink(filename);
394
395 tst_rmdir();
396
subrata_modak04e0bfa2009-06-23 14:11:03 +0000397}
robbiew96f4bb32003-03-13 15:39:53 +0000398
399#else /* O_DIRECT */
400
Wanlong Gao354ebb42012-12-07 10:10:04 +0800401int main()
402{
robbiew96f4bb32003-03-13 15:39:53 +0000403
Wanlong Gao354ebb42012-12-07 10:10:04 +0800404 tst_resm(TCONF, "O_DIRECT is not defined.");
405 return 0;
robbiew96f4bb32003-03-13 15:39:53 +0000406}
Chris Dearmanec6edca2012-10-17 19:54:01 -0700407#endif /* O_DIRECT */