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.c211
1 files changed, 99 insertions, 112 deletions
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index b04897cd995d..41cfb0944201 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -6,7 +6,6 @@
6#include <stdlib.h> 6#include <stdlib.h>
7#include <unistd.h> 7#include <unistd.h>
8#include <signal.h> 8#include <signal.h>
9#include <string.h>
10#include <errno.h> 9#include <errno.h>
11#include <sched.h> 10#include <sched.h>
12#include <sys/syscall.h> 11#include <sys/syscall.h>
@@ -17,31 +16,18 @@
17#include "user.h" 16#include "user.h"
18#include "mode.h" 17#include "mode.h"
19 18
19struct aio_thread_req {
20 enum aio_type type;
21 int io_fd;
22 unsigned long long offset;
23 char *buf;
24 int len;
25 struct aio_context *aio;
26};
27
20static int aio_req_fd_r = -1; 28static int aio_req_fd_r = -1;
21static int aio_req_fd_w = -1; 29static int aio_req_fd_w = -1;
22 30
23static int update_aio(struct aio_context *aio, int res)
24{
25 if(res < 0)
26 aio->len = res;
27 else if((res == 0) && (aio->type == AIO_READ)){
28 /* This is the EOF case - we have hit the end of the file
29 * and it ends in a partial block, so we fill the end of
30 * the block with zeros and claim success.
31 */
32 memset(aio->data, 0, aio->len);
33 aio->len = 0;
34 }
35 else if(res > 0){
36 aio->len -= res;
37 aio->data += res;
38 aio->offset += res;
39 return aio->len;
40 }
41
42 return 0;
43}
44
45#if defined(HAVE_AIO_ABI) 31#if defined(HAVE_AIO_ABI)
46#include <linux/aio_abi.h> 32#include <linux/aio_abi.h>
47 33
@@ -80,7 +66,8 @@ static long io_getevents(aio_context_t ctx_id, long min_nr, long nr,
80 * that it now backs the mmapped area. 66 * that it now backs the mmapped area.
81 */ 67 */
82 68
83static int do_aio(aio_context_t ctx, struct aio_context *aio) 69static int do_aio(aio_context_t ctx, enum aio_type type, int fd, char *buf,
70 int len, unsigned long long offset, struct aio_context *aio)
84{ 71{
85 struct iocb iocb, *iocbp = &iocb; 72 struct iocb iocb, *iocbp = &iocb;
86 char c; 73 char c;
@@ -88,37 +75,40 @@ static int do_aio(aio_context_t ctx, struct aio_context *aio)
88 75
89 iocb = ((struct iocb) { .aio_data = (unsigned long) aio, 76 iocb = ((struct iocb) { .aio_data = (unsigned long) aio,
90 .aio_reqprio = 0, 77 .aio_reqprio = 0,
91 .aio_fildes = aio->fd, 78 .aio_fildes = fd,
92 .aio_buf = (unsigned long) aio->data, 79 .aio_buf = (unsigned long) buf,
93 .aio_nbytes = aio->len, 80 .aio_nbytes = len,
94 .aio_offset = aio->offset, 81 .aio_offset = offset,
95 .aio_reserved1 = 0, 82 .aio_reserved1 = 0,
96 .aio_reserved2 = 0, 83 .aio_reserved2 = 0,
97 .aio_reserved3 = 0 }); 84 .aio_reserved3 = 0 });
98 85
99 switch(aio->type){ 86 switch(type){
100 case AIO_READ: 87 case AIO_READ:
101 iocb.aio_lio_opcode = IOCB_CMD_PREAD; 88 iocb.aio_lio_opcode = IOCB_CMD_PREAD;
89 err = io_submit(ctx, 1, &iocbp);
102 break; 90 break;
103 case AIO_WRITE: 91 case AIO_WRITE:
104 iocb.aio_lio_opcode = IOCB_CMD_PWRITE; 92 iocb.aio_lio_opcode = IOCB_CMD_PWRITE;
93 err = io_submit(ctx, 1, &iocbp);
105 break; 94 break;
106 case AIO_MMAP: 95 case AIO_MMAP:
107 iocb.aio_lio_opcode = IOCB_CMD_PREAD; 96 iocb.aio_lio_opcode = IOCB_CMD_PREAD;
108 iocb.aio_buf = (unsigned long) &c; 97 iocb.aio_buf = (unsigned long) &c;
109 iocb.aio_nbytes = sizeof(c); 98 iocb.aio_nbytes = sizeof(c);
99 err = io_submit(ctx, 1, &iocbp);
110 break; 100 break;
111 default: 101 default:
112 printk("Bogus op in do_aio - %d\n", aio->type); 102 printk("Bogus op in do_aio - %d\n", type);
113 err = -EINVAL; 103 err = -EINVAL;
114 goto out; 104 break;
115 } 105 }
116 106
117 err = io_submit(ctx, 1, &iocbp);
118 if(err > 0) 107 if(err > 0)
119 err = 0; 108 err = 0;
109 else
110 err = -errno;
120 111
121 out:
122 return err; 112 return err;
123} 113}
124 114
@@ -127,9 +117,8 @@ static aio_context_t ctx = 0;
127static int aio_thread(void *arg) 117static int aio_thread(void *arg)
128{ 118{
129 struct aio_thread_reply reply; 119 struct aio_thread_reply reply;
130 struct aio_context *aio;
131 struct io_event event; 120 struct io_event event;
132 int err, n; 121 int err, n, reply_fd;
133 122
134 signal(SIGWINCH, SIG_IGN); 123 signal(SIGWINCH, SIG_IGN);
135 124
@@ -142,21 +131,14 @@ static int aio_thread(void *arg)
142 "errno = %d\n", errno); 131 "errno = %d\n", errno);
143 } 132 }
144 else { 133 else {
145 aio = (struct aio_context *) event.data;
146 if(update_aio(aio, event.res)){
147 do_aio(ctx, aio);
148 continue;
149 }
150
151 reply = ((struct aio_thread_reply) 134 reply = ((struct aio_thread_reply)
152 { .data = aio, 135 { .data = (void *) (long) event.data,
153 .err = aio->len }); 136 .err = event.res });
154 err = os_write_file(aio->reply_fd, &reply, 137 reply_fd = ((struct aio_context *) reply.data)->reply_fd;
155 sizeof(reply)); 138 err = os_write_file(reply_fd, &reply, sizeof(reply));
156 if(err != sizeof(reply)) 139 if(err != sizeof(reply))
157 printk("aio_thread - write failed, " 140 printk("aio_thread - write failed, fd = %d, "
158 "fd = %d, err = %d\n", aio->reply_fd, 141 "err = %d\n", aio_req_fd_r, -err);
159 -err);
160 } 142 }
161 } 143 }
162 return 0; 144 return 0;
@@ -164,35 +146,35 @@ static int aio_thread(void *arg)
164 146
165#endif 147#endif
166 148
167static int do_not_aio(struct aio_context *aio) 149static int do_not_aio(struct aio_thread_req *req)
168{ 150{
169 char c; 151 char c;
170 int err; 152 int err;
171 153
172 switch(aio->type){ 154 switch(req->type){
173 case AIO_READ: 155 case AIO_READ:
174 err = os_seek_file(aio->fd, aio->offset); 156 err = os_seek_file(req->io_fd, req->offset);
175 if(err) 157 if(err)
176 goto out; 158 goto out;
177 159
178 err = os_read_file(aio->fd, aio->data, aio->len); 160 err = os_read_file(req->io_fd, req->buf, req->len);
179 break; 161 break;
180 case AIO_WRITE: 162 case AIO_WRITE:
181 err = os_seek_file(aio->fd, aio->offset); 163 err = os_seek_file(req->io_fd, req->offset);
182 if(err) 164 if(err)
183 goto out; 165 goto out;
184 166
185 err = os_write_file(aio->fd, aio->data, aio->len); 167 err = os_write_file(req->io_fd, req->buf, req->len);
186 break; 168 break;
187 case AIO_MMAP: 169 case AIO_MMAP:
188 err = os_seek_file(aio->fd, aio->offset); 170 err = os_seek_file(req->io_fd, req->offset);
189 if(err) 171 if(err)
190 goto out; 172 goto out;
191 173
192 err = os_read_file(aio->fd, &c, sizeof(c)); 174 err = os_read_file(req->io_fd, &c, sizeof(c));
193 break; 175 break;
194 default: 176 default:
195 printk("do_not_aio - bad request type : %d\n", aio->type); 177 printk("do_not_aio - bad request type : %d\n", req->type);
196 err = -EINVAL; 178 err = -EINVAL;
197 break; 179 break;
198 } 180 }
@@ -203,14 +185,14 @@ static int do_not_aio(struct aio_context *aio)
203 185
204static int not_aio_thread(void *arg) 186static int not_aio_thread(void *arg)
205{ 187{
206 struct aio_context *aio; 188 struct aio_thread_req req;
207 struct aio_thread_reply reply; 189 struct aio_thread_reply reply;
208 int err; 190 int err;
209 191
210 signal(SIGWINCH, SIG_IGN); 192 signal(SIGWINCH, SIG_IGN);
211 while(1){ 193 while(1){
212 err = os_read_file(aio_req_fd_r, &aio, sizeof(aio)); 194 err = os_read_file(aio_req_fd_r, &req, sizeof(req));
213 if(err != sizeof(aio)){ 195 if(err != sizeof(req)){
214 if(err < 0) 196 if(err < 0)
215 printk("not_aio_thread - read failed, " 197 printk("not_aio_thread - read failed, "
216 "fd = %d, err = %d\n", aio_req_fd_r, 198 "fd = %d, err = %d\n", aio_req_fd_r,
@@ -221,34 +203,17 @@ static int not_aio_thread(void *arg)
221 } 203 }
222 continue; 204 continue;
223 } 205 }
224 again: 206 err = do_not_aio(&req);
225 err = do_not_aio(aio); 207 reply = ((struct aio_thread_reply) { .data = req.aio,
226 208 .err = err });
227 if(update_aio(aio, err)) 209 err = os_write_file(req.aio->reply_fd, &reply, sizeof(reply));
228 goto again;
229
230 reply = ((struct aio_thread_reply) { .data = aio,
231 .err = aio->len });
232 err = os_write_file(aio->reply_fd, &reply, sizeof(reply));
233 if(err != sizeof(reply)) 210 if(err != sizeof(reply))
234 printk("not_aio_thread - write failed, fd = %d, " 211 printk("not_aio_thread - write failed, fd = %d, "
235 "err = %d\n", aio_req_fd_r, -err); 212 "err = %d\n", aio_req_fd_r, -err);
236 } 213 }
237} 214}
238 215
239static int submit_aio_24(struct aio_context *aio)
240{
241 int err;
242
243 err = os_write_file(aio_req_fd_w, &aio, sizeof(aio));
244 if(err == sizeof(aio))
245 err = 0;
246
247 return err;
248}
249
250static int aio_pid = -1; 216static int aio_pid = -1;
251static int (*submit_proc)(struct aio_context *aio);
252 217
253static int init_aio_24(void) 218static int init_aio_24(void)
254{ 219{
@@ -280,68 +245,64 @@ static int init_aio_24(void)
280#endif 245#endif
281 printk("2.6 host AIO support not used - falling back to I/O " 246 printk("2.6 host AIO support not used - falling back to I/O "
282 "thread\n"); 247 "thread\n");
283
284 submit_proc = submit_aio_24;
285
286 return 0; 248 return 0;
287} 249}
288 250
289#ifdef HAVE_AIO_ABI 251#ifdef HAVE_AIO_ABI
290#define DEFAULT_24_AIO 0 252#define DEFAULT_24_AIO 0
291static int submit_aio_26(struct aio_context *aio)
292{
293 struct aio_thread_reply reply;
294 int err;
295
296 err = do_aio(ctx, aio);
297 if(err){
298 reply = ((struct aio_thread_reply) { .data = aio,
299 .err = err });
300 err = os_write_file(aio->reply_fd, &reply, sizeof(reply));
301 if(err != sizeof(reply))
302 printk("submit_aio_26 - write failed, "
303 "fd = %d, err = %d\n", aio->reply_fd, -err);
304 else err = 0;
305 }
306
307 return err;
308}
309
310static int init_aio_26(void) 253static int init_aio_26(void)
311{ 254{
312 unsigned long stack; 255 unsigned long stack;
313 int err; 256 int err;
314 257
315 if(io_setup(256, &ctx)){ 258 if(io_setup(256, &ctx)){
259 err = -errno;
316 printk("aio_thread failed to initialize context, err = %d\n", 260 printk("aio_thread failed to initialize context, err = %d\n",
317 errno); 261 errno);
318 return -errno; 262 return err;
319 } 263 }
320 264
321 err = run_helper_thread(aio_thread, NULL, 265 err = run_helper_thread(aio_thread, NULL,
322 CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); 266 CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
323 if(err < 0) 267 if(err < 0)
324 return -errno; 268 return err;
325 269
326 aio_pid = err; 270 aio_pid = err;
327 271
328 printk("Using 2.6 host AIO\n"); 272 printk("Using 2.6 host AIO\n");
273 return 0;
274}
275
276static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
277 unsigned long long offset, struct aio_context *aio)
278{
279 struct aio_thread_reply reply;
280 int err;
329 281
330 submit_proc = submit_aio_26; 282 err = do_aio(ctx, type, io_fd, buf, len, offset, aio);
283 if(err){
284 reply = ((struct aio_thread_reply) { .data = aio,
285 .err = err });
286 err = os_write_file(aio->reply_fd, &reply, sizeof(reply));
287 if(err != sizeof(reply))
288 printk("submit_aio_26 - write failed, "
289 "fd = %d, err = %d\n", aio->reply_fd, -err);
290 else err = 0;
291 }
331 292
332 return 0; 293 return err;
333} 294}
334 295
335#else 296#else
336#define DEFAULT_24_AIO 1 297#define DEFAULT_24_AIO 1
337static int submit_aio_26(struct aio_context *aio) 298static int init_aio_26(void)
338{ 299{
339 return -ENOSYS; 300 return -ENOSYS;
340} 301}
341 302
342static int init_aio_26(void) 303static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
304 unsigned long long offset, struct aio_context *aio)
343{ 305{
344 submit_proc = submit_aio_26;
345 return -ENOSYS; 306 return -ENOSYS;
346} 307}
347#endif 308#endif
@@ -408,7 +369,33 @@ static void exit_aio(void)
408 369
409__uml_exitcall(exit_aio); 370__uml_exitcall(exit_aio);
410 371
411int submit_aio(struct aio_context *aio) 372static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len,
373 unsigned long long offset, struct aio_context *aio)
412{ 374{
413 return (*submit_proc)(aio); 375 struct aio_thread_req req = { .type = type,
376 .io_fd = io_fd,
377 .offset = offset,
378 .buf = buf,
379 .len = len,
380 .aio = aio,
381 };
382 int err;
383
384 err = os_write_file(aio_req_fd_w, &req, sizeof(req));
385 if(err == sizeof(req))
386 err = 0;
387
388 return err;
389}
390
391int submit_aio(enum aio_type type, int io_fd, char *buf, int len,
392 unsigned long long offset, int reply_fd,
393 struct aio_context *aio)
394{
395 aio->reply_fd = reply_fd;
396 if(aio_24)
397 return submit_aio_24(type, io_fd, buf, len, offset, aio);
398 else {
399 return submit_aio_26(type, io_fd, buf, len, offset, aio);
400 }
414} 401}