qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC PATCH 1/9] block: Add bdrv_aio_cancel_async


From: Fam Zheng
Subject: [Qemu-devel] [RFC PATCH 1/9] block: Add bdrv_aio_cancel_async
Date: Thu, 21 Aug 2014 19:56:48 +0800

This is the async version of bdrv_aio_cancel, which doesn't block the
caller. It guarantees that the cb is called either before returning or
some time later.

Signed-off-by: Fam Zheng <address@hidden>
---
 block.c               | 35 +++++++++++++++++++++++++++++++++++
 include/block/aio.h   |  2 ++
 include/block/block.h |  1 +
 3 files changed, 38 insertions(+)

diff --git a/block.c b/block.c
index 6fa0201..1cc8926 100644
--- a/block.c
+++ b/block.c
@@ -4607,6 +4607,41 @@ void bdrv_aio_cancel(BlockDriverAIOCB *acb)
     acb->aiocb_info->cancel(acb);
 }
 
+static void bdrv_aio_cancel_async_cb(void *opaque, int ret)
+{
+    BlockDriverAIOCB *acb = opaque;
+
+    acb->cb     = acb->cancel_acb_save->cb;
+    acb->opaque = acb->cancel_acb_save->opaque;
+    g_free(acb->cancel_acb_save);
+    acb->cancel_acb_save = NULL;
+    acb->cb(acb->opaque, -ECANCELED);
+}
+
+/* Async version of aio cancel. The caller is not blocked if the acb implements
+ * cancel_async, otherwise fall back to bdrv_aio_cancel. In both cases, acb->cb
+ * is guarenteed to be called, before or after function returns. */
+void bdrv_aio_cancel_async(BlockDriverAIOCB *acb)
+{
+    if (acb->aiocb_info->cancel_async) {
+        acb->aiocb_info->cancel_async(acb);
+    } else {
+        BlockDriverAIOCB *save = g_new(BlockDriverAIOCB, 1);
+        save->cb               = acb->cb;
+        save->opaque           = acb->opaque;
+        acb->cb                = bdrv_aio_cancel_async_cb;
+        acb->opaque            = acb;
+        acb->cancel_acb_save   = save;
+
+        /* Use the synchronous version and hope our cb is called. */
+        acb->aiocb_info->cancel(acb);
+        if (acb->cancel_acb_save) {
+            /* cb is not called yet, let's call it */
+            bdrv_aio_cancel_async_cb(acb->opaque, -ECANCELED);
+        }
+    }
+}
+
 /**************************************************************/
 /* async block device emulation */
 
diff --git a/include/block/aio.h b/include/block/aio.h
index c23de3c..fcc5c87 100644
--- a/include/block/aio.h
+++ b/include/block/aio.h
@@ -27,6 +27,7 @@ typedef void BlockDriverCompletionFunc(void *opaque, int ret);
 
 typedef struct AIOCBInfo {
     void (*cancel)(BlockDriverAIOCB *acb);
+    void (*cancel_async)(BlockDriverAIOCB *acb);
     size_t aiocb_size;
 } AIOCBInfo;
 
@@ -35,6 +36,7 @@ struct BlockDriverAIOCB {
     BlockDriverState *bs;
     BlockDriverCompletionFunc *cb;
     void *opaque;
+    BlockDriverAIOCB *cancel_acb_save;
 };
 
 void *qemu_aio_get(const AIOCBInfo *aiocb_info, BlockDriverState *bs,
diff --git a/include/block/block.h b/include/block/block.h
index e94b701..ed2a3a8 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -335,6 +335,7 @@ BlockDriverAIOCB *bdrv_aio_discard(BlockDriverState *bs,
                                    int64_t sector_num, int nb_sectors,
                                    BlockDriverCompletionFunc *cb, void 
*opaque);
 void bdrv_aio_cancel(BlockDriverAIOCB *acb);
+void bdrv_aio_cancel_async(BlockDriverAIOCB *acb);
 
 typedef struct BlockRequest {
     /* Fields to be filled by multiwrite caller */
-- 
2.0.3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]