From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1M1JxE-0001rV-Nd for qemu-devel@nongnu.org; Tue, 05 May 2009 08:41:00 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1M1Jx7-0001oF-GI for qemu-devel@nongnu.org; Tue, 05 May 2009 08:40:58 -0400 Received: from [199.232.76.173] (port=46114 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1M1Jx4-0001ny-Cj for qemu-devel@nongnu.org; Tue, 05 May 2009 08:40:51 -0400 Received: from mx20.gnu.org ([199.232.41.8]:42070) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1M1Jx3-0001Vv-Vg for qemu-devel@nongnu.org; Tue, 05 May 2009 08:40:50 -0400 Received: from mx2.redhat.com ([66.187.237.31]) by mx20.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1M1Jx1-0006DV-V6 for qemu-devel@nongnu.org; Tue, 05 May 2009 08:40:49 -0400 From: Avi Kivity Date: Tue, 5 May 2009 15:40:35 +0300 Message-Id: <1241527235-19755-1-git-send-email-avi@redhat.com> Subject: [Qemu-devel] [PATCH] Serialize qcow2 writes List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Anthony Liguori Cc: qemu-devel@nongnu.org, kvm@vger.kernel.org Commit 641636d ("qcow2 corruption: Fix alloc_cluster_link_l2"; 4df8f71 on stable-0.10) exposes a bug with concurrent allocating qcow2 writes: the writes will trigger a call to free_any_clusters() and corrupt the image. As a temporary workaround until a real fix is written, this patch serializes writes to avoid the issue. With this, I can install Fedora 10 on a virtio disk. Signed-off-by: Avi Kivity --- block-qcow2.c | 27 ++++++++++++++++++++++++++- 1 files changed, 26 insertions(+), 1 deletions(-) diff --git a/block-qcow2.c b/block-qcow2.c index 1f33125..6685915 100644 --- a/block-qcow2.c +++ b/block-qcow2.c @@ -157,6 +157,8 @@ typedef struct BDRVQcowState { int snapshots_size; int nb_snapshots; QCowSnapshot *snapshots; + int write_in_progress; + TAILQ_HEAD(QCow2DeferredWrites, QCowAIOCB) deferred_writes; } BDRVQcowState; static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset); @@ -371,6 +373,9 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags) if (qcow_read_snapshots(bs) < 0) goto fail; + s->write_in_progress = 0; + TAILQ_INIT(&s->deferred_writes); + #ifdef DEBUG_ALLOC check_refcounts(bs); #endif @@ -1274,6 +1279,7 @@ typedef struct QCowAIOCB { QEMUIOVector hd_qiov; QEMUBH *bh; QCowL2Meta l2meta; + TAILQ_ENTRY(QCowAIOCB) deferred_writes_link; } QCowAIOCB; static void qcow_aio_read_cb(void *opaque, int ret); @@ -1439,6 +1445,8 @@ static BlockDriverAIOCB *qcow_aio_readv(BlockDriverState *bs, return &acb->common; } +static void fire_deferred_writes(BDRVQcowState *s); + static void qcow_aio_write_cb(void *opaque, int ret) { QCowAIOCB *acb = opaque; @@ -1509,6 +1517,21 @@ done: qemu_vfree(acb->orig_buf); acb->common.cb(acb->common.opaque, ret); qemu_aio_release(acb); + + s->write_in_progress = 0; + fire_deferred_writes(s); +} + +static void fire_deferred_writes(BDRVQcowState *s) +{ + QCowAIOCB *acb; + + if (!s->write_in_progress && !TAILQ_EMPTY(&s->deferred_writes)) { + s->write_in_progress = 1; + acb = TAILQ_FIRST(&s->deferred_writes); + TAILQ_REMOVE(&s->deferred_writes, acb, deferred_writes_link); + qcow_aio_write_cb(acb, 0); + } } static BlockDriverAIOCB *qcow_aio_writev(BlockDriverState *bs, @@ -1524,7 +1547,9 @@ static BlockDriverAIOCB *qcow_aio_writev(BlockDriverState *bs, if (!acb) return NULL; - qcow_aio_write_cb(acb, 0); + TAILQ_INSERT_TAIL(&s->deferred_writes, acb, deferred_writes_link); + fire_deferred_writes(s); + return &acb->common; } -- 1.6.1.1