1 /*
2 * Copyright (c) 2004 Daniel McNeil <daniel@osdl.org>
3 * 2004 Open Source Development Lab
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12 * the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 *
18 * Module: .c
19 * Change History:
20 *
21 * 2/2004 Marty Ridgeway (mridge@us.ibm.com) Changes to adapt to LTP
22 *
23 */
24
25 #define _GNU_SOURCE
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <sys/types.h>
30 #include <signal.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33
34 #include <libaio.h>
35
36 #define NUM_CHILDREN 8
37
check_zero(unsigned char * buf,int size)38 char *check_zero(unsigned char *buf, int size)
39 {
40 unsigned char *p;
41
42 p = buf;
43
44 while (size > 0) {
45 if (*buf != 0) {
46 fprintf(stderr,
47 "non zero buffer at buf[%d] => 0x%02x,%02x,%02x,%02x\n",
48 buf - p, (unsigned int)buf[0],
49 size > 1 ? (unsigned int)buf[1] : 0,
50 size > 2 ? (unsigned int)buf[2] : 0,
51 size > 3 ? (unsigned int)buf[3] : 0);
52 fprintf(stderr, "buf %p, p %p\n", buf, p);
53 return buf;
54 }
55 buf++;
56 size--;
57 }
58 return 0; /* all zeros */
59 }
60
read_eof(char * filename)61 int read_eof(char *filename)
62 {
63 int fd;
64 int i;
65 int r;
66 char buf[4096];
67
68 while ((fd = open(filename, O_RDONLY)) < 0) {
69 sleep(1); /* wait for file to be created */
70 }
71
72 for (i = 0; i < 1000000; i++) {
73 off_t offset;
74 char *bufoff;
75
76 offset = lseek(fd, SEEK_END, 0);
77 r = read(fd, buf, 4096);
78 if (r > 0) {
79 if ((bufoff = check_zero(buf, r))) {
80 fprintf(stderr, "non-zero read at offset %p\n",
81 offset + bufoff);
82 exit(1);
83 }
84 }
85 }
86 return 0;
87 }
88
89 #define NUM_AIO 16
90 #define AIO_SIZE 64*1024
91
92 /*
93 * append to the end of a file using AIO DIRECT.
94 */
aiodio_append(char * filename)95 void aiodio_append(char *filename)
96 {
97 int fd;
98 void *bufptr;
99 int i;
100 int w;
101 struct iocb iocb_array[NUM_AIO];
102 struct iocb *iocbs[NUM_AIO];
103 off_t offset = 0;
104 io_context_t myctx;
105 struct io_event event;
106 struct timespec timeout;
107
108 fd = open(filename, O_DIRECT | O_WRONLY | O_CREAT, 0666);
109 if (fd < 0) {
110 perror("cannot create file");
111 return;
112 }
113
114 memset(&myctx, 0, sizeof(myctx));
115 io_queue_init(NUM_AIO, &myctx);
116
117 for (i = 0; i < NUM_AIO; i++) {
118 if (posix_memalign(&bufptr, 4096, AIO_SIZE)) {
119 perror("cannot malloc aligned memory");
120 return;
121 }
122 memset(bufptr, 0, AIO_SIZE);
123 io_prep_pwrite(&iocb_array[i], fd, bufptr, AIO_SIZE, offset);
124 iocbs[i] = &iocb_array[i];
125 offset += AIO_SIZE;
126 }
127
128 /*
129 * Start the 1st NUM_AIO requests
130 */
131 if ((w = io_submit(myctx, NUM_AIO, iocbs)) < 0) {
132 fprintf(stderr, "io_submit write returned %d\n", w);
133 }
134
135 /*
136 * As AIO requests finish, keep issuing more AIOs.
137 */
138 for (; i < 1000; i++) {
139 int n = 0;
140 struct iocb *iocbp;
141
142 n = io_getevents(myctx, 1, 1, &event, &timeout);
143 if (n > 0) {
144 iocbp = (struct iocb *)event.obj;
145
146 if (n > 0) {
147 io_prep_pwrite(iocbp, fd, iocbp->u.c.buf,
148 AIO_SIZE, offset);
149 offset += AIO_SIZE;
150 if ((w = io_submit(myctx, 1, &iocbp)) < 0) {
151 fprintf(stderr,
152 "write %d returned %d\n", i, w);
153 }
154 }
155 }
156 }
157 }
158
main(int argc,char ** argv)159 int main(int argc, char **argv)
160 {
161 int pid[NUM_CHILDREN];
162 int num_children = 1;
163 int i;
164 char *filename = argv[1];
165
166 printf("Starting aio/dio append test...\n");
167
168 for (i = 0; i < num_children; i++) {
169 if ((pid[i] = fork()) == 0) {
170 /* child */
171 return read_eof(filename);
172 } else if (pid[i] < 0) {
173 /* error */
174 perror("fork error");
175 break;
176 } else {
177 /* Parent */
178 continue;
179 }
180 }
181
182 /*
183 * Parent appends to end of file using direct i/o
184 */
185
186 aiodio_append(filename);
187
188 for (i = 0; i < num_children; i++) {
189 kill(pid[i], SIGTERM);
190 }
191
192 return 0;
193 }
194