aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/os-Linux/aio.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/os-Linux/aio.c')
-rw-r--r--arch/um/os-Linux/aio.c112
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
18struct aio_thread_req { 18struct 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;
228out: 233out:
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}