From 115c2b5a6806615206dfa5518509911bfc7b1d07 Mon Sep 17 00:00:00 2001 From: MORITA Kazutaka Date: Thu, 3 May 2012 05:26:07 +0900 Subject: [PATCH 1/5] sheepdog: switch to writethrough mode if cluster doesn't support flush This is necessary for qemu to work with the older version of Sheepdog which doesn't support SD_OP_FLUSH_VDI. Signed-off-by: MORITA Kazutaka Signed-off-by: Kevin Wolf --- block/sheepdog.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/block/sheepdog.c b/block/sheepdog.c index 0ed6b193c9..e01d371680 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -1678,6 +1678,14 @@ static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs) return ret; } + if (rsp->result == SD_RES_INVALID_PARMS) { + dprintf("disable write cache since the server doesn't support it\n"); + + s->cache_enabled = 0; + closesocket(s->flush_fd); + return 0; + } + if (rsp->result != SD_RES_SUCCESS) { error_report("%s", sd_strerror(rsp->result)); return -EIO; From 54e6814360ab2110ed3ed07b2b9a3f9907e1202a Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Thu, 26 Apr 2012 19:41:22 +0200 Subject: [PATCH 2/5] qcow2: Limit COW to where it's needed This fixes a regression introduced in commit 250196f1. The bug leads to data corruption, found during an Autotest run with a Fedora 8 guest. Consider a write request whose first part is covered by an already allocated cluster, but additional clusters need to be newly allocated. When counting the number of clusters to allocate, the qcow2 code would decide to do COW for all remaining clusters of the write request, even if some of them are already allocated. If during this COW operation another write request is issued that touches the same cluster, it will still refer to the old cluster. When the COW completes, the first request will update the L2 table and the second write request will be lost. Note that the requests need not overlap, it's enough for them to touch the same cluster. This patch ensures that only clusters that really require COW are considered for allocation. In this case any other request writing to the same cluster will be an allocating write and gets serialised. Reported-by: Marcelo Tosatti Tested-by: Marcelo Tosatti Signed-off-by: Kevin Wolf --- block/qcow2-cluster.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 353889d41b..10c22fe12b 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -883,17 +883,21 @@ again: assert(keep_clusters <= nb_clusters); nb_clusters -= keep_clusters; } else { - /* For the moment, overwrite compressed clusters one by one */ - if (cluster_offset & QCOW_OFLAG_COMPRESSED) { - nb_clusters = 1; - } else { - nb_clusters = count_cow_clusters(s, nb_clusters, l2_table, l2_index); - } - keep_clusters = 0; cluster_offset = 0; } + if (nb_clusters > 0) { + /* For the moment, overwrite compressed clusters one by one */ + uint64_t entry = be64_to_cpu(l2_table[l2_index + keep_clusters]); + if (entry & QCOW_OFLAG_COMPRESSED) { + nb_clusters = 1; + } else { + nb_clusters = count_cow_clusters(s, nb_clusters, l2_table, + l2_index + keep_clusters); + } + } + cluster_offset &= L2E_OFFSET_MASK; /* From 5b7e1542cfa41a281af9629d31cef03704d976e6 Mon Sep 17 00:00:00 2001 From: Zhi Yong Wu Date: Mon, 7 May 2012 16:50:42 +0800 Subject: [PATCH 3/5] block: make bdrv_create adopt coroutine The current qemu.git introduces failure with preallocation and some sizes: qemu-img create -f qcow2 new.img 976563K -o preallocation=metadata qemu-img: qemu-coroutine-lock.c:111: qemu_co_mutex_unlock: Assertion `mutex->locked == 1' failed. And lock needs to work in coroutine context. So to fix this issue, we need to make bdrv_create adopt coroutine at first. Signed-off-by: Zhi Yong Wu Signed-off-by: Kevin Wolf --- block.c | 46 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/block.c b/block.c index 43c794c4d7..ee7d8f220f 100644 --- a/block.c +++ b/block.c @@ -341,13 +341,53 @@ BlockDriver *bdrv_find_whitelisted_format(const char *format_name) return drv && bdrv_is_whitelisted(drv) ? drv : NULL; } +typedef struct CreateCo { + BlockDriver *drv; + char *filename; + QEMUOptionParameter *options; + int ret; +} CreateCo; + +static void coroutine_fn bdrv_create_co_entry(void *opaque) +{ + CreateCo *cco = opaque; + assert(cco->drv); + + cco->ret = cco->drv->bdrv_create(cco->filename, cco->options); +} + int bdrv_create(BlockDriver *drv, const char* filename, QEMUOptionParameter *options) { - if (!drv->bdrv_create) - return -ENOTSUP; + int ret; - return drv->bdrv_create(filename, options); + Coroutine *co; + CreateCo cco = { + .drv = drv, + .filename = g_strdup(filename), + .options = options, + .ret = NOT_DONE, + }; + + if (!drv->bdrv_create) { + return -ENOTSUP; + } + + if (qemu_in_coroutine()) { + /* Fast-path if already in coroutine context */ + bdrv_create_co_entry(&cco); + } else { + co = qemu_coroutine_create(bdrv_create_co_entry); + qemu_coroutine_enter(co, &cco); + while (cco.ret == NOT_DONE) { + qemu_aio_wait(); + } + } + + ret = cco.ret; + g_free(cco.filename); + + return ret; } int bdrv_create_file(const char* filename, QEMUOptionParameter *options) From 15552c4ad38b9ec66792b044cf5ae74538c32717 Mon Sep 17 00:00:00 2001 From: Zhi Yong Wu Date: Mon, 7 May 2012 16:51:03 +0800 Subject: [PATCH 4/5] qcow2: lock on prealloc preallocate() will be locked. This is required because qcow2_alloc_cluster_link_l2() assumes that it runs under a lock that it can drop while COW is being performed. Signed-off-by: Zhi Yong Wu Signed-off-by: Kevin Wolf --- block/qcow2.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/block/qcow2.c b/block/qcow2.c index 8c60a6f061..ee4678f6ed 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1192,7 +1192,10 @@ static int qcow2_create2(const char *filename, int64_t total_size, /* And if we're supposed to preallocate metadata, do that now */ if (prealloc) { + BDRVQcowState *s = bs->opaque; + qemu_co_mutex_lock(&s->lock); ret = preallocate(bs); + qemu_co_mutex_unlock(&s->lock); if (ret < 0) { goto out; } From 21fcf36095939a97fc3df578e12821c3e6c3ba78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Sat, 5 May 2012 19:43:28 +0200 Subject: [PATCH 5/5] fdc: simplify media change handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This also (partly) fixes IBM OS/2 Warp 4.0 floppy installation, where not all floppies have the same format (2x80x18 for the first ones, 2x80x23 for the next ones). Signed-off-by: Hervé Poussineau Signed-off-by: Kevin Wolf --- hw/fdc.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/hw/fdc.c b/hw/fdc.c index 756d4cefd5..cb4cd25c11 100644 --- a/hw/fdc.c +++ b/hw/fdc.c @@ -705,6 +705,15 @@ static void fdctrl_raise_irq(FDCtrl *fdctrl, uint8_t status0) qemu_set_irq(fdctrl->irq, 1); fdctrl->sra |= FD_SRA_INTPEND; } + if (status0 & FD_SR0_SEEK) { + FDrive *cur_drv; + /* A seek clears the disk change line (if a disk is inserted) */ + cur_drv = get_cur_drv(fdctrl); + if (cur_drv->max_track) { + cur_drv->media_changed = 0; + } + } + fdctrl->reset_sensei = 0; fdctrl->status0 = status0; FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", fdctrl->status0); @@ -936,23 +945,7 @@ static void fdctrl_write_ccr(FDCtrl *fdctrl, uint32_t value) static int fdctrl_media_changed(FDrive *drv) { - int ret; - - if (!drv->bs) - return 0; - if (drv->media_changed) { - drv->media_changed = 0; - ret = 1; - } else { - ret = bdrv_media_changed(drv->bs); - if (ret < 0) { - ret = 0; /* we don't know, assume no */ - } - } - if (ret) { - fd_revalidate(drv); - } - return ret; + return drv->media_changed; } /* Digital input register : 0x07 (read-only) */ @@ -1856,6 +1849,7 @@ static void fdctrl_change_cb(void *opaque, bool load) FDrive *drive = opaque; drive->media_changed = 1; + fd_revalidate(drive); } static const BlockDevOps fdctrl_block_ops = { @@ -1886,7 +1880,6 @@ static int fdctrl_connect_drives(FDCtrl *fdctrl) fd_init(drive); fd_revalidate(drive); if (drive->bs) { - drive->media_changed = 1; bdrv_set_dev_ops(drive->bs, &fdctrl_block_ops, drive); } }