blob: 93dc0c80ebaf7d128f08125185a8ba65c5f6f770 [file] [log] [blame]
Jeff Dike75e55842005-09-03 15:57:45 -07001/*
Jeff Dikeba180fd2007-10-16 01:27:00 -07002 * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
Jeff Dike75e55842005-09-03 15:57:45 -07003 * Licensed under the GPL
4 */
5
Jeff Dike75e55842005-09-03 15:57:45 -07006#include <unistd.h>
Jeff Dikeba180fd2007-10-16 01:27:00 -07007#include <sched.h>
Jeff Dike75e55842005-09-03 15:57:45 -07008#include <signal.h>
9#include <errno.h>
Jeff Dikeba180fd2007-10-16 01:27:00 -070010#include <sys/time.h>
11#include <asm/unistd.h>
Jeff Dike75e55842005-09-03 15:57:45 -070012#include "aio.h"
13#include "init.h"
Jeff Dikeda3e30e2007-07-23 18:43:47 -070014#include "kern_constants.h"
Jeff Dikeba180fd2007-10-16 01:27:00 -070015#include "os.h"
16#include "user.h"
Jeff Dike75e55842005-09-03 15:57:45 -070017
Jeff Dike91acb212005-10-10 23:10:32 -040018struct aio_thread_req {
Jeff Diked50084a2006-01-06 00:18:50 -080019 enum aio_type type;
20 int io_fd;
21 unsigned long long offset;
22 char *buf;
23 int len;
24 struct aio_context *aio;
Jeff Dike91acb212005-10-10 23:10:32 -040025};
26
Jeff Dike75e55842005-09-03 15:57:45 -070027#if defined(HAVE_AIO_ABI)
28#include <linux/aio_abi.h>
29
Jeff Dikeba180fd2007-10-16 01:27:00 -070030/*
31 * If we have the headers, we are going to build with AIO enabled.
Jeff Dike75e55842005-09-03 15:57:45 -070032 * If we don't have aio in libc, we define the necessary stubs here.
33 */
34
35#if !defined(HAVE_AIO_LIBC)
36
37static long io_setup(int n, aio_context_t *ctxp)
38{
Jeff Diked50084a2006-01-06 00:18:50 -080039 return syscall(__NR_io_setup, n, ctxp);
Jeff Dike75e55842005-09-03 15:57:45 -070040}
41
42static long io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp)
43{
Jeff Diked50084a2006-01-06 00:18:50 -080044 return syscall(__NR_io_submit, ctx, nr, iocbpp);
Jeff Dike75e55842005-09-03 15:57:45 -070045}
46
47static long io_getevents(aio_context_t ctx_id, long min_nr, long nr,
Jeff Diked50084a2006-01-06 00:18:50 -080048 struct io_event *events, struct timespec *timeout)
Jeff Dike75e55842005-09-03 15:57:45 -070049{
Jeff Diked50084a2006-01-06 00:18:50 -080050 return syscall(__NR_io_getevents, ctx_id, min_nr, nr, events, timeout);
Jeff Dike75e55842005-09-03 15:57:45 -070051}
52
53#endif
54
Jeff Dikeba180fd2007-10-16 01:27:00 -070055/*
56 * The AIO_MMAP cases force the mmapped page into memory here
Jeff Dike75e55842005-09-03 15:57:45 -070057 * rather than in whatever place first touches the data. I used
58 * to do this by touching the page, but that's delicate because
59 * gcc is prone to optimizing that away. So, what's done here
60 * is we read from the descriptor from which the page was
61 * mapped. The caller is required to pass an offset which is
62 * inside the page that was mapped. Thus, when the read
63 * returns, we know that the page is in the page cache, and
64 * that it now backs the mmapped area.
65 */
66
Jeff Dike91acb212005-10-10 23:10:32 -040067static int do_aio(aio_context_t ctx, enum aio_type type, int fd, char *buf,
Jeff Diked50084a2006-01-06 00:18:50 -080068 int len, unsigned long long offset, struct aio_context *aio)
Jeff Dike75e55842005-09-03 15:57:45 -070069{
Jeff Dikeda3e30e2007-07-23 18:43:47 -070070 struct iocb *iocbp = & ((struct iocb) {
71 .aio_data = (unsigned long) aio,
72 .aio_fildes = fd,
73 .aio_buf = (unsigned long) buf,
74 .aio_nbytes = len,
75 .aio_offset = offset
76 });
Jeff Diked50084a2006-01-06 00:18:50 -080077 char c;
Jeff Dike75e55842005-09-03 15:57:45 -070078
Jeff Dikeda3e30e2007-07-23 18:43:47 -070079 switch (type) {
Jeff Diked50084a2006-01-06 00:18:50 -080080 case AIO_READ:
Jeff Dikeda3e30e2007-07-23 18:43:47 -070081 iocbp->aio_lio_opcode = IOCB_CMD_PREAD;
Jeff Diked50084a2006-01-06 00:18:50 -080082 break;
83 case AIO_WRITE:
Jeff Dikeda3e30e2007-07-23 18:43:47 -070084 iocbp->aio_lio_opcode = IOCB_CMD_PWRITE;
Jeff Diked50084a2006-01-06 00:18:50 -080085 break;
86 case AIO_MMAP:
Jeff Dikeda3e30e2007-07-23 18:43:47 -070087 iocbp->aio_lio_opcode = IOCB_CMD_PREAD;
88 iocbp->aio_buf = (unsigned long) &c;
89 iocbp->aio_nbytes = sizeof(c);
Jeff Diked50084a2006-01-06 00:18:50 -080090 break;
91 default:
Jeff Dikeda3e30e2007-07-23 18:43:47 -070092 printk(UM_KERN_ERR "Bogus op in do_aio - %d\n", type);
93 return -EINVAL;
Jeff Diked50084a2006-01-06 00:18:50 -080094 }
Jeff Dike09ace812005-09-03 15:57:46 -070095
Jeff Dikeda3e30e2007-07-23 18:43:47 -070096 return (io_submit(ctx, 1, &iocbp) > 0) ? 0 : -errno;
Jeff Dike75e55842005-09-03 15:57:45 -070097}
98
Jeff Dike9683da92007-02-10 01:44:27 -080099/* Initialized in an initcall and unchanged thereafter */
Jeff Dike75e55842005-09-03 15:57:45 -0700100static aio_context_t ctx = 0;
101
102static int aio_thread(void *arg)
103{
Jeff Diked50084a2006-01-06 00:18:50 -0800104 struct aio_thread_reply reply;
105 struct io_event event;
106 int err, n, reply_fd;
Jeff Dike75e55842005-09-03 15:57:45 -0700107
Jeff Diked50084a2006-01-06 00:18:50 -0800108 signal(SIGWINCH, SIG_IGN);
Jeff Dike75e55842005-09-03 15:57:45 -0700109
Jeff Dikeba180fd2007-10-16 01:27:00 -0700110 while (1) {
Jeff Diked50084a2006-01-06 00:18:50 -0800111 n = io_getevents(ctx, 1, 1, &event, NULL);
Jeff Dikeba180fd2007-10-16 01:27:00 -0700112 if (n < 0) {
113 if (errno == EINTR)
Jeff Diked50084a2006-01-06 00:18:50 -0800114 continue;
Jeff Dikeba180fd2007-10-16 01:27:00 -0700115 printk(UM_KERN_ERR "aio_thread - io_getevents failed, "
Jeff Diked50084a2006-01-06 00:18:50 -0800116 "errno = %d\n", errno);
117 }
118 else {
119 reply = ((struct aio_thread_reply)
120 { .data = (void *) (long) event.data,
121 .err = event.res });
Jeff Dike91acb212005-10-10 23:10:32 -0400122 reply_fd = ((struct aio_context *) reply.data)->reply_fd;
Jeff Dikea61f3342007-05-06 14:51:35 -0700123 err = write(reply_fd, &reply, sizeof(reply));
Jeff Dikeba180fd2007-10-16 01:27:00 -0700124 if (err != sizeof(reply))
125 printk(UM_KERN_ERR "aio_thread - write failed, "
126 "fd = %d, err = %d\n", reply_fd, errno);
Jeff Diked50084a2006-01-06 00:18:50 -0800127 }
128 }
129 return 0;
Jeff Dike75e55842005-09-03 15:57:45 -0700130}
131
132#endif
133
Jeff Dike91acb212005-10-10 23:10:32 -0400134static int do_not_aio(struct aio_thread_req *req)
Jeff Dike75e55842005-09-03 15:57:45 -0700135{
Jeff Diked50084a2006-01-06 00:18:50 -0800136 char c;
Jeff Dikeef0470c2007-05-06 14:51:33 -0700137 unsigned long long actual;
Jeff Dikea61f3342007-05-06 14:51:35 -0700138 int n;
Jeff Dike75e55842005-09-03 15:57:45 -0700139
Jeff Dikeef0470c2007-05-06 14:51:33 -0700140 actual = lseek64(req->io_fd, req->offset, SEEK_SET);
Jeff Dikeba180fd2007-10-16 01:27:00 -0700141 if (actual != req->offset)
Jeff Dikeef0470c2007-05-06 14:51:33 -0700142 return -errno;
143
Jeff Dikeba180fd2007-10-16 01:27:00 -0700144 switch(req->type) {
Jeff Diked50084a2006-01-06 00:18:50 -0800145 case AIO_READ:
Jeff Dikea61f3342007-05-06 14:51:35 -0700146 n = read(req->io_fd, req->buf, req->len);
Jeff Diked50084a2006-01-06 00:18:50 -0800147 break;
148 case AIO_WRITE:
Jeff Dikea61f3342007-05-06 14:51:35 -0700149 n = write(req->io_fd, req->buf, req->len);
Jeff Diked50084a2006-01-06 00:18:50 -0800150 break;
151 case AIO_MMAP:
Jeff Dikea61f3342007-05-06 14:51:35 -0700152 n = read(req->io_fd, &c, sizeof(c));
Jeff Diked50084a2006-01-06 00:18:50 -0800153 break;
154 default:
Jeff Dikeba180fd2007-10-16 01:27:00 -0700155 printk(UM_KERN_ERR "do_not_aio - bad request type : %d\n",
156 req->type);
Jeff Dikea61f3342007-05-06 14:51:35 -0700157 return -EINVAL;
Jeff Diked50084a2006-01-06 00:18:50 -0800158 }
Jeff Dike75e55842005-09-03 15:57:45 -0700159
Jeff Dikeba180fd2007-10-16 01:27:00 -0700160 if (n < 0)
Jeff Dikea61f3342007-05-06 14:51:35 -0700161 return -errno;
162 return 0;
Jeff Dike75e55842005-09-03 15:57:45 -0700163}
164
Jeff Dike9683da92007-02-10 01:44:27 -0800165/* These are initialized in initcalls and not changed */
166static int aio_req_fd_r = -1;
167static int aio_req_fd_w = -1;
168static int aio_pid = -1;
Jeff Dikec4399012007-07-15 23:38:56 -0700169static unsigned long aio_stack;
Jeff Dike9683da92007-02-10 01:44:27 -0800170
Jeff Dike75e55842005-09-03 15:57:45 -0700171static int not_aio_thread(void *arg)
172{
Jeff Diked50084a2006-01-06 00:18:50 -0800173 struct aio_thread_req req;
174 struct aio_thread_reply reply;
175 int err;
Jeff Dike75e55842005-09-03 15:57:45 -0700176
Jeff Diked50084a2006-01-06 00:18:50 -0800177 signal(SIGWINCH, SIG_IGN);
Jeff Dikeba180fd2007-10-16 01:27:00 -0700178 while (1) {
Jeff Dikea61f3342007-05-06 14:51:35 -0700179 err = read(aio_req_fd_r, &req, sizeof(req));
Jeff Dikeba180fd2007-10-16 01:27:00 -0700180 if (err != sizeof(req)) {
181 if (err < 0)
182 printk(UM_KERN_ERR "not_aio_thread - "
183 "read failed, fd = %d, err = %d\n",
184 aio_req_fd_r,
Jeff Dikea61f3342007-05-06 14:51:35 -0700185 errno);
Jeff Diked50084a2006-01-06 00:18:50 -0800186 else {
Jeff Dikeba180fd2007-10-16 01:27:00 -0700187 printk(UM_KERN_ERR "not_aio_thread - short "
188 "read, fd = %d, length = %d\n",
189 aio_req_fd_r, err);
Jeff Diked50084a2006-01-06 00:18:50 -0800190 }
191 continue;
192 }
193 err = do_not_aio(&req);
194 reply = ((struct aio_thread_reply) { .data = req.aio,
Jeff Dikeef0470c2007-05-06 14:51:33 -0700195 .err = err });
Jeff Dikea61f3342007-05-06 14:51:35 -0700196 err = write(req.aio->reply_fd, &reply, sizeof(reply));
Jeff Dikeba180fd2007-10-16 01:27:00 -0700197 if (err != sizeof(reply))
198 printk(UM_KERN_ERR "not_aio_thread - write failed, "
199 "fd = %d, err = %d\n", req.aio->reply_fd, errno);
Jeff Diked50084a2006-01-06 00:18:50 -0800200 }
Jeff Dike1b57e9c2006-01-06 00:18:49 -0800201
202 return 0;
Jeff Dike75e55842005-09-03 15:57:45 -0700203}
204
Jeff Dike75e55842005-09-03 15:57:45 -0700205static int init_aio_24(void)
206{
Jeff Diked50084a2006-01-06 00:18:50 -0800207 int fds[2], err;
Jeff Dike75e55842005-09-03 15:57:45 -0700208
Jeff Diked50084a2006-01-06 00:18:50 -0800209 err = os_pipe(fds, 1, 1);
Jeff Dikeba180fd2007-10-16 01:27:00 -0700210 if (err)
Jeff Diked50084a2006-01-06 00:18:50 -0800211 goto out;
Jeff Dike75e55842005-09-03 15:57:45 -0700212
Jeff Diked50084a2006-01-06 00:18:50 -0800213 aio_req_fd_w = fds[0];
214 aio_req_fd_r = fds[1];
Jeff Dike8603ec82007-05-06 14:51:44 -0700215
216 err = os_set_fd_block(aio_req_fd_w, 0);
Jeff Dikeba180fd2007-10-16 01:27:00 -0700217 if (err)
Jeff Dike8603ec82007-05-06 14:51:44 -0700218 goto out_close_pipe;
219
Jeff Diked50084a2006-01-06 00:18:50 -0800220 err = run_helper_thread(not_aio_thread, NULL,
Stanislaw Gruszka4dbed852007-12-17 16:19:46 -0800221 CLONE_FILES | CLONE_VM, &aio_stack);
Jeff Dikeba180fd2007-10-16 01:27:00 -0700222 if (err < 0)
Jeff Diked50084a2006-01-06 00:18:50 -0800223 goto out_close_pipe;
Jeff Dike75e55842005-09-03 15:57:45 -0700224
Jeff Diked50084a2006-01-06 00:18:50 -0800225 aio_pid = err;
226 goto out;
Jeff Dike75e55842005-09-03 15:57:45 -0700227
Jeff Diked50084a2006-01-06 00:18:50 -0800228out_close_pipe:
Jeff Dike512b6fb2007-10-16 01:27:11 -0700229 close(fds[0]);
230 close(fds[1]);
Jeff Diked50084a2006-01-06 00:18:50 -0800231 aio_req_fd_w = -1;
232 aio_req_fd_r = -1;
233out:
Jeff Dike75e55842005-09-03 15:57:45 -0700234#ifndef HAVE_AIO_ABI
Jeff Dikeba180fd2007-10-16 01:27:00 -0700235 printk(UM_KERN_INFO "/usr/include/linux/aio_abi.h not present during "
236 "build\n");
Jeff Dike75e55842005-09-03 15:57:45 -0700237#endif
Jeff Dikeba180fd2007-10-16 01:27:00 -0700238 printk(UM_KERN_INFO "2.6 host AIO support not used - falling back to "
239 "I/O thread\n");
Jeff Diked50084a2006-01-06 00:18:50 -0800240 return 0;
Jeff Dike75e55842005-09-03 15:57:45 -0700241}
242
243#ifdef HAVE_AIO_ABI
244#define DEFAULT_24_AIO 0
245static int init_aio_26(void)
246{
Jeff Diked50084a2006-01-06 00:18:50 -0800247 int err;
Jeff Dike75e55842005-09-03 15:57:45 -0700248
Jeff Dikeba180fd2007-10-16 01:27:00 -0700249 if (io_setup(256, &ctx)) {
Jeff Dikeb4fd3102005-09-16 19:27:49 -0700250 err = -errno;
Jeff Dikeba180fd2007-10-16 01:27:00 -0700251 printk(UM_KERN_ERR "aio_thread failed to initialize context, "
252 "err = %d\n", errno);
Jeff Diked50084a2006-01-06 00:18:50 -0800253 return err;
254 }
Jeff Dike75e55842005-09-03 15:57:45 -0700255
Jeff Diked50084a2006-01-06 00:18:50 -0800256 err = run_helper_thread(aio_thread, NULL,
Stanislaw Gruszka4dbed852007-12-17 16:19:46 -0800257 CLONE_FILES | CLONE_VM, &aio_stack);
Jeff Dikeba180fd2007-10-16 01:27:00 -0700258 if (err < 0)
Jeff Diked50084a2006-01-06 00:18:50 -0800259 return err;
Jeff Dike75e55842005-09-03 15:57:45 -0700260
Jeff Diked50084a2006-01-06 00:18:50 -0800261 aio_pid = err;
Jeff Dike75e55842005-09-03 15:57:45 -0700262
Jeff Dikeba180fd2007-10-16 01:27:00 -0700263 printk(UM_KERN_INFO "Using 2.6 host AIO\n");
Jeff Diked50084a2006-01-06 00:18:50 -0800264 return 0;
Jeff Dike75e55842005-09-03 15:57:45 -0700265}
266
Jeff Dike91acb212005-10-10 23:10:32 -0400267static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
268 unsigned long long offset, struct aio_context *aio)
269{
Jeff Diked50084a2006-01-06 00:18:50 -0800270 struct aio_thread_reply reply;
271 int err;
Jeff Dike91acb212005-10-10 23:10:32 -0400272
Jeff Diked50084a2006-01-06 00:18:50 -0800273 err = do_aio(ctx, type, io_fd, buf, len, offset, aio);
Jeff Dikeba180fd2007-10-16 01:27:00 -0700274 if (err) {
Jeff Diked50084a2006-01-06 00:18:50 -0800275 reply = ((struct aio_thread_reply) { .data = aio,
276 .err = err });
Jeff Dikea61f3342007-05-06 14:51:35 -0700277 err = write(aio->reply_fd, &reply, sizeof(reply));
Jeff Dikeba180fd2007-10-16 01:27:00 -0700278 if (err != sizeof(reply)) {
Jeff Dikea61f3342007-05-06 14:51:35 -0700279 err = -errno;
Jeff Dikeba180fd2007-10-16 01:27:00 -0700280 printk(UM_KERN_ERR "submit_aio_26 - write failed, "
Jeff Diked50084a2006-01-06 00:18:50 -0800281 "fd = %d, err = %d\n", aio->reply_fd, -err);
Jeff Dikea61f3342007-05-06 14:51:35 -0700282 }
Jeff Diked50084a2006-01-06 00:18:50 -0800283 else err = 0;
284 }
Jeff Dike91acb212005-10-10 23:10:32 -0400285
Jeff Diked50084a2006-01-06 00:18:50 -0800286 return err;
Jeff Dike91acb212005-10-10 23:10:32 -0400287}
288
Jeff Dike75e55842005-09-03 15:57:45 -0700289#else
290#define DEFAULT_24_AIO 1
Jeff Dike91acb212005-10-10 23:10:32 -0400291static int init_aio_26(void)
Jeff Dike75e55842005-09-03 15:57:45 -0700292{
Jeff Diked50084a2006-01-06 00:18:50 -0800293 return -ENOSYS;
Jeff Dike75e55842005-09-03 15:57:45 -0700294}
295
Jeff Dike91acb212005-10-10 23:10:32 -0400296static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
297 unsigned long long offset, struct aio_context *aio)
Jeff Dike75e55842005-09-03 15:57:45 -0700298{
Jeff Diked50084a2006-01-06 00:18:50 -0800299 return -ENOSYS;
Jeff Dike75e55842005-09-03 15:57:45 -0700300}
301#endif
302
Jeff Dike9683da92007-02-10 01:44:27 -0800303/* Initialized in an initcall and unchanged thereafter */
Jeff Dike75e55842005-09-03 15:57:45 -0700304static int aio_24 = DEFAULT_24_AIO;
305
306static int __init set_aio_24(char *name, int *add)
307{
Jeff Diked50084a2006-01-06 00:18:50 -0800308 aio_24 = 1;
309 return 0;
Jeff Dike75e55842005-09-03 15:57:45 -0700310}
311
312__uml_setup("aio=2.4", set_aio_24,
313"aio=2.4\n"
314" This is used to force UML to use 2.4-style AIO even when 2.6 AIO is\n"
315" available. 2.4 AIO is a single thread that handles one request at a\n"
316" time, synchronously. 2.6 AIO is a thread which uses the 2.6 AIO \n"
317" interface to handle an arbitrary number of pending requests. 2.6 AIO \n"
318" is not available in tt mode, on 2.4 hosts, or when UML is built with\n"
319" /usr/include/linux/aio_abi.h not available. Many distributions don't\n"
320" include aio_abi.h, so you will need to copy it from a kernel tree to\n"
321" your /usr/include/linux in order to build an AIO-capable UML\n\n"
322);
323
324static int init_aio(void)
325{
Jeff Diked50084a2006-01-06 00:18:50 -0800326 int err;
Jeff Dike75e55842005-09-03 15:57:45 -0700327
Jeff Dikeba180fd2007-10-16 01:27:00 -0700328 if (!aio_24) {
Jeff Diked50084a2006-01-06 00:18:50 -0800329 err = init_aio_26();
Jeff Dikeba180fd2007-10-16 01:27:00 -0700330 if (err && (errno == ENOSYS)) {
331 printk(UM_KERN_INFO "2.6 AIO not supported on the "
332 "host - reverting to 2.4 AIO\n");
Jeff Diked50084a2006-01-06 00:18:50 -0800333 aio_24 = 1;
334 }
335 else return err;
336 }
Jeff Dike75e55842005-09-03 15:57:45 -0700337
Jeff Dikeba180fd2007-10-16 01:27:00 -0700338 if (aio_24)
Jeff Diked50084a2006-01-06 00:18:50 -0800339 return init_aio_24();
Jeff Dike75e55842005-09-03 15:57:45 -0700340
Jeff Diked50084a2006-01-06 00:18:50 -0800341 return 0;
Jeff Dike75e55842005-09-03 15:57:45 -0700342}
343
Jeff Dikeba180fd2007-10-16 01:27:00 -0700344/*
345 * The reason for the __initcall/__uml_exitcall asymmetry is that init_aio
Jeff Dike75e55842005-09-03 15:57:45 -0700346 * needs to be called when the kernel is running because it calls run_helper,
347 * which needs get_free_page. exit_aio is a __uml_exitcall because the generic
348 * kernel does not run __exitcalls on shutdown, and can't because many of them
349 * break when called outside of module unloading.
350 */
351__initcall(init_aio);
352
353static void exit_aio(void)
354{
Jeff Dikec4399012007-07-15 23:38:56 -0700355 if (aio_pid != -1) {
Jeff Diked50084a2006-01-06 00:18:50 -0800356 os_kill_process(aio_pid, 1);
Jeff Dikec4399012007-07-15 23:38:56 -0700357 free_stack(aio_stack, 0);
358 }
Jeff Dike75e55842005-09-03 15:57:45 -0700359}
360
361__uml_exitcall(exit_aio);
362
Jeff Dike91acb212005-10-10 23:10:32 -0400363static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len,
364 unsigned long long offset, struct aio_context *aio)
Jeff Dike75e55842005-09-03 15:57:45 -0700365{
Jeff Diked50084a2006-01-06 00:18:50 -0800366 struct aio_thread_req req = { .type = type,
367 .io_fd = io_fd,
368 .offset = offset,
369 .buf = buf,
370 .len = len,
371 .aio = aio,
372 };
373 int err;
Jeff Dike91acb212005-10-10 23:10:32 -0400374
Jeff Dikea61f3342007-05-06 14:51:35 -0700375 err = write(aio_req_fd_w, &req, sizeof(req));
Jeff Dikeba180fd2007-10-16 01:27:00 -0700376 if (err == sizeof(req))
Jeff Diked50084a2006-01-06 00:18:50 -0800377 err = 0;
Jeff Dikea61f3342007-05-06 14:51:35 -0700378 else err = -errno;
Jeff Dike91acb212005-10-10 23:10:32 -0400379
Jeff Diked50084a2006-01-06 00:18:50 -0800380 return err;
Jeff Dike91acb212005-10-10 23:10:32 -0400381}
382
383int submit_aio(enum aio_type type, int io_fd, char *buf, int len,
Jeff Diked50084a2006-01-06 00:18:50 -0800384 unsigned long long offset, int reply_fd,
385 struct aio_context *aio)
Jeff Dike91acb212005-10-10 23:10:32 -0400386{
Jeff Diked50084a2006-01-06 00:18:50 -0800387 aio->reply_fd = reply_fd;
Jeff Dikeba180fd2007-10-16 01:27:00 -0700388 if (aio_24)
Jeff Diked50084a2006-01-06 00:18:50 -0800389 return submit_aio_24(type, io_fd, buf, len, offset, aio);
Jeff Dikeba180fd2007-10-16 01:27:00 -0700390 else
Jeff Diked50084a2006-01-06 00:18:50 -0800391 return submit_aio_26(type, io_fd, buf, len, offset, aio);
Jeff Dike75e55842005-09-03 15:57:45 -0700392}