1 /*
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
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 /*
21 * NAME
22 * diotest2.c
23 *
24 * DESCRIPTION
25 * Program tests the combinations of direct and buffered read, write.
26 * The bufsize should be in n*4k size for direct read, write. The offset
27 * value marks the starting position in file from where to start the
28 * read and write. Larger files can be created using the offset parameter.
29 * Test data file can be specified through commandline and is useful
30 * for running test with raw devices as a file.
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 * diotest2 [-b bufsize] [-o offset] [-i iterations] [-f filename]
38 *
39 * History
40 * 04/22/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 <fcntl.h>
50 #include <string.h>
51 #include <sys/file.h>
52 #include <sys/types.h>
53 #include <sys/syscall.h>
54 #include <errno.h>
55
56 #include "diotest_routines.h"
57
58 #include "test.h"
59
60 char *TCID = "diotest02"; /* Test program identifier. */
61 int TST_TOTAL = 3; /* Total number of test conditions */
62
63 #ifdef O_DIRECT
64
65 #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
72 /*
73 * runtest: write the data to the file. Read the data from the file and compare.
74 * For each iteration, write data starting at offse+iter*bufsize
75 * location in the file and read from there.
76 */
runtest(int fd_r,int fd_w,int iter,off64_t offset,int action)77 int runtest(int fd_r, int fd_w, int iter, off64_t offset, int action)
78 {
79 char *buf1;
80 char *buf2;
81 int i, bufsize = BUFSIZE;
82
83 /* Allocate for buffers */
84 if ((buf1 = valloc(bufsize)) == 0) {
85 tst_resm(TFAIL, "valloc() buf1 failed: %s", strerror(errno));
86 return (-1);
87 }
88 if ((buf2 = valloc(bufsize)) == 0) {
89 tst_resm(TFAIL, "valloc() buf2 failed: %s", strerror(errno));
90 return (-1);
91 }
92
93 /* seek bufsize*iteration and write. seek and read. verify. */
94 for (i = 0; i < iter; i++) {
95 fillbuf(buf1, bufsize, i);
96 if (lseek(fd_w, offset + iter * bufsize, SEEK_SET) < 0) {
97 tst_resm(TFAIL, "lseek before write failed: %s",
98 strerror(errno));
99 return (-1);
100 }
101 if (write(fd_w, buf1, bufsize) < bufsize) {
102 tst_resm(TFAIL, "write failed: %s", strerror(errno));
103 return (-1);
104 }
105 if (lseek(fd_r, offset + iter * bufsize, SEEK_SET) < 0) {
106 tst_resm(TFAIL, "lseek before read failed: %s",
107 strerror(errno));
108 return (-1);
109 }
110 if (read(fd_r, buf2, bufsize) < bufsize) {
111 tst_resm(TFAIL, "read failed: %s", strerror(errno));
112 return (-1);
113 }
114 if (bufcmp(buf1, buf2, bufsize) != 0) {
115 tst_resm(TFAIL, "read/write comparision failed");
116 return (-1);
117 }
118 }
119 return 0;
120 }
121
122 /*
123 * prg_usage: display the program usage.
124 */
prg_usage()125 void prg_usage()
126 {
127 fprintf(stderr,
128 "Usage: diotest2 [-b bufsize] [-o offset] [-i iterations] [-f filename]\n");
129 exit(1);
130 }
131
132 int fd1 = -1;
133 char filename[LEN];
134 static void setup(void);
135 static void cleanup(void);
136
main(int argc,char * argv[])137 int main(int argc, char *argv[])
138 {
139 int iter = 100; /* Iterations. Default 100 */
140 int bufsize = BUFSIZE; /* Buffer size. Default 4k */
141 off64_t offset = 0; /* Offset. Default 0 */
142 int i, action, fd_r, fd_w;
143 int fail_count = 0, total = 0, failed = 0;
144
145 /* Options */
146 sprintf(filename, "testdata-2.%ld", syscall(__NR_gettid));
147 while ((i = getopt(argc, argv, "b:o:i:f:")) != -1) {
148 switch (i) {
149 case 'b':
150 if ((bufsize = atoi(optarg)) <= 0) {
151 fprintf(stderr, "bufsize must be > 0\n");
152 prg_usage();
153 }
154 if (bufsize % 4096 != 0) {
155 fprintf(stderr,
156 "bufsize must be multiple of 4k\n");
157 prg_usage();
158 }
159 break;
160 case 'o':
161 if ((offset = atoi(optarg)) <= 0) {
162 fprintf(stderr, "offset must be > 0\n");
163 prg_usage();
164 }
165 break;
166 case 'i':
167 if ((iter = atoi(optarg)) <= 0) {
168 fprintf(stderr, "iterations must be > 0\n");
169 prg_usage();
170 }
171 break;
172 case 'f':
173 strcpy(filename, optarg);
174 break;
175 default:
176 prg_usage();
177 }
178 }
179
180 setup();
181
182 /* Testblock-1: Read with Direct IO, Write without */
183 action = READ_DIRECT;
184 if ((fd_w = open(filename, O_WRONLY | O_CREAT, 0666)) < 0)
185 tst_brkm(TBROK | TERRNO, cleanup,
186 "open(%s, O_WRONLY..) failed", filename);
187 if ((fd_r = open(filename, O_DIRECT | O_RDONLY, 0666)) < 0)
188 tst_brkm(TBROK | TERRNO, cleanup,
189 "open(%s, O_DIRECT|O_RDONLY..) failed", filename);
190 if (runtest(fd_r, fd_w, iter, offset, action) < 0) {
191 failed = TRUE;
192 fail_count++;
193 tst_resm(TFAIL, "Read with Direct IO, Write without");
194 } else
195 tst_resm(TPASS, "Read with Direct IO, Write without");
196 close(fd_w);
197 close(fd_r);
198 unlink(filename);
199 total++;
200
201 /* Testblock-2: Write with Direct IO, Read without */
202 action = WRITE_DIRECT;
203 if ((fd_w = open(filename, O_DIRECT | O_WRONLY | O_CREAT, 0666)) == -1)
204 tst_brkm(TBROK | TERRNO, cleanup,
205 "open(%s, O_DIRECT|O_WRONLY..) failed", filename);
206 if ((fd_r = open(filename, O_RDONLY | O_CREAT, 0666)) == -1)
207 tst_brkm(TBROK | TERRNO, cleanup,
208 "open(%s, O_RDONLY..) failed", filename);
209 if (runtest(fd_r, fd_w, iter, offset, action) < 0) {
210 failed = TRUE;
211 fail_count++;
212 tst_resm(TFAIL, "Write with Direct IO, Read without");
213 } else
214 tst_resm(TPASS, "Write with Direct IO, Read without");
215 close(fd_w);
216 close(fd_r);
217 unlink(filename);
218 total++;
219
220 /* Testblock-3: Read, Write with Direct IO. */
221 action = RDWR_DIRECT;
222 if ((fd_w = open(filename, O_DIRECT | O_WRONLY | O_CREAT, 0666)) == -1)
223 tst_brkm(TBROK | TERRNO, cleanup,
224 "open(%s, O_DIRECT|O_WRONLY|O_CREAT, ..) failed",
225 filename);
226 if ((fd_r = open(filename, O_DIRECT | O_RDONLY | O_CREAT, 0666)) == -1)
227 tst_brkm(TBROK | TERRNO, cleanup,
228 "open(%s, O_DIRECT|O_RDONLY|O_CREAT, ..) failed",
229 filename);
230 if (runtest(fd_r, fd_w, iter, offset, action) < 0) {
231 failed = TRUE;
232 fail_count++;
233 tst_resm(TFAIL, "Read, Write with Direct IO");
234 } else
235 tst_resm(TPASS, "Read, Write with Direct IO");
236 close(fd_w);
237 close(fd_r);
238 unlink(filename);
239 total++;
240
241 if (failed)
242 tst_resm(TINFO, "%d/%d testblocks failed", fail_count, total);
243 else
244 tst_resm(TINFO, "%d testblocks %d iterations completed",
245 total, iter);
246 cleanup();
247
248 tst_exit();
249
250 }
251
setup(void)252 static void setup(void)
253 {
254 tst_tmpdir();
255
256 if ((fd1 = open(filename, O_CREAT | O_EXCL, 0600)) == -1)
257 tst_brkm(TBROK | TERRNO, cleanup,
258 "open(%s, O_CREAT|O_EXCL, ..) failed", filename);
259 close(fd1);
260
261 /* Test for filesystem support of O_DIRECT */
262 if ((fd1 = open(filename, O_DIRECT, 0600)) == -1)
263 tst_brkm(TCONF | TERRNO, cleanup,
264 "open(%s, O_DIRECT, ..) failed", filename);
265 close(fd1);
266
267 }
268
cleanup(void)269 static void cleanup(void)
270 {
271 if (fd1 != -1)
272 unlink(filename);
273
274 tst_rmdir();
275
276 }
277
278 #else /* O_DIRECT */
main()279 int main()
280 {
281 tst_brkm(TCONF, NULL, "O_DIRECT is not defined.");
282 }
283 #endif /* O_DIRECT */
284