1 /*
2 *
3 * Copyright (c) International Business Machines Corp., 2003
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 * aiotest1.c
23 *
24 * DESCRIPTION
25 * Perform aio read, write operations for given number of requests.
26 * Submit i/o for each request individually.
27 * Repeat the test for each of the following cases and measure time.
28 * Testblock1: Write one request at a time.
29 * Testblock2: Read one request at a time.
30 * Testblock3: Prepare, Write one request at a time.
31 * Testblock4: Prepare, Read one request at a time.
32 * Testblock5: Prepare, Write/Read one request at a time.
33 * Testblock6: Prepare, Write/Read/Verify one request at a time.
34 *
35 * Author
36 * 08/24/2002 Narasimha Sharoff nsharoff@us.ibm.com
37 */
38
39 /*
40 * History
41 * 04/18/2003 nsharoff@us.ibm.com
42 * Updated
43 * 05/21/2003 Paul Larson plars@linuxtestproject.org
44 * Rewrote the test under LTP, using LTP test harness
45 * and other minor improvements and fixes
46 */
47
48 #define _XOPEN_SOURCE 600
49
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <unistd.h>
53 #include <fcntl.h>
54 #include <time.h>
55 #include <errno.h>
56 #include <sys/types.h>
57 #include <sys/stat.h>
58 #include <sys/time.h>
59 #include <sys/resource.h>
60
61 #include "test.h"
62 #include "config.h"
63
64 char *TCID = "aio01";
65 int TST_TOTAL = 6;
66
67 #ifdef HAVE_LIBAIO
68 #include <libaio.h>
69
70 static void help(void);
71 static void setup(void);
72 static void cleanup(void);
73
74 #define mapsize (1 << 14)
75
76 int fd;
77 char *maddr;
78
79 size_t bufsize; /* Size of I/O, 8k default */
80 io_context_t io_ctx; /* I/O Context */
81 struct iocb **iocbs; /* I/O Control Blocks */
82 char *srcbuf, *dstbuf;
83 char fname[128];
84 char tbuf[80];
85 int pos, nr;
86 struct stat s;
87
88 struct test_case_t {
89 off_t newsize;
90 char *desc;
91 } TC[] = {
92 {
93 mapsize - 8192, "ftruncate mmaped file to a smaller size"}, {
94 mapsize + 1024, "ftruncate mmaped file to a larger size"}, {
95 0, "ftruncate mmaped file to 0 size"},};
96
main(int argc,char ** argv)97 int main(int argc, char **argv)
98 {
99 int i, j, sec, usec;
100 int failflag = 0;
101 int bflag = 0, nflag = 0, Fflag = 0;
102 char *optb, *optn, *optF;
103 struct io_event event;
104 static struct timespec ts;
105 struct timeval stv, etv;
106
107 option_t options[] = {
108 {"b:", &bflag, &optb},
109 {"n:", &nflag, &optn},
110 {"F:", &Fflag, &optF},
111 {NULL, NULL, NULL}
112 };
113
114 tst_parse_opts(argc, argv, options, &help);
115
116 bufsize = (bflag ? atoi(optb) : 8192);
117 nr = (nflag ? atoi(optn) : 10);
118 if (Fflag) {
119 sprintf(fname, "%s", optF);
120 } else {
121 sprintf(fname, "aiofile");
122 }
123
124 setup();
125
126 /* TEST 1 */
127 pos = 0;
128 gettimeofday(&stv, NULL);
129 io_prep_pwrite(iocbs[0], fd, srcbuf, bufsize, pos);
130 for (i = 0; i < nr; i++) {
131 ts.tv_sec = 30;
132 ts.tv_nsec = 0;
133 do {
134 TEST(io_submit(io_ctx, 1, iocbs));
135 } while (TEST_RETURN == -EAGAIN);
136 if (TEST_RETURN < 0) {
137 tst_resm(TFAIL, "Test 1: io_submit failed - retval=%ld"
138 ", errno=%d", TEST_RETURN, TEST_ERRNO);
139 failflag = 1;
140 continue;
141 }
142 while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1) ;
143 gettimeofday(&etv, NULL);
144 }
145 if (!failflag) {
146 sec = etv.tv_sec - stv.tv_sec;
147 usec = etv.tv_usec - stv.tv_usec;
148 if (usec < 0) {
149 usec += 1000000;
150 sec--;
151 }
152 tst_resm(TPASS, "Test 1: %d writes in %3d.%06d sec",
153 nr, sec, usec);
154 }
155
156 /* TEST 2 */
157 pos = 0;
158 failflag = 0;
159 gettimeofday(&stv, NULL);
160 io_prep_pread(iocbs[0], fd, dstbuf, bufsize, pos);
161 for (i = 0; i < nr; i++) {
162 ts.tv_sec = 30;
163 ts.tv_nsec = 0;
164 do {
165 TEST(io_submit(io_ctx, 1, iocbs));
166 } while (TEST_RETURN == -EAGAIN);
167 if (TEST_RETURN < 0) {
168 tst_resm(TFAIL, "Test 2: io_submit failed - retval=%ld"
169 ", errno=%d", TEST_RETURN, TEST_ERRNO);
170 failflag = 1;
171 continue;
172 }
173 while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1) ;
174 gettimeofday(&etv, NULL);
175 }
176 if (!failflag) {
177 sec = etv.tv_sec - stv.tv_sec;
178 usec = etv.tv_usec - stv.tv_usec;
179 if (usec < 0) {
180 usec += 1000000;
181 sec--;
182 }
183 tst_resm(TPASS, "Test 2: %d reads in %3d.%06d sec",
184 nr, sec, usec);
185 }
186
187 /* TEST 3 */
188 pos = 0;
189 failflag = 0;
190 gettimeofday(&stv, NULL);
191 for (i = 0; i < nr; i++) {
192 io_prep_pwrite(iocbs[0], fd, srcbuf, bufsize, pos);
193 ts.tv_sec = 30;
194 ts.tv_nsec = 0;
195 do {
196 TEST(io_submit(io_ctx, 1, iocbs));
197 } while (TEST_RETURN == -EAGAIN);
198 if (TEST_RETURN < 0) {
199 tst_resm(TFAIL, "Test 3: io_submit failed - retval=%ld"
200 ", errno=%d", TEST_RETURN, TEST_ERRNO);
201 failflag = 1;
202 continue;
203 }
204 while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1) ;
205 gettimeofday(&etv, NULL);
206 }
207 if (!failflag) {
208 sec = etv.tv_sec - stv.tv_sec;
209 usec = etv.tv_usec - stv.tv_usec;
210 if (usec < 0) {
211 usec += 1000000;
212 sec--;
213 }
214 tst_resm(TPASS, "Test 3: %d prep,writes in %3d.%06d sec",
215 nr, sec, usec);
216 }
217
218 /* TEST 4 */
219 pos = 0;
220 failflag = 0;
221 gettimeofday(&stv, NULL);
222 for (i = 0; i < nr; i++) {
223 io_prep_pread(iocbs[0], fd, dstbuf, bufsize, pos);
224 ts.tv_sec = 30;
225 ts.tv_nsec = 0;
226 do {
227 TEST(io_submit(io_ctx, 1, iocbs));
228 } while (TEST_RETURN == -EAGAIN);
229 if (TEST_RETURN < 0) {
230 tst_resm(TFAIL, "Test 4: io_submit failed - retval=%ld"
231 ", errno=%d", TEST_RETURN, TEST_ERRNO);
232 failflag = 1;
233 continue;
234 }
235 while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1) ;
236 gettimeofday(&etv, NULL);
237 }
238 if (!failflag) {
239 sec = etv.tv_sec - stv.tv_sec;
240 usec = etv.tv_usec - stv.tv_usec;
241 if (usec < 0) {
242 usec += 1000000;
243 sec--;
244 }
245 tst_resm(TPASS, "Test 4: %d prep,reads in %3d.%06d sec",
246 nr, sec, usec);
247 }
248
249 /* TEST 5 */
250 pos = 0;
251 failflag = 0;
252 gettimeofday(&stv, NULL);
253 for (i = 0; i < nr; i++) {
254 io_prep_pwrite(iocbs[0], fd, srcbuf, bufsize, pos);
255 ts.tv_sec = 30;
256 ts.tv_nsec = 0;
257 do {
258 TEST(io_submit(io_ctx, 1, iocbs));
259 } while (TEST_RETURN == -EAGAIN);
260 if (TEST_RETURN < 0) {
261 tst_resm(TFAIL, "Test 5: write io_submit failed - "
262 "retval=%ld, errno=%d", TEST_RETURN,
263 TEST_ERRNO);
264 failflag = 1;
265 continue;
266 }
267 while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1) ;
268 io_prep_pread(iocbs[0], fd, dstbuf, bufsize, pos);
269 ts.tv_sec = 30;
270 ts.tv_nsec = 0;
271 do {
272 TEST(io_submit(io_ctx, 1, iocbs));
273 } while (TEST_RETURN == -EAGAIN);
274 if (TEST_RETURN < 0) {
275 tst_resm(TFAIL, "Test 5: read io_submit failed - "
276 "retval=%ld, errno=%d", TEST_RETURN,
277 TEST_ERRNO);
278 failflag = 1;
279 continue;
280 }
281 while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1) ;
282 gettimeofday(&etv, NULL);
283 }
284 if (!failflag) {
285 sec = etv.tv_sec - stv.tv_sec;
286 usec = etv.tv_usec - stv.tv_usec;
287 if (usec < 0) {
288 usec += 1000000;
289 sec--;
290 }
291 tst_resm(TPASS, "Test 5: %d reads and writes in %3d.%06d sec",
292 nr, sec, usec);
293 }
294
295 /* TEST 6 */
296 pos = 0;
297 failflag = 0;
298 gettimeofday(&stv, NULL);
299 for (i = 0; i < nr; i++) {
300 io_prep_pwrite(iocbs[0], fd, srcbuf, bufsize, pos);
301 ts.tv_sec = 30;
302 ts.tv_nsec = 0;
303 do {
304 TEST(io_submit(io_ctx, 1, iocbs));
305 } while (TEST_RETURN == -EAGAIN);
306 if (TEST_RETURN < 0) {
307 tst_resm(TFAIL, "Test 6: write io_submit failed - "
308 "retval=%ld, errno=%d", TEST_RETURN,
309 TEST_ERRNO);
310 failflag = 1;
311 continue;
312 }
313 while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1) ;
314 io_prep_pread(iocbs[0], fd, dstbuf, bufsize, pos);
315 ts.tv_sec = 30;
316 ts.tv_nsec = 0;
317 do {
318 TEST(io_submit(io_ctx, 1, iocbs));
319 } while (TEST_RETURN == -EAGAIN);
320 if (TEST_RETURN < 0) {
321 tst_resm(TFAIL, "Test 6: read io_submit failed - "
322 "retval=%ld, errno=%d", TEST_RETURN,
323 TEST_ERRNO);
324 failflag = 1;
325 continue;
326 }
327 while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1) ;
328 for (j = 0; j < (int)bufsize; j++) {
329 if (srcbuf[j] != dstbuf[j]) {
330 tst_resm(TFAIL, "Test 6: compare failed - "
331 "read: %c, " "actual: %c",
332 dstbuf[j], srcbuf[j]);
333 break;
334 }
335 }
336 gettimeofday(&etv, NULL);
337 }
338 if (!failflag) {
339 sec = etv.tv_sec - stv.tv_sec;
340 usec = etv.tv_usec - stv.tv_usec;
341 if (usec < 0) {
342 usec += 1000000;
343 sec--;
344 }
345 tst_resm(TPASS, "Test 6: %d read,write,verify in %d.%06d sec",
346 i, sec, usec);
347 }
348
349 cleanup();
350
351 tst_exit();
352 }
353
help(void)354 static void help(void)
355 {
356 printf(" -b n Buffersize\n");
357 printf(" -n n Number of requests\n");
358 printf(" -F s Filename to run the tests against\n");
359 }
360
setup(void)361 static void setup(void)
362 {
363 int ret;
364
365 tst_sig(NOFORK, DEF_HANDLER, cleanup);
366
367 /* Pause if option was specified */
368 TEST_PAUSE;
369
370 tst_tmpdir();
371
372 if ((fd = open(fname, O_RDWR | O_CREAT, 0600)) < 0)
373 tst_brkm(TFAIL, cleanup, "failed to open %s "
374 "file, errno: %d", fname, errno);
375 stat(fname, &s);
376 if ((iocbs = malloc(sizeof(int) * nr)) == NULL)
377 tst_brkm(TFAIL, cleanup, "malloc for iocbs failed - "
378 "errno: %d", errno);
379 if ((iocbs[0] = malloc(sizeof(struct iocb))) == NULL)
380 tst_brkm(TFAIL, cleanup, "malloc for iocbs elements failed - "
381 "errno: %d", errno);
382 if (S_ISCHR(s.st_mode)) {
383 if ((ret =
384 posix_memalign((void **)&srcbuf, bufsize, bufsize)) != 0)
385 tst_brkm(TFAIL, cleanup,
386 "posix_memalign for srcbuf "
387 "failed - errno: %d", errno);
388 if ((ret =
389 posix_memalign((void **)&dstbuf, bufsize, bufsize)) != 0)
390 tst_brkm(TFAIL, cleanup,
391 "posix_memalign for dstbuf "
392 "failed - errno: %d", errno);
393 } else {
394 if ((srcbuf = malloc(sizeof(char) * bufsize)) == NULL)
395 tst_brkm(TFAIL, cleanup, "malloc for srcbuf "
396 "failed - errno: %d", errno);
397 if ((dstbuf = malloc(sizeof(char) * bufsize)) == NULL)
398 tst_brkm(TFAIL, cleanup, "malloc for dstbuf "
399 "failed - errno: %d", errno);
400 }
401 memset((void *)srcbuf, 65, bufsize);
402 if ((ret = io_queue_init(1, &io_ctx)) != 0)
403 tst_brkm(TFAIL, cleanup, "io_queue_init failed: %s",
404 strerror(ret));
405 }
406
cleanup(void)407 static void cleanup(void)
408 {
409 free(dstbuf);
410 free(srcbuf);
411 free(iocbs[0]);
412 free(iocbs);
413 close(fd);
414 io_queue_release(io_ctx);
415 tst_rmdir();
416 }
417
418 #else
main(void)419 int main(void)
420 {
421 tst_brkm(TCONF, NULL, "test requires libaio and it's development packages");
422 }
423 #endif
424