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 <errno.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34
35 #include "config.h"
36 #include "test.h"
37
38 char *TCID = "aiodio_append";
39
40 #ifdef HAVE_LIBAIO
41 #include <libaio.h>
42
43 #define NUM_CHILDREN 8
44
45 #include "common_checkzero.h"
46
read_eof(char * filename)47 int read_eof(char *filename)
48 {
49 int fd;
50 int i;
51 int r;
52 char buf[4096];
53
54 while ((fd = open(filename, O_RDONLY)) < 0) {
55 sleep(1); /* wait for file to be created */
56 }
57
58 for (i = 0; i < 1000000; i++) {
59 off_t offset;
60 char *bufoff;
61
62 offset = lseek(fd, SEEK_END, 0);
63 r = read(fd, buf, 4096);
64 if (r > 0) {
65 if ((bufoff = check_zero(buf, r))) {
66 fprintf(stderr, "non-zero read at offset %p\n",
67 offset + bufoff);
68 exit(1);
69 }
70 }
71 }
72 return 0;
73 }
74
75 #define NUM_AIO 16
76 #define AIO_SIZE 64*1024
77
78 /*
79 * append to the end of a file using AIO DIRECT.
80 */
aiodio_append(char * filename)81 void aiodio_append(char *filename)
82 {
83 int fd;
84 void *bufptr;
85 int i;
86 int w;
87 struct iocb iocb_array[NUM_AIO];
88 struct iocb *iocbs[NUM_AIO];
89 off_t offset = 0;
90 io_context_t myctx;
91 struct io_event event;
92 struct timespec timeout;
93
94 fd = open(filename, O_DIRECT | O_WRONLY | O_CREAT, 0666);
95 if (fd < 0) {
96 perror("cannot create file");
97 return;
98 }
99
100 memset(&myctx, 0, sizeof(myctx));
101 io_queue_init(NUM_AIO, &myctx);
102
103 for (i = 0; i < NUM_AIO; i++) {
104 TEST(posix_memalign(&bufptr, 4096, AIO_SIZE));
105 if (TEST_RETURN) {
106 tst_resm(TBROK | TRERRNO, "cannot malloc aligned memory");
107 return;
108 }
109 memset(bufptr, 0, AIO_SIZE);
110 io_prep_pwrite(&iocb_array[i], fd, bufptr, AIO_SIZE, offset);
111 iocbs[i] = &iocb_array[i];
112 offset += AIO_SIZE;
113 }
114
115 /*
116 * Start the 1st NUM_AIO requests
117 */
118 if ((w = io_submit(myctx, NUM_AIO, iocbs)) < 0) {
119 fprintf(stderr, "io_submit write returned %d\n", w);
120 }
121
122 /*
123 * As AIO requests finish, keep issuing more AIOs.
124 */
125 for (; i < 1000; i++) {
126 int n = 0;
127 struct iocb *iocbp;
128
129 n = io_getevents(myctx, 1, 1, &event, &timeout);
130 if (n > 0) {
131 iocbp = (struct iocb *)event.obj;
132
133 if (n > 0) {
134 io_prep_pwrite(iocbp, fd, iocbp->u.c.buf,
135 AIO_SIZE, offset);
136 offset += AIO_SIZE;
137 if ((w = io_submit(myctx, 1, &iocbp)) < 0) {
138 fprintf(stderr,
139 "write %d returned %d\n", i, w);
140 }
141 }
142 }
143 }
144 }
145
main(int argc,char ** argv)146 int main(int argc, char **argv)
147 {
148 int pid[NUM_CHILDREN];
149 int num_children = 1;
150 int i;
151 char *filename = argv[1];
152
153 printf("Starting aio/dio append test...\n");
154
155 for (i = 0; i < num_children; i++) {
156 if ((pid[i] = fork()) == 0) {
157 /* child */
158 return read_eof(filename);
159 } else if (pid[i] < 0) {
160 /* error */
161 perror("fork error");
162 break;
163 } else {
164 /* Parent */
165 continue;
166 }
167 }
168
169 /*
170 * Parent appends to end of file using direct i/o
171 */
172
173 aiodio_append(filename);
174
175 for (i = 0; i < num_children; i++) {
176 kill(pid[i], SIGTERM);
177 }
178
179 return 0;
180 }
181 #else
main(void)182 int main(void)
183 {
184 tst_brkm(TCONF, NULL, "test requires libaio and it's development packages");
185 }
186 #endif
187