Revision 384acbf4 linux-aio.c
b/linux-aio.c | ||
---|---|---|
31 | 31 |
struct iocb iocb; |
32 | 32 |
ssize_t ret; |
33 | 33 |
size_t nbytes; |
34 |
int async_context_id; |
|
35 | 34 |
QLIST_ENTRY(qemu_laiocb) node; |
36 | 35 |
}; |
37 | 36 |
|
... | ... | |
39 | 38 |
io_context_t ctx; |
40 | 39 |
int efd; |
41 | 40 |
int count; |
42 |
QLIST_HEAD(, qemu_laiocb) completed_reqs; |
|
43 | 41 |
}; |
44 | 42 |
|
45 | 43 |
static inline ssize_t io_event_ret(struct io_event *ev) |
... | ... | |
49 | 47 |
|
50 | 48 |
/* |
51 | 49 |
* Completes an AIO request (calls the callback and frees the ACB). |
52 |
* Be sure to be in the right AsyncContext before calling this function. |
|
53 | 50 |
*/ |
54 | 51 |
static void qemu_laio_process_completion(struct qemu_laio_state *s, |
55 | 52 |
struct qemu_laiocb *laiocb) |
... | ... | |
72 | 69 |
} |
73 | 70 |
|
74 | 71 |
/* |
75 |
* Processes all queued AIO requests, i.e. requests that have return from OS |
|
76 |
* but their callback was not called yet. Requests that cannot have their |
|
77 |
* callback called in the current AsyncContext, remain in the queue. |
|
78 |
* |
|
79 |
* Returns 1 if at least one request could be completed, 0 otherwise. |
|
72 |
* All requests are directly processed when they complete, so there's nothing |
|
73 |
* left to do during qemu_aio_wait(). |
|
80 | 74 |
*/ |
81 | 75 |
static int qemu_laio_process_requests(void *opaque) |
82 | 76 |
{ |
83 |
struct qemu_laio_state *s = opaque; |
|
84 |
struct qemu_laiocb *laiocb, *next; |
|
85 |
int res = 0; |
|
86 |
|
|
87 |
QLIST_FOREACH_SAFE (laiocb, &s->completed_reqs, node, next) { |
|
88 |
if (laiocb->async_context_id == get_async_context_id()) { |
|
89 |
qemu_laio_process_completion(s, laiocb); |
|
90 |
QLIST_REMOVE(laiocb, node); |
|
91 |
res = 1; |
|
92 |
} |
|
93 |
} |
|
94 |
|
|
95 |
return res; |
|
96 |
} |
|
97 |
|
|
98 |
/* |
|
99 |
* Puts a request in the completion queue so that its callback is called the |
|
100 |
* next time when it's possible. If we already are in the right AsyncContext, |
|
101 |
* the request is completed immediately instead. |
|
102 |
*/ |
|
103 |
static void qemu_laio_enqueue_completed(struct qemu_laio_state *s, |
|
104 |
struct qemu_laiocb* laiocb) |
|
105 |
{ |
|
106 |
if (laiocb->async_context_id == get_async_context_id()) { |
|
107 |
qemu_laio_process_completion(s, laiocb); |
|
108 |
} else { |
|
109 |
QLIST_INSERT_HEAD(&s->completed_reqs, laiocb, node); |
|
110 |
} |
|
77 |
return 0; |
|
111 | 78 |
} |
112 | 79 |
|
113 | 80 |
static void qemu_laio_completion_cb(void *opaque) |
... | ... | |
141 | 108 |
container_of(iocb, struct qemu_laiocb, iocb); |
142 | 109 |
|
143 | 110 |
laiocb->ret = io_event_ret(&events[i]); |
144 |
qemu_laio_enqueue_completed(s, laiocb);
|
|
111 |
qemu_laio_process_completion(s, laiocb);
|
|
145 | 112 |
} |
146 | 113 |
} |
147 | 114 |
} |
... | ... | |
204 | 171 |
laiocb->nbytes = nb_sectors * 512; |
205 | 172 |
laiocb->ctx = s; |
206 | 173 |
laiocb->ret = -EINPROGRESS; |
207 |
laiocb->async_context_id = get_async_context_id(); |
|
208 | 174 |
|
209 | 175 |
iocbs = &laiocb->iocb; |
210 | 176 |
|
... | ... | |
239 | 205 |
struct qemu_laio_state *s; |
240 | 206 |
|
241 | 207 |
s = qemu_mallocz(sizeof(*s)); |
242 |
QLIST_INIT(&s->completed_reqs); |
|
243 | 208 |
s->efd = eventfd(0, 0); |
244 | 209 |
if (s->efd == -1) |
245 | 210 |
goto out_free_state; |
Also available in: Unified diff