Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
[deliverable/linux.git] / arch / um / os-Linux / aio.c
CommitLineData
75e5584c 1/*
ba180fd4 2 * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
75e5584c
JD
3 * Licensed under the GPL
4 */
5
75e5584c 6#include <unistd.h>
ba180fd4 7#include <sched.h>
75e5584c
JD
8#include <signal.h>
9#include <errno.h>
ba180fd4
JD
10#include <sys/time.h>
11#include <asm/unistd.h>
37185b33
AV
12#include <aio.h>
13#include <init.h>
14#include <kern_util.h>
15#include <os.h>
75e5584c 16
91acb21f 17struct aio_thread_req {
d50084a2
JD
18 enum aio_type type;
19 int io_fd;
20 unsigned long long offset;
21 char *buf;
22 int len;
23 struct aio_context *aio;
91acb21f
JD
24};
25
75e5584c
JD
26#if defined(HAVE_AIO_ABI)
27#include <linux/aio_abi.h>
28
ba180fd4
JD
29/*
30 * If we have the headers, we are going to build with AIO enabled.
75e5584c
JD
31 * If we don't have aio in libc, we define the necessary stubs here.
32 */
33
34#if !defined(HAVE_AIO_LIBC)
35
36static long io_setup(int n, aio_context_t *ctxp)
37{
d50084a2 38 return syscall(__NR_io_setup, n, ctxp);
75e5584c
JD
39}
40
41static long io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp)
42{
d50084a2 43 return syscall(__NR_io_submit, ctx, nr, iocbpp);
75e5584c
JD
44}
45
46static long io_getevents(aio_context_t ctx_id, long min_nr, long nr,
d50084a2 47 struct io_event *events, struct timespec *timeout)
75e5584c 48{
d50084a2 49 return syscall(__NR_io_getevents, ctx_id, min_nr, nr, events, timeout);
75e5584c
JD
50}
51
52#endif
53
ba180fd4
JD
54/*
55 * The AIO_MMAP cases force the mmapped page into memory here
75e5584c
JD
56 * rather than in whatever place first touches the data. I used
57 * to do this by touching the page, but that's delicate because
58 * gcc is prone to optimizing that away. So, what's done here
59 * is we read from the descriptor from which the page was
60 * mapped. The caller is required to pass an offset which is
61 * inside the page that was mapped. Thus, when the read
62 * returns, we know that the page is in the page cache, and
63 * that it now backs the mmapped area.
64 */
65
91acb21f 66static int do_aio(aio_context_t ctx, enum aio_type type, int fd, char *buf,
d50084a2 67 int len, unsigned long long offset, struct aio_context *aio)
75e5584c 68{
da3e30e7
JD
69 struct iocb *iocbp = & ((struct iocb) {
70 .aio_data = (unsigned long) aio,
71 .aio_fildes = fd,
72 .aio_buf = (unsigned long) buf,
73 .aio_nbytes = len,
74 .aio_offset = offset
75 });
d50084a2 76 char c;
da3e30e7
JD
77
78 switch (type) {
d50084a2 79 case AIO_READ:
da3e30e7 80 iocbp->aio_lio_opcode = IOCB_CMD_PREAD;
d50084a2
JD
81 break;
82 case AIO_WRITE:
da3e30e7 83 iocbp->aio_lio_opcode = IOCB_CMD_PWRITE;
d50084a2
JD
84 break;
85 case AIO_MMAP:
da3e30e7
JD
86 iocbp->aio_lio_opcode = IOCB_CMD_PREAD;
87 iocbp->aio_buf = (unsigned long) &c;
88 iocbp->aio_nbytes = sizeof(c);
d50084a2
JD
89 break;
90 default:
da3e30e7
JD
91 printk(UM_KERN_ERR "Bogus op in do_aio - %d\n", type);
92 return -EINVAL;
d50084a2
JD
93 }
94
da3e30e7 95 return (io_submit(ctx, 1, &iocbp) > 0) ? 0 : -errno;
75e5584c
JD
96}
97
9683da91 98/* Initialized in an initcall and unchanged thereafter */
75e5584c
JD
99static aio_context_t ctx = 0;
100
101static int aio_thread(void *arg)
102{
d50084a2
JD
103 struct aio_thread_reply reply;
104 struct io_event event;
105 int err, n, reply_fd;
106
107 signal(SIGWINCH, SIG_IGN);
108
ba180fd4 109 while (1) {
d50084a2 110 n = io_getevents(ctx, 1, 1, &event, NULL);
ba180fd4
JD
111 if (n < 0) {
112 if (errno == EINTR)
d50084a2 113 continue;
ba180fd4 114 printk(UM_KERN_ERR "aio_thread - io_getevents failed, "
d50084a2
JD
115 "errno = %d\n", errno);
116 }
117 else {
118 reply = ((struct aio_thread_reply)
119 { .data = (void *) (long) event.data,
120 .err = event.res });
91acb21f 121 reply_fd = ((struct aio_context *) reply.data)->reply_fd;
a61f334f 122 err = write(reply_fd, &reply, sizeof(reply));
ba180fd4
JD
123 if (err != sizeof(reply))
124 printk(UM_KERN_ERR "aio_thread - write failed, "
125 "fd = %d, err = %d\n", reply_fd, errno);
d50084a2
JD
126 }
127 }
128 return 0;
75e5584c
JD
129}
130
131#endif
132
91acb21f 133static int do_not_aio(struct aio_thread_req *req)
75e5584c 134{
d50084a2 135 char c;
ef0470c0 136 unsigned long long actual;
a61f334f 137 int n;
d50084a2 138
ef0470c0 139 actual = lseek64(req->io_fd, req->offset, SEEK_SET);
ba180fd4 140 if (actual != req->offset)
ef0470c0
JD
141 return -errno;
142
5134d8fe 143 switch (req->type) {
d50084a2 144 case AIO_READ:
a61f334f 145 n = read(req->io_fd, req->buf, req->len);
d50084a2
JD
146 break;
147 case AIO_WRITE:
a61f334f 148 n = write(req->io_fd, req->buf, req->len);
d50084a2
JD
149 break;
150 case AIO_MMAP:
a61f334f 151 n = read(req->io_fd, &c, sizeof(c));
d50084a2
JD
152 break;
153 default:
ba180fd4
JD
154 printk(UM_KERN_ERR "do_not_aio - bad request type : %d\n",
155 req->type);
a61f334f 156 return -EINVAL;
d50084a2
JD
157 }
158
ba180fd4 159 if (n < 0)
a61f334f
JD
160 return -errno;
161 return 0;
75e5584c
JD
162}
163
9683da91
JD
164/* These are initialized in initcalls and not changed */
165static int aio_req_fd_r = -1;
166static int aio_req_fd_w = -1;
167static int aio_pid = -1;
c4399016 168static unsigned long aio_stack;
9683da91 169
75e5584c
JD
170static int not_aio_thread(void *arg)
171{
d50084a2
JD
172 struct aio_thread_req req;
173 struct aio_thread_reply reply;
174 int err;
175
176 signal(SIGWINCH, SIG_IGN);
ba180fd4 177 while (1) {
a61f334f 178 err = read(aio_req_fd_r, &req, sizeof(req));
ba180fd4
JD
179 if (err != sizeof(req)) {
180 if (err < 0)
181 printk(UM_KERN_ERR "not_aio_thread - "
182 "read failed, fd = %d, err = %d\n",
183 aio_req_fd_r,
a61f334f 184 errno);
d50084a2 185 else {
ba180fd4
JD
186 printk(UM_KERN_ERR "not_aio_thread - short "
187 "read, fd = %d, length = %d\n",
188 aio_req_fd_r, err);
d50084a2
JD
189 }
190 continue;
191 }
192 err = do_not_aio(&req);
193 reply = ((struct aio_thread_reply) { .data = req.aio,
ef0470c0 194 .err = err });
a61f334f 195 err = write(req.aio->reply_fd, &reply, sizeof(reply));
ba180fd4
JD
196 if (err != sizeof(reply))
197 printk(UM_KERN_ERR "not_aio_thread - write failed, "
198 "fd = %d, err = %d\n", req.aio->reply_fd, errno);
d50084a2 199 }
1b57e9c2
JD
200
201 return 0;
75e5584c
JD
202}
203
75e5584c
JD
204static int init_aio_24(void)
205{
d50084a2
JD
206 int fds[2], err;
207
208 err = os_pipe(fds, 1, 1);
ba180fd4 209 if (err)
d50084a2
JD
210 goto out;
211
212 aio_req_fd_w = fds[0];
213 aio_req_fd_r = fds[1];
8603ec81
JD
214
215 err = os_set_fd_block(aio_req_fd_w, 0);
ba180fd4 216 if (err)
8603ec81
JD
217 goto out_close_pipe;
218
d50084a2 219 err = run_helper_thread(not_aio_thread, NULL,
4dbed85a 220 CLONE_FILES | CLONE_VM, &aio_stack);
ba180fd4 221 if (err < 0)
d50084a2
JD
222 goto out_close_pipe;
223
224 aio_pid = err;
225 goto out;
226
227out_close_pipe:
512b6fb1
JD
228 close(fds[0]);
229 close(fds[1]);
d50084a2
JD
230 aio_req_fd_w = -1;
231 aio_req_fd_r = -1;
232out:
75e5584c 233#ifndef HAVE_AIO_ABI
ba180fd4
JD
234 printk(UM_KERN_INFO "/usr/include/linux/aio_abi.h not present during "
235 "build\n");
75e5584c 236#endif
ba180fd4
JD
237 printk(UM_KERN_INFO "2.6 host AIO support not used - falling back to "
238 "I/O thread\n");
d50084a2 239 return 0;
75e5584c
JD
240}
241
242#ifdef HAVE_AIO_ABI
243#define DEFAULT_24_AIO 0
244static int init_aio_26(void)
245{
d50084a2 246 int err;
75e5584c 247
ba180fd4 248 if (io_setup(256, &ctx)) {
b4fd310e 249 err = -errno;
ba180fd4
JD
250 printk(UM_KERN_ERR "aio_thread failed to initialize context, "
251 "err = %d\n", errno);
d50084a2
JD
252 return err;
253 }
75e5584c 254
d50084a2 255 err = run_helper_thread(aio_thread, NULL,
4dbed85a 256 CLONE_FILES | CLONE_VM, &aio_stack);
ba180fd4 257 if (err < 0)
d50084a2 258 return err;
75e5584c 259
d50084a2 260 aio_pid = err;
75e5584c 261
ba180fd4 262 printk(UM_KERN_INFO "Using 2.6 host AIO\n");
d50084a2 263 return 0;
91acb21f
JD
264}
265
266static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
267 unsigned long long offset, struct aio_context *aio)
268{
d50084a2
JD
269 struct aio_thread_reply reply;
270 int err;
271
272 err = do_aio(ctx, type, io_fd, buf, len, offset, aio);
ba180fd4 273 if (err) {
d50084a2
JD
274 reply = ((struct aio_thread_reply) { .data = aio,
275 .err = err });
a61f334f 276 err = write(aio->reply_fd, &reply, sizeof(reply));
ba180fd4 277 if (err != sizeof(reply)) {
a61f334f 278 err = -errno;
ba180fd4 279 printk(UM_KERN_ERR "submit_aio_26 - write failed, "
d50084a2 280 "fd = %d, err = %d\n", aio->reply_fd, -err);
a61f334f 281 }
d50084a2
JD
282 else err = 0;
283 }
284
285 return err;
75e5584c
JD
286}
287
288#else
289#define DEFAULT_24_AIO 1
91acb21f 290static int init_aio_26(void)
75e5584c 291{
d50084a2 292 return -ENOSYS;
75e5584c
JD
293}
294
91acb21f
JD
295static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
296 unsigned long long offset, struct aio_context *aio)
75e5584c 297{
d50084a2 298 return -ENOSYS;
75e5584c
JD
299}
300#endif
301
9683da91 302/* Initialized in an initcall and unchanged thereafter */
75e5584c
JD
303static int aio_24 = DEFAULT_24_AIO;
304
305static int __init set_aio_24(char *name, int *add)
306{
d50084a2
JD
307 aio_24 = 1;
308 return 0;
75e5584c
JD
309}
310
311__uml_setup("aio=2.4", set_aio_24,
312"aio=2.4\n"
313" This is used to force UML to use 2.4-style AIO even when 2.6 AIO is\n"
314" available. 2.4 AIO is a single thread that handles one request at a\n"
315" time, synchronously. 2.6 AIO is a thread which uses the 2.6 AIO \n"
316" interface to handle an arbitrary number of pending requests. 2.6 AIO \n"
317" is not available in tt mode, on 2.4 hosts, or when UML is built with\n"
318" /usr/include/linux/aio_abi.h not available. Many distributions don't\n"
319" include aio_abi.h, so you will need to copy it from a kernel tree to\n"
320" your /usr/include/linux in order to build an AIO-capable UML\n\n"
321);
322
323static int init_aio(void)
324{
d50084a2
JD
325 int err;
326
ba180fd4 327 if (!aio_24) {
d50084a2 328 err = init_aio_26();
ba180fd4
JD
329 if (err && (errno == ENOSYS)) {
330 printk(UM_KERN_INFO "2.6 AIO not supported on the "
331 "host - reverting to 2.4 AIO\n");
d50084a2
JD
332 aio_24 = 1;
333 }
334 else return err;
335 }
336
ba180fd4 337 if (aio_24)
d50084a2
JD
338 return init_aio_24();
339
340 return 0;
75e5584c
JD
341}
342
ba180fd4
JD
343/*
344 * The reason for the __initcall/__uml_exitcall asymmetry is that init_aio
75e5584c
JD
345 * needs to be called when the kernel is running because it calls run_helper,
346 * which needs get_free_page. exit_aio is a __uml_exitcall because the generic
347 * kernel does not run __exitcalls on shutdown, and can't because many of them
348 * break when called outside of module unloading.
349 */
350__initcall(init_aio);
351
352static void exit_aio(void)
353{
c4399016 354 if (aio_pid != -1) {
d50084a2 355 os_kill_process(aio_pid, 1);
c4399016
JD
356 free_stack(aio_stack, 0);
357 }
75e5584c
JD
358}
359
360__uml_exitcall(exit_aio);
361
91acb21f
JD
362static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len,
363 unsigned long long offset, struct aio_context *aio)
75e5584c 364{
d50084a2
JD
365 struct aio_thread_req req = { .type = type,
366 .io_fd = io_fd,
367 .offset = offset,
368 .buf = buf,
369 .len = len,
370 .aio = aio,
371 };
372 int err;
373
a61f334f 374 err = write(aio_req_fd_w, &req, sizeof(req));
ba180fd4 375 if (err == sizeof(req))
d50084a2 376 err = 0;
a61f334f 377 else err = -errno;
d50084a2
JD
378
379 return err;
91acb21f
JD
380}
381
382int submit_aio(enum aio_type type, int io_fd, char *buf, int len,
d50084a2
JD
383 unsigned long long offset, int reply_fd,
384 struct aio_context *aio)
91acb21f 385{
d50084a2 386 aio->reply_fd = reply_fd;
ba180fd4 387 if (aio_24)
d50084a2 388 return submit_aio_24(type, io_fd, buf, len, offset, aio);
ba180fd4 389 else
d50084a2 390 return submit_aio_26(type, io_fd, buf, len, offset, aio);
75e5584c 391}
This page took 1.165646 seconds and 5 git commands to generate.