Patchwork [RFC,10/12] block: Add coroutine support to synchronous I/O functions

login
register
mail settings
Submitter Stefan Hajnoczi
Date Jan. 22, 2011, 9:29 a.m.
Message ID <1295688567-25496-11-git-send-email-stefanha@linux.vnet.ibm.com>
Download mbox | patch
Permalink /patch/79985/
State New
Headers show

Comments

Stefan Hajnoczi - Jan. 22, 2011, 9:29 a.m.
Implement transparent support for the following synchronous I/O
functions to be called from coroutines:

bdrv_read()
bdrv_write()
bdrv_pread()
bdrv_pwrite()
bdrv_pwrite_sync()
bdrv_write_sync()
bdrv_flush()

These functions will use asynchronous I/O behind the scenes but
otherwise behave the same as the truly synchronous implementations.

This change allows synchronous I/O code in QEMU to just work in a
coroutine.

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
---
 block.c |   42 ++++++++++++++++++++++++++++++++++++++++++
 block.h |    1 +
 2 files changed, 43 insertions(+), 0 deletions(-)

Patch

diff --git a/block.c b/block.c
index ecb6538..f955ded 100644
--- a/block.c
+++ b/block.c
@@ -924,6 +924,17 @@  int bdrv_read(BlockDriverState *bs, int64_t sector_num,
 {
     BlockDriver *drv = bs->drv;
 
+    if (qemu_in_coroutine()) {
+        QEMUIOVector qiov;
+        struct iovec iov = {
+            .iov_base = buf,
+            .iov_len = nb_sectors * BDRV_SECTOR_SIZE,
+        };
+
+        qemu_iovec_init_external(&qiov, &iov, 1);
+        return bdrv_co_readv(bs, sector_num, &qiov, nb_sectors);
+    }
+
     if (!drv)
         return -ENOMEDIUM;
     if (bdrv_check_request(bs, sector_num, nb_sectors))
@@ -970,6 +981,18 @@  int bdrv_write(BlockDriverState *bs, int64_t sector_num,
                const uint8_t *buf, int nb_sectors)
 {
     BlockDriver *drv = bs->drv;
+
+    if (qemu_in_coroutine()) {
+        QEMUIOVector qiov;
+        struct iovec iov = {
+            .iov_base = (void *)buf,
+            .iov_len = nb_sectors * BDRV_SECTOR_SIZE,
+        };
+
+        qemu_iovec_init_external(&qiov, &iov, 1);
+        return bdrv_co_writev(bs, sector_num, &qiov, nb_sectors);
+    }
+
     if (!bs->drv)
         return -ENOMEDIUM;
     if (bs->read_only)
@@ -1471,6 +1494,10 @@  const char *bdrv_get_device_name(BlockDriverState *bs)
 
 int bdrv_flush(BlockDriverState *bs)
 {
+    if (qemu_in_coroutine()) {
+        return bdrv_co_flush(bs);
+    }
+
     if (bs->open_flags & BDRV_O_NO_FLUSH) {
         return 0;
     }
@@ -2664,6 +2691,21 @@  int coroutine_fn bdrv_co_writev(BlockDriverState *bs, int64_t sector_num,
     return bdrv_co_io(bs, sector_num, iov, nb_sectors, 1);
 }
 
+int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
+{
+    CoroutineIOCompletion co = {
+        .coroutine = qemu_coroutine_self(),
+    };
+    BlockDriverAIOCB *acb;
+
+    acb = bdrv_aio_flush(bs, bdrv_co_complete, &co);
+    if (!acb) {
+        return -EIO;
+    }
+    qemu_coroutine_yield(NULL);
+    return co.ret;
+}
+
 /**************************************************************/
 /* removable device support */
 
diff --git a/block.h b/block.h
index 472e3d4..bced0c5 100644
--- a/block.h
+++ b/block.h
@@ -126,6 +126,7 @@  int coroutine_fn bdrv_co_readv(BlockDriverState *bs, int64_t sector_num,
                                QEMUIOVector *iov, int nb_sectors);
 int coroutine_fn bdrv_co_writev(BlockDriverState *bs, int64_t sector_num,
                                 QEMUIOVector *iov, int nb_sectors);
+int coroutine_fn bdrv_co_flush(BlockDriverState *bs);
 
 typedef struct BlockRequest {
     /* Fields to be filled by multiwrite caller */