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