All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: anthony@codemonkey.ws
Cc: kwolf@redhat.com, qemu-devel@nongnu.org
Subject: [Qemu-devel] [PULL 06/42] gluster: Convert aio routines into coroutines
Date: Wed, 15 Jan 2014 11:22:19 +0100	[thread overview]
Message-ID: <1389781375-11774-7-git-send-email-kwolf@redhat.com> (raw)
In-Reply-To: <1389781375-11774-1-git-send-email-kwolf@redhat.com>

From: Bharata B Rao <bharata@linux.vnet.ibm.com>

Convert the read, write, flush and discard implementations from aio-based
ones to coroutine based ones.

Signed-off-by: Bharata B Rao <bharata@linux.vnet.ibm.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/gluster.c | 221 +++++++++++++++++++-------------------------------------
 1 file changed, 74 insertions(+), 147 deletions(-)

diff --git a/block/gluster.c b/block/gluster.c
index 563d497..f9aea0e 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -21,19 +21,15 @@
 #include "qemu/uri.h"
 
 typedef struct GlusterAIOCB {
-    BlockDriverAIOCB common;
     int64_t size;
     int ret;
-    bool *finished;
     QEMUBH *bh;
+    Coroutine *coroutine;
 } GlusterAIOCB;
 
 typedef struct BDRVGlusterState {
     struct glfs *glfs;
-    int fds[2];
     struct glfs_fd *fd;
-    int event_reader_pos;
-    GlusterAIOCB *event_acb;
 } BDRVGlusterState;
 
 #define GLUSTER_FD_READ  0
@@ -231,46 +227,13 @@ out:
     return NULL;
 }
 
-static void qemu_gluster_complete_aio(GlusterAIOCB *acb, BDRVGlusterState *s)
+static void qemu_gluster_complete_aio(void *opaque)
 {
-    int ret;
-    bool *finished = acb->finished;
-    BlockDriverCompletionFunc *cb = acb->common.cb;
-    void *opaque = acb->common.opaque;
-
-    if (!acb->ret || acb->ret == acb->size) {
-        ret = 0; /* Success */
-    } else if (acb->ret < 0) {
-        ret = acb->ret; /* Read/Write failed */
-    } else {
-        ret = -EIO; /* Partial read/write - fail it */
-    }
+    GlusterAIOCB *acb = (GlusterAIOCB *)opaque;
 
-    qemu_aio_release(acb);
-    cb(opaque, ret);
-    if (finished) {
-        *finished = true;
-    }
-}
-
-static void qemu_gluster_aio_event_reader(void *opaque)
-{
-    BDRVGlusterState *s = opaque;
-    ssize_t ret;
-
-    do {
-        char *p = (char *)&s->event_acb;
-
-        ret = read(s->fds[GLUSTER_FD_READ], p + s->event_reader_pos,
-                   sizeof(s->event_acb) - s->event_reader_pos);
-        if (ret > 0) {
-            s->event_reader_pos += ret;
-            if (s->event_reader_pos == sizeof(s->event_acb)) {
-                s->event_reader_pos = 0;
-                qemu_gluster_complete_aio(s->event_acb, s);
-            }
-        }
-    } while (ret < 0 && errno == EINTR);
+    qemu_bh_delete(acb->bh);
+    acb->bh = NULL;
+    qemu_coroutine_enter(acb->coroutine, NULL);
 }
 
 /* TODO Convert to fine grained options */
@@ -309,7 +272,6 @@ static int qemu_gluster_open(BlockDriverState *bs,  QDict *options,
 
     filename = qemu_opt_get(opts, "filename");
 
-
     s->glfs = qemu_gluster_init(gconf, filename);
     if (!s->glfs) {
         ret = -errno;
@@ -329,17 +291,7 @@ static int qemu_gluster_open(BlockDriverState *bs,  QDict *options,
     s->fd = glfs_open(s->glfs, gconf->image, open_flags);
     if (!s->fd) {
         ret = -errno;
-        goto out;
-    }
-
-    ret = qemu_pipe(s->fds);
-    if (ret < 0) {
-        ret = -errno;
-        goto out;
     }
-    fcntl(s->fds[GLUSTER_FD_READ], F_SETFL, O_NONBLOCK);
-    qemu_aio_set_fd_handler(s->fds[GLUSTER_FD_READ],
-        qemu_gluster_aio_event_reader, NULL, s);
 
 out:
     qemu_opts_del(opts);
@@ -398,58 +350,37 @@ out:
     return ret;
 }
 
-static void qemu_gluster_aio_cancel(BlockDriverAIOCB *blockacb)
-{
-    GlusterAIOCB *acb = (GlusterAIOCB *)blockacb;
-    bool finished = false;
-
-    acb->finished = &finished;
-    while (!finished) {
-        qemu_aio_wait();
-    }
-}
-
-static const AIOCBInfo gluster_aiocb_info = {
-    .aiocb_size = sizeof(GlusterAIOCB),
-    .cancel = qemu_gluster_aio_cancel,
-};
-
+/*
+ * AIO callback routine called from GlusterFS thread.
+ */
 static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg)
 {
     GlusterAIOCB *acb = (GlusterAIOCB *)arg;
-    BlockDriverState *bs = acb->common.bs;
-    BDRVGlusterState *s = bs->opaque;
-    int retval;
-
-    acb->ret = ret;
-    retval = qemu_write_full(s->fds[GLUSTER_FD_WRITE], &acb, sizeof(acb));
-    if (retval != sizeof(acb)) {
-        /*
-         * Gluster AIO callback thread failed to notify the waiting
-         * QEMU thread about IO completion.
-         */
-        error_report("Gluster AIO completion failed: %s", strerror(errno));
-        abort();
+
+    if (!ret || ret == acb->size) {
+        acb->ret = 0; /* Success */
+    } else if (ret < 0) {
+        acb->ret = ret; /* Read/Write failed */
+    } else {
+        acb->ret = -EIO; /* Partial read/write - fail it */
     }
+
+    acb->bh = qemu_bh_new(qemu_gluster_complete_aio, acb);
+    qemu_bh_schedule(acb->bh);
 }
 
-static BlockDriverAIOCB *qemu_gluster_aio_rw(BlockDriverState *bs,
-        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque, int write)
+static coroutine_fn int qemu_gluster_co_rw(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors, QEMUIOVector *qiov, int write)
 {
     int ret;
-    GlusterAIOCB *acb;
+    GlusterAIOCB *acb = g_slice_new(GlusterAIOCB);
     BDRVGlusterState *s = bs->opaque;
-    size_t size;
-    off_t offset;
+    size_t size = nb_sectors * BDRV_SECTOR_SIZE;
+    off_t offset = sector_num * BDRV_SECTOR_SIZE;
 
-    offset = sector_num * BDRV_SECTOR_SIZE;
-    size = nb_sectors * BDRV_SECTOR_SIZE;
-
-    acb = qemu_aio_get(&gluster_aiocb_info, bs, cb, opaque);
     acb->size = size;
     acb->ret = 0;
-    acb->finished = NULL;
+    acb->coroutine = qemu_coroutine_self();
 
     if (write) {
         ret = glfs_pwritev_async(s->fd, qiov->iov, qiov->niov, offset, 0,
@@ -460,13 +391,16 @@ static BlockDriverAIOCB *qemu_gluster_aio_rw(BlockDriverState *bs,
     }
 
     if (ret < 0) {
+        ret = -errno;
         goto out;
     }
-    return &acb->common;
+
+    qemu_coroutine_yield();
+    ret = acb->ret;
 
 out:
-    qemu_aio_release(acb);
-    return NULL;
+    g_slice_free(GlusterAIOCB, acb);
+    return ret;
 }
 
 static int qemu_gluster_truncate(BlockDriverState *bs, int64_t offset)
@@ -482,71 +416,68 @@ static int qemu_gluster_truncate(BlockDriverState *bs, int64_t offset)
     return 0;
 }
 
-static BlockDriverAIOCB *qemu_gluster_aio_readv(BlockDriverState *bs,
-        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque)
+static coroutine_fn int qemu_gluster_co_readv(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
 {
-    return qemu_gluster_aio_rw(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
+    return qemu_gluster_co_rw(bs, sector_num, nb_sectors, qiov, 0);
 }
 
-static BlockDriverAIOCB *qemu_gluster_aio_writev(BlockDriverState *bs,
-        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque)
+static coroutine_fn int qemu_gluster_co_writev(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
 {
-    return qemu_gluster_aio_rw(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
+    return qemu_gluster_co_rw(bs, sector_num, nb_sectors, qiov, 1);
 }
 
-static BlockDriverAIOCB *qemu_gluster_aio_flush(BlockDriverState *bs,
-        BlockDriverCompletionFunc *cb, void *opaque)
+static coroutine_fn int qemu_gluster_co_flush_to_disk(BlockDriverState *bs)
 {
     int ret;
-    GlusterAIOCB *acb;
+    GlusterAIOCB *acb = g_slice_new(GlusterAIOCB);
     BDRVGlusterState *s = bs->opaque;
 
-    acb = qemu_aio_get(&gluster_aiocb_info, bs, cb, opaque);
     acb->size = 0;
     acb->ret = 0;
-    acb->finished = NULL;
+    acb->coroutine = qemu_coroutine_self();
 
     ret = glfs_fsync_async(s->fd, &gluster_finish_aiocb, acb);
     if (ret < 0) {
+        ret = -errno;
         goto out;
     }
-    return &acb->common;
+
+    qemu_coroutine_yield();
+    ret = acb->ret;
 
 out:
-    qemu_aio_release(acb);
-    return NULL;
+    g_slice_free(GlusterAIOCB, acb);
+    return ret;
 }
 
 #ifdef CONFIG_GLUSTERFS_DISCARD
-static BlockDriverAIOCB *qemu_gluster_aio_discard(BlockDriverState *bs,
-        int64_t sector_num, int nb_sectors, BlockDriverCompletionFunc *cb,
-        void *opaque)
+static coroutine_fn int qemu_gluster_co_discard(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors)
 {
     int ret;
-    GlusterAIOCB *acb;
+    GlusterAIOCB *acb = g_slice_new(GlusterAIOCB);
     BDRVGlusterState *s = bs->opaque;
-    size_t size;
-    off_t offset;
-
-    offset = sector_num * BDRV_SECTOR_SIZE;
-    size = nb_sectors * BDRV_SECTOR_SIZE;
+    size_t size = nb_sectors * BDRV_SECTOR_SIZE;
+    off_t offset = sector_num * BDRV_SECTOR_SIZE;
 
-    acb = qemu_aio_get(&gluster_aiocb_info, bs, cb, opaque);
     acb->size = 0;
     acb->ret = 0;
-    acb->finished = NULL;
+    acb->coroutine = qemu_coroutine_self();
 
     ret = glfs_discard_async(s->fd, offset, size, &gluster_finish_aiocb, acb);
     if (ret < 0) {
+        ret = -errno;
         goto out;
     }
-    return &acb->common;
+
+    qemu_coroutine_yield();
+    ret = acb->ret;
 
 out:
-    qemu_aio_release(acb);
-    return NULL;
+    g_slice_free(GlusterAIOCB, acb);
+    return ret;
 }
 #endif
 
@@ -581,10 +512,6 @@ static void qemu_gluster_close(BlockDriverState *bs)
 {
     BDRVGlusterState *s = bs->opaque;
 
-    close(s->fds[GLUSTER_FD_READ]);
-    close(s->fds[GLUSTER_FD_WRITE]);
-    qemu_aio_set_fd_handler(s->fds[GLUSTER_FD_READ], NULL, NULL, NULL);
-
     if (s->fd) {
         glfs_close(s->fd);
         s->fd = NULL;
@@ -618,12 +545,12 @@ static BlockDriver bdrv_gluster = {
     .bdrv_getlength               = qemu_gluster_getlength,
     .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
     .bdrv_truncate                = qemu_gluster_truncate,
-    .bdrv_aio_readv               = qemu_gluster_aio_readv,
-    .bdrv_aio_writev              = qemu_gluster_aio_writev,
-    .bdrv_aio_flush               = qemu_gluster_aio_flush,
+    .bdrv_co_readv                = qemu_gluster_co_readv,
+    .bdrv_co_writev               = qemu_gluster_co_writev,
+    .bdrv_co_flush_to_disk        = qemu_gluster_co_flush_to_disk,
     .bdrv_has_zero_init           = qemu_gluster_has_zero_init,
 #ifdef CONFIG_GLUSTERFS_DISCARD
-    .bdrv_aio_discard             = qemu_gluster_aio_discard,
+    .bdrv_co_discard              = qemu_gluster_co_discard,
 #endif
     .create_options               = qemu_gluster_create_options,
 };
@@ -639,12 +566,12 @@ static BlockDriver bdrv_gluster_tcp = {
     .bdrv_getlength               = qemu_gluster_getlength,
     .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
     .bdrv_truncate                = qemu_gluster_truncate,
-    .bdrv_aio_readv               = qemu_gluster_aio_readv,
-    .bdrv_aio_writev              = qemu_gluster_aio_writev,
-    .bdrv_aio_flush               = qemu_gluster_aio_flush,
+    .bdrv_co_readv                = qemu_gluster_co_readv,
+    .bdrv_co_writev               = qemu_gluster_co_writev,
+    .bdrv_co_flush_to_disk        = qemu_gluster_co_flush_to_disk,
     .bdrv_has_zero_init           = qemu_gluster_has_zero_init,
 #ifdef CONFIG_GLUSTERFS_DISCARD
-    .bdrv_aio_discard             = qemu_gluster_aio_discard,
+    .bdrv_co_discard              = qemu_gluster_co_discard,
 #endif
     .create_options               = qemu_gluster_create_options,
 };
@@ -660,12 +587,12 @@ static BlockDriver bdrv_gluster_unix = {
     .bdrv_getlength               = qemu_gluster_getlength,
     .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
     .bdrv_truncate                = qemu_gluster_truncate,
-    .bdrv_aio_readv               = qemu_gluster_aio_readv,
-    .bdrv_aio_writev              = qemu_gluster_aio_writev,
-    .bdrv_aio_flush               = qemu_gluster_aio_flush,
+    .bdrv_co_readv                = qemu_gluster_co_readv,
+    .bdrv_co_writev               = qemu_gluster_co_writev,
+    .bdrv_co_flush_to_disk        = qemu_gluster_co_flush_to_disk,
     .bdrv_has_zero_init           = qemu_gluster_has_zero_init,
 #ifdef CONFIG_GLUSTERFS_DISCARD
-    .bdrv_aio_discard             = qemu_gluster_aio_discard,
+    .bdrv_co_discard              = qemu_gluster_co_discard,
 #endif
     .create_options               = qemu_gluster_create_options,
 };
@@ -681,12 +608,12 @@ static BlockDriver bdrv_gluster_rdma = {
     .bdrv_getlength               = qemu_gluster_getlength,
     .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
     .bdrv_truncate                = qemu_gluster_truncate,
-    .bdrv_aio_readv               = qemu_gluster_aio_readv,
-    .bdrv_aio_writev              = qemu_gluster_aio_writev,
-    .bdrv_aio_flush               = qemu_gluster_aio_flush,
+    .bdrv_co_readv                = qemu_gluster_co_readv,
+    .bdrv_co_writev               = qemu_gluster_co_writev,
+    .bdrv_co_flush_to_disk        = qemu_gluster_co_flush_to_disk,
     .bdrv_has_zero_init           = qemu_gluster_has_zero_init,
 #ifdef CONFIG_GLUSTERFS_DISCARD
-    .bdrv_aio_discard             = qemu_gluster_aio_discard,
+    .bdrv_co_discard              = qemu_gluster_co_discard,
 #endif
     .create_options               = qemu_gluster_create_options,
 };
-- 
1.8.1.4

  parent reply	other threads:[~2014-01-15 10:23 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 01/42] rbd: switch from pipe to QEMUBH completion notification Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 02/42] qemu-iotests: Introduce _unsupported_imgopts Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 03/42] qemu-iotests: Add _unsupported_imgopts for vmdk subformats Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 04/42] qemu-iotests: Clean up all extents for vmdk Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 05/42] block/iscsi: return -ENOMEM if an async call fails immediately Kevin Wolf
2014-01-15 10:22 ` Kevin Wolf [this message]
2014-01-15 10:22 ` [Qemu-devel] [PULL 07/42] gluster: Implement .bdrv_co_write_zeroes for gluster Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 08/42] gluster: Add support for creating zero-filled image Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 09/42] sheepdog: fix clone operation by 'qemu-img create -b' Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 10/42] qtest: Fix the bug about disable vnc causes "make check" fail Kevin Wolf
2014-01-17 15:06   ` Andreas Färber
2014-01-18 11:54     ` Kewei Yu
2014-01-26  0:06       ` Andreas Färber
2014-01-26  8:04         ` Kewei Yu
2014-01-15 10:22 ` [Qemu-devel] [PULL 11/42] docs: qcow2 compat=1.1 is now the default Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 12/42] vmdk: Fix big flat extent IO Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 13/42] readline: decouple readline from the monitor Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 14/42] readline: move readline to a generic location Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 15/42] osdep: add qemu_set_tty_echo() Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 16/42] qemu-io: use readline.c Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 17/42] qemu-io: add command completion Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 18/42] blkdebug: Use errp for read_config() Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 19/42] blkdebug: Don't require sophisticated filename Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 20/42] qdict: Add qdict_array_split() Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 21/42] qapi: extend qdict_flatten() for QLists Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 22/42] qemu-option: Add qemu_config_parse_qdict() Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 23/42] blkdebug: Always call read_config() Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 24/42] blkdebug: Use command-line in read_config() Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 25/42] block: Allow reference for bdrv_file_open() Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 26/42] block: Pass reference to bdrv_file_open() Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 27/42] block: Allow block devices without files Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 28/42] block: Add bdrv_open_image() Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 29/42] block: Use bdrv_open_image() in bdrv_open() Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 30/42] block: Allow recursive "file"s Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 31/42] blockdev: Move "file" to legacy_opts Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 32/42] blkdebug: Allow command-line file configuration Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 33/42] blkverify: Allow command-line configuration Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 34/42] blkverify: Don't require protocol filename Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 35/42] qapi: Add "errno" to the list of polluted words Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 36/42] qapi: QMP interface for blkdebug and blkverify Kevin Wolf
2014-01-15 15:19   ` Eric Blake
2014-01-15 17:11     ` Paolo Bonzini
2014-01-16 10:03     ` Kevin Wolf
2014-01-17 15:01       ` Andreas Färber
2014-01-15 10:22 ` [Qemu-devel] [PULL 37/42] qemu-io: Make filename optional Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 38/42] tests: Add test for qdict_array_split() Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 39/42] tests: Add test for qdict_flatten() Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 40/42] iotests: Test new blkdebug/blkverify interface Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 41/42] iotests: Test file format nesting Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 42/42] block: fix backing file segfault Kevin Wolf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1389781375-11774-7-git-send-email-kwolf@redhat.com \
    --to=kwolf@redhat.com \
    --cc=anthony@codemonkey.ws \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.