All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
To: qemu-devel@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>,
	Anthony Liguori <aliguori@us.ibm.com>,
	Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Subject: [Qemu-devel] [RFC][PATCH 12/12] qcow2: Serialize all requests
Date: Sat, 22 Jan 2011 09:29:27 +0000	[thread overview]
Message-ID: <1295688567-25496-13-git-send-email-stefanha@linux.vnet.ibm.com> (raw)
In-Reply-To: <1295688567-25496-1-git-send-email-stefanha@linux.vnet.ibm.com>

QCOW2 with coroutines is not safe because synchronous code paths are no
longer guaranteed to execute without interference from pending requests.
A blocking call like bdrv_pread() causes the coroutine to yield and
another request can be processed during that time, causing to race
conditions or interference between pending requests.

The simple solution is to serialize all requests.  This is bad for
performance and a fine-grained solution needs to be implemented in
future patches.

Using this patch, QCOW2 with coroutines can reliably install a RHEL6 VM
with a virtio-blk disk.

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
---
 block/qcow2.c |   21 ++++++++++++++++++++-
 block/qcow2.h |    5 +++--
 2 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index 4b33ef3..0cea0e8 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -231,6 +231,7 @@ static int qcow2_open(BlockDriverState *bs, int flags)
     }
 
     QLIST_INIT(&s->cluster_allocs);
+    QTAILQ_INIT(&s->request_list);
 
     /* read qcow2 extensions */
     if (header.backing_file_offset) {
@@ -365,6 +366,7 @@ typedef struct QCowAIOCB {
     QEMUBH *bh;
     QCowL2Meta l2meta;
     QLIST_ENTRY(QCowAIOCB) next_depend;
+    QTAILQ_ENTRY(QCowAIOCB) next_request;
     Coroutine *coroutine;
     int ret; /* return code for user callback */
 } QCowAIOCB;
@@ -385,11 +387,20 @@ static AIOPool qcow2_aio_pool = {
 static void qcow2_aio_bh(void *opaque)
 {
     QCowAIOCB *acb = opaque;
+    BDRVQcowState *s = acb->common.bs->opaque;
+
     qemu_bh_delete(acb->bh);
     acb->bh = NULL;
     acb->common.cb(acb->common.opaque, acb->ret);
     qemu_iovec_destroy(&acb->hd_qiov);
+    QTAILQ_REMOVE(&s->request_list, acb, next_request);
     qemu_aio_release(acb);
+
+    /* Start next request */
+    if (!QTAILQ_EMPTY(&s->request_list)) {
+        acb = QTAILQ_FIRST(&s->request_list);
+        qemu_coroutine_enter(acb->coroutine, acb);
+    }
 }
 
 static int qcow2_schedule_bh(QEMUBHFunc *cb, QCowAIOCB *acb)
@@ -548,8 +559,10 @@ static BlockDriverAIOCB *qcow2_aio_setup(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
         BlockDriverCompletionFunc *cb, void *opaque, int is_write)
 {
+    BDRVQcowState *s = bs->opaque;
     QCowAIOCB *acb;
     Coroutine *coroutine;
+    int start_request;
 
     acb = qemu_aio_get(&qcow2_aio_pool, bs, cb, opaque);
     if (!acb)
@@ -569,7 +582,13 @@ static BlockDriverAIOCB *qcow2_aio_setup(BlockDriverState *bs,
     coroutine = qemu_coroutine_create(is_write ? qcow2_co_write
                                                : qcow2_co_read);
     acb->coroutine = coroutine;
-    qemu_coroutine_enter(coroutine, acb);
+
+    /* Kick off the request if no others are currently executing */
+    start_request = QTAILQ_EMPTY(&s->request_list);
+    QTAILQ_INSERT_TAIL(&s->request_list, acb, next_request);
+    if (start_request) {
+        qemu_coroutine_enter(coroutine, acb);
+    }
     return &acb->common;
 }
 
diff --git a/block/qcow2.h b/block/qcow2.h
index 5217bea..159f86b 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -78,6 +78,8 @@ typedef struct QCowSnapshot {
     uint64_t vm_clock_nsec;
 } QCowSnapshot;
 
+struct QCowAIOCB;
+
 typedef struct BDRVQcowState {
     int cluster_bits;
     int cluster_size;
@@ -98,6 +100,7 @@ typedef struct BDRVQcowState {
     uint8_t *cluster_data;
     uint64_t cluster_cache_offset;
     QLIST_HEAD(QCowClusterAlloc, QCowL2Meta) cluster_allocs;
+    QTAILQ_HEAD(, QCowAIOCB) request_list;
 
     uint64_t *refcount_table;
     uint64_t refcount_table_offset;
@@ -128,8 +131,6 @@ typedef struct QCowCreateState {
     int64_t refcount_block_offset;
 } QCowCreateState;
 
-struct QCowAIOCB;
-
 /* XXX This could be private for qcow2-cluster.c */
 typedef struct QCowL2Meta
 {
-- 
1.7.2.3

  parent reply	other threads:[~2011-01-22  9:30 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-01-22  9:29 [Qemu-devel] [RFC][PATCH 00/12] qcow2: Convert qcow2 to use coroutines for async I/O Stefan Hajnoczi
2011-01-22  9:29 ` [Qemu-devel] [RFC][PATCH 01/12] coroutine: Add gtk-vnc coroutines library Stefan Hajnoczi
2011-01-26 15:25   ` Avi Kivity
2011-01-26 16:00     ` Anthony Liguori
2011-01-26 16:13       ` Avi Kivity
2011-01-26 16:19         ` Anthony Liguori
2011-01-26 16:22           ` Avi Kivity
2011-01-26 16:29             ` Anthony Liguori
2011-01-26 16:21         ` Anthony Liguori
2011-01-22  9:29 ` [Qemu-devel] [RFC][PATCH 02/12] continuation: Fix container_of() redefinition Stefan Hajnoczi
2011-01-22  9:29 ` [Qemu-devel] [RFC][PATCH 03/12] Make sure to release allocated stack when coroutine is released Stefan Hajnoczi
2011-01-22  9:29 ` [Qemu-devel] [RFC][PATCH 04/12] coroutine: Use thread-local leader and current variables Stefan Hajnoczi
2011-01-22  9:29 ` [Qemu-devel] [RFC][PATCH 05/12] coroutine: Add coroutines Stefan Hajnoczi
2011-01-26 15:29   ` Avi Kivity
2011-01-26 16:00     ` Anthony Liguori
2011-01-27  9:40     ` Stefan Hajnoczi
2011-01-22  9:29 ` [Qemu-devel] [RFC][PATCH 06/12] coroutine: Add qemu_coroutine_self() Stefan Hajnoczi
2011-01-22  9:29 ` [Qemu-devel] [RFC][PATCH 07/12] coroutine: Add coroutine_is_leader() Stefan Hajnoczi
2011-01-22  9:29 ` [Qemu-devel] [RFC][PATCH 08/12] coroutine: Add qemu_in_coroutine() Stefan Hajnoczi
2011-01-22  9:29 ` [Qemu-devel] [RFC][PATCH 09/12] block: Add bdrv_co_readv() and bdrv_co_writev() Stefan Hajnoczi
2011-01-22  9:29 ` [Qemu-devel] [RFC][PATCH 10/12] block: Add coroutine support to synchronous I/O functions Stefan Hajnoczi
2011-01-22  9:29 ` [Qemu-devel] [RFC][PATCH 11/12] qcow2: Convert qcow2 to use coroutines for async I/O Stefan Hajnoczi
2011-01-23 23:40   ` Anthony Liguori
2011-01-24 11:09     ` Stefan Hajnoczi
2011-01-26 15:40   ` Avi Kivity
2011-01-26 15:50     ` Kevin Wolf
2011-01-26 16:08       ` Anthony Liguori
2011-01-26 16:13         ` Avi Kivity
2011-01-26 16:28           ` Anthony Liguori
2011-01-26 16:38             ` Avi Kivity
2011-01-26 17:12               ` Anthony Liguori
2011-01-27  9:25                 ` Avi Kivity
2011-01-27  9:27                 ` Kevin Wolf
2011-01-27  9:49                   ` Avi Kivity
2011-01-27 10:34                     ` Kevin Wolf
2011-01-27 10:41                       ` Avi Kivity
2011-01-27 11:27                         ` Kevin Wolf
2011-01-27 12:21                           ` Avi Kivity
2011-01-26 16:08       ` Avi Kivity
2011-01-27 10:09     ` Stefan Hajnoczi
2011-01-27 10:46       ` Avi Kivity
2011-01-22  9:29 ` Stefan Hajnoczi [this message]
2011-01-23 23:31 ` [Qemu-devel] [RFC][PATCH 00/12] " Anthony Liguori
2011-02-01 13:23   ` Kevin Wolf
2011-01-24 11:58 ` [Qemu-devel] " Kevin Wolf
2011-01-24 13:10   ` Stefan Hajnoczi

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=1295688567-25496-13-git-send-email-stefanha@linux.vnet.ibm.com \
    --to=stefanha@linux.vnet.ibm.com \
    --cc=aliguori@us.ibm.com \
    --cc=kwolf@redhat.com \
    --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.