2 * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
3 * Licensed under the GPL
11 #include <sys/syscall.h>
19 struct aio_thread_req {
22 unsigned long long offset;
29 static int aio_req_fd_r = -1;
30 static int aio_req_fd_w = -1;
32 #if defined(HAVE_AIO_ABI)
33 #include <linux/aio_abi.h>
35 /* If we have the headers, we are going to build with AIO enabled.
36 * If we don't have aio in libc, we define the necessary stubs here.
39 #if !defined(HAVE_AIO_LIBC)
41 #define __NR_io_setup 245
42 #define __NR_io_getevents 247
43 #define __NR_io_submit 248
45 static long io_setup(int n, aio_context_t *ctxp)
47 return(syscall(__NR_io_setup, n, ctxp));
50 static long io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp)
52 return(syscall(__NR_io_submit, ctx, nr, iocbpp));
55 static long io_getevents(aio_context_t ctx_id, long min_nr, long nr,
56 struct io_event *events, struct timespec *timeout)
58 return(syscall(__NR_io_getevents, ctx_id, min_nr, nr, events, timeout));
63 /* The AIO_MMAP cases force the mmapped page into memory here
64 * rather than in whatever place first touches the data. I used
65 * to do this by touching the page, but that's delicate because
66 * gcc is prone to optimizing that away. So, what's done here
67 * is we read from the descriptor from which the page was
68 * mapped. The caller is required to pass an offset which is
69 * inside the page that was mapped. Thus, when the read
70 * returns, we know that the page is in the page cache, and
71 * that it now backs the mmapped area.
74 static int do_aio(aio_context_t ctx, enum aio_type type, int fd, char *buf,
75 int len, unsigned long long offset, void *data)
77 struct iocb iocb, *iocbp = &iocb;
81 iocb = ((struct iocb) { .aio_data = (unsigned long) data,
84 .aio_buf = (unsigned long) buf,
89 .aio_reserved3 = 0 });
93 iocb.aio_lio_opcode = IOCB_CMD_PREAD;
94 err = io_submit(ctx, 1, &iocbp);
97 iocb.aio_lio_opcode = IOCB_CMD_PWRITE;
98 err = io_submit(ctx, 1, &iocbp);
101 iocb.aio_lio_opcode = IOCB_CMD_PREAD;
102 iocb.aio_buf = (unsigned long) &c;
103 iocb.aio_nbytes = sizeof(c);
104 err = io_submit(ctx, 1, &iocbp);
107 printk("Bogus op in do_aio - %d\n", type);
117 static aio_context_t ctx = 0;
119 static int aio_thread(void *arg)
121 struct aio_thread_reply reply;
122 struct io_event event;
123 int err, n, reply_fd;
125 signal(SIGWINCH, SIG_IGN);
128 n = io_getevents(ctx, 1, 1, &event, NULL);
132 printk("aio_thread - io_getevents failed, "
133 "errno = %d\n", errno);
136 reply = ((struct aio_thread_reply)
137 { .data = (void *) event.data,
140 ((struct aio_context *) event.data)->reply_fd;
141 err = os_write_file(reply_fd, &reply, sizeof(reply));
142 if(err != sizeof(reply))
143 printk("not_aio_thread - write failed, "
144 "fd = %d, err = %d\n",
153 static int do_not_aio(struct aio_thread_req *req)
160 err = os_seek_file(req->io_fd, req->offset);
164 err = os_read_file(req->io_fd, req->buf, req->len);
167 err = os_seek_file(req->io_fd, req->offset);
171 err = os_write_file(req->io_fd, req->buf, req->len);
174 err = os_seek_file(req->io_fd, req->offset);
178 err = os_read_file(req->io_fd, &c, sizeof(c));
181 printk("do_not_aio - bad request type : %d\n", req->type);
190 static int not_aio_thread(void *arg)
192 struct aio_thread_req req;
193 struct aio_thread_reply reply;
196 signal(SIGWINCH, SIG_IGN);
198 err = os_read_file(aio_req_fd_r, &req, sizeof(req));
199 if(err != sizeof(req)){
201 printk("not_aio_thread - read failed, fd = %d, "
202 "err = %d\n", aio_req_fd_r, -err);
204 printk("not_aio_thread - short read, fd = %d, "
205 "length = %d\n", aio_req_fd_r, err);
209 err = do_not_aio(&req);
210 reply = ((struct aio_thread_reply) { .data = req.data,
212 err = os_write_file(req.reply_fd, &reply, sizeof(reply));
213 if(err != sizeof(reply))
214 printk("not_aio_thread - write failed, fd = %d, "
215 "err = %d\n", aio_req_fd_r, -err);
219 static int aio_pid = -1;
221 static int init_aio_24(void)
226 err = os_pipe(fds, 1, 1);
230 aio_req_fd_w = fds[0];
231 aio_req_fd_r = fds[1];
232 err = run_helper_thread(not_aio_thread, NULL,
233 CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
241 os_close_file(fds[0]);
242 os_close_file(fds[1]);
250 #define DEFAULT_24_AIO 0
251 static int init_aio_26(void)
256 if(io_setup(256, &ctx)){
257 printk("aio_thread failed to initialize context, err = %d\n",
262 err = run_helper_thread(aio_thread, NULL,
263 CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
273 int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
274 unsigned long long offset, int reply_fd, void *data)
276 struct aio_thread_reply reply;
279 ((struct aio_context *) data)->reply_fd = reply_fd;
281 err = do_aio(ctx, type, io_fd, buf, len, offset, data);
283 reply = ((struct aio_thread_reply) { .data = data,
285 err = os_write_file(reply_fd, &reply, sizeof(reply));
286 if(err != sizeof(reply))
287 printk("submit_aio_26 - write failed, "
288 "fd = %d, err = %d\n", reply_fd, -err);
296 #define DEFAULT_24_AIO 1
297 static int init_aio_26(void)
302 int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
303 unsigned long long offset, int reply_fd, void *data)
309 static int aio_24 = DEFAULT_24_AIO;
311 static int __init set_aio_24(char *name, int *add)
317 __uml_setup("aio=2.4", set_aio_24,
319 " This is used to force UML to use 2.4-style AIO even when 2.6 AIO is\n"
320 " available. 2.4 AIO is a single thread that handles one request at a\n"
321 " time, synchronously. 2.6 AIO is a thread which uses 2.5 AIO interface\n"
322 " to handle an arbitrary number of pending requests. 2.6 AIO is not\n"
323 " available in tt mode, on 2.4 hosts, or when UML is built with\n"
324 " /usr/include/linux/aio_abi no available.\n\n"
327 static int init_aio(void)
333 printk("Disabling 2.6 AIO in tt mode\n");
339 if(err && (errno == ENOSYS)){
340 printk("2.6 AIO not supported on the host - "
341 "reverting to 2.4 AIO\n");
348 return(init_aio_24());
353 __initcall(init_aio);
355 static void exit_aio(void)
358 os_kill_process(aio_pid, 1);
361 __uml_exitcall(exit_aio);
363 int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len,
364 unsigned long long offset, int reply_fd, void *data)
366 struct aio_thread_req req = { .type = type,
371 .reply_fd = reply_fd,
376 err = os_write_file(aio_req_fd_w, &req, sizeof(req));
377 if(err == sizeof(req))
383 int submit_aio(enum aio_type type, int io_fd, char *buf, int len,
384 unsigned long long offset, int reply_fd, void *data)
387 return(submit_aio_24(type, io_fd, buf, len, offset, reply_fd,
390 return(submit_aio_26(type, io_fd, buf, len, offset, reply_fd,
396 * Overrides for Emacs so that we follow Linus's tabbing style.
397 * Emacs will notice this stuff at the end of the file and automatically
398 * adjust the settings for this buffer only. This must remain at the end
400 * ---------------------------------------------------------------------------
402 * c-file-style: "linux"