[Spice-commits] 57 commits - aio-posix.c aio-win32.c async.c block.c block/backup.c block/linux-aio.c block/qcow2.c block/qed.c block/qed.h block/raw-posix.c blockjob.c configure dma-helpers.c docs/aio_notify.promela hw/block hw/char hw/display hw/ide hw/mips hw/scsi hw/timer hw/usb hw/virtio hw/watchdog include/block include/hw include/qemu-common.h iothread.c main-loop.c qemu-char.c qemu-io-cmds.c target-i386/cpu.c target-mips/kvm.c target-mips/translate.c target-s390x/kvm.c tests/libqos tests/qemu-iotests tests/test-aio.c tests/test-thread-pool.c tests/vhost-user-test.c ui/gtk.c ui/spice-core.c util/iov.c util/oslib-posix.c
Gerd Hoffmann
kraxel at kemper.freedesktop.org
Tue Jul 15 08:08:07 PDT 2014
aio-posix.c | 38 ++++-
aio-win32.c | 6
async.c | 19 ++
block.c | 22 ++
block/backup.c | 2
block/linux-aio.c | 5
block/qcow2.c | 11 +
block/qed.c | 38 ++++-
block/qed.h | 1
block/raw-posix.c | 15 +-
blockjob.c | 2
configure | 9 +
dma-helpers.c | 4
docs/aio_notify.promela | 104 +++++++++++++
hw/block/dataplane/virtio-blk.c | 57 ++++---
hw/block/virtio-blk.c | 95 +++++++-----
hw/char/serial-pci.c | 1
hw/char/serial.c | 59 ++++---
hw/display/cirrus_vga.c | 24 ++-
hw/display/cirrus_vga_rop.h | 3
hw/ide/core.c | 28 +++
hw/mips/mips_malta.c | 20 ++
hw/scsi/scsi-bus.c | 3
hw/timer/mc146818rtc.c | 2
hw/usb/dev-mtp.c | 4
hw/virtio/dataplane/vring.c | 22 +-
hw/watchdog/watchdog.c | 6
include/block/aio.h | 32 +---
include/block/blockjob.h | 4
include/block/coroutine.h | 2
include/hw/virtio/dataplane/vring.h | 3
include/hw/virtio/virtio-blk.h | 6
include/hw/virtio/virtio-scsi.h | 2
include/qemu-common.h | 1
iothread.c | 5
main-loop.c | 21 --
qemu-char.c | 23 ++-
qemu-io-cmds.c | 4
target-i386/cpu.c | 2
target-mips/kvm.c | 7
target-mips/translate.c | 8 -
target-s390x/kvm.c | 23 +++
tests/libqos/pci-pc.c | 12 -
tests/qemu-iotests/028 | 27 +++
tests/qemu-iotests/028.out | 269 ++++++++++++++++++++++++++++++++++++
tests/test-aio.c | 38 ++---
tests/test-thread-pool.c | 4
tests/vhost-user-test.c | 4
ui/gtk.c | 9 -
ui/spice-core.c | 5
util/iov.c | 13 +
util/oslib-posix.c | 30 ++--
52 files changed, 917 insertions(+), 237 deletions(-)
New commits:
commit 2c65ebe6465618ca159398dfb15d9118ae0fd99f
Merge: 0e16297 5b2ffbe
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Tue Jul 15 15:06:17 2014 +0100
Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging
Block pull request
# gpg: Signature made Tue 15 Jul 2014 14:49:01 BST using RSA key ID 81AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha at redhat.com>"
# gpg: aka "Stefan Hajnoczi <stefanha at gmail.com>"
* remotes/stefanha/tags/block-pull-request:
virtio-blk: dataplane: notify guest as a batch
virtio-blk: data-plane: fix save/set .complete_request in start
linux-aio: Fix laio resource leak
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
commit 5b2ffbe4d99843fd8305c573a100047a8c962327
Author: Ming Lei <tom.leiming at gmail.com>
Date: Sat Jul 12 12:08:53 2014 +0800
virtio-blk: dataplane: notify guest as a batch
Now requests are submitted as a batch, so it is natural
to notify guest as a batch too.
This may suppress interrupt notification to VM a lot:
- in my test, decreased by ~13K/sec
Signed-off-by: Ming Lei <ming.lei at canonical.com>
Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
index e88862d..d6ba65c 100644
--- a/hw/block/dataplane/virtio-blk.c
+++ b/hw/block/dataplane/virtio-blk.c
@@ -34,6 +34,7 @@ struct VirtIOBlockDataPlane {
VirtIODevice *vdev;
Vring vring; /* virtqueue vring */
EventNotifier *guest_notifier; /* irq */
+ QEMUBH *bh; /* bh for guest notification */
/* Note that these EventNotifiers are assigned by value. This is
* fine as long as you do not call event_notifier_cleanup on them
@@ -61,13 +62,28 @@ static void notify_guest(VirtIOBlockDataPlane *s)
event_notifier_set(s->guest_notifier);
}
+static void notify_guest_bh(void *opaque)
+{
+ VirtIOBlockDataPlane *s = opaque;
+
+ notify_guest(s);
+}
+
static void complete_request_vring(VirtIOBlockReq *req, unsigned char status)
{
+ VirtIOBlockDataPlane *s = req->dev->dataplane;
stb_p(&req->in->status, status);
vring_push(&req->dev->dataplane->vring, &req->elem,
req->qiov.size + sizeof(*req->in));
- notify_guest(req->dev->dataplane);
+
+ /* Suppress notification to guest by BH and its scheduled
+ * flag because requests are completed as a batch after io
+ * plug & unplug is introduced, and the BH can still be
+ * executed in dataplane aio context even after it is
+ * stopped, so needn't worry about notification loss with BH.
+ */
+ qemu_bh_schedule(s->bh);
}
static void handle_notify(EventNotifier *e)
@@ -172,6 +188,7 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
s->iothread = &s->internal_iothread_obj;
}
s->ctx = iothread_get_aio_context(s->iothread);
+ s->bh = aio_bh_new(s->ctx, notify_guest_bh, s);
error_setg(&s->blocker, "block device is in use by data plane");
bdrv_op_block_all(blk->conf.bs, s->blocker);
@@ -190,6 +207,7 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s)
bdrv_op_unblock_all(s->blk->conf.bs, s->blocker);
error_free(s->blocker);
object_unref(OBJECT(s->iothread));
+ qemu_bh_delete(s->bh);
g_free(s);
}
commit e926d9b8c52d5ddf413617df4b341a3114642b14
Author: Ming Lei <ming.lei at canonical.com>
Date: Sat Jul 12 12:08:52 2014 +0800
virtio-blk: data-plane: fix save/set .complete_request in start
The callback has to be saved and reset in virtio_blk_data_plane_start(),
otherwise dataplane's requests will be completed in qemu aio context.
Reviewed-by: Fam Zheng <famz at redhat.com>
Signed-off-by: Ming Lei <ming.lei at canonical.com>
Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
index 227bb15..e88862d 100644
--- a/hw/block/dataplane/virtio-blk.c
+++ b/hw/block/dataplane/virtio-blk.c
@@ -125,7 +125,6 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
Error **errp)
{
VirtIOBlockDataPlane *s;
- VirtIOBlock *vblk = VIRTIO_BLK(vdev);
Error *local_err = NULL;
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
@@ -178,8 +177,6 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
bdrv_op_block_all(blk->conf.bs, s->blocker);
*dataplane = s;
- s->saved_complete_request = vblk->complete_request;
- vblk->complete_request = complete_request_vring;
}
/* Context: QEMU global mutex held */
@@ -201,6 +198,7 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
{
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev)));
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
+ VirtIOBlock *vblk = VIRTIO_BLK(s->vdev);
VirtQueue *vq;
if (s->started) {
@@ -234,6 +232,9 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
}
s->host_notifier = *virtio_queue_get_host_notifier(vq);
+ s->saved_complete_request = vblk->complete_request;
+ vblk->complete_request = complete_request_vring;
+
s->starting = false;
s->started = true;
trace_virtio_blk_data_plane_start(s);
commit a1abf40d6be2fc4b40d90ae3b46442f4a671776b
Author: Gonglei <arei.gonglei at huawei.com>
Date: Sat Jul 12 11:43:37 2014 +0800
linux-aio: Fix laio resource leak
when hotplug virtio-scsi disks using laio, the aio_nr will
increase in laio_init() by io_setup(), we can see the number by
# cat /proc/sys/fs/aio-nr
128
if the aio_nr attach the maxnum, which found from
# cat /proc/sys/fs/aio-max-nr
65536
the hotplug process will fail because of aio context leak.
Fix it by io_destroy in laio_cleanup().
Reported-by: daifulai <daifulai at huawei.com>
Signed-off-by: Gonglei <arei.gonglei at huawei.com>
Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
diff --git a/block/linux-aio.c b/block/linux-aio.c
index 4867369..7ac7e8c 100644
--- a/block/linux-aio.c
+++ b/block/linux-aio.c
@@ -310,5 +310,10 @@ void laio_cleanup(void *s_)
struct qemu_laio_state *s = s_;
event_notifier_cleanup(&s->e);
+
+ if (io_destroy(s->ctx) != 0) {
+ fprintf(stderr, "%s: destroy AIO context %p failed\n",
+ __func__, &s->ctx);
+ }
g_free(s);
}
commit 0e16297461264b3ea8f7282d1195cf53aa8a707c
Author: Andreas Färber <afaerber at suse.de>
Date: Mon Jul 14 17:38:18 2014 +0200
libqos: Fix PC PCI endianness glitches
The libqos implementation of io_read{b,w,l} and io_write{b,w,l} hooks
was relying on qtest_mem{read,write}() respectively. With d81d410 (usb:
improve ehci/uhci test) this resulted in assertion failures on ppc hosts:
ERROR:tests/usb-hcd-ehci-test.c:78:ehci_port_test: assertion failed: ((value & mask) == (expect & mask))
ERROR:tests/usb-hcd-ehci-test.c:128:pci_uhci_port_2: assertion failed: (pcibus != NULL)
ERROR:tests/usb-hcd-ehci-test.c:150:pci_ehci_port_2: assertion failed: (pcibus != NULL)
qtest_read{b,w,l,q}() and qtest_write{b,w,l,q}() had been introduced
as endian-safe replacement for qtest_mem{read,write}() in I2C in
872536b (qtest: Add MMIO support). Use them for PCI as well.
Cc: Anthony Liguori <aliguori at amazon.com>
Cc: Gerd Hoffmann <kraxel at redhat.com>
Fixes: c4efe1c qtest: add libqos including PCI support
Fixes: d81d410 usb: improve ehci/uhci test
Signed-off-by: Andreas Färber <afaerber at suse.de>
Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c
index bf741a4..4adf400 100644
--- a/tests/libqos/pci-pc.c
+++ b/tests/libqos/pci-pc.c
@@ -41,7 +41,7 @@ static uint8_t qpci_pc_io_readb(QPCIBus *bus, void *addr)
if (port < 0x10000) {
value = inb(port);
} else {
- memread(port, &value, sizeof(value));
+ value = readb(port);
}
return value;
@@ -55,7 +55,7 @@ static uint16_t qpci_pc_io_readw(QPCIBus *bus, void *addr)
if (port < 0x10000) {
value = inw(port);
} else {
- memread(port, &value, sizeof(value));
+ value = readw(port);
}
return value;
@@ -69,7 +69,7 @@ static uint32_t qpci_pc_io_readl(QPCIBus *bus, void *addr)
if (port < 0x10000) {
value = inl(port);
} else {
- memread(port, &value, sizeof(value));
+ value = readl(port);
}
return value;
@@ -82,7 +82,7 @@ static void qpci_pc_io_writeb(QPCIBus *bus, void *addr, uint8_t value)
if (port < 0x10000) {
outb(port, value);
} else {
- memwrite(port, &value, sizeof(value));
+ writeb(port, value);
}
}
@@ -93,7 +93,7 @@ static void qpci_pc_io_writew(QPCIBus *bus, void *addr, uint16_t value)
if (port < 0x10000) {
outw(port, value);
} else {
- memwrite(port, &value, sizeof(value));
+ writew(port, value);
}
}
@@ -104,7 +104,7 @@ static void qpci_pc_io_writel(QPCIBus *bus, void *addr, uint32_t value)
if (port < 0x10000) {
outl(port, value);
} else {
- memwrite(port, &value, sizeof(value));
+ writel(port, value);
}
}
commit 0a9934eef166836c8100fce72f7f837cb8b2ed2b
Merge: 7a6d04e 7497bce
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Mon Jul 14 17:01:45 2014 +0100
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
Misc 2.1 fixes regarding character/serial devices and SCSI.
# gpg: Signature made Mon 14 Jul 2014 16:26:08 BST using RSA key ID 9B4D86F2
# gpg: Can't check signature: public key not found
* remotes/bonzini/tags/for-upstream:
serial-pci: remove memory regions from BAR before destroying them
virtio-scsi: fix with -M pc-i440fx-2.0
serial: change retry logic to avoid concurrency
qemu-char: fix deadlock with "-monitor pty"
scsi: Report error when lun number is in use
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
commit 7497bce6c2561f1215fe179e40837774f6243799
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Wed Jun 25 20:21:37 2014 +0200
serial-pci: remove memory regions from BAR before destroying them
Otherwise, hot-unplug of pci-serial-2x trips the assertion
in memory_region_destroy:
(qemu) device_del gg
(qemu) qemu-system-x86_64: /work/armbru/tmp/qemu/memory.c:1021: memory_region_destroy: Assertion `((&mr->subregions)->tqh_first == ((void *)0))' failed.
Aborted (core dumped)
Reported-by: Markus Armbruster <armbru at redhat.com>
Reviewed-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
diff --git a/hw/char/serial-pci.c b/hw/char/serial-pci.c
index f53bb9c..c133c33 100644
--- a/hw/char/serial-pci.c
+++ b/hw/char/serial-pci.c
@@ -148,6 +148,7 @@ static void multi_serial_pci_exit(PCIDevice *dev)
for (i = 0; i < pci->ports; i++) {
s = pci->state + i;
serial_exit_core(s);
+ memory_region_del_subregion(&pci->iobar, &s->io);
memory_region_destroy(&s->io);
g_free(pci->name[i]);
}
commit 1f4e6a069b07869eb5fd3ab711b703b95d363652
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Mon Jul 14 12:03:09 2014 +0200
virtio-scsi: fix with -M pc-i440fx-2.0
Right now starting a machine with virtio-scsi and a <= 2.0 machine type
fails with:
qemu-system-x86_64: -device virtio-scsi-pci: Property .any_layout not found
This is because the any_layout bit was actually never set after
virtio-scsi was changed to support arbitrary layout for virtio buffers.
(This was just a cleanup and a preparation for virtio 1.0; no guest
actually checks the bit, but the new request parsing algorithms are
tested even with old guest).
Reported-by: David Gilbert <dgilbert at redhat.com>
Reviewed-by: David Gilbert <dgilbert at redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
index 0419ee4..188a2d9 100644
--- a/include/hw/virtio/virtio-scsi.h
+++ b/include/hw/virtio/virtio-scsi.h
@@ -178,6 +178,8 @@ typedef struct {
DEFINE_PROP_UINT32("cmd_per_lun", _state, _conf_field.cmd_per_lun, 128)
#define DEFINE_VIRTIO_SCSI_FEATURES(_state, _feature_field) \
+ DEFINE_PROP_BIT("any_layout", _state, _feature_field, \
+ VIRTIO_F_ANY_LAYOUT, true), \
DEFINE_PROP_BIT("hotplug", _state, _feature_field, VIRTIO_SCSI_F_HOTPLUG, \
true), \
DEFINE_PROP_BIT("param_change", _state, _feature_field, \
commit f702e62a193e9ddb41cef95068717e5582b39a64
Author: Kirill Batuzov <batuzovk at ispras.ru>
Date: Fri Jul 11 13:41:08 2014 +0400
serial: change retry logic to avoid concurrency
Whenever serial_xmit fails to transmit a byte it adds a watch that would
call it again when the "line" becomes ready. This results in a retry
chain:
serial_xmit -> add_watch -> serial_xmit
Each chain is able to transmit one character, and for every character
passed to serial by the guest driver a new chain is spawned.
The problem lays with the fact that a new chain is spawned even when
there is one already waiting on the watch. So there can be several retry
chains waiting concurrently on one "line". Every chain tries to transmit
current character, so character order is not messed up. But also every
chain increases retry counter (tsr_retry). If there are enough
concurrent chains this counter will hit MAX_XMIT_RETRY value and
the character will be dropped.
To reproduce this bug you need to feed serial output to some program
consuming it slowly enough. A python script from bug #1335444
description is an example of such program.
This commit changes retry logic in the following way to avoid
concurrency: instead of spawning a new chain for each character being
transmitted spawn only one and make it transmit characters until FIFO is
empty.
The change consists of two parts:
- add a do {} while () loop in serial_xmit (diff is a bit erratic
for this part, diff -w will show actual change),
- do not call serial_xmit from serial_ioport_write if there is one
waiting on the watch already.
This should fix another issue causing bug #1335444.
Signed-off-by: Kirill Batuzov <batuzovk at ispras.ru>
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
diff --git a/hw/char/serial.c b/hw/char/serial.c
index 54180a9..764e184 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -223,37 +223,42 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
{
SerialState *s = opaque;
- if (s->tsr_retry <= 0) {
- if (s->fcr & UART_FCR_FE) {
- if (fifo8_is_empty(&s->xmit_fifo)) {
+ do {
+ if (s->tsr_retry <= 0) {
+ if (s->fcr & UART_FCR_FE) {
+ if (fifo8_is_empty(&s->xmit_fifo)) {
+ return FALSE;
+ }
+ s->tsr = fifo8_pop(&s->xmit_fifo);
+ if (!s->xmit_fifo.num) {
+ s->lsr |= UART_LSR_THRE;
+ }
+ } else if ((s->lsr & UART_LSR_THRE)) {
return FALSE;
- }
- s->tsr = fifo8_pop(&s->xmit_fifo);
- if (!s->xmit_fifo.num) {
+ } else {
+ s->tsr = s->thr;
s->lsr |= UART_LSR_THRE;
+ s->lsr &= ~UART_LSR_TEMT;
}
- } else if ((s->lsr & UART_LSR_THRE)) {
- return FALSE;
- } else {
- s->tsr = s->thr;
- s->lsr |= UART_LSR_THRE;
- s->lsr &= ~UART_LSR_TEMT;
}
- }
- if (s->mcr & UART_MCR_LOOP) {
- /* in loopback mode, say that we just received a char */
- serial_receive1(s, &s->tsr, 1);
- } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1) {
- if (s->tsr_retry >= 0 && s->tsr_retry < MAX_XMIT_RETRY &&
- qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP, serial_xmit, s) > 0) {
- s->tsr_retry++;
- return FALSE;
+ if (s->mcr & UART_MCR_LOOP) {
+ /* in loopback mode, say that we just received a char */
+ serial_receive1(s, &s->tsr, 1);
+ } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1) {
+ if (s->tsr_retry >= 0 && s->tsr_retry < MAX_XMIT_RETRY &&
+ qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP,
+ serial_xmit, s) > 0) {
+ s->tsr_retry++;
+ return FALSE;
+ }
+ s->tsr_retry = 0;
+ } else {
+ s->tsr_retry = 0;
}
- s->tsr_retry = 0;
- } else {
- s->tsr_retry = 0;
- }
+ /* Transmit another byte if it is already available. It is only
+ possible when FIFO is enabled and not empty. */
+ } while ((s->fcr & UART_FCR_FE) && !fifo8_is_empty(&s->xmit_fifo));
s->last_xmit_ts = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
@@ -293,7 +298,9 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
s->thr_ipending = 0;
s->lsr &= ~UART_LSR_THRE;
serial_update_irq(s);
- serial_xmit(NULL, G_IO_OUT, s);
+ if (s->tsr_retry <= 0) {
+ serial_xmit(NULL, G_IO_OUT, s);
+ }
}
break;
case 1:
commit 7b3621f47a990c5099c6385728347f69a8d0e55c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Fri Jul 11 12:11:38 2014 +0200
qemu-char: fix deadlock with "-monitor pty"
qemu_chr_be_generic_open cannot be called with the write lock taken,
because it calls client code that may call qemu_chr_fe_write. This
actually happens for the monitor:
0x00007ffff27dbf79 in __GI_raise (sig=sig at entry=6)
0x00007ffff27df388 in __GI_abort ()
0x00005555555ef489 in error_exit (err=<optimized out>, msg=msg at entry=0x5555559796d0 <__func__.5959> "qemu_mutex_lock")
0x00005555558f9080 in qemu_mutex_lock (mutex=mutex at entry=0x555556248a30)
0x0000555555713936 in qemu_chr_fe_write (s=0x555556248a30, buf=buf at entry=0x5555563d8870 "QEMU 2.0.90 monitor - type 'help' for more information\r\n", len=56)
0x00005555556217fd in monitor_flush_locked (mon=mon at entry=0x555556251fd0)
0x0000555555621a12 in monitor_flush_locked (mon=0x555556251fd0)
monitor_puts (mon=mon at entry=0x555556251fd0, str=0x55555634bfa7 "", str at entry=0x55555634bf70 "QEMU 2.0.90 monitor - type 'help' for more information\n")
0x0000555555624359 in monitor_vprintf (mon=0x555556251fd0, fmt=<optimized out>, ap=<optimized out>)
0x0000555555624414 in monitor_printf (mon=<optimized out>, fmt=fmt at entry=0x5555559105a0 "QEMU %s monitor - type 'help' for more information\n")
0x0000555555629806 in monitor_event (opaque=0x555556251fd0, event=<optimized out>)
0x000055555571343c in qemu_chr_be_generic_open (s=0x555556248a30)
To avoid this, defer the call to an idle callback, which will be
called as soon as the main loop is re-entered. In order to simplify
the cleanup and do it in one place only, change pty_chr_close to
call pty_chr_state.
To reproduce, run with "-monitor pty", then try to read from the
slave /dev/pts/FOO that it creates.
Fixes: 9005b2a7589540a3733b3abdcfbccfe7746cd1a1
Reported-by: Li Liang <liangx.z.li at intel.com>
Reviewed-by: Fam Zheng <famz at redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
diff --git a/qemu-char.c b/qemu-char.c
index 55e372c..7acc03f 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1089,6 +1089,7 @@ typedef struct {
/* Protected by the CharDriverState chr_write_lock. */
int connected;
guint timer_tag;
+ guint open_tag;
} PtyCharDriver;
static void pty_chr_update_read_handler_locked(CharDriverState *chr);
@@ -1101,6 +1102,7 @@ static gboolean pty_chr_timer(gpointer opaque)
qemu_mutex_lock(&chr->chr_write_lock);
s->timer_tag = 0;
+ s->open_tag = 0;
if (!s->connected) {
/* Next poll ... */
pty_chr_update_read_handler_locked(chr);
@@ -1203,12 +1205,26 @@ static gboolean pty_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque)
return TRUE;
}
+static gboolean qemu_chr_be_generic_open_func(gpointer opaque)
+{
+ CharDriverState *chr = opaque;
+ PtyCharDriver *s = chr->opaque;
+
+ s->open_tag = 0;
+ qemu_chr_be_generic_open(chr);
+ return FALSE;
+}
+
/* Called with chr_write_lock held. */
static void pty_chr_state(CharDriverState *chr, int connected)
{
PtyCharDriver *s = chr->opaque;
if (!connected) {
+ if (s->open_tag) {
+ g_source_remove(s->open_tag);
+ s->open_tag = 0;
+ }
remove_fd_in_watch(chr);
s->connected = 0;
/* (re-)connect poll interval for idle guests: once per second.
@@ -1221,8 +1237,9 @@ static void pty_chr_state(CharDriverState *chr, int connected)
s->timer_tag = 0;
}
if (!s->connected) {
+ g_assert(s->open_tag == 0);
s->connected = 1;
- qemu_chr_be_generic_open(chr);
+ s->open_tag = g_idle_add(qemu_chr_be_generic_open_func, chr);
}
if (!chr->fd_in_tag) {
chr->fd_in_tag = io_add_watch_poll(s->fd, pty_chr_read_poll,
@@ -1236,7 +1253,8 @@ static void pty_chr_close(struct CharDriverState *chr)
PtyCharDriver *s = chr->opaque;
int fd;
- remove_fd_in_watch(chr);
+ qemu_mutex_lock(&chr->chr_write_lock);
+ pty_chr_state(chr, 0);
fd = g_io_channel_unix_get_fd(s->fd);
g_io_channel_unref(s->fd);
close(fd);
@@ -1244,6 +1262,7 @@ static void pty_chr_close(struct CharDriverState *chr)
g_source_remove(s->timer_tag);
s->timer_tag = 0;
}
+ qemu_mutex_unlock(&chr->chr_write_lock);
g_free(s);
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
}
commit 7a6d04e73fdd571234e05dcad96895fafb3f22f0
Merge: c15a34e 58ac321
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Mon Jul 14 13:09:29 2014 +0100
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
Block patches for 2.1.0-rc2 (v2)
# gpg: Signature made Mon 14 Jul 2014 11:04:12 BST using RSA key ID C88F2FD6
# gpg: Good signature from "Kevin Wolf <kwolf at redhat.com>"
* remotes/kevin/tags/for-upstream: (22 commits)
ide: Treat read/write beyond end as invalid
virtio-blk: Treat read/write beyond end as invalid
virtio-blk: Bypass error action and I/O accounting on invalid r/w
virtio-blk: Factor common checks out of virtio_blk_handle_read/write()
dma-helpers: Fix too long qiov
qtest: fix vhost-user-test compilation with old GLib
tests: Fix unterminated string output visitor enum human string
AioContext: do not rely on aio_poll(ctx, true) result to end a loop
virtio-blk: embed VirtQueueElement in VirtIOBlockReq
virtio-blk: avoid g_slice_new0() for VirtIOBlockReq and VirtQueueElement
dataplane: do not free VirtQueueElement in vring_push()
virtio-blk: avoid dataplane VirtIOBlockReq early free
block: Assert qiov length matches request length
qed: Make qiov match request size until backing file EOF
qcow2: Make qiov match request size until backing file EOF
block: Make qiov match the request size until EOF
AioContext: speed up aio_notify
test-aio: fix GSource-based timer test
block: drop aio functions that operate on the main AioContext
block: prefer aio_poll to qemu_aio_wait
...
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
commit c15a34eda0f270888a0e4676997317e1bd7894b8
Merge: ab6d374 85ad623
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Mon Jul 14 11:04:11 2014 +0100
Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20140714' into staging
A s390x/kvm bugfix for missing floating point register synchronization.
# gpg: Signature made Mon 14 Jul 2014 08:21:54 BST using RSA key ID C6F02FAF
# gpg: Can't check signature: public key not found
* remotes/cohuck/tags/s390x-20140714:
s390x/kvm: synchronize guest floating point registers
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
commit 58ac321135af890b503ebe56d0d00e184779918f
Author: Markus Armbruster <armbru at redhat.com>
Date: Wed Jul 9 19:07:32 2014 +0200
ide: Treat read/write beyond end as invalid
The block layer fails such reads and writes just fine. However, they
then get treated like valid operations that fail: the error action
gets executed. Unwanted; reporting the error to the guest is the only
sensible action.
Reject them before passing them to the block layer. This bypasses the
error action and I/O accounting. Not quite correct for DMA, because
DMA can fail after some success, and when that happens, the part that
succeeded isn't counted. Tolerable, because I/O accounting is an
inconsistent mess anyway.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 3a38f1e..db191a6 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -499,6 +499,18 @@ static void ide_rw_error(IDEState *s) {
ide_set_irq(s->bus);
}
+static bool ide_sect_range_ok(IDEState *s,
+ uint64_t sector, uint64_t nb_sectors)
+{
+ uint64_t total_sectors;
+
+ bdrv_get_geometry(s->bs, &total_sectors);
+ if (sector > total_sectors || nb_sectors > total_sectors - sector) {
+ return false;
+ }
+ return true;
+}
+
static void ide_sector_read_cb(void *opaque, int ret)
{
IDEState *s = opaque;
@@ -554,6 +566,11 @@ void ide_sector_read(IDEState *s)
printf("sector=%" PRId64 "\n", sector_num);
#endif
+ if (!ide_sect_range_ok(s, sector_num, n)) {
+ ide_rw_error(s);
+ return;
+ }
+
s->iov.iov_base = s->io_buffer;
s->iov.iov_len = n * BDRV_SECTOR_SIZE;
qemu_iovec_init_external(&s->qiov, &s->iov, 1);
@@ -671,6 +688,12 @@ void ide_dma_cb(void *opaque, int ret)
sector_num, n, s->dma_cmd);
#endif
+ if (!ide_sect_range_ok(s, sector_num, n)) {
+ dma_buf_commit(s);
+ ide_dma_error(s);
+ return;
+ }
+
switch (s->dma_cmd) {
case IDE_DMA_READ:
s->bus->dma->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num,
@@ -790,6 +813,11 @@ void ide_sector_write(IDEState *s)
n = s->req_nb_sectors;
}
+ if (!ide_sect_range_ok(s, sector_num, n)) {
+ ide_rw_error(s);
+ return;
+ }
+
s->iov.iov_base = s->io_buffer;
s->iov.iov_len = n * BDRV_SECTOR_SIZE;
qemu_iovec_init_external(&s->qiov, &s->iov, 1);
commit 3c2daac0b98952a858277878cb11294256b39e43
Author: Markus Armbruster <armbru at redhat.com>
Date: Wed Jul 9 19:07:31 2014 +0200
virtio-blk: Treat read/write beyond end as invalid
The block layer fails such reads and writes just fine. However, they
then get treated like valid operations that fail: the error action
gets executed. Unwanted; reporting the error to the guest is the only
sensible action.
Reject them before passing them to the block layer. This bypasses the
error action and I/O accounting.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Reviewed-by: Fam Zheng <famz at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index e6e6276..c241c50 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -291,12 +291,19 @@ static void virtio_blk_handle_flush(VirtIOBlockReq *req, MultiReqBuffer *mrb)
static bool virtio_blk_sect_range_ok(VirtIOBlock *dev,
uint64_t sector, size_t size)
{
+ uint64_t nb_sectors = size >> BDRV_SECTOR_BITS;
+ uint64_t total_sectors;
+
if (sector & dev->sector_mask) {
return false;
}
if (size % dev->conf->logical_block_size) {
return false;
}
+ bdrv_get_geometry(dev->bs, &total_sectors);
+ if (sector > total_sectors || nb_sectors > total_sectors - sector) {
+ return false;
+ }
return true;
}
commit 42e38c1fd0199155d32f3464aedce282d3d7f6a1
Author: Markus Armbruster <armbru at redhat.com>
Date: Wed Jul 9 19:07:30 2014 +0200
virtio-blk: Bypass error action and I/O accounting on invalid r/w
When a device model's I/O operation fails, we execute the error
action. This lets layers above QEMU implement thin provisioning, or
attempt to correct errors before they reach the guest. But when the
I/O operation fails because it's invalid, reporting the error to the
guest is the only sensible action.
If the guest's read or write asks for an invalid sector range, fail
the request right away, without considering the error action. No
change with error action BDRV_ACTION_REPORT.
Furthermore, bypass I/O accounting, because we want to track only I/O
that actually reaches the block layer.
The next commit will extend "invalid sector range" to cover attempts
to read/write beyond the end of the medium.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index 075e6e6..e6e6276 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -307,15 +307,16 @@ static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
sector = virtio_ldq_p(VIRTIO_DEVICE(req->dev), &req->out.sector);
- bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_WRITE);
-
trace_virtio_blk_handle_write(req, sector, req->qiov.size / 512);
if (!virtio_blk_sect_range_ok(req->dev, sector, req->qiov.size)) {
- virtio_blk_rw_complete(req, -EIO);
+ virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
+ virtio_blk_free_request(req);
return;
}
+ bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_WRITE);
+
if (mrb->num_writes == 32) {
virtio_submit_multiwrite(req->dev->bs, mrb);
}
@@ -337,14 +338,15 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
sector = virtio_ldq_p(VIRTIO_DEVICE(req->dev), &req->out.sector);
- bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_READ);
-
trace_virtio_blk_handle_read(req, sector, req->qiov.size / 512);
if (!virtio_blk_sect_range_ok(req->dev, sector, req->qiov.size)) {
- virtio_blk_rw_complete(req, -EIO);
+ virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
+ virtio_blk_free_request(req);
return;
}
+
+ bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_READ);
bdrv_aio_readv(req->dev->bs, sector, &req->qiov,
req->qiov.size / BDRV_SECTOR_SIZE,
virtio_blk_rw_complete, req);
commit d0e14376eefc40b07c8fb42c132c2202c66dcb0b
Author: Markus Armbruster <armbru at redhat.com>
Date: Wed Jul 9 19:07:29 2014 +0200
virtio-blk: Factor common checks out of virtio_blk_handle_read/write()
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Reviewed-by: Fam Zheng <famz at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index 02cd6b0..075e6e6 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -288,6 +288,18 @@ static void virtio_blk_handle_flush(VirtIOBlockReq *req, MultiReqBuffer *mrb)
bdrv_aio_flush(req->dev->bs, virtio_blk_flush_complete, req);
}
+static bool virtio_blk_sect_range_ok(VirtIOBlock *dev,
+ uint64_t sector, size_t size)
+{
+ if (sector & dev->sector_mask) {
+ return false;
+ }
+ if (size % dev->conf->logical_block_size) {
+ return false;
+ }
+ return true;
+}
+
static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
{
BlockRequest *blkreq;
@@ -299,11 +311,7 @@ static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
trace_virtio_blk_handle_write(req, sector, req->qiov.size / 512);
- if (sector & req->dev->sector_mask) {
- virtio_blk_rw_complete(req, -EIO);
- return;
- }
- if (req->qiov.size % req->dev->conf->logical_block_size) {
+ if (!virtio_blk_sect_range_ok(req->dev, sector, req->qiov.size)) {
virtio_blk_rw_complete(req, -EIO);
return;
}
@@ -333,11 +341,7 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
trace_virtio_blk_handle_read(req, sector, req->qiov.size / 512);
- if (sector & req->dev->sector_mask) {
- virtio_blk_rw_complete(req, -EIO);
- return;
- }
- if (req->qiov.size % req->dev->conf->logical_block_size) {
+ if (!virtio_blk_sect_range_ok(req->dev, sector, req->qiov.size)) {
virtio_blk_rw_complete(req, -EIO);
return;
}
commit 58f423fbd5f7f435e8dc56dfa565b043d20d1e1b
Author: Kevin Wolf <kwolf at redhat.com>
Date: Wed Jul 9 19:17:30 2014 +0200
dma-helpers: Fix too long qiov
If the size of the scatter/gather list isn't a multiple of 512, the
number of sectors for the block layer request is rounded down, resulting
in a qiov that doesn't match the request length. Truncate the qiov to the
new length of the request.
This fixes the IDE qtest case /x86_64/ide/bmdma/short_prdt.
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
Reviewed-by: Eric Blake <eblake at redhat.com>
diff --git a/dma-helpers.c b/dma-helpers.c
index 53cbe92..499b52b 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -170,6 +170,10 @@ static void dma_bdrv_cb(void *opaque, int ret)
return;
}
+ if (dbs->iov.size & ~BDRV_SECTOR_MASK) {
+ qemu_iovec_discard_back(&dbs->iov, dbs->iov.size & ~BDRV_SECTOR_MASK);
+ }
+
dbs->acb = dbs->io_func(dbs->bs, dbs->sector_num, &dbs->iov,
dbs->iov.size / 512, dma_bdrv_cb, dbs);
assert(dbs->acb);
diff --git a/include/qemu-common.h b/include/qemu-common.h
index ae76197..6ef8282 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -329,6 +329,7 @@ size_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset,
int fillc, size_t bytes);
ssize_t qemu_iovec_compare(QEMUIOVector *a, QEMUIOVector *b);
void qemu_iovec_clone(QEMUIOVector *dest, const QEMUIOVector *src, void *buf);
+void qemu_iovec_discard_back(QEMUIOVector *qiov, size_t bytes);
bool buffer_is_zero(const void *buf, size_t len);
diff --git a/util/iov.c b/util/iov.c
index 2b4f46d..24566c8 100644
--- a/util/iov.c
+++ b/util/iov.c
@@ -550,3 +550,16 @@ size_t iov_discard_back(struct iovec *iov, unsigned int *iov_cnt,
return total;
}
+
+void qemu_iovec_discard_back(QEMUIOVector *qiov, size_t bytes)
+{
+ size_t total;
+ unsigned int niov = qiov->niov;
+
+ assert(qiov->size >= bytes);
+ total = iov_discard_back(qiov->iov, &niov, bytes);
+ assert(total == bytes);
+
+ qiov->niov = niov;
+ qiov->size -= bytes;
+}
commit 80504dcaa11097b99842312014f5954a54fe1826
Author: Nikolay Nikolaev <n.nikolaev at virtualopensystems.com>
Date: Wed Jul 9 18:06:32 2014 +0300
qtest: fix vhost-user-test compilation with old GLib
Mising G_TIME_SPAN_SECOND definition breaks the RHEL6 compilation as GLib
version before 2.26 does not have it. In such case just define it.
Reported-by: Kevin Wolf <kwolf at redhat.com>
Signed-off-by: Nikolay Nikolaev <n.nikolaev at virtualopensystems.com>
Tested-by: Kevin Wolf <kwolf at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index 2af2381..406ba70 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -22,6 +22,10 @@
#include <qemu/sockets.h>
/* GLIB version compatibility flags */
+#if !GLIB_CHECK_VERSION(2, 26, 0)
+#define G_TIME_SPAN_SECOND (G_GINT64_CONSTANT(1000000))
+#endif
+
#if GLIB_CHECK_VERSION(2, 28, 0)
#define HAVE_MONOTONIC_TIME
#endif
commit b8864245b140c801e826de4acf6d6516e2c550b2
Author: Andreas Färber <afaerber at suse.de>
Date: Wed Jul 9 22:28:49 2014 +0200
tests: Fix unterminated string output visitor enum human string
The buffer was being allocated of size string length plus two.
Around the string two quotes were being added, but no terminating NUL.
It was then compared using g_assert_cmpstr(), resulting in fairly random
assertion failures:
ERROR:tests/test-string-output-visitor.c:213:test_visitor_out_enum: assertion failed (str == str_human): ("\"value1\"" == "\"value1\"\001EEEEEEEEEEEEEE\0171")
There is no g_assert_cmpnstr() counterpart, so use g_strdup_printf()
for safely assembling the string in the first place.
Cc: Hu Tao <hutao at cn.fujitsu.com>
Cc: Michael S. Tsirkin <mst at redhat.com>
Suggested-by: Eric Blake <eblake at redhat.com>
Fixes: b4900c0 tests: add human format test for string output visitor
Signed-off-by: Andreas Färber <afaerber at suse.de>
Reviewed-by: Eric Blake <eblake at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/tests/test-string-output-visitor.c b/tests/test-string-output-visitor.c
index e89e43c..101fb27 100644
--- a/tests/test-string-output-visitor.c
+++ b/tests/test-string-output-visitor.c
@@ -196,16 +196,11 @@ static void test_visitor_out_enum(TestOutputVisitorData *data,
for (i = 0; i < ENUM_ONE_MAX; i++) {
char *str_human;
- int len;
visit_type_EnumOne(data->ov, &i, "unused", &err);
g_assert(!err);
- len = strlen(EnumOne_lookup[i]) + 2;
- str_human = g_malloc0(len);
- str_human[0] = '"';
- strncpy(str_human + 1, EnumOne_lookup[i], strlen(EnumOne_lookup[i]));
- str_human[len - 1] = '"';
+ str_human = g_strdup_printf("\"%s\"", EnumOne_lookup[i]);
str = string_output_get_string(data->sov);
g_assert(str != NULL);
commit acfb23ad3dd8d0ab385a10e483776ba7dcf927ad
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Wed Jul 9 10:49:46 2014 +0200
AioContext: do not rely on aio_poll(ctx, true) result to end a loop
Currently, whenever aio_poll(ctx, true) has completed all pending
work it returns true *and* the next call to aio_poll(ctx, true)
will not block.
This invariant has its roots in qemu_aio_flush()'s implementation
as "while (qemu_aio_wait()) {}". However, qemu_aio_flush() does
not exist anymore and bdrv_drain_all() is implemented differently;
and this invariant is complicated to maintain and subtly different
from the return value of GMainLoop's g_main_context_iteration.
All calls to aio_poll(ctx, true) except one are guarded by a
while() loop checking for a request to be incomplete, or a
BlockDriverState to be idle. The one remaining call (in
iothread.c) uses this to delay the aio_context_release/acquire
pair until the AioContext is quiescent, however:
- we can do the same just by using non-blocking aio_poll,
similar to how vl.c invokes main_loop_wait
- it is buggy, because it does not ensure that the AioContext
is released between an aio_notify and the next time the
iothread goes to sleep. This leads to hangs when stopping
the dataplane thread.
In the end, these semantics are a bad match for the current
users of AioContext. So modify that one exception in iothread.c,
which also fixes the hangs, as well as the testcase so that
it use the same idiom as the actual QEMU code.
Reported-by: Christian Borntraeger <borntraeger at de.ibm.com>
Tested-by: Christian Borntraeger <borntraeger at de.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/include/block/aio.h b/include/block/aio.h
index 433e7ff..c23de3c 100644
--- a/include/block/aio.h
+++ b/include/block/aio.h
@@ -214,9 +214,9 @@ bool aio_pending(AioContext *ctx);
/* Progress in completing AIO work to occur. This can issue new pending
* aio as a result of executing I/O completion or bh callbacks.
*
- * If there is no pending AIO operation or completion (bottom half),
- * return false. If there are pending AIO operations of bottom halves,
- * return true.
+ * Return whether any progress was made by executing AIO or bottom half
+ * handlers. If @blocking == true, this should always be true except
+ * if someone called aio_notify.
*
* If there are no pending bottom halves, but there are pending AIO
* operations, it may not be possible to make any progress without
diff --git a/iothread.c b/iothread.c
index 1fbf9f1..d9403cf 100644
--- a/iothread.c
+++ b/iothread.c
@@ -30,6 +30,7 @@ typedef ObjectClass IOThreadClass;
static void *iothread_run(void *opaque)
{
IOThread *iothread = opaque;
+ bool blocking;
qemu_mutex_lock(&iothread->init_done_lock);
iothread->thread_id = qemu_get_thread_id();
@@ -38,8 +39,10 @@ static void *iothread_run(void *opaque)
while (!iothread->stopping) {
aio_context_acquire(iothread->ctx);
- while (!iothread->stopping && aio_poll(iothread->ctx, true)) {
+ blocking = true;
+ while (!iothread->stopping && aio_poll(iothread->ctx, blocking)) {
/* Progress was made, keep going */
+ blocking = false;
}
aio_context_release(iothread->ctx);
}
diff --git a/tests/test-aio.c b/tests/test-aio.c
index 264dab9..4c40a49 100644
--- a/tests/test-aio.c
+++ b/tests/test-aio.c
@@ -24,14 +24,6 @@ typedef struct {
bool auto_set;
} EventNotifierTestData;
-/* Wait until there are no more BHs or AIO requests */
-static void wait_for_aio(void)
-{
- while (aio_poll(ctx, true)) {
- /* Do nothing */
- }
-}
-
/* Wait until event notifier becomes inactive */
static void wait_until_inactive(EventNotifierTestData *data)
{
@@ -204,7 +196,9 @@ static void test_bh_schedule10(void)
g_assert(aio_poll(ctx, true));
g_assert_cmpint(data.n, ==, 2);
- wait_for_aio();
+ while (data.n < 10) {
+ aio_poll(ctx, true);
+ }
g_assert_cmpint(data.n, ==, 10);
g_assert(!aio_poll(ctx, false));
@@ -252,7 +246,9 @@ static void test_bh_delete_from_cb(void)
qemu_bh_schedule(data1.bh);
g_assert_cmpint(data1.n, ==, 0);
- wait_for_aio();
+ while (data1.n < data1.max) {
+ aio_poll(ctx, true);
+ }
g_assert_cmpint(data1.n, ==, data1.max);
g_assert(data1.bh == NULL);
@@ -287,7 +283,12 @@ static void test_bh_delete_from_cb_many(void)
g_assert_cmpint(data4.n, ==, 1);
g_assert(data1.bh == NULL);
- wait_for_aio();
+ while (data1.n < data1.max ||
+ data2.n < data2.max ||
+ data3.n < data3.max ||
+ data4.n < data4.max) {
+ aio_poll(ctx, true);
+ }
g_assert_cmpint(data1.n, ==, data1.max);
g_assert_cmpint(data2.n, ==, data2.max);
g_assert_cmpint(data3.n, ==, data3.max);
@@ -306,7 +307,7 @@ static void test_bh_flush(void)
qemu_bh_schedule(data.bh);
g_assert_cmpint(data.n, ==, 0);
- wait_for_aio();
+ g_assert(aio_poll(ctx, true));
g_assert_cmpint(data.n, ==, 1);
g_assert(!aio_poll(ctx, false));
commit f897bf751fbd95e4015b95d202c706548586813a
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date: Wed Jul 9 10:05:49 2014 +0200
virtio-blk: embed VirtQueueElement in VirtIOBlockReq
The memory allocation between hw/block/virtio-blk.c,
hw/block/dataplane/virtio-blk.c, and hw/virtio/dataplane/vring.c is
messy. Structs are allocated in different files than they are freed in.
This is risky and makes memory leaks easier.
Embed VirtQueueElement in VirtIOBlockReq to reduce the amount of memory
allocation we need to juggle. This also makes vring.c and virtio.c
slightly more similar.
Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
index bed9f13..227bb15 100644
--- a/hw/block/dataplane/virtio-blk.c
+++ b/hw/block/dataplane/virtio-blk.c
@@ -65,7 +65,7 @@ static void complete_request_vring(VirtIOBlockReq *req, unsigned char status)
{
stb_p(&req->in->status, status);
- vring_push(&req->dev->dataplane->vring, req->elem,
+ vring_push(&req->dev->dataplane->vring, &req->elem,
req->qiov.size + sizeof(*req->in));
notify_guest(req->dev->dataplane);
}
@@ -74,33 +74,32 @@ static void handle_notify(EventNotifier *e)
{
VirtIOBlockDataPlane *s = container_of(e, VirtIOBlockDataPlane,
host_notifier);
-
- VirtQueueElement *elem;
- VirtIOBlockReq *req;
- int ret;
- MultiReqBuffer mrb = {
- .num_writes = 0,
- };
+ VirtIOBlock *vblk = VIRTIO_BLK(s->vdev);
event_notifier_test_and_clear(&s->host_notifier);
bdrv_io_plug(s->blk->conf.bs);
for (;;) {
+ MultiReqBuffer mrb = {
+ .num_writes = 0,
+ };
+ int ret;
+
/* Disable guest->host notifies to avoid unnecessary vmexits */
vring_disable_notification(s->vdev, &s->vring);
for (;;) {
- ret = vring_pop(s->vdev, &s->vring, &elem);
+ VirtIOBlockReq *req = virtio_blk_alloc_request(vblk);
+
+ ret = vring_pop(s->vdev, &s->vring, &req->elem);
if (ret < 0) {
- assert(elem == NULL);
+ virtio_blk_free_request(req);
break; /* no more requests */
}
- trace_virtio_blk_data_plane_process_request(s, elem->out_num,
- elem->in_num, elem->index);
+ trace_virtio_blk_data_plane_process_request(s, req->elem.out_num,
+ req->elem.in_num,
+ req->elem.index);
- req = g_slice_new(VirtIOBlockReq);
- req->dev = VIRTIO_BLK(s->vdev);
- req->elem = elem;
virtio_blk_handle_request(req, &mrb);
}
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index b06a56d..02cd6b0 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -29,20 +29,18 @@
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h"
-static VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s)
+VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s)
{
VirtIOBlockReq *req = g_slice_new(VirtIOBlockReq);
req->dev = s;
req->qiov.size = 0;
req->next = NULL;
- req->elem = g_slice_new(VirtQueueElement);
return req;
}
-static void virtio_blk_free_request(VirtIOBlockReq *req)
+void virtio_blk_free_request(VirtIOBlockReq *req)
{
if (req) {
- g_slice_free(VirtQueueElement, req->elem);
g_slice_free(VirtIOBlockReq, req);
}
}
@@ -56,7 +54,7 @@ static void virtio_blk_complete_request(VirtIOBlockReq *req,
trace_virtio_blk_req_complete(req, status);
stb_p(&req->in->status, status);
- virtqueue_push(s->vq, req->elem, req->qiov.size + sizeof(*req->in));
+ virtqueue_push(s->vq, &req->elem, req->qiov.size + sizeof(*req->in));
virtio_notify(vdev, s->vq);
}
@@ -121,7 +119,7 @@ static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s)
{
VirtIOBlockReq *req = virtio_blk_alloc_request(s);
- if (!virtqueue_pop(s->vq, req->elem)) {
+ if (!virtqueue_pop(s->vq, &req->elem)) {
virtio_blk_free_request(req);
return NULL;
}
@@ -254,7 +252,7 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
{
int status;
- status = virtio_blk_handle_scsi_req(req->dev, req->elem);
+ status = virtio_blk_handle_scsi_req(req->dev, &req->elem);
virtio_blk_req_complete(req, status);
virtio_blk_free_request(req);
}
@@ -351,12 +349,12 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
{
uint32_t type;
- struct iovec *in_iov = req->elem->in_sg;
- struct iovec *iov = req->elem->out_sg;
- unsigned in_num = req->elem->in_num;
- unsigned out_num = req->elem->out_num;
+ struct iovec *in_iov = req->elem.in_sg;
+ struct iovec *iov = req->elem.out_sg;
+ unsigned in_num = req->elem.in_num;
+ unsigned out_num = req->elem.out_num;
- if (req->elem->out_num < 1 || req->elem->in_num < 1) {
+ if (req->elem.out_num < 1 || req->elem.in_num < 1) {
error_report("virtio-blk missing headers");
exit(1);
}
@@ -393,19 +391,19 @@ void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
* NB: per existing s/n string convention the string is
* terminated by '\0' only when shorter than buffer.
*/
- strncpy(req->elem->in_sg[0].iov_base,
+ strncpy(req->elem.in_sg[0].iov_base,
s->blk.serial ? s->blk.serial : "",
- MIN(req->elem->in_sg[0].iov_len, VIRTIO_BLK_ID_BYTES));
+ MIN(req->elem.in_sg[0].iov_len, VIRTIO_BLK_ID_BYTES));
virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
virtio_blk_free_request(req);
} else if (type & VIRTIO_BLK_T_OUT) {
- qemu_iovec_init_external(&req->qiov, &req->elem->out_sg[1],
- req->elem->out_num - 1);
+ qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1],
+ req->elem.out_num - 1);
virtio_blk_handle_write(req, mrb);
} else if (type == VIRTIO_BLK_T_IN || type == VIRTIO_BLK_T_BARRIER) {
/* VIRTIO_BLK_T_IN is 0, so we can't just & it. */
- qemu_iovec_init_external(&req->qiov, &req->elem->in_sg[0],
- req->elem->in_num - 1);
+ qemu_iovec_init_external(&req->qiov, &req->elem.in_sg[0],
+ req->elem.in_num - 1);
virtio_blk_handle_read(req);
} else {
virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
@@ -629,7 +627,7 @@ static void virtio_blk_save_device(VirtIODevice *vdev, QEMUFile *f)
while (req) {
qemu_put_sbyte(f, 1);
- qemu_put_buffer(f, (unsigned char *)req->elem,
+ qemu_put_buffer(f, (unsigned char *)&req->elem,
sizeof(VirtQueueElement));
req = req->next;
}
@@ -654,15 +652,15 @@ static int virtio_blk_load_device(VirtIODevice *vdev, QEMUFile *f,
while (qemu_get_sbyte(f)) {
VirtIOBlockReq *req = virtio_blk_alloc_request(s);
- qemu_get_buffer(f, (unsigned char *)req->elem,
+ qemu_get_buffer(f, (unsigned char *)&req->elem,
sizeof(VirtQueueElement));
req->next = s->rq;
s->rq = req;
- virtqueue_map_sg(req->elem->in_sg, req->elem->in_addr,
- req->elem->in_num, 1);
- virtqueue_map_sg(req->elem->out_sg, req->elem->out_addr,
- req->elem->out_num, 0);
+ virtqueue_map_sg(req->elem.in_sg, req->elem.in_addr,
+ req->elem.in_num, 1);
+ virtqueue_map_sg(req->elem.out_sg, req->elem.out_addr,
+ req->elem.out_num, 0);
}
return 0;
diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c
index 5d17d39..67cb2b8 100644
--- a/hw/virtio/dataplane/vring.c
+++ b/hw/virtio/dataplane/vring.c
@@ -301,14 +301,16 @@ static void vring_unmap_element(VirtQueueElement *elem)
* Stolen from linux/drivers/vhost/vhost.c.
*/
int vring_pop(VirtIODevice *vdev, Vring *vring,
- VirtQueueElement **p_elem)
+ VirtQueueElement *elem)
{
struct vring_desc desc;
unsigned int i, head, found = 0, num = vring->vr.num;
uint16_t avail_idx, last_avail_idx;
- VirtQueueElement *elem = NULL;
int ret;
+ /* Initialize elem so it can be safely unmapped */
+ elem->in_num = elem->out_num = 0;
+
/* If there was a fatal error then refuse operation */
if (vring->broken) {
ret = -EFAULT;
@@ -340,10 +342,8 @@ int vring_pop(VirtIODevice *vdev, Vring *vring,
* the index we've seen. */
head = vring->vr.avail->ring[last_avail_idx % num];
- elem = g_slice_new(VirtQueueElement);
elem->index = head;
- elem->in_num = elem->out_num = 0;
-
+
/* If their number is silly, that's an error. */
if (unlikely(head >= num)) {
error_report("Guest says index %u > %u is available", head, num);
@@ -391,7 +391,6 @@ int vring_pop(VirtIODevice *vdev, Vring *vring,
/* On success, increment avail index. */
vring->last_avail_idx++;
- *p_elem = elem;
return head;
out:
@@ -399,11 +398,7 @@ out:
if (ret == -EFAULT) {
vring->broken = true;
}
- if (elem) {
- vring_unmap_element(elem);
- g_slice_free(VirtQueueElement, elem);
- }
- *p_elem = NULL;
+ vring_unmap_element(elem);
return ret;
}
diff --git a/include/hw/virtio/dataplane/vring.h b/include/hw/virtio/dataplane/vring.h
index b23edd2..af73ee2 100644
--- a/include/hw/virtio/dataplane/vring.h
+++ b/include/hw/virtio/dataplane/vring.h
@@ -53,7 +53,7 @@ void vring_teardown(Vring *vring, VirtIODevice *vdev, int n);
void vring_disable_notification(VirtIODevice *vdev, Vring *vring);
bool vring_enable_notification(VirtIODevice *vdev, Vring *vring);
bool vring_should_notify(VirtIODevice *vdev, Vring *vring);
-int vring_pop(VirtIODevice *vdev, Vring *vring, VirtQueueElement **elem);
+int vring_pop(VirtIODevice *vdev, Vring *vring, VirtQueueElement *elem);
void vring_push(Vring *vring, VirtQueueElement *elem, int len);
#endif /* VRING_H */
diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
index b3080a2..afb7b8d 100644
--- a/include/hw/virtio/virtio-blk.h
+++ b/include/hw/virtio/virtio-blk.h
@@ -144,7 +144,7 @@ typedef struct MultiReqBuffer {
typedef struct VirtIOBlockReq {
VirtIOBlock *dev;
- VirtQueueElement *elem;
+ VirtQueueElement elem;
struct virtio_blk_inhdr *in;
struct virtio_blk_outhdr out;
QEMUIOVector qiov;
@@ -152,6 +152,10 @@ typedef struct VirtIOBlockReq {
BlockAcctCookie acct;
} VirtIOBlockReq;
+VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s);
+
+void virtio_blk_free_request(VirtIOBlockReq *req);
+
int virtio_blk_handle_scsi_req(VirtIOBlock *blk,
VirtQueueElement *elem);
commit 869d66af53d8e04709456c9cae5cca7c560d4b93
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date: Wed Jul 9 10:05:48 2014 +0200
virtio-blk: avoid g_slice_new0() for VirtIOBlockReq and VirtQueueElement
In commit de6c8042ec55da18702fa51f09072fcaa315edc3 ("virtio-blk: Avoid
zeroing every request structure") we avoided the 40 KB memset when
allocating VirtIOBlockReq.
The memset was reintroduced in commit
671ec3f056559f22a2531a91dce3a258b9b5eb8a ("virtio-blk: Convert
VirtIOBlockReq.elem to pointer").
It must be fixed again to avoid a performance regression.
Cc: Fam Zheng <famz at redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index aec3146..b06a56d 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -31,9 +31,11 @@
static VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s)
{
- VirtIOBlockReq *req = g_slice_new0(VirtIOBlockReq);
+ VirtIOBlockReq *req = g_slice_new(VirtIOBlockReq);
req->dev = s;
- req->elem = g_slice_new0(VirtQueueElement);
+ req->qiov.size = 0;
+ req->next = NULL;
+ req->elem = g_slice_new(VirtQueueElement);
return req;
}
commit abd764250fbce6f285513d74f03eb5c526e520f6
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date: Wed Jul 9 10:05:47 2014 +0200
dataplane: do not free VirtQueueElement in vring_push()
VirtQueueElement is allocated in vring_pop() so it seems to make sense
that vring_push() should free it. Alas, virtio-blk frees
VirtQueueElement itself in virtio_blk_free_request().
This patch solves a double-free assertion in glib's g_slice_free().
Rename vring_free_element() to vring_unmap_element() since it no longer
frees the VirtQueueElement.
Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
Tested-by: Christian Borntraeger <borntraeger at de.ibm.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c
index 665a1ff..5d17d39 100644
--- a/hw/virtio/dataplane/vring.c
+++ b/hw/virtio/dataplane/vring.c
@@ -272,7 +272,7 @@ static int get_indirect(Vring *vring, VirtQueueElement *elem,
return 0;
}
-void vring_free_element(VirtQueueElement *elem)
+static void vring_unmap_element(VirtQueueElement *elem)
{
int i;
@@ -287,8 +287,6 @@ void vring_free_element(VirtQueueElement *elem)
for (i = 0; i < elem->in_num; i++) {
vring_unmap(elem->in_sg[i].iov_base, true);
}
-
- g_slice_free(VirtQueueElement, elem);
}
/* This looks in the virtqueue and for the first available buffer, and converts
@@ -402,7 +400,8 @@ out:
vring->broken = true;
}
if (elem) {
- vring_free_element(elem);
+ vring_unmap_element(elem);
+ g_slice_free(VirtQueueElement, elem);
}
*p_elem = NULL;
return ret;
@@ -418,7 +417,7 @@ void vring_push(Vring *vring, VirtQueueElement *elem, int len)
unsigned int head = elem->index;
uint16_t new;
- vring_free_element(elem);
+ vring_unmap_element(elem);
/* Don't touch vring if a fatal error occurred */
if (vring->broken) {
diff --git a/include/hw/virtio/dataplane/vring.h b/include/hw/virtio/dataplane/vring.h
index 63e7bf4..b23edd2 100644
--- a/include/hw/virtio/dataplane/vring.h
+++ b/include/hw/virtio/dataplane/vring.h
@@ -55,6 +55,5 @@ bool vring_enable_notification(VirtIODevice *vdev, Vring *vring);
bool vring_should_notify(VirtIODevice *vdev, Vring *vring);
int vring_pop(VirtIODevice *vdev, Vring *vring, VirtQueueElement **elem);
void vring_push(Vring *vring, VirtQueueElement *elem, int len);
-void vring_free_element(VirtQueueElement *elem);
#endif /* VRING_H */
commit 0a21ea3289c5a3b982386e3eaaa37627c18f5e35
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date: Wed Jul 9 10:05:46 2014 +0200
virtio-blk: avoid dataplane VirtIOBlockReq early free
VirtIOBlockReq is freed later by virtio_blk_free_request() in
hw/block/virtio-blk.c. Remove this extraneous g_slice_free().
This patch fixes the following segfault:
0x00005555556373af in virtio_blk_rw_complete (opaque=0x5555565ff5e0, ret=0) at hw/block/virtio-blk.c:99
99 bdrv_acct_done(req->dev->bs, &req->acct);
(gdb) print req
$1 = (VirtIOBlockReq *) 0x5555565ff5e0
(gdb) print req->dev
$2 = (VirtIOBlock *) 0x0
(gdb) bt
#0 0x00005555556373af in virtio_blk_rw_complete (opaque=0x5555565ff5e0, ret=0) at hw/block/virtio-blk.c:99
#1 0x0000555555840ebe in bdrv_co_em_bh (opaque=0x5555566152d0) at block.c:4675
#2 0x000055555583de77 in aio_bh_poll (ctx=ctx at entry=0x5555563a8150) at async.c:81
#3 0x000055555584b7a7 in aio_poll (ctx=0x5555563a8150, blocking=blocking at entry=true) at aio-posix.c:188
#4 0x00005555556e520e in iothread_run (opaque=0x5555563a7fd8) at iothread.c:41
#5 0x00007ffff42ba124 in start_thread () from /usr/lib/libpthread.so.0
#6 0x00007ffff16d14bd in clone () from /usr/lib/libc.so.6
Reported-by: Max Reitz <mreitz at redhat.com>
Cc: Fam Zheng <famz at redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
Tested-by: Christian Borntraeger <borntraeger at de.ibm.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
index 4bc0729..bed9f13 100644
--- a/hw/block/dataplane/virtio-blk.c
+++ b/hw/block/dataplane/virtio-blk.c
@@ -68,7 +68,6 @@ static void complete_request_vring(VirtIOBlockReq *req, unsigned char status)
vring_push(&req->dev->dataplane->vring, req->elem,
req->qiov.size + sizeof(*req->in));
notify_guest(req->dev->dataplane);
- g_slice_free(VirtIOBlockReq, req);
}
static void handle_notify(EventNotifier *e)
commit 8eb029c26ecf61da6c2b45c3c23472e8c477ba34
Author: Kevin Wolf <kwolf at redhat.com>
Date: Tue Jul 1 16:09:54 2014 +0200
block: Assert qiov length matches request length
At least raw-posix relies on this because it can allocate bounce buffers
based on the request length, but access it using all of the qiov entries
later.
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
Reviewed-by: Max Reitz <mreitz at redhat.com>
diff --git a/block.c b/block.c
index 0143268..3e252a2 100644
--- a/block.c
+++ b/block.c
@@ -3010,6 +3010,7 @@ static int coroutine_fn bdrv_aligned_preadv(BlockDriverState *bs,
assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
+ assert(!qiov || bytes == qiov->size);
/* Handle Copy on Read and associated serialisation */
if (flags & BDRV_REQ_COPY_ON_READ) {
@@ -3279,6 +3280,7 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs,
assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
+ assert(!qiov || bytes == qiov->size);
waited = wait_serialising_requests(req);
assert(!waited || !req->serialising);
diff --git a/block/raw-posix.c b/block/raw-posix.c
index a857def..2bcc73d 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -790,6 +790,7 @@ static ssize_t handle_aiocb_rw(RawPosixAIOData *aiocb)
memcpy(p, aiocb->aio_iov[i].iov_base, aiocb->aio_iov[i].iov_len);
p += aiocb->aio_iov[i].iov_len;
}
+ assert(p - buf == aiocb->aio_nbytes);
}
nbytes = handle_aiocb_rw_linear(aiocb, buf);
@@ -804,9 +805,11 @@ static ssize_t handle_aiocb_rw(RawPosixAIOData *aiocb)
copy = aiocb->aio_iov[i].iov_len;
}
memcpy(aiocb->aio_iov[i].iov_base, p, copy);
+ assert(count >= copy);
p += copy;
count -= copy;
}
+ assert(count == 0);
}
qemu_vfree(buf);
@@ -993,12 +996,14 @@ static int paio_submit_co(BlockDriverState *bs, int fd,
acb->aio_type = type;
acb->aio_fildes = fd;
+ acb->aio_nbytes = nb_sectors * BDRV_SECTOR_SIZE;
+ acb->aio_offset = sector_num * BDRV_SECTOR_SIZE;
+
if (qiov) {
acb->aio_iov = qiov->iov;
acb->aio_niov = qiov->niov;
+ assert(qiov->size == acb->aio_nbytes);
}
- acb->aio_nbytes = nb_sectors * 512;
- acb->aio_offset = sector_num * 512;
trace_paio_submit_co(sector_num, nb_sectors, type);
pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
@@ -1016,12 +1021,14 @@ static BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
acb->aio_type = type;
acb->aio_fildes = fd;
+ acb->aio_nbytes = nb_sectors * BDRV_SECTOR_SIZE;
+ acb->aio_offset = sector_num * BDRV_SECTOR_SIZE;
+
if (qiov) {
acb->aio_iov = qiov->iov;
acb->aio_niov = qiov->niov;
+ assert(qiov->size == acb->aio_nbytes);
}
- acb->aio_nbytes = nb_sectors * 512;
- acb->aio_offset = sector_num * 512;
trace_paio_submit(acb, opaque, sector_num, nb_sectors, type);
pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
commit f06ee3d4aa547df8d7d2317b2b6db7a88c1f3744
Author: Kevin Wolf <kwolf at redhat.com>
Date: Fri Jul 4 17:11:28 2014 +0200
qed: Make qiov match request size until backing file EOF
If a QED image has a shorter backing file and a read request to
unallocated clusters goes across EOF of the backing file, the backing
file sees a shortened request and the rest is filled with zeros.
However, the original too long qiov was used with the shortened request.
This patch makes the qiov size match the request size, avoiding a
potential buffer overflow in raw-posix.
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
Reviewed-by: Eric Blake <eblake at redhat.com>
diff --git a/block/qed.c b/block/qed.c
index b69374b..cd4872b 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -761,17 +761,19 @@ static BDRVQEDState *acb_to_s(QEDAIOCB *acb)
/**
* Read from the backing file or zero-fill if no backing file
*
- * @s: QED state
- * @pos: Byte position in device
- * @qiov: Destination I/O vector
- * @cb: Completion function
- * @opaque: User data for completion function
+ * @s: QED state
+ * @pos: Byte position in device
+ * @qiov: Destination I/O vector
+ * @backing_qiov: Possibly shortened copy of qiov, to be allocated here
+ * @cb: Completion function
+ * @opaque: User data for completion function
*
* This function reads qiov->size bytes starting at pos from the backing file.
* If there is no backing file then zeroes are read.
*/
static void qed_read_backing_file(BDRVQEDState *s, uint64_t pos,
QEMUIOVector *qiov,
+ QEMUIOVector **backing_qiov,
BlockDriverCompletionFunc *cb, void *opaque)
{
uint64_t backing_length = 0;
@@ -804,15 +806,21 @@ static void qed_read_backing_file(BDRVQEDState *s, uint64_t pos,
/* If the read straddles the end of the backing file, shorten it */
size = MIN((uint64_t)backing_length - pos, qiov->size);
+ assert(*backing_qiov == NULL);
+ *backing_qiov = g_new(QEMUIOVector, 1);
+ qemu_iovec_init(*backing_qiov, qiov->niov);
+ qemu_iovec_concat(*backing_qiov, qiov, 0, size);
+
BLKDBG_EVENT(s->bs->file, BLKDBG_READ_BACKING_AIO);
bdrv_aio_readv(s->bs->backing_hd, pos / BDRV_SECTOR_SIZE,
- qiov, size / BDRV_SECTOR_SIZE, cb, opaque);
+ *backing_qiov, size / BDRV_SECTOR_SIZE, cb, opaque);
}
typedef struct {
GenericCB gencb;
BDRVQEDState *s;
QEMUIOVector qiov;
+ QEMUIOVector *backing_qiov;
struct iovec iov;
uint64_t offset;
} CopyFromBackingFileCB;
@@ -829,6 +837,12 @@ static void qed_copy_from_backing_file_write(void *opaque, int ret)
CopyFromBackingFileCB *copy_cb = opaque;
BDRVQEDState *s = copy_cb->s;
+ if (copy_cb->backing_qiov) {
+ qemu_iovec_destroy(copy_cb->backing_qiov);
+ g_free(copy_cb->backing_qiov);
+ copy_cb->backing_qiov = NULL;
+ }
+
if (ret) {
qed_copy_from_backing_file_cb(copy_cb, ret);
return;
@@ -866,11 +880,12 @@ static void qed_copy_from_backing_file(BDRVQEDState *s, uint64_t pos,
copy_cb = gencb_alloc(sizeof(*copy_cb), cb, opaque);
copy_cb->s = s;
copy_cb->offset = offset;
+ copy_cb->backing_qiov = NULL;
copy_cb->iov.iov_base = qemu_blockalign(s->bs, len);
copy_cb->iov.iov_len = len;
qemu_iovec_init_external(©_cb->qiov, ©_cb->iov, 1);
- qed_read_backing_file(s, pos, ©_cb->qiov,
+ qed_read_backing_file(s, pos, ©_cb->qiov, ©_cb->backing_qiov,
qed_copy_from_backing_file_write, copy_cb);
}
@@ -1313,7 +1328,7 @@ static void qed_aio_read_data(void *opaque, int ret,
return;
} else if (ret != QED_CLUSTER_FOUND) {
qed_read_backing_file(s, acb->cur_pos, &acb->cur_qiov,
- qed_aio_next_io, acb);
+ &acb->backing_qiov, qed_aio_next_io, acb);
return;
}
@@ -1339,6 +1354,12 @@ static void qed_aio_next_io(void *opaque, int ret)
trace_qed_aio_next_io(s, acb, ret, acb->cur_pos + acb->cur_qiov.size);
+ if (acb->backing_qiov) {
+ qemu_iovec_destroy(acb->backing_qiov);
+ g_free(acb->backing_qiov);
+ acb->backing_qiov = NULL;
+ }
+
/* Handle I/O error */
if (ret) {
qed_aio_complete(acb, ret);
@@ -1378,6 +1399,7 @@ static BlockDriverAIOCB *qed_aio_setup(BlockDriverState *bs,
acb->qiov_offset = 0;
acb->cur_pos = (uint64_t)sector_num * BDRV_SECTOR_SIZE;
acb->end_pos = acb->cur_pos + nb_sectors * BDRV_SECTOR_SIZE;
+ acb->backing_qiov = NULL;
acb->request.l2_table = NULL;
qemu_iovec_init(&acb->cur_qiov, qiov->niov);
diff --git a/block/qed.h b/block/qed.h
index b024751..2b0e724 100644
--- a/block/qed.h
+++ b/block/qed.h
@@ -142,6 +142,7 @@ typedef struct QEDAIOCB {
/* Current cluster scatter-gather list */
QEMUIOVector cur_qiov;
+ QEMUIOVector *backing_qiov;
uint64_t cur_pos; /* position on block device, in bytes */
uint64_t cur_cluster; /* cluster offset in image file */
unsigned int cur_nclusters; /* number of clusters being accessed */
commit 44deba5a52576508f27edadf953e435141e2a76a
Author: Kevin Wolf <kwolf at redhat.com>
Date: Thu Jul 3 14:43:32 2014 +0200
qcow2: Make qiov match request size until backing file EOF
If a qcow2 image has a shorter backing file and a read request to
unallocated clusters goes across EOF of the backing file, the backing
file sees a shortened request and the rest is filled with zeros.
However, the original too long qiov was used with the shortened request.
This patch makes the qiov size match the request size, avoiding a
potential buffer overflow in raw-posix.
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
Reviewed-by: Max Reitz <mreitz at redhat.com>
diff --git a/block/qcow2.c b/block/qcow2.c
index 67e55c9..b0faa69 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1020,11 +1020,20 @@ static coroutine_fn int qcow2_co_readv(BlockDriverState *bs, int64_t sector_num,
n1 = qcow2_backing_read1(bs->backing_hd, &hd_qiov,
sector_num, cur_nr_sectors);
if (n1 > 0) {
+ QEMUIOVector local_qiov;
+
+ qemu_iovec_init(&local_qiov, hd_qiov.niov);
+ qemu_iovec_concat(&local_qiov, &hd_qiov, 0,
+ n1 * BDRV_SECTOR_SIZE);
+
BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
qemu_co_mutex_unlock(&s->lock);
ret = bdrv_co_readv(bs->backing_hd, sector_num,
- n1, &hd_qiov);
+ n1, &local_qiov);
qemu_co_mutex_lock(&s->lock);
+
+ qemu_iovec_destroy(&local_qiov);
+
if (ret < 0) {
goto fail;
}
commit 33f461e0c5d8efa21ef7e746be561fc57a1df106
Author: Kevin Wolf <kwolf at redhat.com>
Date: Thu Jul 3 13:21:24 2014 +0200
block: Make qiov match the request size until EOF
If a read request goes across EOF, the block driver sees a shortened
request that stops at EOF (the rest is memsetted in block.c), however
the original qiov was used for this request.
This patch makes the qiov size match the request size, avoiding a
potential buffer overflow in raw-posix.
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
Reviewed-by: Max Reitz <mreitz at redhat.com>
diff --git a/block.c b/block.c
index 510430d..0143268 100644
--- a/block.c
+++ b/block.c
@@ -3054,8 +3054,20 @@ static int coroutine_fn bdrv_aligned_preadv(BlockDriverState *bs,
max_nb_sectors = ROUND_UP(MAX(0, total_sectors - sector_num),
align >> BDRV_SECTOR_BITS);
if (max_nb_sectors > 0) {
- ret = drv->bdrv_co_readv(bs, sector_num,
- MIN(nb_sectors, max_nb_sectors), qiov);
+ QEMUIOVector local_qiov;
+ size_t local_sectors;
+
+ max_nb_sectors = MIN(max_nb_sectors, SIZE_MAX / BDRV_SECTOR_BITS);
+ local_sectors = MIN(max_nb_sectors, nb_sectors);
+
+ qemu_iovec_init(&local_qiov, qiov->niov);
+ qemu_iovec_concat(&local_qiov, qiov, 0,
+ local_sectors * BDRV_SECTOR_SIZE);
+
+ ret = drv->bdrv_co_readv(bs, sector_num, local_sectors,
+ &local_qiov);
+
+ qemu_iovec_destroy(&local_qiov);
} else {
ret = 0;
}
commit 2039511b8f573165420c86380762ae829dc398d9
Author: Fam Zheng <famz at redhat.com>
Date: Tue Jun 10 14:55:58 2014 +0800
scsi: Report error when lun number is in use
In the case that the lun number is taken by another scsi device, don't
release the existing device siliently, but report an error to user.
Signed-off-by: Fam Zheng <famz at redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index ea1ac09..4341754 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -177,7 +177,8 @@ static int scsi_qdev_init(DeviceState *qdev)
d = scsi_device_find(bus, dev->channel, dev->id, dev->lun);
assert(d);
if (d->lun == dev->lun && dev != d) {
- object_unparent(OBJECT(d));
+ error_report("lun already used by '%s'", d->qdev.id);
+ goto err;
}
}
commit 85ad6230b3af048109b3e949ca95ade4dd9a0bfa
Author: Jason J. Herne <jjherne at us.ibm.com>
Date: Thu Nov 29 10:09:42 2012 -0500
s390x/kvm: synchronize guest floating point registers
Add code to kvm_arch_get_registers and kvm_arch_put_registers to
save/restore floating point registers. This missing sync was
unnoticed until migration of userspace that uses fprs.
Signed-off-by: Jason J. Herne <jjherne at us.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger at de.ibm.com>
[Update patch to latest upstream]
Cc: qemu-stable at nongnu.org
Reviewed-by: Alexander Graf <agraf at suse.de>
Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com>
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index a6e587b..a32d91a 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -207,6 +207,7 @@ int kvm_arch_put_registers(CPUState *cs, int level)
CPUS390XState *env = &cpu->env;
struct kvm_sregs sregs;
struct kvm_regs regs;
+ struct kvm_fpu fpu;
int r;
int i;
@@ -229,6 +230,17 @@ int kvm_arch_put_registers(CPUState *cs, int level)
}
}
+ /* Floating point */
+ for (i = 0; i < 16; i++) {
+ fpu.fprs[i] = env->fregs[i].ll;
+ }
+ fpu.fpc = env->fpc;
+
+ r = kvm_vcpu_ioctl(cs, KVM_SET_FPU, &fpu);
+ if (r < 0) {
+ return r;
+ }
+
/* Do we need to save more than that? */
if (level == KVM_PUT_RUNTIME_STATE) {
return 0;
@@ -296,6 +308,7 @@ int kvm_arch_get_registers(CPUState *cs)
CPUS390XState *env = &cpu->env;
struct kvm_sregs sregs;
struct kvm_regs regs;
+ struct kvm_fpu fpu;
int i, r;
/* get the PSW */
@@ -336,6 +349,16 @@ int kvm_arch_get_registers(CPUState *cs)
}
}
+ /* Floating point */
+ r = kvm_vcpu_ioctl(cs, KVM_GET_FPU, &fpu);
+ if (r < 0) {
+ return r;
+ }
+ for (i = 0; i < 16; i++) {
+ env->fregs[i].ll = fpu.fprs[i];
+ }
+ env->fpc = fpu.fpc;
+
/* The prefix */
if (cap_sync_regs && cs->kvm_run->kvm_valid_regs & KVM_SYNC_PREFIX) {
env->psa = cs->kvm_run->s.regs.prefix;
commit ab6d3749c4915cd5692633e321f7745dce06fe77
Merge: aee230d d16136d
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Fri Jul 11 17:50:38 2014 +0100
Merge remote-tracking branch 'remotes/kraxel/tags/pull-vga-20140711-1' into staging
vga: some cirrus fixes.
# gpg: Signature made Fri 11 Jul 2014 10:38:32 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel at redhat.com>"
# gpg: aka "Gerd Hoffmann <gerd at kraxel.org>"
# gpg: aka "Gerd Hoffmann (private) <kraxel at gmail.com>"
* remotes/kraxel/tags/pull-vga-20140711-1:
cirrus: Fix host CPU blits
cirrus: Fix build of debug code
cirrus_vga: adding sanity check for vram size
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
commit aee230d707155a957c8300ee12049377d3ffebef
Merge: 42ca32f 13d5412
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Fri Jul 11 16:01:38 2014 +0100
Merge remote-tracking branch 'remotes/kraxel/tags/pull-usb-20140711-1' into staging
mtp: linux guest detection fix
# gpg: Signature made Fri 11 Jul 2014 11:32:20 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel at redhat.com>"
# gpg: aka "Gerd Hoffmann <gerd at kraxel.org>"
# gpg: aka "Gerd Hoffmann (private) <kraxel at gmail.com>"
* remotes/kraxel/tags/pull-usb-20140711-1:
mtp: linux guest detection fix.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
commit 42ca32f776c364c6a4c10d7100505b00b7a7f14e
Merge: 22df345 b1ea7b7
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Fri Jul 11 14:50:18 2014 +0100
Merge remote-tracking branch 'remotes/spice/tags/pull-spice-20140711-1' into staging
spice: auth fixes
# gpg: Signature made Fri 11 Jul 2014 10:17:15 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel at redhat.com>"
# gpg: aka "Gerd Hoffmann <gerd at kraxel.org>"
# gpg: aka "Gerd Hoffmann (private) <kraxel at gmail.com>"
* remotes/spice/tags/pull-spice-20140711-1:
spice: auth fixes
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
commit 22df3452dcab04adf57bda370ced35193395a475
Merge: 74aeb37 e72b59f
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Fri Jul 11 13:48:07 2014 +0100
Merge remote-tracking branch 'remotes/kraxel/tags/pull-gtk-20140711-1' into staging
ui/gtk: Restore keyboard focus after Page change
# gpg: Signature made Fri 11 Jul 2014 09:46:21 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel at redhat.com>"
# gpg: aka "Gerd Hoffmann <gerd at kraxel.org>"
# gpg: aka "Gerd Hoffmann (private) <kraxel at gmail.com>"
* remotes/kraxel/tags/pull-gtk-20140711-1:
ui/gtk: Restore keyboard focus after Page change
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
commit 13d54125a3482a5837682499d25f6be10aa824be
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Tue Jul 1 17:49:25 2014 +0200
mtp: linux guest detection fix.
Attach a name to the MTP interface (android phones have this too).
With this patch recent linux guests such as fedora 20 happily detect and
use the device. It shows up in nautilus file manager automatically, and
simple-mtpfs can mount it.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
index 380b465..1b51a90 100644
--- a/hw/usb/dev-mtp.c
+++ b/hw/usb/dev-mtp.c
@@ -145,6 +145,7 @@ enum {
STR_MANUFACTURER = 1,
STR_PRODUCT,
STR_SERIALNUMBER,
+ STR_MTP,
STR_CONFIG_FULL,
STR_CONFIG_HIGH,
STR_CONFIG_SUPER,
@@ -154,6 +155,7 @@ static const USBDescStrings desc_strings = {
[STR_MANUFACTURER] = MTP_MANUFACTURER,
[STR_PRODUCT] = MTP_PRODUCT,
[STR_SERIALNUMBER] = "34617",
+ [STR_MTP] = "MTP",
[STR_CONFIG_FULL] = "Full speed config (usb 1.1)",
[STR_CONFIG_HIGH] = "High speed config (usb 2.0)",
[STR_CONFIG_SUPER] = "Super speed config (usb 3.0)",
@@ -165,6 +167,7 @@ static const USBDescIface desc_iface_full = {
.bInterfaceClass = USB_CLASS_STILL_IMAGE,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01,
+ .iInterface = STR_MTP,
.eps = (USBDescEndpoint[]) {
{
.bEndpointAddress = USB_DIR_IN | EP_DATA_IN,
@@ -206,6 +209,7 @@ static const USBDescIface desc_iface_high = {
.bInterfaceClass = USB_CLASS_STILL_IMAGE,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01,
+ .iInterface = STR_MTP,
.eps = (USBDescEndpoint[]) {
{
.bEndpointAddress = USB_DIR_IN | EP_DATA_IN,
commit e72b59fa93b68635f42cdb1b1134f60dd4040d7b
Author: John Snow <jsnow at redhat.com>
Date: Tue Jul 8 14:28:57 2014 -0400
ui/gtk: Restore keyboard focus after Page change
(Resending for correct email addresses via MAINTAINERS ...)
In the GTK UI, after changing focus to the qemu monitor Notebook Page,
when restoring focus to the virtual machine page, the keyboard focus is lost
to a hidden GTK widget. Focus can only be restored to the virtual machine by
pressing "tab" or any of the four directional arrow keys.
Clicking in the window or grabbing/ungrabbing input does not restore keyboard
focus to the child widget.
This patch adjusts the Notebook page switching callback to automatically
steal keyboard focus on the Page switch event, so that keyboard input
does not appear to break or disappear after tabbing to the QEMU monitor.
Signed-off-by: John Snow <jsnow at redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/ui/gtk.c b/ui/gtk.c
index b02fcd6..2345d7e 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -992,13 +992,16 @@ static void gd_menu_switch_vc(GtkMenuItem *item, void *opaque)
{
GtkDisplayState *s = opaque;
VirtualConsole *vc = gd_vc_find_by_menu(s);
+ GtkNotebook *nb = GTK_NOTEBOOK(s->notebook);
+ GtkWidget *child;
gint page;
gtk_release_modifiers(s);
if (vc) {
- page = gtk_notebook_page_num(GTK_NOTEBOOK(s->notebook),
- vc->tab_item);
- gtk_notebook_set_current_page(GTK_NOTEBOOK(s->notebook), page);
+ page = gtk_notebook_page_num(nb, vc->tab_item);
+ gtk_notebook_set_current_page(nb, page);
+ child = gtk_notebook_get_nth_page(nb, page);
+ gtk_widget_grab_focus(child);
}
}
commit d16136d22af0fcf0d651de04c9e3cbc7137cc6f9
Author: Benjamin Herrenschmidt <benh at kernel.crashing.org>
Date: Mon Jul 7 10:32:34 2014 +1000
cirrus: Fix host CPU blits
Commit b2eb849d4b1fdb6f35d5c46958c7f703cf64cfef
"CVE-2007-1320 - Cirrus LGD-54XX "bitblt" heap overflow" broke
cpu to video blits.
When the ROP function is called from cirrus_bitblt_cputovideo_next(),
we pass 0 for the pitch but only operate on one line at a time. The
added test was tripping because after the initial substraction, the
pitch becomes negative. Make the test only trip when the height is
larger than one (ie. the pitch is actually used).
This fixes HW cursor support in Windows NT4.0 (which otherwise was
a white rectangle) and general display of icons in that OS when using
8bpp mode.
Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/display/cirrus_vga_rop.h b/hw/display/cirrus_vga_rop.h
index 9c7bb09..0925a00 100644
--- a/hw/display/cirrus_vga_rop.h
+++ b/hw/display/cirrus_vga_rop.h
@@ -52,8 +52,7 @@ glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s,
dstpitch -= bltwidth;
srcpitch -= bltwidth;
- if (dstpitch < 0 || srcpitch < 0) {
- /* is 0 valid? srcpitch == 0 could be useful */
+ if (bltheight > 1 && (dstpitch < 0 || srcpitch < 0)) {
return;
}
commit e8ee4b68bed36471b014c23209299c84b8d4a01b
Author: Benjamin Herrenschmidt <benh at kernel.crashing.org>
Date: Wed Jul 2 20:32:08 2014 +1000
cirrus: Fix build of debug code
Use PRIu64 to print uint64_t
Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index 52d039e..db330e9 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -2059,7 +2059,7 @@ static void cirrus_vga_mem_write(void *opaque,
}
} else {
#ifdef DEBUG_CIRRUS
- printf("cirrus: mem_writeb " TARGET_FMT_plx " value %02x\n", addr,
+ printf("cirrus: mem_writeb " TARGET_FMT_plx " value 0x%02" PRIu64 "\n", addr,
mem_value);
#endif
}
@@ -2594,7 +2594,7 @@ static void cirrus_vga_ioport_write(void *opaque, hwaddr addr, uint64_t val,
break;
case 0x3c5:
#ifdef DEBUG_VGA_REG
- printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
+ printf("vga: write SR%x = 0x%02" PRIu64 "\n", s->sr_index, val);
#endif
cirrus_vga_write_sr(c, val);
break;
@@ -2619,7 +2619,7 @@ static void cirrus_vga_ioport_write(void *opaque, hwaddr addr, uint64_t val,
break;
case 0x3cf:
#ifdef DEBUG_VGA_REG
- printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
+ printf("vga: write GR%x = 0x%02" PRIu64 "\n", s->gr_index, val);
#endif
cirrus_vga_write_gr(c, s->gr_index, val);
break;
@@ -2630,7 +2630,7 @@ static void cirrus_vga_ioport_write(void *opaque, hwaddr addr, uint64_t val,
case 0x3b5:
case 0x3d5:
#ifdef DEBUG_VGA_REG
- printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
+ printf("vga: write CR%x = 0x%02"PRIu64"\n", s->cr_index, val);
#endif
cirrus_vga_write_cr(c, val);
break;
commit f61d82c2dfe02a60642a76e8f0034a0244eef2bf
Author: Gonglei <arei.gonglei at huawei.com>
Date: Mon May 12 15:10:38 2014 +0800
cirrus_vga: adding sanity check for vram size
when configure a invalid vram size for cirrus card, such as less
2 MB, which will crash qemu. Follow the real hardware, the cirrus
card has 4 MB video memory. Also for backward compatibility, accept
8 MB and 16 MB vram size.
Signed-off-by: Gonglei <arei.gonglei at huawei.com>
Reviewed-by: Andreas Färber <afaerber at suse.de>
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index 6fbe39d..52d039e 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -2911,6 +2911,14 @@ static void isa_cirrus_vga_realizefn(DeviceState *dev, Error **errp)
ISACirrusVGAState *d = ISA_CIRRUS_VGA(dev);
VGACommonState *s = &d->cirrus_vga.vga;
+ /* follow real hardware, cirrus card emulated has 4 MB video memory.
+ Also accept 8 MB/16 MB for backward compatibility. */
+ if (s->vram_size_mb != 4 && s->vram_size_mb != 8 &&
+ s->vram_size_mb != 16) {
+ error_setg(errp, "Invalid cirrus_vga ram size '%u'",
+ s->vram_size_mb);
+ return;
+ }
vga_common_init(s, OBJECT(dev), true);
cirrus_init_common(&d->cirrus_vga, OBJECT(dev), CIRRUS_ID_CLGD5430, 0,
isa_address_space(isadev),
@@ -2957,6 +2965,14 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
int16_t device_id = pc->device_id;
+ /* follow real hardware, cirrus card emulated has 4 MB video memory.
+ Also accept 8 MB/16 MB for backward compatibility. */
+ if (s->vga.vram_size_mb != 4 && s->vga.vram_size_mb != 8 &&
+ s->vga.vram_size_mb != 16) {
+ error_report("Invalid cirrus_vga ram size '%u'",
+ s->vga.vram_size_mb);
+ return -1;
+ }
/* setup VGA */
vga_common_init(&s->vga, OBJECT(dev), true);
cirrus_init_common(s, OBJECT(dev), device_id, 1, pci_address_space(dev),
commit b1ea7b79e1675355ea7abe2548ad71dcf7d64b60
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Wed Jul 2 12:56:42 2014 +0200
spice: auth fixes
Set auth to sasl when sasl is enabled, this makes "info spice" correctly
display sasl auth. Also throw an error in case someone tries to set
a spice password via monitor without auth mode being "spice".
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/ui/spice-core.c b/ui/spice-core.c
index 70df446..7bb91e6 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -741,6 +741,7 @@ void qemu_spice_init(void)
error_report("spice: failed to enable sasl");
exit(1);
}
+ auth = "sasl";
}
if (qemu_opt_get_bool(opts, "disable-ticketing", 0)) {
auth = "none";
@@ -894,6 +895,10 @@ static int qemu_spice_set_ticket(bool fail_if_conn, bool disconnect_if_conn)
int qemu_spice_set_passwd(const char *passwd,
bool fail_if_conn, bool disconnect_if_conn)
{
+ if (strcmp(auth, "spice") != 0) {
+ return -1;
+ }
+
g_free(auth_passwd);
auth_passwd = g_strdup(passwd);
return qemu_spice_set_ticket(fail_if_conn, disconnect_if_conn);
commit 74aeb37de06083ab130bf0da7c264043887c6c04
Merge: 9e99c5f 0a58991
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Thu Jul 10 17:37:16 2014 +0100
Merge remote-tracking branch 'remotes/kvm/uq/master' into staging
* remotes/kvm/uq/master:
qtest: fix vhost-user-test compilation with old GLib
mc146818rtc: register the clock reset notifier on the right clock
oslib-posix: Fix new compiler error with -Wclobbered
target-i386: Add "kvmclock-stable-bit" feature bit name
Enforce stack protector usage
watchdog: fix deadlock with -watchdog-action pause
mips_malta: Catch kernels linked at wrong address
mips_malta: Remove incorrect KVM T&E references
mips/kvm: Disable FPU on reset with KVM
mips/kvm: Init EBase to correct KSEG0
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
commit 0a58991a5f7efd6eb8a66643f4fd894b9c6874b7
Author: Nikolay Nikolaev <n.nikolaev at virtualopensystems.com>
Date: Wed Jul 9 18:06:32 2014 +0300
qtest: fix vhost-user-test compilation with old GLib
Mising G_TIME_SPAN_SECOND definition breaks the RHEL6 compilation as GLib
version before 2.26 does not have it. In such case just define it.
Reported-by: Kevin Wolf <kwolf at redhat.com>
Signed-off-by: Nikolay Nikolaev <n.nikolaev at virtualopensystems.com>
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index 2af2381..406ba70 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -22,6 +22,10 @@
#include <qemu/sockets.h>
/* GLIB version compatibility flags */
+#if !GLIB_CHECK_VERSION(2, 26, 0)
+#define G_TIME_SPAN_SECOND (G_GINT64_CONSTANT(1000000))
+#endif
+
#if GLIB_CHECK_VERSION(2, 28, 0)
#define HAVE_MONOTONIC_TIME
#endif
commit 13c0cbaec5698f3984606e52bfcfb63ddfc29f00
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Tue Jul 8 07:42:05 2014 +0200
mc146818rtc: register the clock reset notifier on the right clock
Commit 884f17c (aio / timers: Convert rtc_clock to be a QEMUClockType,
2013-08-21) erroneously changed an occurrence of rtc_clock to
QEMU_CLOCK_REALTIME, which broke the RTC reset notifier in
mc146818rtc. Fix this.
I redid the patch myself since the original reporter did not sign
off on his.
Cc: qemu-stable at nongnu.org
Reported-by: Lb peace <peaceustc at gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 9d817ca..233fc70 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -895,7 +895,7 @@ static void rtc_realizefn(DeviceState *dev, Error **errp)
check_update_timer(s);
s->clock_reset_notifier.notify = rtc_notify_clock_reset;
- qemu_clock_register_reset_notifier(QEMU_CLOCK_REALTIME,
+ qemu_clock_register_reset_notifier(rtc_clock,
&s->clock_reset_notifier);
s->suspend_notifier.notify = rtc_notify_suspend;
commit b7bf8f5657d48e4625c86cd5f1d3cc83e830d8f7
Author: Stefan Weil <sw at weilnetz.de>
Date: Tue Jun 24 22:52:29 2014 +0200
oslib-posix: Fix new compiler error with -Wclobbered
Newer versions of gcc report a warning (or an error with -Werror) when
compiler option -Wclobbered (or -Wextra) is active:
util/oslib-posix.c:372:12: error:
variable âhpagesizeâ might be clobbered by âlongjmpâ or âvforkâ [-Werror=clobbered]
The rewritten code fixes this warning: variable 'hpagesize' is now set and
used in a block without any call of sigsetjmp or similar functions.
Signed-off-by: Stefan Weil <sw at weilnetz.de>
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index 1524ead..cdbfb2e 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -366,10 +366,9 @@ static size_t fd_getpagesize(int fd)
void os_mem_prealloc(int fd, char *area, size_t memory)
{
- int ret, i;
+ int ret;
struct sigaction act, oldact;
sigset_t set, oldset;
- size_t hpagesize = fd_getpagesize(fd);
memset(&act, 0, sizeof(act));
act.sa_handler = &sigbus_handler;
@@ -389,19 +388,22 @@ void os_mem_prealloc(int fd, char *area, size_t memory)
if (sigsetjmp(sigjump, 1)) {
fprintf(stderr, "os_mem_prealloc: failed to preallocate pages\n");
exit(1);
- }
+ } else {
+ int i;
+ size_t hpagesize = fd_getpagesize(fd);
- /* MAP_POPULATE silently ignores failures */
- memory = (memory + hpagesize - 1) & -hpagesize;
- for (i = 0; i < (memory/hpagesize); i++) {
- memset(area + (hpagesize*i), 0, 1);
- }
+ /* MAP_POPULATE silently ignores failures */
+ memory = (memory + hpagesize - 1) & -hpagesize;
+ for (i = 0; i < (memory / hpagesize); i++) {
+ memset(area + (hpagesize * i), 0, 1);
+ }
- ret = sigaction(SIGBUS, &oldact, NULL);
- if (ret) {
- perror("os_mem_prealloc: failed to reinstall signal handler");
- exit(1);
- }
+ ret = sigaction(SIGBUS, &oldact, NULL);
+ if (ret) {
+ perror("os_mem_prealloc: failed to reinstall signal handler");
+ exit(1);
+ }
- pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+ pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+ }
}
commit 8248c36a5db6ff7d5f07f05148be0dd0160e650c
Author: Eduardo Habkost <ehabkost at redhat.com>
Date: Fri Jul 4 16:44:34 2014 -0300
target-i386: Add "kvmclock-stable-bit" feature bit name
KVM_FEATURE_CLOCKSOURCE_STABLE_BIT is enabled by default and supported
by KVM. But not having a name defined makes QEMU treat it as an unknown
and unmigratable feature flag (as any unknown feature may possibly
require state to be migrated), and disable it by default on "-cpu host".
As a side-effect, the new name also makes the flag configurable,
allowing the user to disable it (which may be useful for testing or for
compatibility with old kernels).
Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 45c662d..6d008ab 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -241,7 +241,7 @@ static const char *kvm_feature_name[] = {
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
+ "kvmclock-stable-bit", NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
};
commit 3b463a3fa8f7690ffa3ef273993dff349b3a73d3
Author: Miroslav Rezanina <mrezanin at redhat.com>
Date: Wed Jul 2 10:05:24 2014 +0200
Enforce stack protector usage
If --enable-stack-protector is used is used, configure script try to use
--fstack-protector-strong. In case it's not supported, --fstack-protector-all
is enabled. If both protectors are not supported, configure does not use
any protector at all without any notification.
This patch reports error when user requests stack protector to be used and
both protector modes are not supported. Behavior is not changed in case
user do not use any of --enable-stack-protector/--disable-stack-protector.
Signed-off-by: Miroslav Rezanina <mrezanin at redhat.com>
[Fix non-POSIX operator in test. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
diff --git a/configure b/configure
index 7dd43fd..f7685b5 100755
--- a/configure
+++ b/configure
@@ -1489,8 +1489,9 @@ for flag in $gcc_flags; do
fi
done
-if test "$stack_protector" != "no" ; then
+if test "$stack_protector" != "no"; then
gcc_flags="-fstack-protector-strong -fstack-protector-all"
+ sp_on=0
for flag in $gcc_flags; do
# We need to check both a compile and a link, since some compiler
# setups fail only on a .c->.o compile and some only at link time
@@ -1498,9 +1499,15 @@ if test "$stack_protector" != "no" ; then
compile_prog "-Werror $flag" ""; then
QEMU_CFLAGS="$QEMU_CFLAGS $flag"
LIBTOOLFLAGS="$LIBTOOLFLAGS -Wc,$flag"
+ sp_on=1
break
fi
done
+ if test "$stack_protector" = yes; then
+ if test $sp_on = 0; then
+ error_exit "Stack protector not supported"
+ fi
+ fi
fi
# Workaround for http://gcc.gnu.org/PR55489. Happens with -fPIE/-fPIC and
commit 30e5210a706ca6b52cbefa8b71e40ae614ffd6e5
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Fri Jun 27 16:31:07 2014 +0200
watchdog: fix deadlock with -watchdog-action pause
qemu_clock_enable says:
/* Disabling the clock will wait for related timerlists to stop
* executing qemu_run_timers. Thus, this functions should not
* be used from the callback of a timer that is based on @clock.
* Doing so would cause a deadlock.
*/
and it indeed does: vm_stop uses qemu_clock_enable on QEMU_CLOCK_VIRTUAL
and watchdogs are based on QEMU_CLOCK_VIRTUAL, and we get a deadlock.
Use qemu_system_vmstop_request_prepare()/qemu_system_vmstop_request()
instead; yet another alternative could be a BH.
I checked other occurrences of vm_stop and they should not have this
problem. RUN_STATE_IO_ERROR could in principle (it depends on the
code in the drivers) but it has been fixed by commit 2bd3bce, "block:
asynchronously stop the VM on I/O errors", 2014-06-05.
Tested-by: Luiz Capitulino <lcapitulino at redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
diff --git a/hw/watchdog/watchdog.c b/hw/watchdog/watchdog.c
index 9f607d4..c307f9b 100644
--- a/hw/watchdog/watchdog.c
+++ b/hw/watchdog/watchdog.c
@@ -122,8 +122,12 @@ void watchdog_perform_action(void)
exit(0);
case WDT_PAUSE: /* same as 'stop' command in monitor */
+ /* In a timer callback, when vm_stop calls qemu_clock_enable
+ * you would get a deadlock. Bypass the problem.
+ */
+ qemu_system_vmstop_request_prepare();
qapi_event_send_watchdog(WATCHDOG_EXPIRATION_ACTION_PAUSE, &error_abort);
- vm_stop(RUN_STATE_WATCHDOG);
+ qemu_system_vmstop_request(RUN_STATE_WATCHDOG);
break;
case WDT_DEBUG:
commit f7f152458e953690f1c8025f507a26d554f6ee4d
Author: James Hogan <james.hogan at imgtec.com>
Date: Thu Jun 26 10:44:25 2014 +0100
mips_malta: Catch kernels linked at wrong address
Add error reporting if the wrong type of kernel is provided for the
current mode of acceleration.
Currently a KVM kernel linked at 0x40000000 can't be used with TCG, and
a normal kernel linked at 0x80000000 can't be used with KVM.
Cc: Aurelien Jarno <aurelien at aurel32.net>
Cc: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: James Hogan <james.hogan at imgtec.com>
Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index 3305a25..cfb60af 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -792,9 +792,23 @@ static int64_t load_kernel (void)
loaderparams.kernel_filename);
exit(1);
}
+
+ /* Sanity check where the kernel has been linked */
if (kvm_enabled()) {
+ if (kernel_entry & 0x80000000ll) {
+ error_report("KVM guest kernels must be linked in useg. "
+ "Did you forget to enable CONFIG_KVM_GUEST?");
+ exit(1);
+ }
+
xlate_to_kseg0 = cpu_mips_kvm_um_phys_to_kseg0;
} else {
+ if (!(kernel_entry & 0x80000000ll)) {
+ error_report("KVM guest kernels aren't supported with TCG. "
+ "Did you unintentionally enable CONFIG_KVM_GUEST?");
+ exit(1);
+ }
+
xlate_to_kseg0 = cpu_mips_phys_to_kseg0;
}
commit fbdb1d955511c38e61e3aa3ba4fb3944b126eb28
Author: James Hogan <james.hogan at imgtec.com>
Date: Thu Jun 26 10:44:24 2014 +0100
mips_malta: Remove incorrect KVM T&E references
Fix the error message and code comments relating to KVM not supporting
booting from the flash mapping when no kernel is provided. The issue is
a general MIPS KVM issue and isn't specific to the Trap & Emulate
version of MIPS KVM.
Cc: Aurelien Jarno <aurelien at aurel32.net>
Cc: Paolo Bonzini <pbonzini at redhat.com>
Reported-by: Andreas Färber <afaerber at suse.de>
Signed-off-by: James Hogan <james.hogan at imgtec.com>
Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index 2868ee5..3305a25 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -1028,7 +1028,7 @@ void mips_malta_init(MachineState *machine)
fl_idx++;
if (kernel_filename) {
ram_low_size = MIN(ram_size, 256 << 20);
- /* For KVM T&E we reserve 1MB of RAM for running bootloader */
+ /* For KVM we reserve 1MB of RAM for running bootloader */
if (kvm_enabled()) {
ram_low_size -= 0x100000;
bootloader_run_addr = 0x40000000 + ram_low_size;
@@ -1052,10 +1052,10 @@ void mips_malta_init(MachineState *machine)
bootloader_run_addr, kernel_entry);
}
} else {
- /* The flash region isn't executable from a KVM T&E guest */
+ /* The flash region isn't executable from a KVM guest */
if (kvm_enabled()) {
error_report("KVM enabled but no -kernel argument was specified. "
- "Booting from flash is not supported with KVM T&E.");
+ "Booting from flash is not supported with KVM.");
exit(1);
}
/* Load firmware from flash. */
commit 0e928b12c94a4eea56028dec676422b165063ea5
Author: James Hogan <james.hogan at imgtec.com>
Date: Fri Jun 27 16:22:42 2014 +0100
mips/kvm: Disable FPU on reset with KVM
KVM doesn't yet support the MIPS FPU, or writing to the guest's Config1
register which contains the FPU implemented bit. Clear QEMU's version of
that bit on reset and display a warning that the FPU has been disabled.
The previous incorrect Config1 CP0 register value wasn't being passed to
KVM yet, however we should ensure it is set correctly now to reduce the
risk of breaking migration/loadvm to a future version of QEMU/Linux that
does support it.
Signed-off-by: James Hogan <james.hogan at imgtec.com>
Cc: Aurelien Jarno <aurelien at aurel32.net>
Cc: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
diff --git a/target-mips/kvm.c b/target-mips/kvm.c
index 844e5bb..97fd51a 100644
--- a/target-mips/kvm.c
+++ b/target-mips/kvm.c
@@ -61,6 +61,13 @@ int kvm_arch_init_vcpu(CPUState *cs)
void kvm_mips_reset_vcpu(MIPSCPU *cpu)
{
+ CPUMIPSState *env = &cpu->env;
+
+ if (env->CP0_Config1 & (1 << CP0C1_FP)) {
+ fprintf(stderr, "Warning: FPU not supported with KVM, disabling\n");
+ env->CP0_Config1 &= ~(1 << CP0C1_FP);
+ }
+
DPRINTF("%s\n", __func__);
}
commit 0ceb849bd336a5f9b6e1ed56d45cf5773d251ad8
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Mon Jul 7 15:18:04 2014 +0200
AioContext: speed up aio_notify
In many cases, the call to event_notifier_set in aio_notify is unnecessary.
In particular, if we are executing aio_dispatch, or if aio_poll is not
blocking, we know that we will soon get to the next loop iteration (if
necessary); the thread that hosts the AioContext's event loop does not
need any nudging.
The patch includes a Promela formal model that shows that this really
works and does not need any further complication such as generation
counts. It needs a memory barrier though.
The generation counts are not needed because any change to
ctx->dispatching after the memory barrier is okay for aio_notify.
If it changes from zero to one, it is the right thing to skip
event_notifier_set. If it changes from one to zero, the
event_notifier_set is unnecessary but harmless.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/aio-posix.c b/aio-posix.c
index 44c4df3..2eada2e 100644
--- a/aio-posix.c
+++ b/aio-posix.c
@@ -175,11 +175,38 @@ static bool aio_dispatch(AioContext *ctx)
bool aio_poll(AioContext *ctx, bool blocking)
{
AioHandler *node;
+ bool was_dispatching;
int ret;
bool progress;
+ was_dispatching = ctx->dispatching;
progress = false;
+ /* aio_notify can avoid the expensive event_notifier_set if
+ * everything (file descriptors, bottom halves, timers) will
+ * be re-evaluated before the next blocking poll(). This happens
+ * in two cases:
+ *
+ * 1) when aio_poll is called with blocking == false
+ *
+ * 2) when we are called after poll(). If we are called before
+ * poll(), bottom halves will not be re-evaluated and we need
+ * aio_notify() if blocking == true.
+ *
+ * The first aio_dispatch() only does something when AioContext is
+ * running as a GSource, and in that case aio_poll is used only
+ * with blocking == false, so this optimization is already quite
+ * effective. However, the code is ugly and should be restructured
+ * to have a single aio_dispatch() call. To do this, we need to
+ * reorganize aio_poll into a prepare/poll/dispatch model like
+ * glib's.
+ *
+ * If we're in a nested event loop, ctx->dispatching might be true.
+ * In that case we can restore it just before returning, but we
+ * have to clear it now.
+ */
+ aio_set_dispatching(ctx, !blocking);
+
/*
* If there are callbacks left that have been queued, we need to call them.
* Do not call select in this case, because it is possible that the caller
@@ -190,12 +217,14 @@ bool aio_poll(AioContext *ctx, bool blocking)
progress = true;
}
+ /* Re-evaluate condition (1) above. */
+ aio_set_dispatching(ctx, !blocking);
if (aio_dispatch(ctx)) {
progress = true;
}
if (progress && !blocking) {
- return true;
+ goto out;
}
ctx->walking_handlers++;
@@ -234,9 +263,12 @@ bool aio_poll(AioContext *ctx, bool blocking)
}
/* Run dispatch even if there were no readable fds to run timers */
+ aio_set_dispatching(ctx, true);
if (aio_dispatch(ctx)) {
progress = true;
}
+out:
+ aio_set_dispatching(ctx, was_dispatching);
return progress;
}
diff --git a/async.c b/async.c
index 5b6fe6b..34af0b2 100644
--- a/async.c
+++ b/async.c
@@ -26,6 +26,7 @@
#include "block/aio.h"
#include "block/thread-pool.h"
#include "qemu/main-loop.h"
+#include "qemu/atomic.h"
/***********************************************************/
/* bottom halves (can be seen as timers which expire ASAP) */
@@ -247,9 +248,25 @@ ThreadPool *aio_get_thread_pool(AioContext *ctx)
return ctx->thread_pool;
}
+void aio_set_dispatching(AioContext *ctx, bool dispatching)
+{
+ ctx->dispatching = dispatching;
+ if (!dispatching) {
+ /* Write ctx->dispatching before reading e.g. bh->scheduled.
+ * Optimization: this is only needed when we're entering the "unsafe"
+ * phase where other threads must call event_notifier_set.
+ */
+ smp_mb();
+ }
+}
+
void aio_notify(AioContext *ctx)
{
- event_notifier_set(&ctx->notifier);
+ /* Write e.g. bh->scheduled before reading ctx->dispatching. */
+ smp_mb();
+ if (!ctx->dispatching) {
+ event_notifier_set(&ctx->notifier);
+ }
}
static void aio_timerlist_notify(void *opaque)
diff --git a/docs/aio_notify.promela b/docs/aio_notify.promela
new file mode 100644
index 0000000..ad3f6f0
--- /dev/null
+++ b/docs/aio_notify.promela
@@ -0,0 +1,104 @@
+/*
+ * This model describes the interaction between aio_set_dispatching()
+ * and aio_notify().
+ *
+ * Author: Paolo Bonzini <pbonzini at redhat.com>
+ *
+ * This file is in the public domain. If you really want a license,
+ * the WTFPL will do.
+ *
+ * To simulate it:
+ * spin -p docs/aio_notify.promela
+ *
+ * To verify it:
+ * spin -a docs/aio_notify.promela
+ * gcc -O2 pan.c
+ * ./a.out -a
+ */
+
+#define MAX 4
+#define LAST (1 << (MAX - 1))
+#define FINAL ((LAST << 1) - 1)
+
+bool dispatching;
+bool event;
+
+int req, done;
+
+active proctype waiter()
+{
+ int fetch, blocking;
+
+ do
+ :: done != FINAL -> {
+ // Computing "blocking" is separate from execution of the
+ // "bottom half"
+ blocking = (req == 0);
+
+ // This is our "bottom half"
+ atomic { fetch = req; req = 0; }
+ done = done | fetch;
+
+ // Wait for a nudge from the other side
+ do
+ :: event == 1 -> { event = 0; break; }
+ :: !blocking -> break;
+ od;
+
+ dispatching = 1;
+
+ // If you are simulating this model, you may want to add
+ // something like this here:
+ //
+ // int foo; foo++; foo++; foo++;
+ //
+ // This only wastes some time and makes it more likely
+ // that the notifier process hits the "fast path".
+
+ dispatching = 0;
+ }
+ :: else -> break;
+ od
+}
+
+active proctype notifier()
+{
+ int next = 1;
+ int sets = 0;
+
+ do
+ :: next <= LAST -> {
+ // generate a request
+ req = req | next;
+ next = next << 1;
+
+ // aio_notify
+ if
+ :: dispatching == 0 -> sets++; event = 1;
+ :: else -> skip;
+ fi;
+
+ // Test both synchronous and asynchronous delivery
+ if
+ :: 1 -> do
+ :: req == 0 -> break;
+ od;
+ :: 1 -> skip;
+ fi;
+ }
+ :: else -> break;
+ od;
+ printf("Skipped %d event_notifier_set\n", MAX - sets);
+}
+
+#define p (done == FINAL)
+
+never {
+ do
+ :: 1 // after an arbitrarily long prefix
+ :: p -> break // p becomes true
+ od;
+ do
+ :: !p -> accept: break // it then must remains true forever after
+ od
+}
diff --git a/include/block/aio.h b/include/block/aio.h
index d81250c..433e7ff 100644
--- a/include/block/aio.h
+++ b/include/block/aio.h
@@ -60,8 +60,14 @@ struct AioContext {
*/
int walking_handlers;
+ /* Used to avoid unnecessary event_notifier_set calls in aio_notify.
+ * Writes protected by lock or BQL, reads are lockless.
+ */
+ bool dispatching;
+
/* lock to protect between bh's adders and deleter */
QemuMutex bh_lock;
+
/* Anchor of the list of Bottom Halves belonging to the context */
struct QEMUBH *first_bh;
@@ -83,6 +89,9 @@ struct AioContext {
QEMUTimerListGroup tlg;
};
+/* Used internally to synchronize aio_poll against qemu_bh_schedule. */
+void aio_set_dispatching(AioContext *ctx, bool dispatching);
+
/**
* aio_context_new: Allocate a new AioContext.
*
commit ef508f427b348c7f0ef2bfe7c080fe5fcaee9f6b
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Mon Jul 7 15:18:03 2014 +0200
test-aio: fix GSource-based timer test
The current test depends too much on the implementation of the AioContext
GSource. Just iterate on the main loop until the callback has been invoked
the right number of times.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/tests/test-aio.c b/tests/test-aio.c
index e5f8b55..264dab9 100644
--- a/tests/test-aio.c
+++ b/tests/test-aio.c
@@ -806,17 +806,16 @@ static void test_source_timer_schedule(void)
g_usleep(1 * G_USEC_PER_SEC);
g_assert_cmpint(data.n, ==, 0);
- g_assert(g_main_context_iteration(NULL, false));
+ g_assert(g_main_context_iteration(NULL, true));
g_assert_cmpint(data.n, ==, 1);
+ expiry += data.ns;
- /* The comment above was not kidding when it said this wakes up itself */
- do {
- g_assert(g_main_context_iteration(NULL, true));
- } while (qemu_clock_get_ns(data.clock_type) <= expiry);
- g_usleep(1 * G_USEC_PER_SEC);
- g_main_context_iteration(NULL, false);
+ while (data.n < 2) {
+ g_main_context_iteration(NULL, true);
+ }
g_assert_cmpint(data.n, ==, 2);
+ g_assert(qemu_clock_get_ns(data.clock_type) > expiry);
aio_set_fd_handler(ctx, pipefd[0], NULL, NULL, NULL);
close(pipefd[0]);
commit 87f68d318222563822b5c6b28192215fc4b4e441
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Mon Jul 7 15:18:02 2014 +0200
block: drop aio functions that operate on the main AioContext
The main AioContext should be accessed explicitly via qemu_get_aio_context().
Most of the time, using it is not the right thing to do.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/aio-posix.c b/aio-posix.c
index f921d4f..44c4df3 100644
--- a/aio-posix.c
+++ b/aio-posix.c
@@ -125,7 +125,7 @@ static bool aio_dispatch(AioContext *ctx)
bool progress = false;
/*
- * We have to walk very carefully in case qemu_aio_set_fd_handler is
+ * We have to walk very carefully in case aio_set_fd_handler is
* called while we're walking.
*/
node = QLIST_FIRST(&ctx->aio_handlers);
@@ -183,7 +183,7 @@ bool aio_poll(AioContext *ctx, bool blocking)
/*
* If there are callbacks left that have been queued, we need to call them.
* Do not call select in this case, because it is possible that the caller
- * does not need a complete flush (as is the case for qemu_aio_wait loops).
+ * does not need a complete flush (as is the case for aio_poll loops).
*/
if (aio_bh_poll(ctx)) {
blocking = false;
diff --git a/aio-win32.c b/aio-win32.c
index 23f4e5b..c12f61e 100644
--- a/aio-win32.c
+++ b/aio-win32.c
@@ -102,7 +102,7 @@ bool aio_poll(AioContext *ctx, bool blocking)
/*
* If there are callbacks left that have been queued, we need to call then.
* Do not call select in this case, because it is possible that the caller
- * does not need a complete flush (as is the case for qemu_aio_wait loops).
+ * does not need a complete flush (as is the case for aio_poll loops).
*/
if (aio_bh_poll(ctx)) {
blocking = false;
@@ -115,7 +115,7 @@ bool aio_poll(AioContext *ctx, bool blocking)
/*
* Then dispatch any pending callbacks from the GSource.
*
- * We have to walk very carefully in case qemu_aio_set_fd_handler is
+ * We have to walk very carefully in case aio_set_fd_handler is
* called while we're walking.
*/
node = QLIST_FIRST(&ctx->aio_handlers);
@@ -177,7 +177,7 @@ bool aio_poll(AioContext *ctx, bool blocking)
blocking = false;
/* we have to walk very carefully in case
- * qemu_aio_set_fd_handler is called while we're walking */
+ * aio_set_fd_handler is called while we're walking */
node = QLIST_FIRST(&ctx->aio_handlers);
while (node) {
AioHandler *tmp;
diff --git a/include/block/aio.h b/include/block/aio.h
index a92511b..d81250c 100644
--- a/include/block/aio.h
+++ b/include/block/aio.h
@@ -220,7 +220,7 @@ bool aio_poll(AioContext *ctx, bool blocking);
#ifdef CONFIG_POSIX
/* Register a file descriptor and associated callbacks. Behaves very similarly
* to qemu_set_fd_handler2. Unlike qemu_set_fd_handler2, these callbacks will
- * be invoked when using qemu_aio_wait().
+ * be invoked when using aio_poll().
*
* Code that invokes AIO completion functions should rely on this function
* instead of qemu_set_fd_handler[2].
@@ -234,7 +234,7 @@ void aio_set_fd_handler(AioContext *ctx,
/* Register an event notifier and associated callbacks. Behaves very similarly
* to event_notifier_set_handler. Unlike event_notifier_set_handler, these callbacks
- * will be invoked when using qemu_aio_wait().
+ * will be invoked when using aio_poll().
*
* Code that invokes AIO completion functions should rely on this function
* instead of event_notifier_set_handler.
@@ -251,19 +251,6 @@ GSource *aio_get_g_source(AioContext *ctx);
/* Return the ThreadPool bound to this AioContext */
struct ThreadPool *aio_get_thread_pool(AioContext *ctx);
-/* Functions to operate on the main QEMU AioContext. */
-
-bool qemu_aio_wait(void);
-void qemu_aio_set_event_notifier(EventNotifier *notifier,
- EventNotifierHandler *io_read);
-
-#ifdef CONFIG_POSIX
-void qemu_aio_set_fd_handler(int fd,
- IOHandler *io_read,
- IOHandler *io_write,
- void *opaque);
-#endif
-
/**
* aio_timer_new:
* @ctx: the aio context
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
index f3cf63f..60aa835 100644
--- a/include/block/blockjob.h
+++ b/include/block/blockjob.h
@@ -74,7 +74,7 @@ struct BlockJob {
* Set to true if the job should cancel itself. The flag must
* always be tested just before toggling the busy flag from false
* to true. After a job has been cancelled, it should only yield
- * if #qemu_aio_wait will ("sooner or later") reenter the coroutine.
+ * if #aio_poll will ("sooner or later") reenter the coroutine.
*/
bool cancelled;
@@ -87,7 +87,7 @@ struct BlockJob {
/**
* Set to false by the job while it is in a quiescent state, where
* no I/O is pending and the job has yielded on any condition
- * that is not detected by #qemu_aio_wait, such as a timer.
+ * that is not detected by #aio_poll, such as a timer.
*/
bool busy;
diff --git a/include/block/coroutine.h b/include/block/coroutine.h
index a1797ae..b408f96 100644
--- a/include/block/coroutine.h
+++ b/include/block/coroutine.h
@@ -212,7 +212,7 @@ void coroutine_fn co_sleep_ns(QEMUClockType type, int64_t ns);
* Yield the coroutine for a given duration
*
* Behaves similarly to co_sleep_ns(), but the sleeping coroutine will be
- * resumed when using qemu_aio_wait().
+ * resumed when using aio_poll().
*/
void coroutine_fn co_aio_sleep_ns(AioContext *ctx, QEMUClockType type,
int64_t ns);
diff --git a/main-loop.c b/main-loop.c
index 8a85493..3cc79f8 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -498,24 +498,3 @@ QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
{
return aio_bh_new(qemu_aio_context, cb, opaque);
}
-
-bool qemu_aio_wait(void)
-{
- return aio_poll(qemu_aio_context, true);
-}
-
-#ifdef CONFIG_POSIX
-void qemu_aio_set_fd_handler(int fd,
- IOHandler *io_read,
- IOHandler *io_write,
- void *opaque)
-{
- aio_set_fd_handler(qemu_aio_context, fd, io_read, io_write, opaque);
-}
-#endif
-
-void qemu_aio_set_event_notifier(EventNotifier *notifier,
- EventNotifierHandler *io_read)
-{
- aio_set_event_notifier(qemu_aio_context, notifier, io_read);
-}
diff --git a/tests/test-thread-pool.c b/tests/test-thread-pool.c
index aa156bc..f40b7fc 100644
--- a/tests/test-thread-pool.c
+++ b/tests/test-thread-pool.c
@@ -83,7 +83,7 @@ static void co_test_cb(void *opaque)
data->ret = 0;
active--;
- /* The test continues in test_submit_co, after qemu_aio_wait_all... */
+ /* The test continues in test_submit_co, after aio_poll... */
}
static void test_submit_co(void)
@@ -98,7 +98,7 @@ static void test_submit_co(void)
g_assert_cmpint(active, ==, 1);
g_assert_cmpint(data.ret, ==, -EINPROGRESS);
- /* qemu_aio_wait_all will execute the rest of the coroutine. */
+ /* aio_poll will execute the rest of the coroutine. */
while (data.ret == -EINPROGRESS) {
aio_poll(ctx, true);
commit b47ec2c4562117728be36ec2edfbdf9ef2868c6e
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Mon Jul 7 15:18:01 2014 +0200
block: prefer aio_poll to qemu_aio_wait
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block.c b/block.c
index c9629a4..510430d 100644
--- a/block.c
+++ b/block.c
@@ -471,7 +471,7 @@ int bdrv_create(BlockDriver *drv, const char* filename,
co = qemu_coroutine_create(bdrv_create_co_entry);
qemu_coroutine_enter(co, &cco);
while (cco.ret == NOT_DONE) {
- qemu_aio_wait();
+ aio_poll(qemu_get_aio_context(), true);
}
}
diff --git a/blockjob.c b/blockjob.c
index 67a64ea..ca0b4e2 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -187,7 +187,7 @@ int block_job_cancel_sync(BlockJob *job)
job->opaque = &data;
block_job_cancel(job);
while (data.ret == -EINPROGRESS) {
- qemu_aio_wait();
+ aio_poll(bdrv_get_aio_context(bs), true);
}
return (data.cancelled && data.ret == 0) ? -ECANCELED : data.ret;
}
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index 60c1ceb..c503fc6 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -483,7 +483,7 @@ static int do_co_write_zeroes(BlockDriverState *bs, int64_t offset, int count,
co = qemu_coroutine_create(co_write_zeroes_entry);
qemu_coroutine_enter(co, &data);
while (!data.done) {
- qemu_aio_wait();
+ aio_poll(bdrv_get_aio_context(bs), true);
}
if (data.ret < 0) {
return data.ret;
@@ -2027,7 +2027,7 @@ static const cmdinfo_t resume_cmd = {
static int wait_break_f(BlockDriverState *bs, int argc, char **argv)
{
while (!bdrv_debug_is_suspended(bs, argv[1])) {
- qemu_aio_wait();
+ aio_poll(bdrv_get_aio_context(bs), true);
}
return 0;
commit 01fb2705bd19a6e9c1207446793064dbd141df5f
Author: Kevin Wolf <kwolf at redhat.com>
Date: Mon Jul 7 17:00:37 2014 +0200
block: Fix bdrv_is_allocated() return value
bdrv_is_allocated() should return either 0 or 1 in successful cases.
We're lucky that currently, the callers that rely on this (e.g. because
they check for ret == 1) don't seem to break badly. They just might skip
some optimisation or in the case of qemu-io 'map' print separate lines
where a single line would suffice. In theory, a wrong allocation status
could lead to image corruption with certain operations, so let's fix
this quickly.
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
Reviewed-by: Eric Blake <eblake at redhat.com>
diff --git a/block.c b/block.c
index 8800a6b..c9629a4 100644
--- a/block.c
+++ b/block.c
@@ -4040,7 +4040,7 @@ int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num,
if (ret < 0) {
return ret;
}
- return (ret & BDRV_BLOCK_ALLOCATED);
+ return !!(ret & BDRV_BLOCK_ALLOCATED);
}
/*
commit d40593dd9033d39a5e4cc32915c5eb28f3e858b6
Author: Kevin Wolf <kwolf at redhat.com>
Date: Mon Jul 7 16:38:58 2014 +0200
block/backup: Fix hang for unaligned image size
When doing a block backup of an image with an unaligned size (with
respect to the BACKUP_CLUSTER_SIZE), qemu would check the allocation
status of sectors after the end of the image. bdrv_is_allocated()
returns a result that is valid for 0 sectors in this case, so the backup
job ran into an endless loop.
Stop looping when seeing a result valid for 0 sectors, we're at EOF then.
The test case looks somewhat unrelated at first sight because I
originally tried to reproduce a different suspected bug that turned out
to not exist. Still a good test case and it accidentally found this one.
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
Reviewed-by: Eric Blake <eblake at redhat.com>
diff --git a/block/backup.c b/block/backup.c
index 7978ae2..d0b0225 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -307,7 +307,7 @@ static void coroutine_fn backup_run(void *opaque)
BACKUP_SECTORS_PER_CLUSTER - i, &n);
i += n;
- if (alloced == 1) {
+ if (alloced == 1 || n == 0) {
break;
}
}
diff --git a/tests/qemu-iotests/028 b/tests/qemu-iotests/028
index a99e4fa..d5718c5 100755
--- a/tests/qemu-iotests/028
+++ b/tests/qemu-iotests/028
@@ -33,7 +33,8 @@ status=1 # failure is the default!
_cleanup()
{
- _cleanup_test_img
+ rm -f "${TEST_IMG}.copy"
+ _cleanup_test_img
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -41,6 +42,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
. ./common.rc
. ./common.filter
. ./common.pattern
+. ./common.qemu
# Any format supporting backing files except vmdk and qcow which do not support
# smaller backing files.
@@ -99,6 +101,29 @@ _check_test_img
# Rebase it on top of its base image
$QEMU_IMG rebase -b "$TEST_IMG.base" "$TEST_IMG"
+echo
+echo block-backup
+echo
+
+qemu_comm_method="monitor"
+_launch_qemu -drive file="${TEST_IMG}",cache=${CACHEMODE},id=disk
+h=$QEMU_HANDLE
+QEMU_COMM_TIMEOUT=1
+
+_send_qemu_cmd $h "drive_backup disk ${TEST_IMG}.copy" "(qemu)"
+qemu_cmd_repeat=20 _send_qemu_cmd $h "info block-jobs" "No active jobs"
+_send_qemu_cmd $h 'quit' ""
+
+# Base image sectors
+TEST_IMG="${TEST_IMG}.copy" io readv $(( offset )) 512 1024 32
+
+# Image sectors
+TEST_IMG="${TEST_IMG}.copy" io readv $(( offset + 512 )) 512 1024 64
+
+# Zero sectors beyond end of base image
+TEST_IMG="${TEST_IMG}.copy" io_zero readv $(( offset + 32 * 1024 )) 512 1024 32
+
+
_check_test_img
# success, all done
diff --git a/tests/qemu-iotests/028.out b/tests/qemu-iotests/028.out
index 8affb7f..38099e4 100644
--- a/tests/qemu-iotests/028.out
+++ b/tests/qemu-iotests/028.out
@@ -465,5 +465,274 @@ read 512/512 bytes at offset 3221257728
read 512/512 bytes at offset 3221258752
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
No errors were found on the image.
+
+block-backup
+
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) d[K[Ddr[K[D[Ddri[K[D[D[Ddriv[K[D[D[D[Ddrive[K[D[D[D[D[Ddrive_[K[D[D[D[D[D[Ddrive_b[K[D[D[D[D[D[D[Ddrive_ba[K[D[D[D[D[D[D[D[Ddrive_bac[K[D[D[D[D[D[D[D[D[Ddrive_back[K[D[D[D[D[D[D[D[D[D[Ddrive_backu[K[D[D[D[D[D[D[D[D[D[D[Ddrive_backup[K[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup [K[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup d[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup di[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup dis[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /h[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /ho[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddri
ve_backup disk /hom[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kw[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwo[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwol[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/s[K[D
[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/so[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/sou[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/sour[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/sourc[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/q[K[D[D[D[D[D[D[
D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qe[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qem[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/t[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/te[K[D[D[D[D[D[D[D
[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tes[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/test[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/q[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D
[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qe[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qem[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-i[K[D[D[D[D[D[D[D[D[D[D[D[
D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-io[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-iot[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-iote[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotes[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[
D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotest[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/s[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D
[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/sc[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/scr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/scra[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/scrat[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[
D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk /home/kwolf/source/qemu/tests/qemu-iotests/scratc[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/t[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[
D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/t.[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/t.q[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/t.qc[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/t.qco[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D
[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/t.qcow[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/t.qcow2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/t.qcow2.[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/t.qcow2.c[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[
D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/t.qcow2.co[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/t.qcow2.cop[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Ddrive_backup disk TEST_DIR/t.qcow2.copy[K
+Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=4294968832 backing_file='TEST_DIR/t.qcow2.base' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off
+(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K[D[D[D[D[D[D[D[D[D[Dinfo block-[K[D[D[D[D[D[D[D[D[D[D[Dinfo block-j[K[D[D[D[D[D[D[D[D[D[D[D[Dinfo block-jo[K[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block-job[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block-jobs[K
+Type backup, device disk: Completed 0 of 4294968832 bytes, speed limit 0 bytes/s
+i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K[D[D[D[D[D[D[D[D[D[Dinfo block-[K[D[D[D[D[D[D[D[D[D[D[Dinfo block-j[K[D[D[D[D[D[D[D[D[D[D[D[Dinfo block-jo[K[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block-job[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block-jobs[K
+No active jobs
+=== IO: pattern 195
+read 512/512 bytes at offset 3221194240
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221195264
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221196288
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221197312
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221198336
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221199360
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221200384
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221201408
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221202432
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221203456
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221204480
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221205504
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221206528
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221207552
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221208576
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221209600
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221210624
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221211648
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221212672
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221213696
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221214720
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221215744
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221216768
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221217792
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221218816
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221219840
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221220864
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221221888
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221222912
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221223936
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221224960
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221225984
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+=== IO: pattern 196
+read 512/512 bytes at offset 3221194752
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221195776
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221196800
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221197824
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221198848
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221199872
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221200896
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221201920
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221202944
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221203968
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221204992
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221206016
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221207040
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221208064
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221209088
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221210112
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221211136
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221212160
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221213184
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221214208
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221215232
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221216256
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221217280
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221218304
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221219328
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221220352
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221221376
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221222400
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221223424
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221224448
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221225472
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221226496
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221227520
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221228544
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221229568
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221230592
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221231616
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221232640
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221233664
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221234688
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221235712
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221236736
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221237760
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221238784
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221239808
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221240832
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221241856
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221242880
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221243904
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221244928
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221245952
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221246976
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221248000
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221249024
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221250048
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221251072
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221252096
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221253120
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221254144
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221255168
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221256192
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221257216
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221258240
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221259264
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+=== IO: pattern 0
+read 512/512 bytes at offset 3221227008
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221228032
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221229056
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221230080
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221231104
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221232128
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221233152
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221234176
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221235200
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221236224
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221237248
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221238272
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221239296
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221240320
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221241344
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221242368
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221243392
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221244416
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221245440
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221246464
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221247488
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221248512
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221249536
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221250560
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221251584
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221252608
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221253632
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221254656
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221255680
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221256704
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221257728
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221258752
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
No errors were found on the image.
*** done
commit 0a2672b7ead72b7c788200499a63a4d5f2faa74a
Author: James Hogan <james.hogan at imgtec.com>
Date: Thu Jun 26 10:44:22 2014 +0100
mips/kvm: Init EBase to correct KSEG0
The EBase CP0 register is initialised to 0x80000000, however with KVM
the guest's KSEG0 is at 0x40000000. The incorrect value doesn't get
passed to KVM yet as KVM doesn't implement the EBase register, however
we should set it correctly now so as not to break migration/loadvm to a
future version of QEMU that does support EBase.
Cc: Aurelien Jarno <aurelien at aurel32.net>
Cc: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: James Hogan <james.hogan at imgtec.com>
Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 2f91959..d7b8c4d 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -28,6 +28,7 @@
#include "exec/helper-proto.h"
#include "exec/helper-gen.h"
+#include "sysemu/kvm.h"
#define MIPS_DEBUG_DISAS 0
//#define MIPS_DEBUG_SIGN_EXTENSIONS
@@ -16076,7 +16077,12 @@ void cpu_state_reset(CPUMIPSState *env)
env->CP0_Random = env->tlb->nb_tlb - 1;
env->tlb->tlb_in_use = env->tlb->nb_tlb;
env->CP0_Wired = 0;
- env->CP0_EBase = 0x80000000 | (cs->cpu_index & 0x3FF);
+ env->CP0_EBase = (cs->cpu_index & 0x3FF);
+ if (kvm_enabled()) {
+ env->CP0_EBase |= 0x40000000;
+ } else {
+ env->CP0_EBase |= 0x80000000;
+ }
env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
/* vectored interrupts not implemented, timer on int 7,
no performance counters. */
More information about the Spice-commits
mailing list