aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/os-Linux/aio.c
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2005-09-03 18:57:46 -0400
committerLinus Torvalds <torvalds@evo.osdl.org>2005-09-05 03:06:23 -0400
commit09ace81c1d737bcbb2423db235ac980cac4d5de9 (patch)
treed31987b15d57429bd40843c02b2283b8e2d90cb0 /arch/um/os-Linux/aio.c
parent75e5584c89d213d6089f64f22cd899fb172e4c95 (diff)
[PATCH] uml: add host AIO support to block driver
This adds AIO support to the ubd driver. The driver breaks a struct request into IO requests to the host, based on the hardware segments in the request and on any COW blocks covered by the request. The ubd IO thread is gone, since there is now an equivalent thread in the AIO module. There is provision for multiple outstanding requests now. Requests aren't retired until all pieces of it have been completed. The AIO requests have a shared count, which is decremented as IO operations come in until it reaches 0. This can be possibly moved to the request struct - haven't looked at this yet. Signed-off-by: Jeff Dike <jdike@addtoit.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
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}