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 <avi@xxxxxxxxxx> --- 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 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html