+/*
+ * Completes an AIO request (calls the callback and frees the ACB).
+ * Be sure to be in the right AsyncContext before calling this function.
+ */
+static void qemu_laio_process_completion(struct qemu_laio_state *s,
+ struct qemu_laiocb *laiocb)
+{
+ int ret;
+
+ s->count--;
+
+ ret = laiocb->ret;
+ if (ret != -ECANCELED) {
+ if (ret == laiocb->nbytes)
+ ret = 0;
+ else if (ret >= 0)
+ ret = -EINVAL;
+
+ laiocb->common.cb(laiocb->common.opaque, ret);
+ }
+
+ qemu_aio_release(laiocb);
+}
+
+/*
+ * Processes all queued AIO requests, i.e. requests that have return from OS
+ * but their callback was not called yet. Requests that cannot have their
+ * callback called in the current AsyncContext, remain in the queue.
+ *
+ * Returns 1 if at least one request could be completed, 0 otherwise.
+ */
+static int qemu_laio_process_requests(void *opaque)
+{
+ struct qemu_laio_state *s = opaque;
+ struct qemu_laiocb *laiocb, *next;
+ int res = 0;
+
+ QLIST_FOREACH_SAFE (laiocb, &s->completed_reqs, node, next) {
+ if (laiocb->async_context_id == get_async_context_id()) {
+ qemu_laio_process_completion(s, laiocb);
+ QLIST_REMOVE(laiocb, node);
+ res = 1;
+ }
+ }
+
+ return res;
+}
+
+/*
+ * Puts a request in the completion queue so that its callback is called the
+ * next time when it's possible. If we already are in the right AsyncContext,
+ * the request is completed immediately instead.
+ */
+static void qemu_laio_enqueue_completed(struct qemu_laio_state *s,
+ struct qemu_laiocb* laiocb)
+{
+ if (laiocb->async_context_id == get_async_context_id()) {
+ qemu_laio_process_completion(s, laiocb);
+ } else {
+ QLIST_INSERT_HEAD(&s->completed_reqs, laiocb, node);
+ }
+}
+