]> git.pld-linux.org Git - packages/xen.git/blob - xen-blktap-no-aio-epoll.patch
- separated -libs
[packages/xen.git] / xen-blktap-no-aio-epoll.patch
1 --- a/tools/blktap/drivers/block-aio.c  2006-09-21 13:45:44.000000000 +0100
2 +++ b/tools/blktap/drivers/block-aio.c  2006-09-21 19:58:18.000000000 +0100
3 @@ -38,20 +38,13 @@
4  #include <stdio.h>
5  #include <stdlib.h>
6  #include <unistd.h>
7 +#include <pthread.h>
8  #include <sys/statvfs.h>
9  #include <sys/stat.h>
10  #include <sys/ioctl.h>
11  #include <linux/fs.h>
12  #include "tapdisk.h"
13  
14 -
15 -/**
16 - * We used a kernel patch to return an fd associated with the AIO context
17 - * so that we can concurrently poll on synchronous and async descriptors.
18 - * This is signalled by passing 1 as the io context to io_setup.
19 - */
20 -#define REQUEST_ASYNC_FD 1
21 -
22  #define MAX_AIO_REQS (MAX_REQUESTS * MAX_SEGMENTS_PER_REQ)
23  
24  struct pending_aio {
25 @@ -71,19 +64,24 @@
26         int                iocb_free_count;
27         struct iocb       *iocb_queue[MAX_AIO_REQS];
28         int                iocb_queued;
29 -       int                poll_fd; /* NB: we require aio_poll support */
30         struct io_event    aio_events[MAX_AIO_REQS];
31 +
32 +       pthread_t          aio_thread;
33 +       /* pipe fds for communication with the aio completion thread */
34 +       int                command_fd[2];
35 +       int                completion_fd[2];
36  };
37  
38  #define IOCB_IDX(_s, _io) ((_io) - (_s)->iocb_list)
39  
40 +static void *tdaio_completion_thread(void *);
41 +
42  /*Get Image size, secsize*/
43  static int get_image_info(struct td_state *s, int fd)
44  {
45         int ret;
46         long size;
47         unsigned long total_size;
48 -       struct statvfs statBuf;
49         struct stat stat;
50  
51         ret = fstat(fd, &stat);
52 @@ -108,7 +106,6 @@
53                 /*Get the sector size*/
54  #if defined(BLKSSZGET)
55                 {
56 -                       int arg;
57                         s->sector_size = DEFAULT_SECTOR_SIZE;
58                         ioctl(fd, BLKSSZGET, &s->sector_size);
59                         
60 @@ -151,11 +148,10 @@
61         prv->iocb_free_count = MAX_AIO_REQS;
62         prv->iocb_queued     = 0;
63         
64 -       prv->aio_ctx = (io_context_t) REQUEST_ASYNC_FD;
65 -       prv->poll_fd = io_setup(MAX_AIO_REQS, &prv->aio_ctx);
66 +       prv->aio_ctx = (io_context_t) 0;
67 +       ret = io_setup(MAX_AIO_REQS, &prv->aio_ctx);
68  
69 -       if (prv->poll_fd < 0) {
70 -               ret = prv->poll_fd;
71 +       if (ret < 0) {
72                  if (ret == -EAGAIN) {
73                          DPRINTF("Couldn't setup AIO context.  If you are "
74                                  "trying to concurrently use a large number "
75 @@ -164,9 +160,7 @@
76                                  "(e.g. 'echo echo 1048576 > /proc/sys/fs/"
77                                  "aio-max-nr')\n");
78                  } else {
79 -                        DPRINTF("Couldn't get fd for AIO poll support.  This "
80 -                                "is probably because your kernel does not "
81 -                                "have the aio-poll patch applied.\n");
82 +                        DPRINTF("Couldn't setup AIO context.\n");
83                  }
84                 goto done;
85         }
86 @@ -194,6 +188,15 @@
87  
88          prv->fd = fd;
89  
90 +       pipe(prv->command_fd);
91 +       pipe(prv->completion_fd);
92 +       
93 +       ret = pthread_create(&prv->aio_thread, NULL, 
94 +                            tdaio_completion_thread, prv);
95 +       ret = 0;
96 +       write(prv->command_fd[1], &ret, sizeof(ret));
97 +
98 +                            
99         ret = get_image_info(s, fd);
100  done:
101         return ret;     
102 @@ -281,7 +284,7 @@
103         /*initialise the FD array*/
104         for(i=0;i<MAX_IOFD;i++) fds[i] = 0;
105  
106 -       fds[0] = prv->poll_fd;
107 +       fds[0] = prv->completion_fd[0];
108  
109         return fds;     
110  }
111 @@ -296,17 +299,61 @@
112         return 0;
113  }
114  
115 +/* 
116 + * We don't have any way to do epoll on aio events in a normal kernel, so
117 + * wait for aio events in a separate thread and return completion status 
118 + * that via a pipe that can be waited on normally.
119 + * 
120 + * To keep locking problems between the completion thread and the submit
121 + * thread to a minimum, there's a handshake which allows only one thread
122 + * to be doing work on the completion queue at a time:
123 + * 
124 + * 1) main thread sends completion thread a command via the command pipe;
125 + * 2) completion thread waits for aio events and returns the number 
126 + *    received on the completion pipe
127 + * 3) main thread processes the received prv->aio_events events
128 + * 4) loop back to 1) to let the completion thread refill the aio_events 
129 + *    buffer.
130 + *
131 + * This workaround needs to disappear once the kernel provides a single
132 + * mechanism for waiting on both aio and normal fd wakeups.
133 + */
134 +
135 +static void *tdaio_completion_thread(void *arg)
136 +{
137 +       struct tdaio_state *prv = (struct tdaio_state *) arg;
138 +       int command;
139 +       int nr_events;
140 +       int rc;
141 +       
142 +       while (1) {
143 +               rc = read(prv->command_fd[0], &command, sizeof(command));
144 +
145 +               do {
146 +                       /* Non-blocking test for completed io. */
147 +                       rc = io_getevents(prv->aio_ctx, 0, 
148 +                                         MAX_AIO_REQS, prv->aio_events,
149 +                                         NULL);
150 +                       if (rc) {
151 +                               nr_events = rc;
152 +                               rc = write(prv->completion_fd[1], &nr_events, 
153 +                                          sizeof(nr_events));
154 +                       }
155 +               } while (!rc);
156 +       }
157 +}
158 +
159  int tdaio_do_callbacks(struct td_state *s, int sid)
160  {
161 -       int ret, i, rsp = 0;
162 +       int ret, i, nr_events, rsp = 0;
163         struct io_event *ep;
164         struct tdaio_state *prv = (struct tdaio_state *)s->private;
165  
166         /* Non-blocking test for completed io. */
167 -       ret = io_getevents(prv->aio_ctx, 0, MAX_AIO_REQS, prv->aio_events,
168 -                          NULL);
169 -                       
170 -       for (ep=prv->aio_events,i=ret; i-->0; ep++) {
171 +       ret = read(prv->completion_fd[0], &nr_events, sizeof(nr_events));
172 +
173 +repeat:        
174 +       for (ep=prv->aio_events,i=nr_events; i-->0; ep++) {
175                 struct iocb        *io  = ep->obj;
176                 struct pending_aio *pio;
177                 
178 @@ -320,6 +367,16 @@
179  
180                 prv->iocb_free[prv->iocb_free_count++] = io;
181         }
182 +
183 +       if (nr_events) {
184 +               nr_events = io_getevents(prv->aio_ctx, 0, 
185 +                                        MAX_AIO_REQS, prv->aio_events,
186 +                                        NULL);
187 +               goto repeat;
188 +       }
189 +
190 +       write(prv->command_fd[1], &nr_events, sizeof(nr_events));
191 +
192         return rsp;
193  }
194         
195 --- xen-unstable-11539/tools/blktap/drivers/block-aio.c.~1~     2006-09-25 19:27:39.000000000 +0100
196 +++ xen-unstable-11539/tools/blktap/drivers/block-aio.c 2006-09-25 20:00:24.000000000 +0100
197 @@ -331,7 +331,7 @@
198  
199                 do {
200                         /* Non-blocking test for completed io. */
201 -                       rc = io_getevents(prv->aio_ctx, 0, 
202 +                       rc = io_getevents(prv->aio_ctx, 1, 
203                                           MAX_AIO_REQS, prv->aio_events,
204                                           NULL);
205                         if (rc) {
This page took 0.037988 seconds and 3 git commands to generate.