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