This patch adds dequeue_work threadlet API and shows how the paio_cancel changes to dequeue_work.
Signed-off-by: Arun R Bharadwaj <a...@linux.vnet.ibm.com> --- posix-aio-compat.c | 46 ++++++++++++++++++++++++++-------------------- 1 files changed, 26 insertions(+), 20 deletions(-) diff --git a/posix-aio-compat.c b/posix-aio-compat.c index ff6e08b..8f1a9b6 100644 --- a/posix-aio-compat.c +++ b/posix-aio-compat.c @@ -574,33 +574,39 @@ static void paio_remove(struct qemu_paiocb *acb) } } -static void paio_cancel(BlockDriverAIOCB *blockacb) +/** + * dequeue_work: Cancel a task queued on the global queue. + * @work: Contains the information of the task that needs to be cancelled. + * + * Returns: 0 if the task is successfully cancelled. + * 1 otherwise. + */ +static int dequeue_work(ThreadletWork *work) { - struct qemu_paiocb *acb = (struct qemu_paiocb *)blockacb; - int active = 0; + int ret = 1; qemu_mutex_lock(&globalqueue.lock); - if (!acb->active) { - QTAILQ_REMOVE(&globalqueue.request_list, &acb->work, node); - acb->ret = -ECANCELED; - } else if (acb->ret == -EINPROGRESS) { - active = 1; - } + QTAILQ_REMOVE(&globalqueue.request_list, work, node); + ret = 0; qemu_mutex_unlock(&globalqueue.lock); - qemu_mutex_lock(&aiocb_mutex); - if (!active) { - acb->ret = -ECANCELED; - } else { - while (acb->ret == -EINPROGRESS) { - /* - * fail safe: if the aio could not be canceled, - * we wait for it - */ - qemu_cond_wait(&aiocb_completion, &aiocb_mutex); + return ret; +} + +static void paio_cancel(BlockDriverAIOCB *blockacb) +{ + struct qemu_paiocb *acb = (struct qemu_paiocb *)blockacb; + if (!acb->active) { + if (dequeue_work(&acb->work) != 0) { + /* Wait for running work item to complete */ + qemu_mutex_lock(&aiocb_mutex); + while (acb->ret == -EINPROGRESS) { + qemu_cond_wait(&aiocb_completion, &aiocb_mutex); + } + qemu_mutex_unlock(&aiocb_mutex); } } - qemu_mutex_unlock(&aiocb_mutex); + paio_remove(acb); }