diff options
Diffstat (limited to 'arch/um/os-Linux/aio.c')
-rw-r--r-- | arch/um/os-Linux/aio.c | 112 |
1 files changed, 59 insertions, 53 deletions
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c index 11c2b01a92bd..68454daf958d 100644 --- a/arch/um/os-Linux/aio.c +++ b/arch/um/os-Linux/aio.c | |||
@@ -1,19 +1,19 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) | 2 | * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <stdlib.h> | ||
7 | #include <unistd.h> | 6 | #include <unistd.h> |
7 | #include <sched.h> | ||
8 | #include <signal.h> | 8 | #include <signal.h> |
9 | #include <errno.h> | 9 | #include <errno.h> |
10 | #include <sched.h> | 10 | #include <sys/time.h> |
11 | #include <sys/syscall.h> | 11 | #include <asm/unistd.h> |
12 | #include "os.h" | ||
13 | #include "aio.h" | 12 | #include "aio.h" |
14 | #include "init.h" | 13 | #include "init.h" |
15 | #include "user.h" | ||
16 | #include "kern_constants.h" | 14 | #include "kern_constants.h" |
15 | #include "os.h" | ||
16 | #include "user.h" | ||
17 | 17 | ||
18 | struct aio_thread_req { | 18 | struct aio_thread_req { |
19 | enum aio_type type; | 19 | enum aio_type type; |
@@ -27,7 +27,8 @@ struct aio_thread_req { | |||
27 | #if defined(HAVE_AIO_ABI) | 27 | #if defined(HAVE_AIO_ABI) |
28 | #include <linux/aio_abi.h> | 28 | #include <linux/aio_abi.h> |
29 | 29 | ||
30 | /* If we have the headers, we are going to build with AIO enabled. | 30 | /* |
31 | * If we have the headers, we are going to build with AIO enabled. | ||
31 | * If we don't have aio in libc, we define the necessary stubs here. | 32 | * If we don't have aio in libc, we define the necessary stubs here. |
32 | */ | 33 | */ |
33 | 34 | ||
@@ -51,7 +52,8 @@ static long io_getevents(aio_context_t ctx_id, long min_nr, long nr, | |||
51 | 52 | ||
52 | #endif | 53 | #endif |
53 | 54 | ||
54 | /* The AIO_MMAP cases force the mmapped page into memory here | 55 | /* |
56 | * The AIO_MMAP cases force the mmapped page into memory here | ||
55 | * rather than in whatever place first touches the data. I used | 57 | * rather than in whatever place first touches the data. I used |
56 | * to do this by touching the page, but that's delicate because | 58 | * to do this by touching the page, but that's delicate because |
57 | * gcc is prone to optimizing that away. So, what's done here | 59 | * gcc is prone to optimizing that away. So, what's done here |
@@ -105,12 +107,12 @@ static int aio_thread(void *arg) | |||
105 | 107 | ||
106 | signal(SIGWINCH, SIG_IGN); | 108 | signal(SIGWINCH, SIG_IGN); |
107 | 109 | ||
108 | while(1){ | 110 | while (1) { |
109 | n = io_getevents(ctx, 1, 1, &event, NULL); | 111 | n = io_getevents(ctx, 1, 1, &event, NULL); |
110 | if(n < 0){ | 112 | if (n < 0) { |
111 | if(errno == EINTR) | 113 | if (errno == EINTR) |
112 | continue; | 114 | continue; |
113 | printk("aio_thread - io_getevents failed, " | 115 | printk(UM_KERN_ERR "aio_thread - io_getevents failed, " |
114 | "errno = %d\n", errno); | 116 | "errno = %d\n", errno); |
115 | } | 117 | } |
116 | else { | 118 | else { |
@@ -119,9 +121,9 @@ static int aio_thread(void *arg) | |||
119 | .err = event.res }); | 121 | .err = event.res }); |
120 | reply_fd = ((struct aio_context *) reply.data)->reply_fd; | 122 | reply_fd = ((struct aio_context *) reply.data)->reply_fd; |
121 | err = write(reply_fd, &reply, sizeof(reply)); | 123 | err = write(reply_fd, &reply, sizeof(reply)); |
122 | if(err != sizeof(reply)) | 124 | if (err != sizeof(reply)) |
123 | printk("aio_thread - write failed, fd = %d, " | 125 | printk(UM_KERN_ERR "aio_thread - write failed, " |
124 | "err = %d\n", reply_fd, errno); | 126 | "fd = %d, err = %d\n", reply_fd, errno); |
125 | } | 127 | } |
126 | } | 128 | } |
127 | return 0; | 129 | return 0; |
@@ -136,10 +138,10 @@ static int do_not_aio(struct aio_thread_req *req) | |||
136 | int n; | 138 | int n; |
137 | 139 | ||
138 | actual = lseek64(req->io_fd, req->offset, SEEK_SET); | 140 | actual = lseek64(req->io_fd, req->offset, SEEK_SET); |
139 | if(actual != req->offset) | 141 | if (actual != req->offset) |
140 | return -errno; | 142 | return -errno; |
141 | 143 | ||
142 | switch(req->type){ | 144 | switch(req->type) { |
143 | case AIO_READ: | 145 | case AIO_READ: |
144 | n = read(req->io_fd, req->buf, req->len); | 146 | n = read(req->io_fd, req->buf, req->len); |
145 | break; | 147 | break; |
@@ -150,11 +152,12 @@ static int do_not_aio(struct aio_thread_req *req) | |||
150 | n = read(req->io_fd, &c, sizeof(c)); | 152 | n = read(req->io_fd, &c, sizeof(c)); |
151 | break; | 153 | break; |
152 | default: | 154 | default: |
153 | printk("do_not_aio - bad request type : %d\n", req->type); | 155 | printk(UM_KERN_ERR "do_not_aio - bad request type : %d\n", |
156 | req->type); | ||
154 | return -EINVAL; | 157 | return -EINVAL; |
155 | } | 158 | } |
156 | 159 | ||
157 | if(n < 0) | 160 | if (n < 0) |
158 | return -errno; | 161 | return -errno; |
159 | return 0; | 162 | return 0; |
160 | } | 163 | } |
@@ -172,16 +175,18 @@ static int not_aio_thread(void *arg) | |||
172 | int err; | 175 | int err; |
173 | 176 | ||
174 | signal(SIGWINCH, SIG_IGN); | 177 | signal(SIGWINCH, SIG_IGN); |
175 | while(1){ | 178 | while (1) { |
176 | err = read(aio_req_fd_r, &req, sizeof(req)); | 179 | err = read(aio_req_fd_r, &req, sizeof(req)); |
177 | if(err != sizeof(req)){ | 180 | if (err != sizeof(req)) { |
178 | if(err < 0) | 181 | if (err < 0) |
179 | printk("not_aio_thread - read failed, " | 182 | printk(UM_KERN_ERR "not_aio_thread - " |
180 | "fd = %d, err = %d\n", aio_req_fd_r, | 183 | "read failed, fd = %d, err = %d\n", |
184 | aio_req_fd_r, | ||
181 | errno); | 185 | errno); |
182 | else { | 186 | else { |
183 | printk("not_aio_thread - short read, fd = %d, " | 187 | printk(UM_KERN_ERR "not_aio_thread - short " |
184 | "length = %d\n", aio_req_fd_r, err); | 188 | "read, fd = %d, length = %d\n", |
189 | aio_req_fd_r, err); | ||
185 | } | 190 | } |
186 | continue; | 191 | continue; |
187 | } | 192 | } |
@@ -189,9 +194,9 @@ static int not_aio_thread(void *arg) | |||
189 | reply = ((struct aio_thread_reply) { .data = req.aio, | 194 | reply = ((struct aio_thread_reply) { .data = req.aio, |
190 | .err = err }); | 195 | .err = err }); |
191 | err = write(req.aio->reply_fd, &reply, sizeof(reply)); | 196 | err = write(req.aio->reply_fd, &reply, sizeof(reply)); |
192 | if(err != sizeof(reply)) | 197 | if (err != sizeof(reply)) |
193 | printk("not_aio_thread - write failed, fd = %d, " | 198 | printk(UM_KERN_ERR "not_aio_thread - write failed, " |
194 | "err = %d\n", req.aio->reply_fd, errno); | 199 | "fd = %d, err = %d\n", req.aio->reply_fd, errno); |
195 | } | 200 | } |
196 | 201 | ||
197 | return 0; | 202 | return 0; |
@@ -202,19 +207,19 @@ static int init_aio_24(void) | |||
202 | int fds[2], err; | 207 | int fds[2], err; |
203 | 208 | ||
204 | err = os_pipe(fds, 1, 1); | 209 | err = os_pipe(fds, 1, 1); |
205 | if(err) | 210 | if (err) |
206 | goto out; | 211 | goto out; |
207 | 212 | ||
208 | aio_req_fd_w = fds[0]; | 213 | aio_req_fd_w = fds[0]; |
209 | aio_req_fd_r = fds[1]; | 214 | aio_req_fd_r = fds[1]; |
210 | 215 | ||
211 | err = os_set_fd_block(aio_req_fd_w, 0); | 216 | err = os_set_fd_block(aio_req_fd_w, 0); |
212 | if(err) | 217 | if (err) |
213 | goto out_close_pipe; | 218 | goto out_close_pipe; |
214 | 219 | ||
215 | err = run_helper_thread(not_aio_thread, NULL, | 220 | err = run_helper_thread(not_aio_thread, NULL, |
216 | CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack); | 221 | CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack); |
217 | if(err < 0) | 222 | if (err < 0) |
218 | goto out_close_pipe; | 223 | goto out_close_pipe; |
219 | 224 | ||
220 | aio_pid = err; | 225 | aio_pid = err; |
@@ -227,10 +232,11 @@ out_close_pipe: | |||
227 | aio_req_fd_r = -1; | 232 | aio_req_fd_r = -1; |
228 | out: | 233 | out: |
229 | #ifndef HAVE_AIO_ABI | 234 | #ifndef HAVE_AIO_ABI |
230 | printk("/usr/include/linux/aio_abi.h not present during build\n"); | 235 | printk(UM_KERN_INFO "/usr/include/linux/aio_abi.h not present during " |
236 | "build\n"); | ||
231 | #endif | 237 | #endif |
232 | printk("2.6 host AIO support not used - falling back to I/O " | 238 | printk(UM_KERN_INFO "2.6 host AIO support not used - falling back to " |
233 | "thread\n"); | 239 | "I/O thread\n"); |
234 | return 0; | 240 | return 0; |
235 | } | 241 | } |
236 | 242 | ||
@@ -240,21 +246,21 @@ static int init_aio_26(void) | |||
240 | { | 246 | { |
241 | int err; | 247 | int err; |
242 | 248 | ||
243 | if(io_setup(256, &ctx)){ | 249 | if (io_setup(256, &ctx)) { |
244 | err = -errno; | 250 | err = -errno; |
245 | printk("aio_thread failed to initialize context, err = %d\n", | 251 | printk(UM_KERN_ERR "aio_thread failed to initialize context, " |
246 | errno); | 252 | "err = %d\n", errno); |
247 | return err; | 253 | return err; |
248 | } | 254 | } |
249 | 255 | ||
250 | err = run_helper_thread(aio_thread, NULL, | 256 | err = run_helper_thread(aio_thread, NULL, |
251 | CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack); | 257 | CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack); |
252 | if(err < 0) | 258 | if (err < 0) |
253 | return err; | 259 | return err; |
254 | 260 | ||
255 | aio_pid = err; | 261 | aio_pid = err; |
256 | 262 | ||
257 | printk("Using 2.6 host AIO\n"); | 263 | printk(UM_KERN_INFO "Using 2.6 host AIO\n"); |
258 | return 0; | 264 | return 0; |
259 | } | 265 | } |
260 | 266 | ||
@@ -265,13 +271,13 @@ static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len, | |||
265 | int err; | 271 | int err; |
266 | 272 | ||
267 | err = do_aio(ctx, type, io_fd, buf, len, offset, aio); | 273 | err = do_aio(ctx, type, io_fd, buf, len, offset, aio); |
268 | if(err){ | 274 | if (err) { |
269 | reply = ((struct aio_thread_reply) { .data = aio, | 275 | reply = ((struct aio_thread_reply) { .data = aio, |
270 | .err = err }); | 276 | .err = err }); |
271 | err = write(aio->reply_fd, &reply, sizeof(reply)); | 277 | err = write(aio->reply_fd, &reply, sizeof(reply)); |
272 | if(err != sizeof(reply)){ | 278 | if (err != sizeof(reply)) { |
273 | err = -errno; | 279 | err = -errno; |
274 | printk("submit_aio_26 - write failed, " | 280 | printk(UM_KERN_ERR "submit_aio_26 - write failed, " |
275 | "fd = %d, err = %d\n", aio->reply_fd, -err); | 281 | "fd = %d, err = %d\n", aio->reply_fd, -err); |
276 | } | 282 | } |
277 | else err = 0; | 283 | else err = 0; |
@@ -319,23 +325,24 @@ static int init_aio(void) | |||
319 | { | 325 | { |
320 | int err; | 326 | int err; |
321 | 327 | ||
322 | if(!aio_24){ | 328 | if (!aio_24) { |
323 | err = init_aio_26(); | 329 | err = init_aio_26(); |
324 | if(err && (errno == ENOSYS)){ | 330 | if (err && (errno == ENOSYS)) { |
325 | printk("2.6 AIO not supported on the host - " | 331 | printk(UM_KERN_INFO "2.6 AIO not supported on the " |
326 | "reverting to 2.4 AIO\n"); | 332 | "host - reverting to 2.4 AIO\n"); |
327 | aio_24 = 1; | 333 | aio_24 = 1; |
328 | } | 334 | } |
329 | else return err; | 335 | else return err; |
330 | } | 336 | } |
331 | 337 | ||
332 | if(aio_24) | 338 | if (aio_24) |
333 | return init_aio_24(); | 339 | return init_aio_24(); |
334 | 340 | ||
335 | return 0; | 341 | return 0; |
336 | } | 342 | } |
337 | 343 | ||
338 | /* The reason for the __initcall/__uml_exitcall asymmetry is that init_aio | 344 | /* |
345 | * The reason for the __initcall/__uml_exitcall asymmetry is that init_aio | ||
339 | * needs to be called when the kernel is running because it calls run_helper, | 346 | * needs to be called when the kernel is running because it calls run_helper, |
340 | * which needs get_free_page. exit_aio is a __uml_exitcall because the generic | 347 | * which needs get_free_page. exit_aio is a __uml_exitcall because the generic |
341 | * kernel does not run __exitcalls on shutdown, and can't because many of them | 348 | * kernel does not run __exitcalls on shutdown, and can't because many of them |
@@ -366,7 +373,7 @@ static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len, | |||
366 | int err; | 373 | int err; |
367 | 374 | ||
368 | err = write(aio_req_fd_w, &req, sizeof(req)); | 375 | err = write(aio_req_fd_w, &req, sizeof(req)); |
369 | if(err == sizeof(req)) | 376 | if (err == sizeof(req)) |
370 | err = 0; | 377 | err = 0; |
371 | else err = -errno; | 378 | else err = -errno; |
372 | 379 | ||
@@ -378,9 +385,8 @@ int submit_aio(enum aio_type type, int io_fd, char *buf, int len, | |||
378 | struct aio_context *aio) | 385 | struct aio_context *aio) |
379 | { | 386 | { |
380 | aio->reply_fd = reply_fd; | 387 | aio->reply_fd = reply_fd; |
381 | if(aio_24) | 388 | if (aio_24) |
382 | return submit_aio_24(type, io_fd, buf, len, offset, aio); | 389 | return submit_aio_24(type, io_fd, buf, len, offset, aio); |
383 | else { | 390 | else |
384 | return submit_aio_26(type, io_fd, buf, len, offset, aio); | 391 | return submit_aio_26(type, io_fd, buf, len, offset, aio); |
385 | } | ||
386 | } | 392 | } |