]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blame - arch/um/os-Linux/aio.c
Merge tag 'jfs-3.12' of git://github.com/kleikamp/linux-shaggy
[mirror_ubuntu-eoan-kernel.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
91d44ff8 107 os_fix_helper_signals();
ba180fd4 108 while (1) {
d50084a2 109 n = io_getevents(ctx, 1, 1, &event, NULL);
ba180fd4
JD
110 if (n < 0) {
111 if (errno == EINTR)
d50084a2 112 continue;
ba180fd4 113 printk(UM_KERN_ERR "aio_thread - io_getevents failed, "
d50084a2
JD
114 "errno = %d\n", errno);
115 }
116 else {
117 reply = ((struct aio_thread_reply)
118 { .data = (void *) (long) event.data,
119 .err = event.res });
91acb21f 120 reply_fd = ((struct aio_context *) reply.data)->reply_fd;
a61f334f 121 err = write(reply_fd, &reply, sizeof(reply));
ba180fd4
JD
122 if (err != sizeof(reply))
123 printk(UM_KERN_ERR "aio_thread - write failed, "
124 "fd = %d, err = %d\n", reply_fd, errno);
d50084a2
JD
125 }
126 }
127 return 0;
75e5584c
JD
128}
129
130#endif
131
91acb21f 132static int do_not_aio(struct aio_thread_req *req)
75e5584c 133{
d50084a2 134 char c;
ef0470c0 135 unsigned long long actual;
a61f334f 136 int n;
d50084a2 137
ef0470c0 138 actual = lseek64(req->io_fd, req->offset, SEEK_SET);
ba180fd4 139 if (actual != req->offset)
ef0470c0
JD
140 return -errno;
141
5134d8fe 142 switch (req->type) {
d50084a2 143 case AIO_READ:
a61f334f 144 n = read(req->io_fd, req->buf, req->len);
d50084a2
JD
145 break;
146 case AIO_WRITE:
a61f334f 147 n = write(req->io_fd, req->buf, req->len);
d50084a2
JD
148 break;
149 case AIO_MMAP:
a61f334f 150 n = read(req->io_fd, &c, sizeof(c));
d50084a2
JD
151 break;
152 default:
ba180fd4
JD
153 printk(UM_KERN_ERR "do_not_aio - bad request type : %d\n",
154 req->type);
a61f334f 155 return -EINVAL;
d50084a2
JD
156 }
157
ba180fd4 158 if (n < 0)
a61f334f
JD
159 return -errno;
160 return 0;
75e5584c
JD
161}
162
9683da91
JD
163/* These are initialized in initcalls and not changed */
164static int aio_req_fd_r = -1;
165static int aio_req_fd_w = -1;
166static int aio_pid = -1;
c4399016 167static unsigned long aio_stack;
9683da91 168
75e5584c
JD
169static int not_aio_thread(void *arg)
170{
d50084a2
JD
171 struct aio_thread_req req;
172 struct aio_thread_reply reply;
173 int err;
174
91d44ff8 175 os_fix_helper_signals();
ba180fd4 176 while (1) {
a61f334f 177 err = read(aio_req_fd_r, &req, sizeof(req));
ba180fd4
JD
178 if (err != sizeof(req)) {
179 if (err < 0)
180 printk(UM_KERN_ERR "not_aio_thread - "
181 "read failed, fd = %d, err = %d\n",
182 aio_req_fd_r,
a61f334f 183 errno);
d50084a2 184 else {
ba180fd4
JD
185 printk(UM_KERN_ERR "not_aio_thread - short "
186 "read, fd = %d, length = %d\n",
187 aio_req_fd_r, err);
d50084a2
JD
188 }
189 continue;
190 }
191 err = do_not_aio(&req);
192 reply = ((struct aio_thread_reply) { .data = req.aio,
ef0470c0 193 .err = err });
a61f334f 194 err = write(req.aio->reply_fd, &reply, sizeof(reply));
ba180fd4
JD
195 if (err != sizeof(reply))
196 printk(UM_KERN_ERR "not_aio_thread - write failed, "
197 "fd = %d, err = %d\n", req.aio->reply_fd, errno);
d50084a2 198 }
1b57e9c2
JD
199
200 return 0;
75e5584c
JD
201}
202
75e5584c
JD
203static int init_aio_24(void)
204{
d50084a2
JD
205 int fds[2], err;
206
207 err = os_pipe(fds, 1, 1);
ba180fd4 208 if (err)
d50084a2
JD
209 goto out;
210
211 aio_req_fd_w = fds[0];
212 aio_req_fd_r = fds[1];
8603ec81
JD
213
214 err = os_set_fd_block(aio_req_fd_w, 0);
ba180fd4 215 if (err)
8603ec81
JD
216 goto out_close_pipe;
217
d50084a2 218 err = run_helper_thread(not_aio_thread, NULL,
4dbed85a 219 CLONE_FILES | CLONE_VM, &aio_stack);
ba180fd4 220 if (err < 0)
d50084a2
JD
221 goto out_close_pipe;
222
223 aio_pid = err;
224 goto out;
225
226out_close_pipe:
512b6fb1
JD
227 close(fds[0]);
228 close(fds[1]);
d50084a2
JD
229 aio_req_fd_w = -1;
230 aio_req_fd_r = -1;
231out:
75e5584c 232#ifndef HAVE_AIO_ABI
ba180fd4
JD
233 printk(UM_KERN_INFO "/usr/include/linux/aio_abi.h not present during "
234 "build\n");
75e5584c 235#endif
ba180fd4
JD
236 printk(UM_KERN_INFO "2.6 host AIO support not used - falling back to "
237 "I/O thread\n");
d50084a2 238 return 0;
75e5584c
JD
239}
240
241#ifdef HAVE_AIO_ABI
242#define DEFAULT_24_AIO 0
243static int init_aio_26(void)
244{
d50084a2 245 int err;
75e5584c 246
ba180fd4 247 if (io_setup(256, &ctx)) {
b4fd310e 248 err = -errno;
ba180fd4
JD
249 printk(UM_KERN_ERR "aio_thread failed to initialize context, "
250 "err = %d\n", errno);
d50084a2
JD
251 return err;
252 }
75e5584c 253
d50084a2 254 err = run_helper_thread(aio_thread, NULL,
4dbed85a 255 CLONE_FILES | CLONE_VM, &aio_stack);
ba180fd4 256 if (err < 0)
d50084a2 257 return err;
75e5584c 258
d50084a2 259 aio_pid = err;
75e5584c 260
ba180fd4 261 printk(UM_KERN_INFO "Using 2.6 host AIO\n");
d50084a2 262 return 0;
91acb21f
JD
263}
264
265static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
266 unsigned long long offset, struct aio_context *aio)
267{
d50084a2
JD
268 struct aio_thread_reply reply;
269 int err;
270
271 err = do_aio(ctx, type, io_fd, buf, len, offset, aio);
ba180fd4 272 if (err) {
d50084a2
JD
273 reply = ((struct aio_thread_reply) { .data = aio,
274 .err = err });
a61f334f 275 err = write(aio->reply_fd, &reply, sizeof(reply));
ba180fd4 276 if (err != sizeof(reply)) {
a61f334f 277 err = -errno;
ba180fd4 278 printk(UM_KERN_ERR "submit_aio_26 - write failed, "
d50084a2 279 "fd = %d, err = %d\n", aio->reply_fd, -err);
a61f334f 280 }
d50084a2
JD
281 else err = 0;
282 }
283
284 return err;
75e5584c
JD
285}
286
287#else
288#define DEFAULT_24_AIO 1
91acb21f 289static int init_aio_26(void)
75e5584c 290{
d50084a2 291 return -ENOSYS;
75e5584c
JD
292}
293
91acb21f
JD
294static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
295 unsigned long long offset, struct aio_context *aio)
75e5584c 296{
d50084a2 297 return -ENOSYS;
75e5584c
JD
298}
299#endif
300
9683da91 301/* Initialized in an initcall and unchanged thereafter */
75e5584c
JD
302static int aio_24 = DEFAULT_24_AIO;
303
304static int __init set_aio_24(char *name, int *add)
305{
d50084a2
JD
306 aio_24 = 1;
307 return 0;
75e5584c
JD
308}
309
310__uml_setup("aio=2.4", set_aio_24,
311"aio=2.4\n"
312" This is used to force UML to use 2.4-style AIO even when 2.6 AIO is\n"
313" available. 2.4 AIO is a single thread that handles one request at a\n"
314" time, synchronously. 2.6 AIO is a thread which uses the 2.6 AIO \n"
315" interface to handle an arbitrary number of pending requests. 2.6 AIO \n"
316" is not available in tt mode, on 2.4 hosts, or when UML is built with\n"
317" /usr/include/linux/aio_abi.h not available. Many distributions don't\n"
318" include aio_abi.h, so you will need to copy it from a kernel tree to\n"
319" your /usr/include/linux in order to build an AIO-capable UML\n\n"
320);
321
322static int init_aio(void)
323{
d50084a2
JD
324 int err;
325
ba180fd4 326 if (!aio_24) {
d50084a2 327 err = init_aio_26();
ba180fd4
JD
328 if (err && (errno == ENOSYS)) {
329 printk(UM_KERN_INFO "2.6 AIO not supported on the "
330 "host - reverting to 2.4 AIO\n");
d50084a2
JD
331 aio_24 = 1;
332 }
333 else return err;
334 }
335
ba180fd4 336 if (aio_24)
d50084a2
JD
337 return init_aio_24();
338
339 return 0;
75e5584c
JD
340}
341
ba180fd4
JD
342/*
343 * The reason for the __initcall/__uml_exitcall asymmetry is that init_aio
75e5584c
JD
344 * needs to be called when the kernel is running because it calls run_helper,
345 * which needs get_free_page. exit_aio is a __uml_exitcall because the generic
346 * kernel does not run __exitcalls on shutdown, and can't because many of them
347 * break when called outside of module unloading.
348 */
349__initcall(init_aio);
350
351static void exit_aio(void)
352{
c4399016 353 if (aio_pid != -1) {
d50084a2 354 os_kill_process(aio_pid, 1);
c4399016
JD
355 free_stack(aio_stack, 0);
356 }
75e5584c
JD
357}
358
359__uml_exitcall(exit_aio);
360
91acb21f
JD
361static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len,
362 unsigned long long offset, struct aio_context *aio)
75e5584c 363{
d50084a2
JD
364 struct aio_thread_req req = { .type = type,
365 .io_fd = io_fd,
366 .offset = offset,
367 .buf = buf,
368 .len = len,
369 .aio = aio,
370 };
371 int err;
372
a61f334f 373 err = write(aio_req_fd_w, &req, sizeof(req));
ba180fd4 374 if (err == sizeof(req))
d50084a2 375 err = 0;
a61f334f 376 else err = -errno;
d50084a2
JD
377
378 return err;
91acb21f
JD
379}
380
381int submit_aio(enum aio_type type, int io_fd, char *buf, int len,
d50084a2
JD
382 unsigned long long offset, int reply_fd,
383 struct aio_context *aio)
91acb21f 384{
d50084a2 385 aio->reply_fd = reply_fd;
ba180fd4 386 if (aio_24)
d50084a2 387 return submit_aio_24(type, io_fd, buf, len, offset, aio);
ba180fd4 388 else
d50084a2 389 return submit_aio_26(type, io_fd, buf, len, offset, aio);
75e5584c 390}