qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 1/3] block: introduce IO queue APIs


From: Ming Lei
Subject: [Qemu-devel] [PATCH 1/3] block: introduce IO queue APIs
Date: Mon, 30 Jun 2014 17:49:14 +0800

This patch introduces IO queue related APIs so that following
patches can support queuing I/O requests and submitting them
at batch for improving I/O performance.

Signed-off-by: Ming Lei <address@hidden>
---
 aio-posix.c               |   13 ++++++++
 block.c                   |   78 +++++++++++++++++++++++++++++++++++++++++++++
 include/block/aio.h       |   12 +++++++
 include/block/block.h     |    6 ++++
 include/block/block_int.h |    3 ++
 5 files changed, 112 insertions(+)

diff --git a/aio-posix.c b/aio-posix.c
index f921d4f..3e065c1 100644
--- a/aio-posix.c
+++ b/aio-posix.c
@@ -240,3 +240,16 @@ bool aio_poll(AioContext *ctx, bool blocking)
 
     return progress;
 }
+
+/* IO queue support */
+void aio_init_io_queue(AioContext *ctx, unsigned int size)
+{
+    ctx->io_queue.iocbs = g_new0(void *, size);
+    ctx->io_queue.size = size;
+    ctx->io_queue.idx = 0;
+}
+
+void aio_exit_io_queue(AioContext *ctx)
+{
+    g_free(ctx->io_queue.iocbs);
+}
diff --git a/block.c b/block.c
index 217f523..c4a6f8b 100644
--- a/block.c
+++ b/block.c
@@ -1910,6 +1910,7 @@ void bdrv_drain_all(void)
             bool bs_busy;
 
             aio_context_acquire(aio_context);
+            bdrv_io_unplug(bs);
             bdrv_start_throttled_reqs(bs);
             bs_busy = bdrv_requests_pending(bs);
             bs_busy |= aio_poll(aio_context, bs_busy);
@@ -5774,3 +5775,80 @@ bool bdrv_is_first_non_filter(BlockDriverState 
*candidate)
 
     return false;
 }
+
+/* IO queue APIs */
+void bdrv_init_io_queue(BlockDriverState *bs, unsigned int size)
+{
+    aio_init_io_queue(bs->aio_context, size);
+}
+
+void bdrv_exit_io_queue(BlockDriverState *bs)
+{
+    aio_exit_io_queue(bs->aio_context);
+}
+
+/* We think one block driver supports feature of io queue if
+ * they implement callback of .bdrv_submit_io_queue
+ */
+static bool __bdrv_support_io_queue(BlockDriverState *bs)
+{
+    if (bs && bs->drv && bs->drv->bdrv_submit_io_queue)
+        return true;
+    return false;
+}
+bool bdrv_support_io_queue(BlockDriverState *bs)
+{
+    if (__bdrv_support_io_queue(bs->file))
+        return true;
+    if (__bdrv_support_io_queue(bs->backing_hd))
+        return true;
+    return false;
+}
+
+static void __bdrv_io_unplug(BlockDriverState *bs)
+{
+    if (!bdrv_support_io_queue(bs))
+        return;
+
+    if (!bs->aio_context->io_queue.idx)
+        return;
+
+    if (__bdrv_support_io_queue(bs->file))
+        bs->file->drv->bdrv_submit_io_queue(bs->file);
+    if (__bdrv_support_io_queue(bs->backing_hd))
+        bs->backing_hd->drv->bdrv_submit_io_queue(bs->backing_hd);
+    bs->aio_context->io_queue.idx = 0;
+}
+
+/* BlockDriver may call this function for queuing current IO request
+ * represented by iocb to io_queue, and will submit them at batch.
+ */
+void bdrv_queue_io(BlockDriverState *bs, void *iocb)
+{
+    unsigned int idx = bs->aio_context->io_queue.idx;
+
+    bs->aio_context->io_queue.iocbs[idx++] = iocb;
+    bs->aio_context->io_queue.idx = idx;
+
+    /* unplug immediately if queue is full */
+    if (idx == bs->aio_context->io_queue.size)
+        __bdrv_io_unplug(bs);
+}
+
+/* Block device calls this function to let driver queue IO request
+ * and submit them at batch later, but it is just a hint because
+ * block driver may not support the feature.
+ */
+void bdrv_io_plug(BlockDriverState *bs)
+{
+    bs->aio_context->io_plugged = true;
+}
+
+/* Block device calls this function to ask driver to submit
+ * all requests in io queue immediatelly.
+ */
+void bdrv_io_unplug(BlockDriverState *bs)
+{
+    __bdrv_io_unplug(bs);
+    bs->aio_context->io_plugged = false;
+}
diff --git a/include/block/aio.h b/include/block/aio.h
index a92511b..b7fdcfb 100644
--- a/include/block/aio.h
+++ b/include/block/aio.h
@@ -45,6 +45,12 @@ typedef struct AioHandler AioHandler;
 typedef void QEMUBHFunc(void *opaque);
 typedef void IOHandler(void *opaque);
 
+typedef struct AioIOQueue {
+    void **iocbs;
+    unsigned int size;
+    unsigned int idx;
+} AioIOQueue;
+
 struct AioContext {
     GSource source;
 
@@ -81,6 +87,10 @@ struct AioContext {
 
     /* TimerLists for calling timers - one per clock type */
     QEMUTimerListGroup tlg;
+
+    /* IOQueue support */
+    AioIOQueue io_queue;
+    bool io_plugged;
 };
 
 /**
@@ -307,4 +317,6 @@ static inline void aio_timer_init(AioContext *ctx,
     timer_init(ts, ctx->tlg.tl[type], scale, cb, opaque);
 }
 
+void aio_init_io_queue(AioContext *ctx, unsigned int size);
+void aio_exit_io_queue(AioContext *ctx);
 #endif
diff --git a/include/block/block.h b/include/block/block.h
index d0baf4f..702b79a 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -578,4 +578,10 @@ AioContext *bdrv_get_aio_context(BlockDriverState *bs);
  */
 void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context);
 
+void bdrv_init_io_queue(BlockDriverState *bs, unsigned int size);
+void bdrv_exit_io_queue(BlockDriverState *bs);
+bool bdrv_support_io_queue(BlockDriverState *bs);
+void bdrv_queue_io(BlockDriverState *bs, void *iocb);
+void bdrv_io_plug(BlockDriverState *bs);
+void bdrv_io_unplug(BlockDriverState *bs);
 #endif
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 715c761..a24fe2d 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -257,6 +257,9 @@ struct BlockDriver {
     void (*bdrv_attach_aio_context)(BlockDriverState *bs,
                                     AioContext *new_context);
 
+    /* io_queue */
+    int (*bdrv_submit_io_queue)(BlockDriverState *bs);
+
     QLIST_ENTRY(BlockDriver) list;
 };
 
-- 
1.7.9.5




reply via email to

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