Merge remote-tracking branch 'origin/master' into epel7

Basically throwing away whatever's left in the EPEL branch, bringing into sync
with Fedora master.

Conflicts:
	0001-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch
	0002-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch
	0003-iohandlers-Add-enable-disable_write_fd_handler-funct.patch
	0004-char-Add-framework-for-a-write-unblocked-callback.patch
	0005-char-Update-send_all-to-handle-nonblocking-chardev-w.patch
	0006-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch
	0007-virtio-console-Enable-port-throttling-when-chardev-i.patch
	0008-spice-qemu-char.c-add-throttling.patch
	0009-spice-qemu-char.c-remove-intermediate-buffer.patch
	0010-usb-redir-Add-flow-control-support.patch
	0011-char-Disable-write-callback-if-throttled-chardev-is-.patch
	0012-hw-virtio-serial-bus-replay-guest-open-on-destinatio.patch
	0201-configure-Add-enable-migration-from-qemu-kvm.patch
	0202-acpi_piix4-Drop-minimum_version_id-to-handle-qemu-kv.patch
	0203-i8254-Fix-migration-from-qemu-kvm-1.1.patch
	0204-pc_piix-Add-compat-handling-for-qemu-kvm-VGA-mem-siz.patch
	0205-qxl-Add-rom_size-compat-property-fix-migration-from-.patch
This commit is contained in:
Lubomir Rintel 2014-02-26 19:31:34 +01:00
commit 5f9089d1b5
131 changed files with 2220 additions and 11315 deletions

8
.gitignore vendored
View File

@ -19,4 +19,10 @@ qemu-kvm-0.13.0-25fdf4a.tar.gz
/qemu-1.3.0.tar.bz2
/qemu-1.4.0.tar.bz2
/qemu-1.4.1.tar.bz2
/qemu-1.4.2.tar.bz2
/qemu-1.5.0.tar.bz2
/qemu-1.5.1.tar.bz2
/qemu-1.5.2.tar.bz2
/qemu-1.6.0.tar.bz2
/qemu-1.6.1.tar.bz2
/qemu-1.7.0-rc1.tar.bz2
/qemu-1.7.0.tar.bz2

View File

@ -1,54 +0,0 @@
From f85faeccdc2b98c4aab0d9781c9650a71a30c23b Mon Sep 17 00:00:00 2001
From: Amit Shah <amit.shah@redhat.com>
Date: Mon, 21 Mar 2011 21:57:47 +0100
Subject: [PATCH] char: Split out tcp socket close code in a separate function
Signed-off-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Cole Robinson <crobinso@redhat.com>
---
qemu-char.c | 25 ++++++++++++++++---------
1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/qemu-char.c b/qemu-char.c
index f4a74ac..ac2abeb 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2155,6 +2155,21 @@ typedef struct {
static void tcp_chr_accept(void *opaque);
+static void tcp_closed(void *opaque)
+{
+ CharDriverState *chr = opaque;
+ TCPCharDriver *s = chr->opaque;
+
+ s->connected = 0;
+ if (s->listen_fd >= 0) {
+ qemu_set_fd_handler2(s->listen_fd, NULL, tcp_chr_accept, NULL, chr);
+ }
+ qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
+ closesocket(s->fd);
+ s->fd = -1;
+ qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
+}
+
static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
{
TCPCharDriver *s = chr->opaque;
@@ -2316,15 +2331,7 @@ static void tcp_chr_read(void *opaque)
len = s->max_size;
size = tcp_chr_recv(chr, (void *)buf, len);
if (size == 0) {
- /* connection closed */
- s->connected = 0;
- if (s->listen_fd >= 0) {
- qemu_set_fd_handler2(s->listen_fd, NULL, tcp_chr_accept, NULL, chr);
- }
- qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
- closesocket(s->fd);
- s->fd = -1;
- qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
+ tcp_closed(chr);
} else if (size > 0) {
if (s->do_telnetopt)
tcp_chr_process_IAC_bytes(chr, s, buf, &size);

View File

@ -1,4 +1,4 @@
From 5ff013a13ea2530c94ffdfb829f922ba450ddef0 Mon Sep 17 00:00:00 2001
From 4f9f83c8b0a26a24ab2963e57a375b0ba99638f1 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Thu, 2 May 2013 11:38:37 +0200
Subject: [PATCH] pci: do not export pci_bus_reset
@ -12,18 +12,17 @@ qbus_reset_all *before* invoking pcibus_reset itself.
Tested-by: Claudio Bley <cbley@av-test.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Cole Robinson <crobinso@redhat.com>
---
hw/pci/pci.c | 8 ++------
hw/pci/pci.h | 1 -
hw/pci/pci_bridge.c | 2 +-
hw/pci/pci.c | 8 ++------
hw/pci/pci_bridge.c | 2 +-
include/hw/pci/pci.h | 1 -
3 files changed, 3 insertions(+), 8 deletions(-)
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 2f45c8f..5813ef0 100644
index 49eca95..504ed9d 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -209,8 +209,9 @@ void pci_device_reset(PCIDevice *dev)
@@ -212,8 +212,9 @@ void pci_device_reset(PCIDevice *dev)
* Trigger pci bus reset under a given bus.
* To be called on RST# assert.
*/
@ -34,7 +33,7 @@ index 2f45c8f..5813ef0 100644
int i;
for (i = 0; i < bus->nirq; i++) {
@@ -221,11 +222,6 @@ void pci_bus_reset(PCIBus *bus)
@@ -224,11 +225,6 @@ void pci_bus_reset(PCIBus *bus)
pci_device_reset(bus->devices[i]);
}
}
@ -46,23 +45,11 @@ index 2f45c8f..5813ef0 100644
/* topology traverse is done by pci_bus_reset().
Tell qbus/qdev walker not to traverse the tree */
diff --git a/hw/pci/pci.h b/hw/pci/pci.h
index f340fe5..b9f2a5a 100644
--- a/hw/pci/pci.h
+++ b/hw/pci/pci.h
@@ -346,7 +346,6 @@ void pci_bus_fire_intx_routing_notifier(PCIBus *bus);
void pci_device_set_intx_routing_notifier(PCIDevice *dev,
PCIINTxRoutingNotifier notifier);
void pci_device_reset(PCIDevice *dev);
-void pci_bus_reset(PCIBus *bus);
PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
const char *default_devaddr);
diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
index 995842a..1b9722e 100644
index 290abab..41d8755 100644
--- a/hw/pci/pci_bridge.c
+++ b/hw/pci/pci_bridge.c
@@ -234,7 +234,7 @@ void pci_bridge_write_config(PCIDevice *d,
@@ -268,7 +268,7 @@ void pci_bridge_write_config(PCIDevice *d,
newctl = pci_get_word(d->config + PCI_BRIDGE_CONTROL);
if (~oldctl & newctl & PCI_BRIDGE_CTL_BUS_RESET) {
/* Trigger hot reset on 0->1 transition. */
@ -71,3 +58,15 @@ index 995842a..1b9722e 100644
}
}
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index b783e68..754b82d 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -373,7 +373,6 @@ void pci_bus_fire_intx_routing_notifier(PCIBus *bus);
void pci_device_set_intx_routing_notifier(PCIDevice *dev,
PCIINTxRoutingNotifier notifier);
void pci_device_reset(PCIDevice *dev);
-void pci_bus_reset(PCIBus *bus);
PCIDevice *pci_nic_init(NICInfo *nd, PCIBus *rootbus,
const char *default_model,

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
From ed7dc4037ba6f105ef2826cf20a8663256e40823 Mon Sep 17 00:00:00 2001
From 60ab1ca9f2a40610902b610fa0a06fccea7f0f57 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Thu, 2 May 2013 11:38:38 +0200
Subject: [PATCH] qdev: allow both pre- and post-order vists in qdev walking
@ -10,41 +10,16 @@ it by adding two extra arguments to the functions.
Tested-by: Claudio Bley <cbley@av-test.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Cole Robinson <crobinso@redhat.com>
---
hw/qdev-core.h | 13 +++++++++----
hw/qdev.c | 45 +++++++++++++++++++++++++++++++++------------
hw/core/qdev.c | 45 +++++++++++++++++++++++++++++++++------------
include/hw/qdev-core.h | 13 +++++++++----
2 files changed, 42 insertions(+), 16 deletions(-)
diff --git a/hw/qdev-core.h b/hw/qdev-core.h
index cc5bb2a..5dc25ec 100644
--- a/hw/qdev-core.h
+++ b/hw/qdev-core.h
@@ -237,10 +237,15 @@ BusState *qbus_create(const char *typename, DeviceState *parent, const char *nam
/* Returns > 0 if either devfn or busfn skip walk somewhere in cursion,
* < 0 if either devfn or busfn terminate walk somewhere in cursion,
* 0 otherwise. */
-int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
- qbus_walkerfn *busfn, void *opaque);
-int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
- qbus_walkerfn *busfn, void *opaque);
+int qbus_walk_children(BusState *bus,
+ qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn,
+ qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
+ void *opaque);
+int qdev_walk_children(DeviceState *dev,
+ qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn,
+ qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
+ void *opaque);
+
void qdev_reset_all(DeviceState *dev);
/**
diff --git a/hw/qdev.c b/hw/qdev.c
index 1cbd910..50be0f8 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -237,12 +237,12 @@ static int qbus_reset_one(BusState *bus, void *opaque)
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index e374a93..5ddf1aa 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -240,12 +240,12 @@ static int qbus_reset_one(BusState *bus, void *opaque)
void qdev_reset_all(DeviceState *dev)
{
@ -59,7 +34,7 @@ index 1cbd910..50be0f8 100644
}
void qbus_reset_all_fn(void *opaque)
@@ -340,49 +340,70 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
@@ -337,49 +337,70 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
return NULL;
}
@ -140,3 +115,27 @@ index 1cbd910..50be0f8 100644
return 0;
}
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index f2043a6..ecf5cb3 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -253,10 +253,15 @@ BusState *qbus_create(const char *typename, DeviceState *parent, const char *nam
/* Returns > 0 if either devfn or busfn skip walk somewhere in cursion,
* < 0 if either devfn or busfn terminate walk somewhere in cursion,
* 0 otherwise. */
-int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
- qbus_walkerfn *busfn, void *opaque);
-int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
- qbus_walkerfn *busfn, void *opaque);
+int qbus_walk_children(BusState *bus,
+ qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn,
+ qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
+ void *opaque);
+int qdev_walk_children(DeviceState *dev,
+ qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn,
+ qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
+ void *opaque);
+
void qdev_reset_all(DeviceState *dev);
/**

View File

@ -1,74 +0,0 @@
From 1f039120d2d1b4b97dbb92ec84492a7e917ab09e Mon Sep 17 00:00:00 2001
From: Amit Shah <amit.shah@redhat.com>
Date: Mon, 21 Mar 2011 20:32:58 +0100
Subject: [PATCH] iohandlers: Add enable/disable_write_fd_handler() functions
These will be used to provide a cleaner API for the nonblocking case.
Signed-off-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Cole Robinson <crobinso@redhat.com>
---
include/qemu/main-loop.h | 3 +++
iohandler.c | 35 +++++++++++++++++++++++++++++++++++
2 files changed, 38 insertions(+)
diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h
index e8059c3..faaf47d 100644
--- a/include/qemu/main-loop.h
+++ b/include/qemu/main-loop.h
@@ -166,6 +166,9 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size);
typedef int IOCanReadHandler(void *opaque);
+void enable_write_fd_handler(int fd, IOHandler *fd_write);
+void disable_write_fd_handler(int fd);
+
/**
* qemu_set_fd_handler2: Register a file descriptor with the main loop
*
diff --git a/iohandler.c b/iohandler.c
index 2523adc..a49cfd4 100644
--- a/iohandler.c
+++ b/iohandler.c
@@ -45,6 +45,41 @@ typedef struct IOHandlerRecord {
static QLIST_HEAD(, IOHandlerRecord) io_handlers =
QLIST_HEAD_INITIALIZER(io_handlers);
+static IOHandlerRecord *find_iohandler(int fd)
+{
+ IOHandlerRecord *ioh;
+
+ QLIST_FOREACH(ioh, &io_handlers, next) {
+ if (ioh->fd == fd) {
+ return ioh;
+ }
+ }
+ return NULL;
+}
+
+void enable_write_fd_handler(int fd, IOHandler *fd_write)
+{
+ IOHandlerRecord *ioh;
+
+ ioh = find_iohandler(fd);
+ if (!ioh) {
+ return;
+ }
+
+ ioh->fd_write = fd_write;
+}
+
+void disable_write_fd_handler(int fd)
+{
+ IOHandlerRecord *ioh;
+
+ ioh = find_iohandler(fd);
+ if (!ioh) {
+ return;
+ }
+
+ ioh->fd_write = NULL;
+}
/* XXX: fd_read_poll should be suppressed, but an API change is
necessary in the character devices to suppress fd_can_read(). */

View File

@ -1,4 +1,4 @@
From bca7fa0f8de47d691473257c6d6c9a58ee5d05e8 Mon Sep 17 00:00:00 2001
From b7906779d6a9eac1815d61cb34aa3d71154025bb Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Thu, 2 May 2013 11:38:39 +0200
Subject: [PATCH] qdev: switch reset to post-order
@ -25,27 +25,53 @@ which used and still uses pci_device_reset.
Tested-by: Claudio Bley <cbley@av-test.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Cole Robinson <crobinso@redhat.com>
---
hw/pci/pci.c | 31 ++++++++++++++++---------------
hw/qdev-core.h | 2 +-
hw/qdev.c | 6 +++---
hw/core/qdev.c | 6 +++---
hw/pci/pci.c | 31 ++++++++++++++++---------------
include/hw/qdev-core.h | 2 +-
3 files changed, 20 insertions(+), 19 deletions(-)
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 5ddf1aa..d2ffe35 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -233,19 +233,19 @@ static int qbus_reset_one(BusState *bus, void *opaque)
{
BusClass *bc = BUS_GET_CLASS(bus);
if (bc->reset) {
- return bc->reset(bus);
+ bc->reset(bus);
}
return 0;
}
void qdev_reset_all(DeviceState *dev)
{
- qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL, NULL, NULL);
+ qdev_walk_children(dev, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
}
void qbus_reset_all(BusState *bus)
{
- qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL, NULL, NULL);
+ qbus_walk_children(bus, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
}
void qbus_reset_all_fn(void *opaque)
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 5813ef0..9826b6e 100644
index 504ed9d..8806636 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -45,7 +45,7 @@
@@ -46,7 +46,7 @@
static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent);
static char *pcibus_get_dev_path(DeviceState *dev);
static char *pcibus_get_fw_dev_path(DeviceState *dev);
-static int pcibus_reset(BusState *qbus);
+static void pcibus_reset(BusState *qbus);
static void pci_bus_finalize(Object *obj);
static Property pci_props[] = {
DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
@@ -164,16 +164,10 @@ void pci_device_deassert_intx(PCIDevice *dev)
@@ -167,16 +167,10 @@ void pci_device_deassert_intx(PCIDevice *dev)
}
}
@ -63,7 +89,7 @@ index 5813ef0..9826b6e 100644
dev->irq_state = 0;
pci_update_irq_status(dev);
pci_device_deassert_intx(dev);
@@ -206,10 +200,21 @@ void pci_device_reset(PCIDevice *dev)
@@ -209,10 +203,21 @@ void pci_device_reset(PCIDevice *dev)
}
/*
@ -87,7 +113,7 @@ index 5813ef0..9826b6e 100644
{
PCIBus *bus = DO_UPCAST(PCIBus, qbus, qbus);
int i;
@@ -219,13 +224,9 @@ static int pcibus_reset(BusState *qbus)
@@ -222,13 +227,9 @@ static int pcibus_reset(BusState *qbus)
}
for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
if (bus->devices[i]) {
@ -101,12 +127,12 @@ index 5813ef0..9826b6e 100644
- return 1;
}
static void pci_host_bus_register(int domain, PCIBus *bus)
diff --git a/hw/qdev-core.h b/hw/qdev-core.h
index 5dc25ec..083e5ab 100644
--- a/hw/qdev-core.h
+++ b/hw/qdev-core.h
@@ -144,7 +144,7 @@ struct BusClass {
static void pci_host_bus_register(PCIBus *bus, DeviceState *parent)
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index ecf5cb3..a9ce4a3 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -158,7 +158,7 @@ struct BusClass {
* bindings can be found at http://playground.sun.com/1275/bindings/.
*/
char *(*get_fw_dev_path)(DeviceState *dev);
@ -115,30 +141,3 @@ index 5dc25ec..083e5ab 100644
/* maximum devices allowed on the bus, 0: no limit. */
int max_dev;
};
diff --git a/hw/qdev.c b/hw/qdev.c
index 50be0f8..fd2b99e 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -230,19 +230,19 @@ static int qbus_reset_one(BusState *bus, void *opaque)
{
BusClass *bc = BUS_GET_CLASS(bus);
if (bc->reset) {
- return bc->reset(bus);
+ bc->reset(bus);
}
return 0;
}
void qdev_reset_all(DeviceState *dev)
{
- qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL, NULL, NULL);
+ qdev_walk_children(dev, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
}
void qbus_reset_all(BusState *bus)
{
- qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL, NULL, NULL);
+ qbus_walk_children(bus, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
}
void qbus_reset_all_fn(void *opaque)

View File

@ -1,59 +0,0 @@
From bd1a691c11f718cbd6018a8ef5077c47a2e6d883 Mon Sep 17 00:00:00 2001
From: Amit Shah <amit.shah@redhat.com>
Date: Mon, 21 Mar 2011 21:41:42 +0100
Subject: [PATCH] char: Add framework for a 'write unblocked' callback
The char layer can let users know that the driver will block on further
input. For users interested in not blocking, they can assign a function
pointer that will be called back when the driver becomes writable. This
patch just adds the function pointers to the CharDriverState structure,
future patches will enable the nonblocking and callback functionality.
Signed-off-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Cole Robinson <crobinso@redhat.com>
---
include/char/char.h | 4 ++++
qemu-char.c | 3 +++
2 files changed, 7 insertions(+)
diff --git a/include/char/char.h b/include/char/char.h
index 3027cc1..2fee107 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -63,6 +63,9 @@ struct CharDriverState {
IOEventHandler *chr_event;
IOCanReadHandler *chr_can_read;
IOReadHandler *chr_read;
+ IOHandler *chr_write_unblocked;
+ void (*chr_enable_write_fd_handler)(struct CharDriverState *chr);
+ void (*chr_disable_write_fd_handler)(struct CharDriverState *chr);
void *handler_opaque;
void (*chr_close)(struct CharDriverState *chr);
void (*chr_accept_input)(struct CharDriverState *chr);
@@ -76,6 +79,7 @@ struct CharDriverState {
int opened;
int avail_connections;
QemuOpts *opts;
+ bool write_blocked; /* Are we in a blocked state? */
QTAILQ_ENTRY(CharDriverState) next;
};
diff --git a/qemu-char.c b/qemu-char.c
index 0c97bdf..ab0c552 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -211,11 +211,14 @@ void qemu_chr_add_handlers(CharDriverState *s,
}
s->chr_can_read = handlers->fd_can_read;
s->chr_read = handlers->fd_read;
+ s->chr_write_unblocked = handlers->fd_write_unblocked;
s->chr_event = handlers->fd_event;
s->handler_opaque = opaque;
if (s->chr_update_read_handler)
s->chr_update_read_handler(s);
+ s->write_blocked = false;
+
/* We're connecting to an already opened device, so let's make sure we
also get the open event */
if (s->opened) {

View File

@ -0,0 +1,248 @@
From d704692d459a40bd28950e734a57075b0ab87393 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 20 Sep 2013 16:57:50 +0200
Subject: [PATCH] virtio-bus: remove vdev field
The vdev field is complicated to synchronize. Just access the
BusState's list of children.
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/virtio/virtio-bus.c | 65 +++++++++++++++++++++++++-----------------
hw/virtio/virtio-mmio.c | 9 +++---
hw/virtio/virtio-pci.c | 2 +-
include/hw/virtio/virtio-bus.h | 16 ++++++++---
4 files changed, 57 insertions(+), 35 deletions(-)
diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c
index e6b103c..17dd06e 100644
--- a/hw/virtio/virtio-bus.c
+++ b/hw/virtio/virtio-bus.c
@@ -46,8 +46,6 @@ int virtio_bus_plug_device(VirtIODevice *vdev)
VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(bus);
DPRINTF("%s: plug device.\n", qbus->name);
- bus->vdev = vdev;
-
if (klass->device_plugged != NULL) {
klass->device_plugged(qbus->parent);
}
@@ -58,9 +56,11 @@ int virtio_bus_plug_device(VirtIODevice *vdev)
/* Reset the virtio_bus */
void virtio_bus_reset(VirtioBusState *bus)
{
+ VirtIODevice *vdev = virtio_bus_get_device(bus);
+
DPRINTF("%s: reset device.\n", qbus->name);
- if (bus->vdev != NULL) {
- virtio_reset(bus->vdev);
+ if (vdev != NULL) {
+ virtio_reset(vdev);
}
}
@@ -69,62 +69,71 @@ void virtio_bus_destroy_device(VirtioBusState *bus)
{
BusState *qbus = BUS(bus);
VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(bus);
+ VirtIODevice *vdev = virtio_bus_get_device(bus);
+
DPRINTF("%s: remove device.\n", qbus->name);
- if (bus->vdev != NULL) {
+ if (vdev != NULL) {
if (klass->device_unplug != NULL) {
klass->device_unplug(qbus->parent);
}
- object_unparent(OBJECT(bus->vdev));
- bus->vdev = NULL;
+ object_unparent(OBJECT(vdev));
}
}
/* Get the device id of the plugged device. */
uint16_t virtio_bus_get_vdev_id(VirtioBusState *bus)
{
- assert(bus->vdev != NULL);
- return bus->vdev->device_id;
+ VirtIODevice *vdev = virtio_bus_get_device(bus);
+ assert(vdev != NULL);
+ return vdev->device_id;
}
/* Get the config_len field of the plugged device. */
size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus)
{
- assert(bus->vdev != NULL);
- return bus->vdev->config_len;
+ VirtIODevice *vdev = virtio_bus_get_device(bus);
+ assert(vdev != NULL);
+ return vdev->config_len;
}
/* Get the features of the plugged device. */
uint32_t virtio_bus_get_vdev_features(VirtioBusState *bus,
uint32_t requested_features)
{
+ VirtIODevice *vdev = virtio_bus_get_device(bus);
VirtioDeviceClass *k;
- assert(bus->vdev != NULL);
- k = VIRTIO_DEVICE_GET_CLASS(bus->vdev);
+
+ assert(vdev != NULL);
+ k = VIRTIO_DEVICE_GET_CLASS(vdev);
assert(k->get_features != NULL);
- return k->get_features(bus->vdev, requested_features);
+ return k->get_features(vdev, requested_features);
}
/* Set the features of the plugged device. */
void virtio_bus_set_vdev_features(VirtioBusState *bus,
uint32_t requested_features)
{
+ VirtIODevice *vdev = virtio_bus_get_device(bus);
VirtioDeviceClass *k;
- assert(bus->vdev != NULL);
- k = VIRTIO_DEVICE_GET_CLASS(bus->vdev);
+
+ assert(vdev != NULL);
+ k = VIRTIO_DEVICE_GET_CLASS(vdev);
if (k->set_features != NULL) {
- k->set_features(bus->vdev, requested_features);
+ k->set_features(vdev, requested_features);
}
}
/* Get bad features of the plugged device. */
uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus)
{
+ VirtIODevice *vdev = virtio_bus_get_device(bus);
VirtioDeviceClass *k;
- assert(bus->vdev != NULL);
- k = VIRTIO_DEVICE_GET_CLASS(bus->vdev);
+
+ assert(vdev != NULL);
+ k = VIRTIO_DEVICE_GET_CLASS(vdev);
if (k->bad_features != NULL) {
- return k->bad_features(bus->vdev);
+ return k->bad_features(vdev);
} else {
return 0;
}
@@ -133,22 +142,26 @@ uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus)
/* Get config of the plugged device. */
void virtio_bus_get_vdev_config(VirtioBusState *bus, uint8_t *config)
{
+ VirtIODevice *vdev = virtio_bus_get_device(bus);
VirtioDeviceClass *k;
- assert(bus->vdev != NULL);
- k = VIRTIO_DEVICE_GET_CLASS(bus->vdev);
+
+ assert(vdev != NULL);
+ k = VIRTIO_DEVICE_GET_CLASS(vdev);
if (k->get_config != NULL) {
- k->get_config(bus->vdev, config);
+ k->get_config(vdev, config);
}
}
/* Set config of the plugged device. */
void virtio_bus_set_vdev_config(VirtioBusState *bus, uint8_t *config)
{
+ VirtIODevice *vdev = virtio_bus_get_device(bus);
VirtioDeviceClass *k;
- assert(bus->vdev != NULL);
- k = VIRTIO_DEVICE_GET_CLASS(bus->vdev);
+
+ assert(vdev != NULL);
+ k = VIRTIO_DEVICE_GET_CLASS(vdev);
if (k->set_config != NULL) {
- k->set_config(bus->vdev, config);
+ k->set_config(vdev, config);
}
}
diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c
index 29cf284..8829eb0 100644
--- a/hw/virtio/virtio-mmio.c
+++ b/hw/virtio/virtio-mmio.c
@@ -95,7 +95,7 @@ static void virtio_mmio_bus_new(VirtioBusState *bus, size_t bus_size,
static uint64_t virtio_mmio_read(void *opaque, hwaddr offset, unsigned size)
{
VirtIOMMIOProxy *proxy = (VirtIOMMIOProxy *)opaque;
- VirtIODevice *vdev = proxy->bus.vdev;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
DPRINTF("virtio_mmio_read offset 0x%x\n", (int)offset);
@@ -185,7 +185,7 @@ static void virtio_mmio_write(void *opaque, hwaddr offset, uint64_t value,
unsigned size)
{
VirtIOMMIOProxy *proxy = (VirtIOMMIOProxy *)opaque;
- VirtIODevice *vdev = proxy->bus.vdev;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
DPRINTF("virtio_mmio_write offset 0x%x value 0x%" PRIx64 "\n",
(int)offset, value);
@@ -298,12 +298,13 @@ static const MemoryRegionOps virtio_mem_ops = {
static void virtio_mmio_update_irq(DeviceState *opaque, uint16_t vector)
{
VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
int level;
- if (!proxy->bus.vdev) {
+ if (!vdev) {
return;
}
- level = (proxy->bus.vdev->isr != 0);
+ level = (vdev->isr != 0);
DPRINTF("virtio_mmio setting IRQ %d\n", level);
qemu_set_irq(proxy->irq, level);
}
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 7647be8..76b7652 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -943,7 +943,7 @@ static void virtio_pci_device_plugged(DeviceState *d)
uint8_t *config;
uint32_t size;
- proxy->vdev = bus->vdev;
+ proxy->vdev = virtio_bus_get_device(bus);
config = proxy->pci_dev.config;
if (proxy->class_code) {
diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h
index 9217f85..ba0f86a 100644
--- a/include/hw/virtio/virtio-bus.h
+++ b/include/hw/virtio/virtio-bus.h
@@ -72,10 +72,6 @@ typedef struct VirtioBusClass {
struct VirtioBusState {
BusState parent_obj;
- /*
- * Only one VirtIODevice can be plugged on the bus.
- */
- VirtIODevice *vdev;
};
int virtio_bus_plug_device(VirtIODevice *vdev);
@@ -98,4 +94,16 @@ void virtio_bus_get_vdev_config(VirtioBusState *bus, uint8_t *config);
/* Set config of the plugged device. */
void virtio_bus_set_vdev_config(VirtioBusState *bus, uint8_t *config);
+static inline VirtIODevice *virtio_bus_get_device(VirtioBusState *bus)
+{
+ BusState *qbus = &bus->parent_obj;
+ BusChild *kid = QTAILQ_FIRST(&qbus->children);
+ DeviceState *qdev = kid ? kid->child : NULL;
+
+ /* This is used on the data path, the cast is guaranteed
+ * to succeed by the qdev machinery.
+ */
+ return (VirtIODevice *)qdev;
+}
+
#endif /* VIRTIO_BUS_H */

View File

@ -1,178 +0,0 @@
From c2dfb673b44dc776109b6c1a9f6a3e28b3e32cf4 Mon Sep 17 00:00:00 2001
From: Amit Shah <amit.shah@redhat.com>
Date: Mon, 21 Mar 2011 22:00:27 +0100
Subject: [PATCH] char: Update send_all() to handle nonblocking chardev write
requests
The send_all function is modified to return to the caller in case the
driver cannot handle any more data. It returns -EAGAIN or
WSAEWOULDBLOCK on non-Windows and Windows platforms respectively. This
is only done when the caller sets a callback function handler indicating
it's not interested in blocking till the driver has written out all the
data.
Currently there's no driver or caller that supports this. Future
commits will add such capability.
Signed-off-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Cole Robinson <crobinso@redhat.com>
---
include/qemu/sockets.h | 3 ++-
qemu-char.c | 69 +++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 65 insertions(+), 7 deletions(-)
diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index 0ccf32f..42ca690 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -29,6 +29,7 @@ int inet_aton(const char *cp, struct in_addr *ia);
#include "qemu/option.h"
#include "qapi/error.h"
#include "qapi/qmp/qerror.h"
+#include "char/char.h"
/* misc helpers */
int qemu_socket(int domain, int type, int protocol);
@@ -36,7 +37,7 @@ int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
int socket_set_cork(int fd, int v);
void qemu_set_block(int fd);
void qemu_set_nonblock(int fd);
-int send_all(int fd, const void *buf, int len1);
+int send_all(CharDriverState *chr, int fd, const void *buf, int len1);
/* callback function for nonblocking connect
* valid fd on success, negative error code on failure
diff --git a/qemu-char.c b/qemu-char.c
index ab0c552..96fc54e 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -508,7 +508,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
#ifdef _WIN32
-int send_all(int fd, const void *buf, int len1)
+static int do_send(int fd, const void *buf, int len1, bool nonblock)
{
int ret, len;
@@ -516,9 +516,14 @@ int send_all(int fd, const void *buf, int len1)
while (len > 0) {
ret = send(fd, buf, len, 0);
if (ret < 0) {
+ if (nonblock && len1 - len) {
+ return len1 - len;
+ }
errno = WSAGetLastError();
if (errno != WSAEWOULDBLOCK) {
return -1;
+ } else if (errno == WSAEWOULDBLOCK && nonblock) {
+ return WSAEWOULDBLOCK;
}
} else if (ret == 0) {
break;
@@ -532,7 +537,7 @@ int send_all(int fd, const void *buf, int len1)
#else
-int send_all(int fd, const void *_buf, int len1)
+static int do_send(int fd, const void *_buf, int len1, bool nonblock)
{
int ret, len;
const uint8_t *buf = _buf;
@@ -541,8 +546,15 @@ int send_all(int fd, const void *_buf, int len1)
while (len > 0) {
ret = write(fd, buf, len);
if (ret < 0) {
- if (errno != EINTR && errno != EAGAIN)
+ if (nonblock && len1 - len) {
+ return len1 - len;
+ }
+ if (errno == EAGAIN && nonblock) {
+ return -EAGAIN;
+ }
+ if (errno != EINTR && errno != EAGAIN) {
return -1;
+ }
} else if (ret == 0) {
break;
} else {
@@ -557,6 +569,44 @@ int send_all(int fd, const void *_buf, int len1)
#define STDIO_MAX_CLIENTS 1
static int stdio_nb_clients;
+int send_all(CharDriverState *chr, int fd, const void *_buf, int len1)
+{
+ int ret, eagain_errno;
+ bool nonblock;
+
+ if (chr && chr->write_blocked) {
+ /*
+ * The caller should not send us data while we're blocked,
+ * but this can happen when multiple writers are woken at once,
+ * so simply return -EAGAIN.
+ */
+ return -EAGAIN;
+ }
+
+ nonblock = false;
+ /*
+ * Ensure the char backend is able to receive and handle the
+ * 'write unblocked' event before we turn on nonblock support.
+ */
+ if (chr && chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) {
+ nonblock = true;
+ }
+ ret = do_send(fd, _buf, len1, nonblock);
+
+#ifdef _WIN32
+ eagain_errno = WSAEWOULDBLOCK;
+#else
+ eagain_errno = -EAGAIN;
+#endif
+
+ if (nonblock && (ret == eagain_errno || (ret >= 0 && ret < len1))) {
+ /* Update fd handler to wake up when chr becomes writable */
+ chr->chr_enable_write_fd_handler(chr);
+ chr->write_blocked = true;
+ }
+ return ret;
+}
+
#ifndef _WIN32
typedef struct {
@@ -568,7 +618,7 @@ typedef struct {
static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
{
FDCharDriver *s = chr->opaque;
- return send_all(s->fd_out, buf, len);
+ return send_all(chr, s->fd_out, buf, len);
}
static int fd_chr_read_poll(void *opaque)
@@ -893,7 +943,7 @@ static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
pty_chr_update_read_handler(chr);
return 0;
}
- return send_all(s->fd, buf, len);
+ return send_all(chr, s->fd, buf, len);
}
static int pty_chr_read_poll(void *opaque)
@@ -2188,8 +2238,15 @@ static void tcp_closed(void *opaque)
static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
{
TCPCharDriver *s = chr->opaque;
+
if (s->connected) {
- return send_all(s->fd, buf, len);
+ int ret;
+
+ ret = send_all(chr, s->fd, buf, len);
+ if (ret == -1 && errno == EPIPE) {
+ tcp_closed(chr);
+ }
+ return ret;
} else {
/* XXX: indicate an error ? */
return len;

View File

@ -0,0 +1,447 @@
From 3dfc39e3dcdf006d3aef8b8be1f3947f9393b90f Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 20 Sep 2013 16:57:51 +0200
Subject: [PATCH] virtio-pci: remove vdev field
The vdev field is complicated to synchronize. Just access the
BusState's list of children.
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/s390x/virtio-ccw.h | 1 -
hw/virtio/virtio-pci.c | 107 +++++++++++++++++++++++++++++--------------------
hw/virtio/virtio-pci.h | 1 -
3 files changed, 63 insertions(+), 46 deletions(-)
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index 96d6f5d..00932c7 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -77,7 +77,6 @@ typedef struct VirtIOCCWDeviceClass {
struct VirtioCcwDevice {
DeviceState parent_obj;
SubchDev *sch;
- VirtIODevice *vdev;
char *bus_id;
uint32_t host_features[VIRTIO_CCW_FEATURE_SIZE];
VirtioBusState bus;
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 76b7652..be18e92 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -113,31 +113,39 @@ static inline VirtIOPCIProxy *to_virtio_pci_proxy_fast(DeviceState *d)
static void virtio_pci_notify(DeviceState *d, uint16_t vector)
{
VirtIOPCIProxy *proxy = to_virtio_pci_proxy_fast(d);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+
if (msix_enabled(&proxy->pci_dev))
msix_notify(&proxy->pci_dev, vector);
else
- pci_set_irq(&proxy->pci_dev, proxy->vdev->isr & 1);
+ pci_set_irq(&proxy->pci_dev, vdev->isr & 1);
}
static void virtio_pci_save_config(DeviceState *d, QEMUFile *f)
{
VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+
pci_device_save(&proxy->pci_dev, f);
msix_save(&proxy->pci_dev, f);
if (msix_present(&proxy->pci_dev))
- qemu_put_be16(f, proxy->vdev->config_vector);
+ qemu_put_be16(f, vdev->config_vector);
}
static void virtio_pci_save_queue(DeviceState *d, int n, QEMUFile *f)
{
VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+
if (msix_present(&proxy->pci_dev))
- qemu_put_be16(f, virtio_queue_vector(proxy->vdev, n));
+ qemu_put_be16(f, virtio_queue_vector(vdev, n));
}
static int virtio_pci_load_config(DeviceState *d, QEMUFile *f)
{
VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+
int ret;
ret = pci_device_load(&proxy->pci_dev, f);
if (ret) {
@@ -146,12 +154,12 @@ static int virtio_pci_load_config(DeviceState *d, QEMUFile *f)
msix_unuse_all_vectors(&proxy->pci_dev);
msix_load(&proxy->pci_dev, f);
if (msix_present(&proxy->pci_dev)) {
- qemu_get_be16s(f, &proxy->vdev->config_vector);
+ qemu_get_be16s(f, &vdev->config_vector);
} else {
- proxy->vdev->config_vector = VIRTIO_NO_VECTOR;
+ vdev->config_vector = VIRTIO_NO_VECTOR;
}
- if (proxy->vdev->config_vector != VIRTIO_NO_VECTOR) {
- return msix_vector_use(&proxy->pci_dev, proxy->vdev->config_vector);
+ if (vdev->config_vector != VIRTIO_NO_VECTOR) {
+ return msix_vector_use(&proxy->pci_dev, vdev->config_vector);
}
return 0;
}
@@ -159,13 +167,15 @@ static int virtio_pci_load_config(DeviceState *d, QEMUFile *f)
static int virtio_pci_load_queue(DeviceState *d, int n, QEMUFile *f)
{
VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+
uint16_t vector;
if (msix_present(&proxy->pci_dev)) {
qemu_get_be16s(f, &vector);
} else {
vector = VIRTIO_NO_VECTOR;
}
- virtio_queue_set_vector(proxy->vdev, n, vector);
+ virtio_queue_set_vector(vdev, n, vector);
if (vector != VIRTIO_NO_VECTOR) {
return msix_vector_use(&proxy->pci_dev, vector);
}
@@ -175,7 +185,8 @@ static int virtio_pci_load_queue(DeviceState *d, int n, QEMUFile *f)
static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy,
int n, bool assign, bool set_handler)
{
- VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+ VirtQueue *vq = virtio_get_queue(vdev, n);
EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
int r = 0;
@@ -200,6 +211,7 @@ static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy,
static void virtio_pci_start_ioeventfd(VirtIOPCIProxy *proxy)
{
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
int n, r;
if (!(proxy->flags & VIRTIO_PCI_FLAG_USE_IOEVENTFD) ||
@@ -209,7 +221,7 @@ static void virtio_pci_start_ioeventfd(VirtIOPCIProxy *proxy)
}
for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
- if (!virtio_queue_get_num(proxy->vdev, n)) {
+ if (!virtio_queue_get_num(vdev, n)) {
continue;
}
@@ -223,7 +235,7 @@ static void virtio_pci_start_ioeventfd(VirtIOPCIProxy *proxy)
assign_error:
while (--n >= 0) {
- if (!virtio_queue_get_num(proxy->vdev, n)) {
+ if (!virtio_queue_get_num(vdev, n)) {
continue;
}
@@ -236,6 +248,7 @@ assign_error:
static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
{
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
int r;
int n;
@@ -244,7 +257,7 @@ static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
}
for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
- if (!virtio_queue_get_num(proxy->vdev, n)) {
+ if (!virtio_queue_get_num(vdev, n)) {
continue;
}
@@ -257,7 +270,7 @@ static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
VirtIOPCIProxy *proxy = opaque;
- VirtIODevice *vdev = proxy->vdev;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
hwaddr pa;
switch (addr) {
@@ -272,7 +285,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
pa = (hwaddr)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
if (pa == 0) {
virtio_pci_stop_ioeventfd(proxy);
- virtio_reset(proxy->vdev);
+ virtio_reset(vdev);
msix_unuse_all_vectors(&proxy->pci_dev);
}
else
@@ -299,7 +312,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
}
if (vdev->status == 0) {
- virtio_reset(proxy->vdev);
+ virtio_reset(vdev);
msix_unuse_all_vectors(&proxy->pci_dev);
}
@@ -335,7 +348,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr)
{
- VirtIODevice *vdev = proxy->vdev;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
uint32_t ret = 0xFFFFFFFF;
switch (addr) {
@@ -381,6 +394,7 @@ static uint64_t virtio_pci_config_read(void *opaque, hwaddr addr,
unsigned size)
{
VirtIOPCIProxy *proxy = opaque;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
uint64_t val = 0;
if (addr < config) {
@@ -390,16 +404,16 @@ static uint64_t virtio_pci_config_read(void *opaque, hwaddr addr,
switch (size) {
case 1:
- val = virtio_config_readb(proxy->vdev, addr);
+ val = virtio_config_readb(vdev, addr);
break;
case 2:
- val = virtio_config_readw(proxy->vdev, addr);
+ val = virtio_config_readw(vdev, addr);
if (virtio_is_big_endian()) {
val = bswap16(val);
}
break;
case 4:
- val = virtio_config_readl(proxy->vdev, addr);
+ val = virtio_config_readl(vdev, addr);
if (virtio_is_big_endian()) {
val = bswap32(val);
}
@@ -413,6 +427,7 @@ static void virtio_pci_config_write(void *opaque, hwaddr addr,
{
VirtIOPCIProxy *proxy = opaque;
uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
if (addr < config) {
virtio_ioport_write(proxy, addr, val);
return;
@@ -424,19 +439,19 @@ static void virtio_pci_config_write(void *opaque, hwaddr addr,
*/
switch (size) {
case 1:
- virtio_config_writeb(proxy->vdev, addr, val);
+ virtio_config_writeb(vdev, addr, val);
break;
case 2:
if (virtio_is_big_endian()) {
val = bswap16(val);
}
- virtio_config_writew(proxy->vdev, addr, val);
+ virtio_config_writew(vdev, addr, val);
break;
case 4:
if (virtio_is_big_endian()) {
val = bswap32(val);
}
- virtio_config_writel(proxy->vdev, addr, val);
+ virtio_config_writel(vdev, addr, val);
break;
}
}
@@ -455,6 +470,7 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
uint32_t val, int len)
{
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
pci_default_write_config(pci_dev, address, val, len);
@@ -462,8 +478,7 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
!(pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER) &&
!(proxy->flags & VIRTIO_PCI_FLAG_BUS_MASTER_BUG)) {
virtio_pci_stop_ioeventfd(proxy);
- virtio_set_status(proxy->vdev,
- proxy->vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK);
+ virtio_set_status(vdev, vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK);
}
}
@@ -506,7 +521,8 @@ static int kvm_virtio_pci_irqfd_use(VirtIOPCIProxy *proxy,
unsigned int vector)
{
VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
- VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+ VirtQueue *vq = virtio_get_queue(vdev, queue_no);
EventNotifier *n = virtio_queue_get_guest_notifier(vq);
int ret;
ret = kvm_irqchip_add_irqfd_notifier(kvm_state, n, NULL, irqfd->virq);
@@ -517,7 +533,8 @@ static void kvm_virtio_pci_irqfd_release(VirtIOPCIProxy *proxy,
unsigned int queue_no,
unsigned int vector)
{
- VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+ VirtQueue *vq = virtio_get_queue(vdev, queue_no);
EventNotifier *n = virtio_queue_get_guest_notifier(vq);
VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
int ret;
@@ -529,7 +546,7 @@ static void kvm_virtio_pci_irqfd_release(VirtIOPCIProxy *proxy,
static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs)
{
PCIDevice *dev = &proxy->pci_dev;
- VirtIODevice *vdev = proxy->vdev;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
unsigned int vector;
int ret, queue_no;
@@ -578,7 +595,7 @@ undo:
static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs)
{
PCIDevice *dev = &proxy->pci_dev;
- VirtIODevice *vdev = proxy->vdev;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
unsigned int vector;
int queue_no;
VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
@@ -606,8 +623,9 @@ static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy,
unsigned int vector,
MSIMessage msg)
{
- VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(proxy->vdev);
- VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+ VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
+ VirtQueue *vq = virtio_get_queue(vdev, queue_no);
EventNotifier *n = virtio_queue_get_guest_notifier(vq);
VirtIOIRQFD *irqfd;
int ret = 0;
@@ -626,10 +644,10 @@ static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy,
* Otherwise, set it up now.
*/
if (k->guest_notifier_mask) {
- k->guest_notifier_mask(proxy->vdev, queue_no, false);
+ k->guest_notifier_mask(vdev, queue_no, false);
/* Test after unmasking to avoid losing events. */
if (k->guest_notifier_pending &&
- k->guest_notifier_pending(proxy->vdev, queue_no)) {
+ k->guest_notifier_pending(vdev, queue_no)) {
event_notifier_set(n);
}
} else {
@@ -642,13 +660,14 @@ static void virtio_pci_vq_vector_mask(VirtIOPCIProxy *proxy,
unsigned int queue_no,
unsigned int vector)
{
- VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(proxy->vdev);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+ VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
/* If guest supports masking, keep irqfd but mask it.
* Otherwise, clean it up now.
*/
if (k->guest_notifier_mask) {
- k->guest_notifier_mask(proxy->vdev, queue_no, true);
+ k->guest_notifier_mask(vdev, queue_no, true);
} else {
kvm_virtio_pci_irqfd_release(proxy, queue_no, vector);
}
@@ -658,7 +677,7 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector,
MSIMessage msg)
{
VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
- VirtIODevice *vdev = proxy->vdev;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
int ret, queue_no;
for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) {
@@ -688,7 +707,7 @@ undo:
static void virtio_pci_vector_mask(PCIDevice *dev, unsigned vector)
{
VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
- VirtIODevice *vdev = proxy->vdev;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
int queue_no;
for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) {
@@ -707,7 +726,7 @@ static void virtio_pci_vector_poll(PCIDevice *dev,
unsigned int vector_end)
{
VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
- VirtIODevice *vdev = proxy->vdev;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
int queue_no;
unsigned int vector;
@@ -739,8 +758,9 @@ static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign,
bool with_irqfd)
{
VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
- VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(proxy->vdev);
- VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+ VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
+ VirtQueue *vq = virtio_get_queue(vdev, n);
EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
if (assign) {
@@ -755,7 +775,7 @@ static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign,
}
if (!msix_enabled(&proxy->pci_dev) && vdc->guest_notifier_mask) {
- vdc->guest_notifier_mask(proxy->vdev, n, !assign);
+ vdc->guest_notifier_mask(vdev, n, !assign);
}
return 0;
@@ -770,7 +790,7 @@ static bool virtio_pci_query_guest_notifiers(DeviceState *d)
static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign)
{
VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
- VirtIODevice *vdev = proxy->vdev;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
int r, n;
bool with_irqfd = msix_enabled(&proxy->pci_dev) &&
@@ -864,11 +884,12 @@ static int virtio_pci_set_host_notifier(DeviceState *d, int n, bool assign)
static void virtio_pci_vmstate_change(DeviceState *d, bool running)
{
VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
if (running) {
/* Try to find out if the guest has bus master disabled, but is
in ready state. Then we have a buggy guest OS. */
- if ((proxy->vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) &&
+ if ((vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) &&
!(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
}
@@ -943,8 +964,6 @@ static void virtio_pci_device_plugged(DeviceState *d)
uint8_t *config;
uint32_t size;
- proxy->vdev = virtio_bus_get_device(bus);
-
config = proxy->pci_dev.config;
if (proxy->class_code) {
pci_config_set_class(config, proxy->class_code);
diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
index 917bcc5..dc332ae 100644
--- a/hw/virtio/virtio-pci.h
+++ b/hw/virtio/virtio-pci.h
@@ -82,7 +82,6 @@ typedef struct VirtioPCIClass {
struct VirtIOPCIProxy {
PCIDevice pci_dev;
- VirtIODevice *vdev;
MemoryRegion bar;
uint32_t flags;
uint32_t class_code;

View File

@ -1,72 +0,0 @@
From cf067f179258c741547a792eb7c38542d2574165 Mon Sep 17 00:00:00 2001
From: Amit Shah <amit.shah@redhat.com>
Date: Mon, 21 Mar 2011 22:02:47 +0100
Subject: [PATCH] char: Equip the unix/tcp backend to handle nonblocking
writes#
Now that the infrastructure is in place to return -EAGAIN to callers,
individual char drivers can set their update_fd_handlers() function to
set or remove an fd's write handler. This handler checks if the driver
became writable.
A generic callback routine is used for unblocking writes and letting
users of chardevs know that a driver became writable again.
Signed-off-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Cole Robinson <crobinso@redhat.com>
---
qemu-char.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/qemu-char.c b/qemu-char.c
index 96fc54e..53d2c13 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -105,6 +105,19 @@
static QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs =
QTAILQ_HEAD_INITIALIZER(chardevs);
+/*
+ * Generic routine that gets called when chardev becomes writable.
+ * Lets chardev user know it's OK to send more data.
+ */
+static void char_write_unblocked(void *opaque)
+{
+ CharDriverState *chr = opaque;
+
+ chr->write_blocked = false;
+ chr->chr_disable_write_fd_handler(chr);
+ chr->chr_write_unblocked(chr->handler_opaque);
+}
+
void qemu_chr_be_event(CharDriverState *s, int event)
{
/* Keep track if the char device is open */
@@ -126,6 +139,9 @@ static void qemu_chr_fire_open_event(void *opaque)
{
CharDriverState *s = opaque;
qemu_chr_be_event(s, CHR_EVENT_OPENED);
+ if (s->write_blocked) {
+ char_write_unblocked(s);
+ }
qemu_free_timer(s->open_timer);
s->open_timer = NULL;
}
@@ -2245,6 +2261,17 @@ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
ret = send_all(chr, s->fd, buf, len);
if (ret == -1 && errno == EPIPE) {
tcp_closed(chr);
+
+ if (chr->chr_enable_write_fd_handler && chr->chr_write_unblocked) {
+ /*
+ * Since we haven't written out anything, let's say
+ * we're throttled. This will prevent any output from
+ * the guest getting lost if host-side chardev goes
+ * down. Unthrottle when we re-connect.
+ */
+ chr->write_blocked = true;
+ return 0;
+ }
}
return ret;
} else {

View File

@ -0,0 +1,293 @@
From 6f5e351c3f91e76a70c0684276af8070cfeb07da Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 20 Sep 2013 16:57:52 +0200
Subject: [PATCH] virtio-ccw: remove vdev field
The vdev field is complicated to synchronize. Just access the
BusState's list of children.
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/s390x/virtio-ccw.c | 80 ++++++++++++++++++++++++++++-----------------------
1 file changed, 44 insertions(+), 36 deletions(-)
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index f93a81c..8947196 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -57,9 +57,10 @@ static const TypeInfo virtual_css_bus_info = {
VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch)
{
VirtIODevice *vdev = NULL;
+ VirtioCcwDevice *dev = sch->driver_data;
- if (sch->driver_data) {
- vdev = ((VirtioCcwDevice *)sch->driver_data)->vdev;
+ if (dev) {
+ vdev = virtio_bus_get_device(&dev->bus);
}
return vdev;
}
@@ -67,7 +68,8 @@ VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch)
static int virtio_ccw_set_guest2host_notifier(VirtioCcwDevice *dev, int n,
bool assign, bool set_handler)
{
- VirtQueue *vq = virtio_get_queue(dev->vdev, n);
+ VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
+ VirtQueue *vq = virtio_get_queue(vdev, n);
EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
int r = 0;
SubchDev *sch = dev->sch;
@@ -97,6 +99,7 @@ static int virtio_ccw_set_guest2host_notifier(VirtioCcwDevice *dev, int n,
static void virtio_ccw_start_ioeventfd(VirtioCcwDevice *dev)
{
+ VirtIODevice *vdev;
int n, r;
if (!(dev->flags & VIRTIO_CCW_FLAG_USE_IOEVENTFD) ||
@@ -104,8 +107,9 @@ static void virtio_ccw_start_ioeventfd(VirtioCcwDevice *dev)
dev->ioeventfd_started) {
return;
}
+ vdev = virtio_bus_get_device(&dev->bus);
for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
- if (!virtio_queue_get_num(dev->vdev, n)) {
+ if (!virtio_queue_get_num(vdev, n)) {
continue;
}
r = virtio_ccw_set_guest2host_notifier(dev, n, true, true);
@@ -118,7 +122,7 @@ static void virtio_ccw_start_ioeventfd(VirtioCcwDevice *dev)
assign_error:
while (--n >= 0) {
- if (!virtio_queue_get_num(dev->vdev, n)) {
+ if (!virtio_queue_get_num(vdev, n)) {
continue;
}
r = virtio_ccw_set_guest2host_notifier(dev, n, false, false);
@@ -132,13 +136,15 @@ static void virtio_ccw_start_ioeventfd(VirtioCcwDevice *dev)
static void virtio_ccw_stop_ioeventfd(VirtioCcwDevice *dev)
{
+ VirtIODevice *vdev;
int n, r;
if (!dev->ioeventfd_started) {
return;
}
+ vdev = virtio_bus_get_device(&dev->bus);
for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
- if (!virtio_queue_get_num(dev->vdev, n)) {
+ if (!virtio_queue_get_num(vdev, n)) {
continue;
}
r = virtio_ccw_set_guest2host_notifier(dev, n, false, false);
@@ -189,7 +195,7 @@ typedef struct VirtioFeatDesc {
static int virtio_ccw_set_vqs(SubchDev *sch, uint64_t addr, uint32_t align,
uint16_t index, uint16_t num)
{
- VirtioCcwDevice *dev = sch->driver_data;
+ VirtIODevice *vdev = virtio_ccw_get_vdev(sch);
if (index > VIRTIO_PCI_QUEUE_MAX) {
return -EINVAL;
@@ -200,23 +206,23 @@ static int virtio_ccw_set_vqs(SubchDev *sch, uint64_t addr, uint32_t align,
return -EINVAL;
}
- if (!dev) {
+ if (!vdev) {
return -EINVAL;
}
- virtio_queue_set_addr(dev->vdev, index, addr);
+ virtio_queue_set_addr(vdev, index, addr);
if (!addr) {
- virtio_queue_set_vector(dev->vdev, index, 0);
+ virtio_queue_set_vector(vdev, index, 0);
} else {
/* Fail if we don't have a big enough queue. */
/* TODO: Add interface to handle vring.num changing */
- if (virtio_queue_get_num(dev->vdev, index) > num) {
+ if (virtio_queue_get_num(vdev, index) > num) {
return -EINVAL;
}
- virtio_queue_set_vector(dev->vdev, index, index);
+ virtio_queue_set_vector(vdev, index, index);
}
/* tell notify handler in case of config change */
- dev->vdev->config_vector = VIRTIO_PCI_QUEUE_MAX;
+ vdev->config_vector = VIRTIO_PCI_QUEUE_MAX;
return 0;
}
@@ -230,6 +236,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
hwaddr indicators;
VqConfigBlock vq_config;
VirtioCcwDevice *dev = sch->driver_data;
+ VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
bool check_len;
int len;
hwaddr hw_len;
@@ -272,7 +279,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
break;
case CCW_CMD_VDEV_RESET:
virtio_ccw_stop_ioeventfd(dev);
- virtio_reset(dev->vdev);
+ virtio_reset(vdev);
ret = 0;
break;
case CCW_CMD_READ_FEAT:
@@ -319,7 +326,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
features.features = ldl_le_phys(ccw.cda);
if (features.index < ARRAY_SIZE(dev->host_features)) {
virtio_bus_set_vdev_features(&dev->bus, features.features);
- dev->vdev->guest_features = features.features;
+ vdev->guest_features = features.features;
} else {
/*
* If the guest supports more feature bits, assert that it
@@ -337,30 +344,30 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
break;
case CCW_CMD_READ_CONF:
if (check_len) {
- if (ccw.count > dev->vdev->config_len) {
+ if (ccw.count > vdev->config_len) {
ret = -EINVAL;
break;
}
}
- len = MIN(ccw.count, dev->vdev->config_len);
+ len = MIN(ccw.count, vdev->config_len);
if (!ccw.cda) {
ret = -EFAULT;
} else {
- virtio_bus_get_vdev_config(&dev->bus, dev->vdev->config);
+ virtio_bus_get_vdev_config(&dev->bus, vdev->config);
/* XXX config space endianness */
- cpu_physical_memory_write(ccw.cda, dev->vdev->config, len);
+ cpu_physical_memory_write(ccw.cda, vdev->config, len);
sch->curr_status.scsw.count = ccw.count - len;
ret = 0;
}
break;
case CCW_CMD_WRITE_CONF:
if (check_len) {
- if (ccw.count > dev->vdev->config_len) {
+ if (ccw.count > vdev->config_len) {
ret = -EINVAL;
break;
}
}
- len = MIN(ccw.count, dev->vdev->config_len);
+ len = MIN(ccw.count, vdev->config_len);
hw_len = len;
if (!ccw.cda) {
ret = -EFAULT;
@@ -371,9 +378,9 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
} else {
len = hw_len;
/* XXX config space endianness */
- memcpy(dev->vdev->config, config, len);
+ memcpy(vdev->config, config, len);
cpu_physical_memory_unmap(config, hw_len, 0, hw_len);
- virtio_bus_set_vdev_config(&dev->bus, dev->vdev->config);
+ virtio_bus_set_vdev_config(&dev->bus, vdev->config);
sch->curr_status.scsw.count = ccw.count - len;
ret = 0;
}
@@ -397,9 +404,9 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
virtio_ccw_stop_ioeventfd(dev);
}
- virtio_set_status(dev->vdev, status);
- if (dev->vdev->status == 0) {
- virtio_reset(dev->vdev);
+ virtio_set_status(vdev, status);
+ if (vdev->status == 0) {
+ virtio_reset(vdev);
}
if (status & VIRTIO_CONFIG_S_DRIVER_OK) {
virtio_ccw_start_ioeventfd(dev);
@@ -463,7 +470,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
ret = -EFAULT;
} else {
vq_config.index = lduw_phys(ccw.cda);
- vq_config.num_max = virtio_queue_get_num(dev->vdev,
+ vq_config.num_max = virtio_queue_get_num(vdev,
vq_config.index);
stw_phys(ccw.cda + sizeof(vq_config.index), vq_config.num_max);
sch->curr_status.scsw.count = ccw.count - sizeof(vq_config);
@@ -495,7 +502,6 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev)
sch->driver_data = dev;
dev->sch = sch;
- dev->vdev = vdev;
dev->indicators = 0;
/* Initialize subchannel structure. */
@@ -608,7 +614,7 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev)
memset(&sch->id, 0, sizeof(SenseId));
sch->id.reserved = 0xff;
sch->id.cu_type = VIRTIO_CCW_CU_TYPE;
- sch->id.cu_model = dev->vdev->device_id;
+ sch->id.cu_model = vdev->device_id;
/* Only the first 32 feature bits are used. */
dev->host_features[0] = virtio_bus_get_vdev_features(&dev->bus,
@@ -892,9 +898,10 @@ static unsigned virtio_ccw_get_features(DeviceState *d)
static void virtio_ccw_reset(DeviceState *d)
{
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
+ VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
virtio_ccw_stop_ioeventfd(dev);
- virtio_reset(dev->vdev);
+ virtio_reset(vdev);
css_reset_sch(dev->sch);
dev->indicators = 0;
dev->indicators2 = 0;
@@ -934,9 +941,10 @@ static int virtio_ccw_set_host_notifier(DeviceState *d, int n, bool assign)
static int virtio_ccw_set_guest_notifier(VirtioCcwDevice *dev, int n,
bool assign, bool with_irqfd)
{
- VirtQueue *vq = virtio_get_queue(dev->vdev, n);
+ VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
+ VirtQueue *vq = virtio_get_queue(vdev, n);
EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
- VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(dev->vdev);
+ VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
if (assign) {
int r = event_notifier_init(notifier, 0);
@@ -952,16 +960,16 @@ static int virtio_ccw_set_guest_notifier(VirtioCcwDevice *dev, int n,
* land in qemu (and only the irq fd) in this code.
*/
if (k->guest_notifier_mask) {
- k->guest_notifier_mask(dev->vdev, n, false);
+ k->guest_notifier_mask(vdev, n, false);
}
/* get lost events and re-inject */
if (k->guest_notifier_pending &&
- k->guest_notifier_pending(dev->vdev, n)) {
+ k->guest_notifier_pending(vdev, n)) {
event_notifier_set(notifier);
}
} else {
if (k->guest_notifier_mask) {
- k->guest_notifier_mask(dev->vdev, n, true);
+ k->guest_notifier_mask(vdev, n, true);
}
virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd);
event_notifier_cleanup(notifier);
@@ -973,7 +981,7 @@ static int virtio_ccw_set_guest_notifiers(DeviceState *d, int nvqs,
bool assigned)
{
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
- VirtIODevice *vdev = dev->vdev;
+ VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
int r, n;
for (n = 0; n < nvqs; n++) {

View File

@ -0,0 +1,148 @@
From e26f88b6280b2386c36d3b3d5ec820deb1ac7749 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 20 Sep 2013 16:57:53 +0200
Subject: [PATCH] virtio-bus: cleanup plug/unplug interface
Right now we have these pairs:
- virtio_bus_plug_device/virtio_bus_destroy_device. The first
takes a VirtIODevice, the second takes a VirtioBusState
- device_plugged/device_unplug callbacks in the VirtioBusClass
(here it's just the naming that is inconsistent)
- virtio_bus_destroy_device is not called by anyone (and since
it calls qdev_free, it would be called by the proxies---but
then the callback is useless since the proxies can do whatever
they want before calling virtio_bus_destroy_device)
And there is a k->init but no k->exit, hence virtio_device_exit is
overwritten by subclasses (except virtio-9p). This cleans it up by:
- renaming the device_unplug callback to device_unplugged
- renaming virtio_bus_plug_device to virtio_bus_device_plugged,
matching the callback name
- renaming virtio_bus_destroy_device to virtio_bus_device_unplugged,
removing the qdev_free, making it take a VirtIODevice and calling it
from virtio_device_exit
- adding a k->exit callback
virtio_device_exit is still overwritten, the next patches will fix that.
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/virtio/virtio-bus.c | 18 +++++++++---------
hw/virtio/virtio.c | 7 ++++++-
include/hw/virtio/virtio-bus.h | 6 +++---
include/hw/virtio/virtio.h | 1 +
4 files changed, 19 insertions(+), 13 deletions(-)
diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c
index 17dd06e..7aed6a4 100644
--- a/hw/virtio/virtio-bus.c
+++ b/hw/virtio/virtio-bus.c
@@ -37,8 +37,8 @@ do { printf("virtio_bus: " fmt , ## __VA_ARGS__); } while (0)
#define DPRINTF(fmt, ...) do { } while (0)
#endif
-/* Plug the VirtIODevice */
-int virtio_bus_plug_device(VirtIODevice *vdev)
+/* A VirtIODevice is being plugged */
+int virtio_bus_device_plugged(VirtIODevice *vdev)
{
DeviceState *qdev = DEVICE(vdev);
BusState *qbus = BUS(qdev_get_parent_bus(qdev));
@@ -64,20 +64,20 @@ void virtio_bus_reset(VirtioBusState *bus)
}
}
-/* Destroy the VirtIODevice */
-void virtio_bus_destroy_device(VirtioBusState *bus)
+/* A VirtIODevice is being unplugged */
+void virtio_bus_device_unplugged(VirtIODevice *vdev)
{
- BusState *qbus = BUS(bus);
+ DeviceState *qdev = DEVICE(vdev);
+ BusState *qbus = BUS(qdev_get_parent_bus(qdev));
+ VirtioBusState *bus = VIRTIO_BUS(qbus);
VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(bus);
- VirtIODevice *vdev = virtio_bus_get_device(bus);
DPRINTF("%s: remove device.\n", qbus->name);
if (vdev != NULL) {
- if (klass->device_unplug != NULL) {
- klass->device_unplug(qbus->parent);
+ if (klass->device_unplugged != NULL) {
+ klass->device_unplugged(qbus->parent);
}
- object_unparent(OBJECT(vdev));
}
}
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 2f1e73b..965b2c0 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -1158,14 +1158,19 @@ static int virtio_device_init(DeviceState *qdev)
if (k->init(vdev) < 0) {
return -1;
}
- virtio_bus_plug_device(vdev);
+ virtio_bus_device_plugged(vdev);
return 0;
}
static int virtio_device_exit(DeviceState *qdev)
{
VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
+ VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(qdev);
+ virtio_bus_device_unplugged(vdev);
+ if (k->exit) {
+ k->exit(vdev);
+ }
if (vdev->bus_name) {
g_free(vdev->bus_name);
vdev->bus_name = NULL;
diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h
index ba0f86a..0756545 100644
--- a/include/hw/virtio/virtio-bus.h
+++ b/include/hw/virtio/virtio-bus.h
@@ -61,7 +61,7 @@ typedef struct VirtioBusClass {
* transport independent exit function.
* This is called by virtio-bus just before the device is unplugged.
*/
- void (*device_unplug)(DeviceState *d);
+ void (*device_unplugged)(DeviceState *d);
/*
* Does the transport have variable vring alignment?
* (ie can it ever call virtio_queue_set_align()?)
@@ -74,9 +74,9 @@ struct VirtioBusState {
BusState parent_obj;
};
-int virtio_bus_plug_device(VirtIODevice *vdev);
+int virtio_bus_device_plugged(VirtIODevice *vdev);
void virtio_bus_reset(VirtioBusState *bus);
-void virtio_bus_destroy_device(VirtioBusState *bus);
+void virtio_bus_device_unplugged(VirtIODevice *bus);
/* Get the device id of the plugged device. */
uint16_t virtio_bus_get_vdev_id(VirtioBusState *bus);
/* Get the config_len field of the plugged device. */
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index a90522d..59756c2 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -127,6 +127,7 @@ typedef struct VirtioDeviceClass {
/* This is what a VirtioDevice must implement */
DeviceClass parent;
int (*init)(VirtIODevice *vdev);
+ void (*exit)(VirtIODevice *vdev);
uint32_t (*get_features)(VirtIODevice *vdev, uint32_t requested_features);
uint32_t (*bad_features)(VirtIODevice *vdev);
void (*set_features)(VirtIODevice *vdev, uint32_t val);

View File

@ -1,47 +0,0 @@
From 563ef1912e4b0c0b5728bc53d2b225d2ff3cd9ef Mon Sep 17 00:00:00 2001
From: Amit Shah <amit.shah@redhat.com>
Date: Mon, 21 Mar 2011 22:06:41 +0100
Subject: [PATCH] virtio-console: Enable port throttling when chardev is slow
to consume data
When a chardev indicates it can't accept more data, we tell the
virtio-serial code to stop sending us any more data till we tell
otherwise. This helps in guests continuing to run normally while the vq
keeps getting full and eventually the guest stops queueing more data.
As soon as the chardev indicates it can accept more data, start pushing!
Signed-off-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Cole Robinson <crobinso@redhat.com>
---
hw/virtio-console.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index dd6f614..0e12514 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -20,6 +20,16 @@ typedef struct VirtConsole {
CharDriverState *chr;
} VirtConsole;
+/*
+ * Callback function that's called from chardevs when backend becomes
+ * writable.
+ */
+static void chr_write_unblocked(void *opaque)
+{
+ VirtConsole *vcon = opaque;
+
+ virtio_serial_throttle_port(&vcon->port, false);
+}
/* Callback function that's called when the guest sends us data */
static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
@@ -110,6 +120,7 @@ static const QemuChrHandlers chr_handlers = {
.fd_can_read = chr_can_read,
.fd_read = chr_read,
.fd_event = chr_event,
+ .fd_write_unblocked = chr_write_unblocked,
};
static int virtconsole_initfn(VirtIOSerialPort *port)

View File

@ -1,132 +0,0 @@
From 7f533f631ffb62d2330003e687d47c83d3359026 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Tue, 22 Mar 2011 12:27:59 +0200
Subject: [PATCH] spice-qemu-char.c: add throttling
BZ: 672191
upstream: not submitted (explained below)
Adds throttling support to spicevmc chardev. Uses a timer to avoid recursing:
1. spice-server: reds.c: read_from_vdi_port
2. qemu: spice-qemu-char.c: vmc_read
3. chr_write_unblocked
(calls virtio_serial_throttle_port(port, false))
4. qemu: virtio ...
5. qemu: spice-qemu-char.c: spice_chr_write
6. qemu: spice-qemu-char.c: wakeup (calls into spice-server)
7. spice-server: ...
8. qemu: spice-qemu-char.c: vmc_read
Instead, in vmc_read if we were throttled and we are just about to return
all the bytes we will set a timer to be triggered immediately to call
chr_write_unblocked. Then we return after 2 above, and 3 is called from the
timer callback. This also means we can later remove some ugly recursion protection
from spice-server.
The other tricky point in this patch is not returning the leftover chunk twice.
When we throttle, by definition we have data that spice server didn't consume.
It is being kept by virtio-serial, and by us. The next vmc_read callback needs
to not return it, but just do unthrottling. Then virtio will give us the remaining
chunk as usual in spice_chr_write, and we will pass it to spice server in the
next vmc_read.
This patch relies on Amit's series to expose throttling to chardev's, which
was not accepted upstream, and will not be accepted upstream until the mainloop
is reworked to use glib.
Signed-off-by: Cole Robinson <crobinso@redhat.com>
---
spice-qemu-char.c | 39 +++++++++++++++++++++++++++++++++++----
1 file changed, 35 insertions(+), 4 deletions(-)
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index a4d7de8..75bb125 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -1,4 +1,6 @@
#include "config-host.h"
+#include "qemu-common.h"
+#include "qemu/timer.h"
#include "trace.h"
#include "ui/qemu-spice.h"
#include "char/char.h"
@@ -25,6 +27,7 @@ typedef struct SpiceCharDriver {
uint8_t *datapos;
ssize_t bufsize, datalen;
uint32_t debug;
+ QEMUTimer *unblock_timer;
QLIST_ENTRY(SpiceCharDriver) next;
} SpiceCharDriver;
@@ -54,6 +57,17 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
return out;
}
+static void spice_chr_unblock(void *opaque)
+{
+ SpiceCharDriver *scd = opaque;
+
+ if (scd->chr->chr_write_unblocked == NULL) {
+ dprintf(scd, 1, "%s: backend doesn't support unthrottling.\n", __func__);
+ return;
+ }
+ scd->chr->chr_write_unblocked(scd->chr->handler_opaque);
+}
+
static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
{
SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
@@ -65,9 +79,16 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
scd->datapos += bytes;
scd->datalen -= bytes;
assert(scd->datalen >= 0);
- if (scd->datalen == 0) {
- scd->datapos = 0;
- }
+ }
+ if (scd->datalen == 0 && scd->chr->write_blocked) {
+ dprintf(scd, 1, "%s: unthrottling (%d)\n", __func__, bytes);
+ scd->chr->write_blocked = false;
+ /*
+ * set a timer instead of calling scd->chr->chr_write_unblocked directly,
+ * because that will call back into spice_chr_write (see
+ * virtio-console.c:chr_write_unblocked), which is unwanted.
+ */
+ qemu_mod_timer(scd->unblock_timer, 0);
}
trace_spice_vmc_read(bytes, len);
return bytes;
@@ -163,6 +184,7 @@ static void vmc_unregister_interface(SpiceCharDriver *scd)
static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
{
SpiceCharDriver *s = chr->opaque;
+ int read_bytes;
dprintf(s, 2, "%s: %d\n", __func__, len);
vmc_register_interface(s);
@@ -175,7 +197,15 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
s->datapos = s->buffer;
s->datalen = len;
spice_server_char_device_wakeup(&s->sin);
- return len;
+ read_bytes = len - s->datalen;
+ if (read_bytes != len) {
+ dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__,
+ read_bytes, len, s->bufsize);
+ s->chr->write_blocked = true;
+ /* We'll get passed in the unconsumed data with the next call */
+ s->datalen = 0;
+ }
+ return read_bytes;
}
static void spice_chr_close(struct CharDriverState *chr)
@@ -234,6 +264,7 @@ static CharDriverState *chr_open(QemuOpts *opts, const char *subtype)
chr->chr_close = spice_chr_close;
chr->chr_guest_open = spice_chr_guest_open;
chr->chr_guest_close = spice_chr_guest_close;
+ s->unblock_timer = qemu_new_timer_ms(vm_clock, spice_chr_unblock, s);
QLIST_INSERT_HEAD(&spice_chars, s, next);

View File

@ -0,0 +1,53 @@
From e8821c68009a5b801ffef6d7d9ed5d770c0bfd9f Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 20 Sep 2013 16:57:54 +0200
Subject: [PATCH] virtio-blk: switch exit callback to VirtioDeviceClass
This ensures hot-unplug is handled properly by the proxy.
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/block/virtio-blk.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index 13f6d82..7f0440f 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -728,20 +728,18 @@ static int virtio_blk_device_init(VirtIODevice *vdev)
return 0;
}
-static int virtio_blk_device_exit(DeviceState *dev)
+static void virtio_blk_device_exit(VirtIODevice *vdev)
{
- VirtIODevice *vdev = VIRTIO_DEVICE(dev);
- VirtIOBlock *s = VIRTIO_BLK(dev);
+ VirtIOBlock *s = VIRTIO_BLK(vdev);
#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
remove_migration_state_change_notifier(&s->migration_state_notifier);
virtio_blk_data_plane_destroy(s->dataplane);
s->dataplane = NULL;
#endif
qemu_del_vm_change_state_handler(s->change);
- unregister_savevm(dev, "virtio-blk", s);
+ unregister_savevm(DEVICE(vdev), "virtio-blk", s);
blockdev_mark_auto_del(s->bs);
virtio_cleanup(vdev);
- return 0;
}
static Property virtio_blk_properties[] = {
@@ -753,10 +751,10 @@ static void virtio_blk_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
- dc->exit = virtio_blk_device_exit;
dc->props = virtio_blk_properties;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
vdc->init = virtio_blk_device_init;
+ vdc->exit = virtio_blk_device_exit;
vdc->get_config = virtio_blk_update_config;
vdc->set_config = virtio_blk_set_config;
vdc->get_features = virtio_blk_get_features;

View File

@ -1,70 +0,0 @@
From d126441f71fde3b8a1d1cfea62d05382faea0985 Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Tue, 22 Mar 2011 12:28:00 +0200
Subject: [PATCH] spice-qemu-char.c: remove intermediate buffer
BZ: 672191
upstream: not submitted (explained below)
virtio-serial's buffer is valid when it calls us, and we don't
access it otherwise: vmc_read is only called in response to wakeup,
or else we set datalen=0 and throttle. Then vmc_read is called back,
we return 0 (not accessing the buffer) and set the timer to unthrottle.
Also make datalen int and not ssize_t (to fit spice_chr_write signature).
This relied on the previous patch that introduces throttling, which
can't go upstream right now as explained in that patch.
Signed-off-by: Cole Robinson <crobinso@redhat.com>
---
spice-qemu-char.c | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index 75bb125..5065240 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -23,9 +23,8 @@ typedef struct SpiceCharDriver {
SpiceCharDeviceInstance sin;
char *subtype;
bool active;
- uint8_t *buffer;
- uint8_t *datapos;
- ssize_t bufsize, datalen;
+ const uint8_t *datapos;
+ int datalen;
uint32_t debug;
QEMUTimer *unblock_timer;
QLIST_ENTRY(SpiceCharDriver) next;
@@ -73,7 +72,7 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
int bytes = MIN(len, scd->datalen);
- dprintf(scd, 2, "%s: %p %d/%d/%zd\n", __func__, scd->datapos, len, bytes, scd->datalen);
+ dprintf(scd, 2, "%s: %p %d/%d/%d\n", __func__, scd->datapos, len, bytes, scd->datalen);
if (bytes > 0) {
memcpy(buf, scd->datapos, bytes);
scd->datapos += bytes;
@@ -189,18 +188,13 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
dprintf(s, 2, "%s: %d\n", __func__, len);
vmc_register_interface(s);
assert(s->datalen == 0);
- if (s->bufsize < len) {
- s->bufsize = len;
- s->buffer = g_realloc(s->buffer, s->bufsize);
- }
- memcpy(s->buffer, buf, len);
- s->datapos = s->buffer;
+ s->datapos = buf;
s->datalen = len;
spice_server_char_device_wakeup(&s->sin);
read_bytes = len - s->datalen;
if (read_bytes != len) {
- dprintf(s, 1, "%s: throttling: %d < %d (%zd)\n", __func__,
- read_bytes, len, s->bufsize);
+ dprintf(s, 1, "%s: throttling: %d < %d\n", __func__,
+ read_bytes, len);
s->chr->write_blocked = true;
/* We'll get passed in the unconsumed data with the next call */
s->datalen = 0;

View File

@ -0,0 +1,53 @@
From b4ea3493c8c99bd854eec8640bd5c90c31e8ac14 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 20 Sep 2013 16:57:55 +0200
Subject: [PATCH] virtio-serial: switch exit callback to VirtioDeviceClass
This ensures hot-unplug is handled properly by the proxy.
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/char/virtio-serial-bus.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
index 703f026..a7ede90 100644
--- a/hw/char/virtio-serial-bus.c
+++ b/hw/char/virtio-serial-bus.c
@@ -987,12 +987,11 @@ static const TypeInfo virtio_serial_port_type_info = {
.class_init = virtio_serial_port_class_init,
};
-static int virtio_serial_device_exit(DeviceState *dev)
+static void virtio_serial_device_exit(VirtIODevice *vdev)
{
- VirtIOSerial *vser = VIRTIO_SERIAL(dev);
- VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VirtIOSerial *vser = VIRTIO_SERIAL(vdev);
- unregister_savevm(dev, "virtio-console", vser);
+ unregister_savevm(DEVICE(vdev), "virtio-console", vser);
g_free(vser->ivqs);
g_free(vser->ovqs);
@@ -1004,7 +1003,6 @@ static int virtio_serial_device_exit(DeviceState *dev)
g_free(vser->post_load);
}
virtio_cleanup(vdev);
- return 0;
}
static Property virtio_serial_properties[] = {
@@ -1016,10 +1014,10 @@ static void virtio_serial_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
- dc->exit = virtio_serial_device_exit;
dc->props = virtio_serial_properties;
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
vdc->init = virtio_serial_device_init;
+ vdc->exit = virtio_serial_device_exit;
vdc->get_features = get_features;
vdc->get_config = get_config;
vdc->set_config = set_config;

View File

@ -1,62 +0,0 @@
From a0d12b6040efbe6aa8e6e74cef91cf613ff2bf55 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Tue, 19 Jul 2011 10:56:19 +0200
Subject: [PATCH] usb-redir: Add flow control support
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
hw/usb/redirect.c | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 2ee9ad1..bf6aaf0 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -257,8 +257,9 @@ static int usbredir_read(void *priv, uint8_t *data, int count)
static int usbredir_write(void *priv, uint8_t *data, int count)
{
USBRedirDevice *dev = priv;
+ int r;
- if (!dev->cs->opened) {
+ if (!dev->cs->opened || dev->cs->write_blocked) {
return 0;
}
@@ -267,7 +268,16 @@ static int usbredir_write(void *priv, uint8_t *data, int count)
return 0;
}
- return qemu_chr_fe_write(dev->cs, data, count);
+ r = qemu_chr_fe_write(dev->cs, data, count);
+
+ if (r < 0) {
+ if (dev->cs->write_blocked) {
+ return 0;
+ }
+ return -1;
+ }
+
+ return r;
}
/*
@@ -1227,10 +1237,18 @@ static void usbredir_chardev_event(void *opaque, int event)
}
}
+static void usbredir_chardev_write_unblocked(void *opaque)
+{
+ USBRedirDevice *dev = opaque;
+
+ usbredirparser_do_write(dev->parser);
+}
+
static const QemuChrHandlers usbredir_chr_handlers = {
.fd_can_read = usbredir_chardev_can_read,
.fd_read = usbredir_chardev_read,
.fd_event = usbredir_chardev_event,
+ .fd_write_unblocked = usbredir_chardev_write_unblocked,
};
/*

View File

@ -0,0 +1,58 @@
From d399f7bf1a035d6158d20d3f11a44f03e15132d0 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 20 Sep 2013 16:57:56 +0200
Subject: [PATCH] virtio-net: switch exit callback to VirtioDeviceClass
This ensures hot-unplug is handled properly by the proxy.
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/net/virtio-net.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index b75c753..93a81eb 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1570,16 +1570,15 @@ static int virtio_net_device_init(VirtIODevice *vdev)
return 0;
}
-static int virtio_net_device_exit(DeviceState *qdev)
+static void virtio_net_device_exit(VirtIODevice *vdev)
{
- VirtIONet *n = VIRTIO_NET(qdev);
- VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
+ VirtIONet *n = VIRTIO_NET(vdev);
int i;
/* This will stop vhost backend if appropriate. */
virtio_net_set_status(vdev, 0);
- unregister_savevm(qdev, "virtio-net", n);
+ unregister_savevm(DEVICE(vdev), "virtio-net", n);
if (n->netclient_name) {
g_free(n->netclient_name);
@@ -1610,8 +1609,6 @@ static int virtio_net_device_exit(DeviceState *qdev)
g_free(n->vqs);
qemu_del_nic(n->nic);
virtio_cleanup(vdev);
-
- return 0;
}
static void virtio_net_instance_init(Object *obj)
@@ -1638,10 +1635,10 @@ static void virtio_net_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
- dc->exit = virtio_net_device_exit;
dc->props = virtio_net_properties;
set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
vdc->init = virtio_net_device_init;
+ vdc->exit = virtio_net_device_exit;
vdc->get_config = virtio_net_get_config;
vdc->set_config = virtio_net_set_config;
vdc->get_features = virtio_net_get_features;

View File

@ -1,33 +0,0 @@
From 8dec49852492007b4e5afc599376a4d88623cba8 Mon Sep 17 00:00:00 2001
From: Amit Shah <amit.shah@redhat.com>
Date: Fri, 2 Dec 2011 15:42:55 +0530
Subject: [PATCH] char: Disable write callback if throttled chardev is detached
If a throttled chardev is detached from the frontend device, all future
callbacks should be suppressed. Not doing this results in a segfault.
Bugzilla: 745758
Upstream: Not applicable, since throttling is a RHEL6-only feature.
Signed-off-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Cole Robinson <crobinso@redhat.com>
---
qemu-char.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/qemu-char.c b/qemu-char.c
index 53d2c13..fde72ff 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -223,6 +223,11 @@ void qemu_chr_add_handlers(CharDriverState *s,
++s->avail_connections;
}
if (!handlers) {
+ if (s->write_blocked) {
+ /* Ensure we disable the callback if we were throttled */
+ s->chr_disable_write_fd_handler(s);
+ /* s->write_blocked is cleared below */
+ }
handlers = &null_handlers;
}
s->chr_can_read = handlers->fd_can_read;

View File

@ -0,0 +1,112 @@
From 18a73436b50ec6c28afde849c6de23ad7ebed459 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 20 Sep 2013 16:57:57 +0200
Subject: [PATCH] virtio-scsi: switch exit callback to VirtioDeviceClass
This ensures hot-unplug is handled properly by the proxy.
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/scsi/vhost-scsi.c | 11 +++++------
hw/scsi/virtio-scsi.c | 15 +++++++--------
include/hw/virtio/virtio-scsi.h | 2 +-
3 files changed, 13 insertions(+), 15 deletions(-)
diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index 9e770fb..5e3cc61 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -240,11 +240,10 @@ static int vhost_scsi_init(VirtIODevice *vdev)
return 0;
}
-static int vhost_scsi_exit(DeviceState *qdev)
+static void vhost_scsi_exit(VirtIODevice *vdev)
{
- VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
- VHostSCSI *s = VHOST_SCSI(qdev);
- VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(qdev);
+ VHostSCSI *s = VHOST_SCSI(vdev);
+ VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
migrate_del_blocker(s->migration_blocker);
error_free(s->migration_blocker);
@@ -253,7 +252,7 @@ static int vhost_scsi_exit(DeviceState *qdev)
vhost_scsi_set_status(vdev, 0);
g_free(s->dev.vqs);
- return virtio_scsi_common_exit(vs);
+ virtio_scsi_common_exit(vs);
}
static Property vhost_scsi_properties[] = {
@@ -265,10 +264,10 @@ static void vhost_scsi_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
- dc->exit = vhost_scsi_exit;
dc->props = vhost_scsi_properties;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
vdc->init = vhost_scsi_init;
+ vdc->exit = vhost_scsi_exit;
vdc->get_features = vhost_scsi_get_features;
vdc->set_config = vhost_scsi_set_config;
vdc->set_status = vhost_scsi_set_status;
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 26d95a1..83344ea 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -644,22 +644,21 @@ static int virtio_scsi_device_init(VirtIODevice *vdev)
return 0;
}
-int virtio_scsi_common_exit(VirtIOSCSICommon *vs)
+void virtio_scsi_common_exit(VirtIOSCSICommon *vs)
{
VirtIODevice *vdev = VIRTIO_DEVICE(vs);
g_free(vs->cmd_vqs);
virtio_cleanup(vdev);
- return 0;
}
-static int virtio_scsi_device_exit(DeviceState *qdev)
+static void virtio_scsi_device_exit(VirtIODevice *vdev)
{
- VirtIOSCSI *s = VIRTIO_SCSI(qdev);
- VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(qdev);
+ VirtIOSCSI *s = VIRTIO_SCSI(vdev);
+ VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
- unregister_savevm(qdev, "virtio-scsi", s);
- return virtio_scsi_common_exit(vs);
+ unregister_savevm(DEVICE(vdev), "virtio-scsi", s);
+ virtio_scsi_common_exit(vs);
}
static Property virtio_scsi_properties[] = {
@@ -680,10 +679,10 @@ static void virtio_scsi_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
- dc->exit = virtio_scsi_device_exit;
dc->props = virtio_scsi_properties;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
vdc->init = virtio_scsi_device_init;
+ vdc->exit = virtio_scsi_device_exit;
vdc->set_config = virtio_scsi_set_config;
vdc->get_features = virtio_scsi_get_features;
vdc->reset = virtio_scsi_reset;
diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
index 9a98540..206c61d 100644
--- a/include/hw/virtio/virtio-scsi.h
+++ b/include/hw/virtio/virtio-scsi.h
@@ -187,6 +187,6 @@ typedef struct {
VIRTIO_SCSI_F_CHANGE, true)
int virtio_scsi_common_init(VirtIOSCSICommon *vs);
-int virtio_scsi_common_exit(VirtIOSCSICommon *vs);
+void virtio_scsi_common_exit(VirtIOSCSICommon *vs);
#endif /* _QEMU_VIRTIO_SCSI_H */

View File

@ -1,51 +0,0 @@
From 1a888642291d5bc49c657c313e4bc01b59f47d2a Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Fri, 16 Nov 2012 16:24:47 +0200
Subject: [PATCH] hw/virtio-serial-bus: replay guest open on destination
This is rewrite of a patch carried in Fedora previously based
on new code upstream, here is the original message, it still applies:
(the original fedora patch was commit id
a9bc20afc1f0604ee81c23b7c67d627e51d2e8d4, this is useful for grepping in
logs, it isn't in upstream)
When migrating a host with with a spice agent running the mouse becomes
non operational after the migration. This is rhbz #725965.
The problem is that after migration spice doesn't know the guest agent
is open. Spice is just a char dev here. And a chardev cannot query it's
device, the device has to let the chardev know when it is open. Right
now after migration the chardev which is recreated is in it's default
state, which assumes the guest is disconnected.
Char devices carry no information across migration, but the
virtio-serial does already carry the guest_connected state. This patch
passes that bit to the chardev.
---
hw/virtio-serial-bus.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index aa7d0d7..5078129 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -642,6 +642,7 @@ static void virtio_serial_post_load_timer_cb(void *opaque)
VirtIOSerial *s = opaque;
VirtIOSerialPort *port;
uint8_t host_connected;
+ VirtIOSerialPortClass *vsc;
if (!s->post_load) {
return;
@@ -657,6 +658,11 @@ static void virtio_serial_post_load_timer_cb(void *opaque)
send_control_event(s, port->id, VIRTIO_CONSOLE_PORT_OPEN,
port->host_connected);
}
+ vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
+ if (port->guest_connected && vsc->guest_open) {
+ /* replay guest open */
+ vsc->guest_open(port);
+ }
}
g_free(s->post_load->connected);
qemu_free_timer(s->post_load->timer);

View File

@ -0,0 +1,49 @@
From 7f334f1eb88807e2fc7ae42cc729f8dd371833e4 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 20 Sep 2013 16:57:58 +0200
Subject: [PATCH] virtio-balloon: switch exit callback to VirtioDeviceClass
This ensures hot-unplug is handled properly by the proxy.
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/virtio/virtio-balloon.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index 9504877..d7a392d 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -370,16 +370,14 @@ static int virtio_balloon_device_init(VirtIODevice *vdev)
return 0;
}
-static int virtio_balloon_device_exit(DeviceState *qdev)
+static void virtio_balloon_device_exit(VirtIODevice *vdev)
{
- VirtIOBalloon *s = VIRTIO_BALLOON(qdev);
- VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
+ VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
balloon_stats_destroy_timer(s);
qemu_remove_balloon_handler(s);
- unregister_savevm(qdev, "virtio-balloon", s);
+ unregister_savevm(DEVICE(vdev), "virtio-balloon", s);
virtio_cleanup(vdev);
- return 0;
}
static Property virtio_balloon_properties[] = {
@@ -390,10 +388,10 @@ static void virtio_balloon_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
- dc->exit = virtio_balloon_device_exit;
dc->props = virtio_balloon_properties;
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
vdc->init = virtio_balloon_device_init;
+ vdc->exit = virtio_balloon_device_exit;
vdc->get_config = virtio_balloon_get_config;
vdc->set_config = virtio_balloon_set_config;
vdc->get_features = virtio_balloon_get_features;

View File

@ -0,0 +1,49 @@
From 8b9a562e23dbfdfb23a5eeb1b619619290216ad8 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 20 Sep 2013 16:57:59 +0200
Subject: [PATCH] virtio-rng: switch exit callback to VirtioDeviceClass
This ensures hot-unplug is handled properly by the proxy.
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/virtio/virtio-rng.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c
index b22ccf1..42ca568 100644
--- a/hw/virtio/virtio-rng.c
+++ b/hw/virtio/virtio-rng.c
@@ -190,16 +190,14 @@ static int virtio_rng_device_init(VirtIODevice *vdev)
return 0;
}
-static int virtio_rng_device_exit(DeviceState *qdev)
+static void virtio_rng_device_exit(VirtIODevice *vdev)
{
- VirtIORNG *vrng = VIRTIO_RNG(qdev);
- VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
+ VirtIORNG *vrng = VIRTIO_RNG(vdev);
timer_del(vrng->rate_limit_timer);
timer_free(vrng->rate_limit_timer);
- unregister_savevm(qdev, "virtio-rng", vrng);
+ unregister_savevm(DEVICE(vdev), "virtio-rng", vrng);
virtio_cleanup(vdev);
- return 0;
}
static Property virtio_rng_properties[] = {
@@ -211,10 +209,10 @@ static void virtio_rng_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
- dc->exit = virtio_rng_device_exit;
dc->props = virtio_rng_properties;
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
vdc->init = virtio_rng_device_init;
+ vdc->exit = virtio_rng_device_exit;
vdc->get_features = get_features;
}

View File

@ -0,0 +1,59 @@
From 96412e68c312ae4d91d6febc2284951f8b295ef7 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 20 Sep 2013 16:58:00 +0200
Subject: [PATCH] virtio-pci: add device_unplugged callback
This fixes a crash in hot-unplug of virtio-pci devices behind a PCIe
switch. The crash happens because the ioeventfd is still set whent the
child is destroyed (destruction happens in postorder). Then the proxy
tries to unset to ioeventfd, but the virtqueue structure that holds the
EventNotifier has been trashed in the meanwhile. kvm_set_ioeventfd_pio
does not expect failure and aborts.
The fix is simply to move parts of uninitialization to a new
device_unplugged callback, which is called before the child is destroyed.
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/virtio/virtio-pci.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index be18e92..1a363ca 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1001,6 +1001,15 @@ static void virtio_pci_device_plugged(DeviceState *d)
proxy->host_features);
}
+static void virtio_pci_device_unplugged(DeviceState *d)
+{
+ PCIDevice *pci_dev = PCI_DEVICE(d);
+ VirtIOPCIProxy *proxy = VIRTIO_PCI(d);
+
+ virtio_pci_stop_ioeventfd(proxy);
+ msix_uninit_exclusive_bar(pci_dev);
+}
+
static int virtio_pci_init(PCIDevice *pci_dev)
{
VirtIOPCIProxy *dev = VIRTIO_PCI(pci_dev);
@@ -1015,9 +1024,7 @@ static int virtio_pci_init(PCIDevice *pci_dev)
static void virtio_pci_exit(PCIDevice *pci_dev)
{
VirtIOPCIProxy *proxy = VIRTIO_PCI(pci_dev);
- virtio_pci_stop_ioeventfd(proxy);
memory_region_destroy(&proxy->bar);
- msix_uninit_exclusive_bar(pci_dev);
}
static void virtio_pci_reset(DeviceState *qdev)
@@ -1552,6 +1559,7 @@ static void virtio_pci_bus_class_init(ObjectClass *klass, void *data)
k->set_guest_notifiers = virtio_pci_set_guest_notifiers;
k->vmstate_change = virtio_pci_vmstate_change;
k->device_plugged = virtio_pci_device_plugged;
+ k->device_unplugged = virtio_pci_device_unplugged;
}
static const TypeInfo virtio_pci_bus_info = {

View File

@ -0,0 +1,72 @@
From 62a30a970548466900ac45962a0fe8c051514329 Mon Sep 17 00:00:00 2001
From: Max Reitz <mreitz@redhat.com>
Date: Tue, 3 Dec 2013 14:57:52 +0100
Subject: [PATCH] block: Close backing file early in bdrv_img_create
Leaving the backing file open although it is not needed anymore can
cause problems if it is opened through a block driver which allows
exclusive access only and if the create function of the block driver
used for the top image (the one being created) tries to close and reopen
the image file (which will include opening the backing file a second
time).
In particular, this will happen with a backing file opened through
qemu-nbd and using qcow2 as the top image file format (which reopens the
image to flush it to disk).
In addition, the BlockDriverState in bdrv_img_create() is used for the
backing file only; it should therefore be made local to the respective
block.
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
block.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/block.c b/block.c
index 382ea71..0468765 100644
--- a/block.c
+++ b/block.c
@@ -4504,7 +4504,6 @@ void bdrv_img_create(const char *filename, const char *fmt,
{
QEMUOptionParameter *param = NULL, *create_options = NULL;
QEMUOptionParameter *backing_fmt, *backing_file, *size;
- BlockDriverState *bs = NULL;
BlockDriver *drv, *proto_drv;
BlockDriver *backing_drv = NULL;
Error *local_err = NULL;
@@ -4583,6 +4582,7 @@ void bdrv_img_create(const char *filename, const char *fmt,
size = get_option_parameter(param, BLOCK_OPT_SIZE);
if (size && size->value.n == -1) {
if (backing_file && backing_file->value.s) {
+ BlockDriverState *bs;
uint64_t size;
char buf[32];
int back_flags;
@@ -4601,6 +4601,7 @@ void bdrv_img_create(const char *filename, const char *fmt,
error_get_pretty(local_err));
error_free(local_err);
local_err = NULL;
+ bdrv_unref(bs);
goto out;
}
bdrv_get_geometry(bs, &size);
@@ -4608,6 +4609,8 @@ void bdrv_img_create(const char *filename, const char *fmt,
snprintf(buf, sizeof(buf), "%" PRId64, size);
set_option_parameter(param, BLOCK_OPT_SIZE, buf);
+
+ bdrv_unref(bs);
} else {
error_setg(errp, "Image creation needs a size parameter");
goto out;
@@ -4638,9 +4641,6 @@ out:
free_option_parameters(create_options);
free_option_parameters(param);
- if (bs) {
- bdrv_unref(bs);
- }
if (error_is_set(&local_err)) {
error_propagate(errp, local_err);
}

View File

@ -1,47 +0,0 @@
From 0aa1a9b167ca8a32d7c7112df375ddfa608f1f72 Mon Sep 17 00:00:00 2001
From: Andre Przywara <andre.przywara@amd.com>
Date: Thu, 18 Oct 2012 11:16:58 +0200
Subject: [PATCH] vnc-tls: Fix compilation with newer versions of GNU-TLS
In my installation of GNU-TLS (v3.0.23) the type
gnutls_anon_server_credentials is marked deprecated, so -Werror
breaks compilation.
Simply replacing it with the newer ..._t version fixed the compilation
on my machine (Slackware 14.0). I cannot tell how far back this "new"
type goes, at least the header file in RHEL 5.0 (v1.4.1) seems to have
it already. If someone finds a broken distribution, tell me and I
insert some compat code.
Signed-off-by: Andre Przywara <andre.przywara@amd.com>
Message-id: 1350551818-14717-1-git-send-email-andre.przywara@amd.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 7d2a929feba319c18603e324b1750830d6c8b7a1)
---
ui/vnc-tls.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/ui/vnc-tls.c b/ui/vnc-tls.c
index 5629263..8d4cc8e 100644
--- a/ui/vnc-tls.c
+++ b/ui/vnc-tls.c
@@ -99,9 +99,9 @@ static ssize_t vnc_tls_pull(gnutls_transport_ptr_t transport,
}
-static gnutls_anon_server_credentials vnc_tls_initialize_anon_cred(void)
+static gnutls_anon_server_credentials_t vnc_tls_initialize_anon_cred(void)
{
- gnutls_anon_server_credentials anon_cred;
+ gnutls_anon_server_credentials_t anon_cred;
int ret;
if ((ret = gnutls_anon_allocate_server_credentials(&anon_cred)) < 0) {
@@ -382,7 +382,7 @@ int vnc_tls_client_setup(struct VncState *vs,
}
} else {
- gnutls_anon_server_credentials anon_cred = vnc_tls_initialize_anon_cred();
+ gnutls_anon_server_credentials_t anon_cred = vnc_tls_initialize_anon_cred();
if (!anon_cred) {
gnutls_deinit(vs->tls.session);
vs->tls.session = NULL;

View File

@ -1,29 +0,0 @@
From 60388b2884f904b408ec8650ab2af0a03ea7073e Mon Sep 17 00:00:00 2001
From: Juan Quintela <quintela@redhat.com>
Date: Fri, 1 Feb 2013 11:12:26 +0100
Subject: [PATCH] migration: change initial value of expected_downtime
0 is a very bad initial value, what we are trying to get is
max_downtime, so that is a much better estimation.
Signed-off-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
(cherry picked from commit cc283e3bf04d2f64eb6ec2ee5bcd36edd779fe89)
---
migration.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/migration.c b/migration.c
index 98c7696..3584a24 100644
--- a/migration.c
+++ b/migration.c
@@ -774,6 +774,8 @@ void migrate_fd_connect(MigrationState *s)
s->buffer = NULL;
s->buffer_size = 0;
s->buffer_capacity = 0;
+ /* This is a best 1st approximation. ns to ms */
+ s->expected_downtime = max_downtime/1000000;
s->xfer_limit = s->bandwidth_limit / XFER_LIMIT_RATIO;
s->complete = false;

View File

@ -1,4 +1,4 @@
From b16e5be879fd7386f0ad672ea02e3acee36d1e8e Mon Sep 17 00:00:00 2001
From cebb1cd8d123360634243ac527c136721fb7fba7 Mon Sep 17 00:00:00 2001
From: Paul Moore <pmoore@redhat.com>
Date: Thu, 21 Nov 2013 10:40:15 -0500
Subject: [PATCH] seccomp: add kill() to the syscall whitelist
@ -29,10 +29,10 @@ Acked-by: Eduardo Otubo <otubo@linux.vnet.ibm.com>
1 file changed, 1 insertion(+)
diff --git a/qemu-seccomp.c b/qemu-seccomp.c
index 4a57b4b..c85f608 100644
index 69cee44..cf07869 100644
--- a/qemu-seccomp.c
+++ b/qemu-seccomp.c
@@ -121,6 +121,7 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
@@ -114,6 +114,7 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
{ SCMP_SYS(write), 244 },
{ SCMP_SYS(fcntl), 243 },
{ SCMP_SYS(tgkill), 242 },

View File

@ -1,34 +0,0 @@
From f34eeb6b65d36c31a0e412eefae1f735e48a3a69 Mon Sep 17 00:00:00 2001
From: Juan Quintela <quintela@redhat.com>
Date: Fri, 1 Feb 2013 12:39:08 +0100
Subject: [PATCH] migration: calculate end time after we have sent the data
Signed-off-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
(cherry picked from commit a3e879cd51c4f614f702117c4b1449f0218c00f3)
---
migration.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/migration.c b/migration.c
index 3584a24..0026f08 100644
--- a/migration.c
+++ b/migration.c
@@ -673,7 +673,7 @@ static void *buffered_file_thread(void *opaque)
qemu_mutex_unlock_iothread();
while (true) {
- int64_t current_time = qemu_get_clock_ms(rt_clock);
+ int64_t current_time;
uint64_t pending_size;
qemu_mutex_lock_iothread();
@@ -727,6 +727,7 @@ static void *buffered_file_thread(void *opaque)
}
}
qemu_mutex_unlock_iothread();
+ current_time = qemu_get_clock_ms(rt_clock);
if (current_time >= initial_time + BUFFER_DELAY) {
uint64_t transferred_bytes = s->bytes_xfer;
uint64_t time_spent = current_time - initial_time;

View File

@ -1,4 +1,4 @@
From 3bbf8ef814e238de967eb1ef90f63c23e1942ecd Mon Sep 17 00:00:00 2001
From 200413b505dfc4ae8611d523e87f1dee18a6bf0f Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Mon, 2 Dec 2013 11:17:04 +0100
Subject: [PATCH] spice: flip streaming video mode to off by default
@ -19,10 +19,10 @@ Reviewed-by: Alon Levy <alevy@redhat.com>
1 file changed, 2 insertions(+)
diff --git a/ui/spice-core.c b/ui/spice-core.c
index bcc4199..76e5dcd 100644
index e4d533d..9fb9544 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -764,6 +764,8 @@ void qemu_spice_init(void)
@@ -776,6 +776,8 @@ void qemu_spice_init(void)
if (str) {
int streaming_video = parse_stream_video(str);
spice_server_set_streaming_video(spice_server, streaming_video);

View File

@ -1,51 +0,0 @@
From 84b78ab739083a154713d89384b85550b39f2057 Mon Sep 17 00:00:00 2001
From: Juan Quintela <quintela@redhat.com>
Date: Fri, 1 Feb 2013 12:41:38 +0100
Subject: [PATCH] migration: don't account sleep time for calculating bandwidth
While we are sleeping we are not sending, so we should not use that
time to estimate our bandwidth.
Signed-off-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
(cherry picked from commit 7161082c8d8cf167c508976887a0a63f4db92b51)
---
migration.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/migration.c b/migration.c
index 0026f08..ebfbbde 100644
--- a/migration.c
+++ b/migration.c
@@ -658,6 +658,7 @@ static void *buffered_file_thread(void *opaque)
{
MigrationState *s = opaque;
int64_t initial_time = qemu_get_clock_ms(rt_clock);
+ int64_t sleep_time = 0;
int64_t max_size = 0;
bool last_round = false;
int ret;
@@ -730,7 +731,7 @@ static void *buffered_file_thread(void *opaque)
current_time = qemu_get_clock_ms(rt_clock);
if (current_time >= initial_time + BUFFER_DELAY) {
uint64_t transferred_bytes = s->bytes_xfer;
- uint64_t time_spent = current_time - initial_time;
+ uint64_t time_spent = current_time - initial_time - sleep_time;
double bandwidth = transferred_bytes / time_spent;
max_size = bandwidth * migrate_max_downtime() / 1000000;
@@ -739,11 +740,13 @@ static void *buffered_file_thread(void *opaque)
transferred_bytes, time_spent, bandwidth, max_size);
s->bytes_xfer = 0;
+ sleep_time = 0;
initial_time = current_time;
}
if (!last_round && (s->bytes_xfer >= s->xfer_limit)) {
/* usleep expects microseconds */
g_usleep((initial_time + BUFFER_DELAY - current_time)*1000);
+ sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
}
ret = buffered_flush(s);
if (ret < 0) {

View File

@ -0,0 +1,59 @@
From 3b1f248f3f8ff06ed4a4269871138db66e336ec5 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Thu, 28 Nov 2013 11:01:13 +0100
Subject: [PATCH] scsi-bus: fix transfer length and direction for VERIFY
command
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The amount of bytes to transfer depends on the BYTCHK field.
If any data is transferred, it is sent to the device.
Cc: qemu-stable@nongnu.org
Tested-by: Hervé Poussineau <hpoussin@reactos.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit d12ad44cc4cc9142179e64295608611f118b8ad8)
---
hw/scsi/scsi-bus.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index ea916d1..2d6ce4d 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -886,7 +886,6 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
case RELEASE:
case ERASE:
case ALLOW_MEDIUM_REMOVAL:
- case VERIFY_10:
case SEEK_10:
case SYNCHRONIZE_CACHE:
case SYNCHRONIZE_CACHE_16:
@@ -903,6 +902,16 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
case ALLOW_OVERWRITE:
cmd->xfer = 0;
break;
+ case VERIFY_10:
+ case VERIFY_12:
+ case VERIFY_16:
+ if ((buf[1] & 2) == 0) {
+ cmd->xfer = 0;
+ } else if ((buf[1] & 4) == 1) {
+ cmd->xfer = 1;
+ }
+ cmd->xfer *= dev->blocksize;
+ break;
case MODE_SENSE:
break;
case WRITE_SAME_10:
@@ -1100,6 +1109,9 @@ static void scsi_cmd_xfer_mode(SCSICommand *cmd)
case WRITE_VERIFY_12:
case WRITE_16:
case WRITE_VERIFY_16:
+ case VERIFY_10:
+ case VERIFY_12:
+ case VERIFY_16:
case COPY:
case COPY_VERIFY:
case COMPARE:

View File

@ -1,61 +0,0 @@
From 0d9d4a5c179f09bd801ba3470b97e1fd3f184ce2 Mon Sep 17 00:00:00 2001
From: Juan Quintela <quintela@redhat.com>
Date: Fri, 1 Feb 2013 13:22:37 +0100
Subject: [PATCH] migration: calculate expected_downtime
We removed the calculation in commit e4ed1541ac9413eac494a03532e34beaf8a7d1c5
Now we add it back. We need to create dirty_bytes_rate because we
can't include cpu-all.h from migration.c, and there is no other way to
include TARGET_PAGE_SIZE.
Signed-off-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
(cherry picked from commit 90f8ae724a575861f093fbdbfd49a925bcfec327)
---
arch_init.c | 1 +
include/migration/migration.h | 1 +
migration.c | 5 +++++
3 files changed, 7 insertions(+)
diff --git a/arch_init.c b/arch_init.c
index 8da868b..8daeafa 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -414,6 +414,7 @@ static void migration_bitmap_sync(void)
if (end_time > start_time + 1000) {
s->dirty_pages_rate = num_dirty_pages_period * 1000
/ (end_time - start_time);
+ s->dirty_bytes_rate = s->dirty_pages_rate * TARGET_PAGE_SIZE;
start_time = end_time;
num_dirty_pages_period = 0;
}
diff --git a/include/migration/migration.h b/include/migration/migration.h
index a8c9639..d121409 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -51,6 +51,7 @@ struct MigrationState
int64_t downtime;
int64_t expected_downtime;
int64_t dirty_pages_rate;
+ int64_t dirty_bytes_rate;
bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
int64_t xbzrle_cache_size;
bool complete;
diff --git a/migration.c b/migration.c
index ebfbbde..59e479d 100644
--- a/migration.c
+++ b/migration.c
@@ -738,6 +738,11 @@ static void *buffered_file_thread(void *opaque)
DPRINTF("transferred %" PRIu64 " time_spent %" PRIu64
" bandwidth %g max_size %" PRId64 "\n",
transferred_bytes, time_spent, bandwidth, max_size);
+ /* if we haven't sent anything, we don't want to recalculate
+ 10000 is a small enough number for our purposes */
+ if (s->dirty_bytes_rate && transferred_bytes > 10000) {
+ s->expected_downtime = s->dirty_bytes_rate / bandwidth;
+ }
s->bytes_xfer = 0;
sleep_time = 0;

View File

@ -0,0 +1,90 @@
From ddc0dda3d6352e4c28e0bd11cce1d90734dce0db Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Thu, 28 Nov 2013 11:18:56 +0100
Subject: [PATCH] scsi-disk: fix VERIFY emulation
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
VERIFY emulation was completely botched (and remained botched through
all the refactorings). The command must be emulated both in check-medium
mode (BYTCHK=00, which we implement by doing nothing) and in check-bytes
mode (which we do not implement yet). Unlike WRITE AND VERIFY (which we
treat simply as WRITE with FUA bit set), VERIFY cannot be handled like
READ. In fact the device is _receiving_ data for VERIFY, not _sending_
it like READ.
Cc: qemu-stable@nongnu.org
Tested-by: Hervé Poussineau <hpoussin@reactos.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit d97e7730816094a71cd1f19a56d7a73f77cdbf96)
Conflicts:
hw/scsi/scsi-disk.c
---
hw/scsi/scsi-disk.c | 26 +++++++++++++++++++-------
1 file changed, 19 insertions(+), 7 deletions(-)
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 74e6a14..1fd1c26 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -1597,6 +1597,14 @@ static void scsi_disk_emulate_write_data(SCSIRequest *req)
scsi_disk_emulate_unmap(r, r->iov.iov_base);
break;
+ case VERIFY_10:
+ case VERIFY_12:
+ case VERIFY_16:
+ if (r->req.status == -1) {
+ scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
+ }
+ break;
+
default:
abort();
}
@@ -1837,6 +1845,14 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
case UNMAP:
DPRINTF("Unmap (len %lu)\n", (long)r->req.cmd.xfer);
break;
+ case VERIFY_10:
+ case VERIFY_12:
+ case VERIFY_16:
+ DPRINTF("Verify (bytchk %lu)\n", (r->req.buf[1] >> 1) & 3);
+ if (req->cmd.buf[1] & 6) {
+ goto illegal_request;
+ }
+ break;
case WRITE_SAME_10:
case WRITE_SAME_16:
nb_sectors = scsi_data_cdb_length(r->req.cmd.buf);
@@ -1936,10 +1952,6 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf)
scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED));
return 0;
}
- /* fallthrough */
- case VERIFY_10:
- case VERIFY_12:
- case VERIFY_16:
DPRINTF("Write %s(sector %" PRId64 ", count %u)\n",
(command & 0xe) == 0xe ? "And Verify " : "",
r->req.cmd.lba, len);
@@ -2207,14 +2219,14 @@ static const SCSIReqOps *const scsi_disk_reqops_dispatch[256] = {
[UNMAP] = &scsi_disk_emulate_reqops,
[WRITE_SAME_10] = &scsi_disk_emulate_reqops,
[WRITE_SAME_16] = &scsi_disk_emulate_reqops,
+ [VERIFY_10] = &scsi_disk_emulate_reqops,
+ [VERIFY_12] = &scsi_disk_emulate_reqops,
+ [VERIFY_16] = &scsi_disk_emulate_reqops,
[READ_6] = &scsi_disk_dma_reqops,
[READ_10] = &scsi_disk_dma_reqops,
[READ_12] = &scsi_disk_dma_reqops,
[READ_16] = &scsi_disk_dma_reqops,
- [VERIFY_10] = &scsi_disk_dma_reqops,
- [VERIFY_12] = &scsi_disk_dma_reqops,
- [VERIFY_16] = &scsi_disk_dma_reqops,
[WRITE_6] = &scsi_disk_dma_reqops,
[WRITE_10] = &scsi_disk_dma_reqops,
[WRITE_12] = &scsi_disk_dma_reqops,

View File

@ -1,48 +0,0 @@
From 8dd1a13b6ce0a9d83080823c8bc9d82d09100576 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:07 +0100
Subject: [PATCH] migration: simplify while loop
Unify the goto around the loop, with the exit condition at the end of it.
Both can be expressed as "while (ret >= 0)".
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 5da5aad068def65b5e278a6380192d4bfe279585)
---
migration.c | 11 +----------
1 file changed, 1 insertion(+), 10 deletions(-)
diff --git a/migration.c b/migration.c
index 59e479d..71c0eec 100644
--- a/migration.c
+++ b/migration.c
@@ -666,14 +666,9 @@ static void *buffered_file_thread(void *opaque)
qemu_mutex_lock_iothread();
DPRINTF("beginning savevm\n");
ret = qemu_savevm_state_begin(s->file, &s->params);
- if (ret < 0) {
- DPRINTF("failed, %d\n", ret);
- qemu_mutex_unlock_iothread();
- goto out;
- }
qemu_mutex_unlock_iothread();
- while (true) {
+ while (ret >= 0) {
int64_t current_time;
uint64_t pending_size;
@@ -754,12 +749,8 @@ static void *buffered_file_thread(void *opaque)
sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
}
ret = buffered_flush(s);
- if (ret < 0) {
- break;
- }
}
-out:
if (ret < 0) {
migrate_fd_error(s);
}

View File

@ -1,50 +0,0 @@
From e78d91a594e42f11a915bd95afcaee2f4f11bc1a Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:08 +0100
Subject: [PATCH] migration: always use vm_stop_force_state
vm_stop_force_state does:
if (runstate_is_running()) {
vm_stop(state);
} else {
runstate_set(state);
}
migration.c does:
if (runstate_is_running()) {
vm_stop(state);
} else {
vm_stop_force_state(state);
}
The code run is the same even if we always use vm_stop_force_state in
migration.c.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 891518abd804401978e402d588733e282be960ad)
---
migration.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/migration.c b/migration.c
index 71c0eec..d601641 100644
--- a/migration.c
+++ b/migration.c
@@ -699,11 +699,7 @@ static void *buffered_file_thread(void *opaque)
DPRINTF("done iterating\n");
start_time = qemu_get_clock_ms(rt_clock);
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
- if (old_vm_running) {
- vm_stop(RUN_STATE_FINISH_MIGRATE);
- } else {
- vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
- }
+ vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
ret = qemu_savevm_state_complete(s->file);
if (ret < 0) {
qemu_mutex_unlock_iothread();

View File

@ -1,66 +0,0 @@
From b259853dce28b7a8e0efe6bfedc7850821c8c76b Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:09 +0100
Subject: [PATCH] migration: move more error handling to migrate_fd_cleanup
The next patch will add more cases where qemu_savevm_state_cancel
needs to be called; prepare for that already, the function can be
called twice with no ill effect.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 7a2c17216cd5ae4c22844123b8e9360d517932f8)
---
migration.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/migration.c b/migration.c
index d601641..739e38c 100644
--- a/migration.c
+++ b/migration.c
@@ -260,7 +260,7 @@ void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
/* shared migration helpers */
-static int migrate_fd_cleanup(MigrationState *s)
+static void migrate_fd_cleanup(MigrationState *s)
{
int ret = 0;
@@ -271,7 +271,13 @@ static int migrate_fd_cleanup(MigrationState *s)
}
assert(s->fd == -1);
- return ret;
+ if (ret < 0 && s->state == MIG_STATE_ACTIVE) {
+ s->state = MIG_STATE_ERROR;
+ }
+
+ if (s->state != MIG_STATE_ACTIVE) {
+ qemu_savevm_state_cancel();
+ }
}
void migrate_fd_error(MigrationState *s)
@@ -285,9 +291,8 @@ void migrate_fd_error(MigrationState *s)
static void migrate_fd_completed(MigrationState *s)
{
DPRINTF("setting completed state\n");
- if (migrate_fd_cleanup(s) < 0) {
- s->state = MIG_STATE_ERROR;
- } else {
+ migrate_fd_cleanup(s);
+ if (s->state == MIG_STATE_ACTIVE) {
s->state = MIG_STATE_COMPLETED;
runstate_set(RUN_STATE_POSTMIGRATE);
}
@@ -322,7 +327,6 @@ static void migrate_fd_cancel(MigrationState *s)
s->state = MIG_STATE_CANCELLED;
notifier_list_notify(&migration_state_notifiers, s);
- qemu_savevm_state_cancel();
migrate_fd_cleanup(s);
}

View File

@ -1,70 +0,0 @@
From bd0d732bc7d23b686f13ab377f58e227c4edc707 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:10 +0100
Subject: [PATCH] migration: push qemu_savevm_state_cancel out of
qemu_savevm_state_*
This is useful, because it lets us keep the cancellation callbacks
inside the big lock while pushing the others out.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 04943ebaa9e4f5f9ac080198a7b0d25c6d7ac444)
---
savevm.c | 15 ++++-----------
1 file changed, 4 insertions(+), 11 deletions(-)
diff --git a/savevm.c b/savevm.c
index a8a53ef..4302903 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1621,17 +1621,11 @@ int qemu_savevm_state_begin(QEMUFile *f,
ret = se->ops->save_live_setup(f, se->opaque);
if (ret < 0) {
- qemu_savevm_state_cancel();
return ret;
}
}
ret = qemu_file_get_error(f);
- if (ret != 0) {
- qemu_savevm_state_cancel();
- }
-
return ret;
-
}
/*
@@ -1677,9 +1671,6 @@ int qemu_savevm_state_iterate(QEMUFile *f)
return ret;
}
ret = qemu_file_get_error(f);
- if (ret != 0) {
- qemu_savevm_state_cancel();
- }
return ret;
}
@@ -1778,8 +1769,7 @@ static int qemu_savevm_state(QEMUFile *f)
};
if (qemu_savevm_state_blocked(NULL)) {
- ret = -EINVAL;
- goto out;
+ return -EINVAL;
}
ret = qemu_savevm_state_begin(f, &params);
@@ -1798,6 +1788,9 @@ out:
if (ret == 0) {
ret = qemu_file_get_error(f);
}
+ if (ret != 0) {
+ qemu_savevm_state_cancel();
+ }
return ret;
}

View File

@ -1,103 +0,0 @@
From a52c9450418c1a03aebbd95216fbd177430e2fc7 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:11 +0100
Subject: [PATCH] block-migration: remove useless calls to blk_mig_cleanup
Now that the cancel callback is called consistently for all errors,
we can avoid doing its work in the other callbacks.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit d418cf57a3e699746ef0bfa772bbe8c7e17cebb5)
---
block-migration.c | 26 ++++++++------------------
1 file changed, 8 insertions(+), 18 deletions(-)
diff --git a/block-migration.c b/block-migration.c
index 43ab202..e6c917d 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -524,16 +524,10 @@ static int block_save_setup(QEMUFile *f, void *opaque)
set_dirty_tracking(1);
ret = flush_blks(f);
- if (ret) {
- blk_mig_cleanup();
- return ret;
- }
-
blk_mig_reset_dirty_cursor();
-
qemu_put_be64(f, BLK_MIG_FLAG_EOS);
- return 0;
+ return ret;
}
static int block_save_iterate(QEMUFile *f, void *opaque)
@@ -546,7 +540,6 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
ret = flush_blks(f);
if (ret) {
- blk_mig_cleanup();
return ret;
}
@@ -564,20 +557,18 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
}
} else {
ret = blk_mig_save_dirty_block(f, 1);
+ if (ret < 0) {
+ return ret;
+ }
if (ret != 0) {
/* no more dirty blocks */
break;
}
}
}
- if (ret < 0) {
- blk_mig_cleanup();
- return ret;
- }
ret = flush_blks(f);
if (ret) {
- blk_mig_cleanup();
return ret;
}
@@ -595,7 +586,6 @@ static int block_save_complete(QEMUFile *f, void *opaque)
ret = flush_blks(f);
if (ret) {
- blk_mig_cleanup();
return ret;
}
@@ -607,12 +597,11 @@ static int block_save_complete(QEMUFile *f, void *opaque)
do {
ret = blk_mig_save_dirty_block(f, 0);
+ if (ret < 0) {
+ return ret;
+ }
} while (ret == 0);
- blk_mig_cleanup();
- if (ret < 0) {
- return ret;
- }
/* report completion */
qemu_put_be64(f, (100 << BDRV_SECTOR_BITS) | BLK_MIG_FLAG_PROGRESS);
@@ -620,6 +609,7 @@ static int block_save_complete(QEMUFile *f, void *opaque)
qemu_put_be64(f, BLK_MIG_FLAG_EOS);
+ blk_mig_cleanup();
return 0;
}

View File

@ -1,84 +0,0 @@
From d35fb24839d0a0dd18b322ba8d9fbcd0b587819b Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:12 +0100
Subject: [PATCH] qemu-file: pass errno from qemu_fflush via f->last_error
This is done by almost all callers of qemu_fflush, move the code
directly to qemu_fflush.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 93bf21044c38134bc7d35577b675d9f2bdcb8419)
---
savevm.c | 25 ++++++++++++-------------
1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/savevm.c b/savevm.c
index 4302903..a681177 100644
--- a/savevm.c
+++ b/savevm.c
@@ -453,13 +453,13 @@ static void qemu_file_set_error(QEMUFile *f, int ret)
/** Flushes QEMUFile buffer
*
*/
-static int qemu_fflush(QEMUFile *f)
+static void qemu_fflush(QEMUFile *f)
{
int ret = 0;
- if (!f->ops->put_buffer)
- return 0;
-
+ if (!f->ops->put_buffer) {
+ return;
+ }
if (f->is_write && f->buf_index > 0) {
ret = f->ops->put_buffer(f->opaque, f->buf, f->buf_offset, f->buf_index);
if (ret >= 0) {
@@ -467,7 +467,9 @@ static int qemu_fflush(QEMUFile *f)
}
f->buf_index = 0;
}
- return ret;
+ if (ret < 0) {
+ qemu_file_set_error(f, ret);
+ }
}
static void qemu_fill_buffer(QEMUFile *f)
@@ -518,7 +520,8 @@ int qemu_get_fd(QEMUFile *f)
int qemu_fclose(QEMUFile *f)
{
int ret;
- ret = qemu_fflush(f);
+ qemu_fflush(f);
+ ret = qemu_file_get_error(f);
if (f->ops->close) {
int ret2 = f->ops->close(f->opaque);
@@ -560,9 +563,8 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
buf += l;
size -= l;
if (f->buf_index >= IO_BUF_SIZE) {
- int ret = qemu_fflush(f);
- if (ret < 0) {
- qemu_file_set_error(f, ret);
+ qemu_fflush(f);
+ if (qemu_file_get_error(f)) {
break;
}
}
@@ -584,10 +586,7 @@ void qemu_put_byte(QEMUFile *f, int v)
f->buf[f->buf_index++] = v;
f->is_write = 1;
if (f->buf_index >= IO_BUF_SIZE) {
- int ret = qemu_fflush(f);
- if (ret < 0) {
- qemu_file_set_error(f, ret);
- }
+ qemu_fflush(f);
}
}

View File

@ -1,143 +0,0 @@
From 8d5406a6a42ece0d7d9e250aabe68ea8a0e3fbf6 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:13 +0100
Subject: [PATCH] migration: use qemu_file_set_error to pass error codes back
to qemu_savevm_state
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 47c8c17af883b5bd0f147cfcec8d7ef8ff76023b)
---
include/sysemu/sysemu.h | 6 +++---
savevm.c | 44 ++++++++++++++++++--------------------------
2 files changed, 21 insertions(+), 29 deletions(-)
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 1d9599e..28a9221 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -73,10 +73,10 @@ void do_info_snapshots(Monitor *mon, const QDict *qdict);
void qemu_announce_self(void);
bool qemu_savevm_state_blocked(Error **errp);
-int qemu_savevm_state_begin(QEMUFile *f,
- const MigrationParams *params);
+void qemu_savevm_state_begin(QEMUFile *f,
+ const MigrationParams *params);
int qemu_savevm_state_iterate(QEMUFile *f);
-int qemu_savevm_state_complete(QEMUFile *f);
+void qemu_savevm_state_complete(QEMUFile *f);
void qemu_savevm_state_cancel(void);
uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size);
int qemu_loadvm_state(QEMUFile *f);
diff --git a/savevm.c b/savevm.c
index a681177..a1690b4 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1579,8 +1579,8 @@ bool qemu_savevm_state_blocked(Error **errp)
return false;
}
-int qemu_savevm_state_begin(QEMUFile *f,
- const MigrationParams *params)
+void qemu_savevm_state_begin(QEMUFile *f,
+ const MigrationParams *params)
{
SaveStateEntry *se;
int ret;
@@ -1620,11 +1620,10 @@ int qemu_savevm_state_begin(QEMUFile *f,
ret = se->ops->save_live_setup(f, se->opaque);
if (ret < 0) {
- return ret;
+ qemu_file_set_error(f, ret);
+ break;
}
}
- ret = qemu_file_get_error(f);
- return ret;
}
/*
@@ -1658,6 +1657,9 @@ int qemu_savevm_state_iterate(QEMUFile *f)
ret = se->ops->save_live_iterate(f, se->opaque);
trace_savevm_section_end(se->section_id);
+ if (ret < 0) {
+ qemu_file_set_error(f, ret);
+ }
if (ret <= 0) {
/* Do not proceed to the next vmstate before this one reported
completion of the current stage. This serializes the migration
@@ -1666,14 +1668,10 @@ int qemu_savevm_state_iterate(QEMUFile *f)
break;
}
}
- if (ret != 0) {
- return ret;
- }
- ret = qemu_file_get_error(f);
return ret;
}
-int qemu_savevm_state_complete(QEMUFile *f)
+void qemu_savevm_state_complete(QEMUFile *f)
{
SaveStateEntry *se;
int ret;
@@ -1697,7 +1695,8 @@ int qemu_savevm_state_complete(QEMUFile *f)
ret = se->ops->save_live_complete(f, se->opaque);
trace_savevm_section_end(se->section_id);
if (ret < 0) {
- return ret;
+ qemu_file_set_error(f, ret);
+ return;
}
}
@@ -1725,8 +1724,6 @@ int qemu_savevm_state_complete(QEMUFile *f)
}
qemu_put_byte(f, QEMU_VM_EOF);
-
- return qemu_file_get_error(f);
}
uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size)
@@ -1771,26 +1768,21 @@ static int qemu_savevm_state(QEMUFile *f)
return -EINVAL;
}
- ret = qemu_savevm_state_begin(f, &params);
- if (ret < 0)
- goto out;
-
- do {
- ret = qemu_savevm_state_iterate(f);
- if (ret < 0)
- goto out;
- } while (ret == 0);
-
- ret = qemu_savevm_state_complete(f);
+ qemu_savevm_state_begin(f, &params);
+ while (qemu_file_get_error(f) == 0) {
+ if (qemu_savevm_state_iterate(f) > 0) {
+ break;
+ }
+ }
-out:
+ ret = qemu_file_get_error(f);
if (ret == 0) {
+ qemu_savevm_state_complete(f);
ret = qemu_file_get_error(f);
}
if (ret != 0) {
qemu_savevm_state_cancel();
}
-
return ret;
}

View File

@ -1,69 +0,0 @@
From 8c77add1c1b00cdfc3d7380aabec3add69381150 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:14 +0100
Subject: [PATCH] qemu-file: temporarily expose qemu_file_set_error and
qemu_fflush
Right now, migration cannot entirely rely on QEMUFile's automatic
drop of I/O after an error, because it does its "real" I/O outside
the put_buffer callback. To fix this until buffering is gone, expose
qemu_file_set_error which we will use in buffered_flush.
Similarly, buffered_flush is not a complete flush because some data may
still reside in the QEMUFile's own buffer. This somewhat complicates the
process of closing the migration thread. Again, when buffering is gone
buffered_flush will disappear and calling qemu_fflush will not be needed;
in the meanwhile, we expose the function for use in migration.c.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 4eb938102b3d533e142de23e255e46da1326fc5a)
---
include/migration/qemu-file.h | 2 ++
savevm.c | 4 ++--
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
index 46fc11d..5e0c287 100644
--- a/include/migration/qemu-file.h
+++ b/include/migration/qemu-file.h
@@ -82,6 +82,7 @@ QEMUFile *qemu_popen_cmd(const char *command, const char *mode);
int qemu_get_fd(QEMUFile *f);
int qemu_fclose(QEMUFile *f);
int64_t qemu_ftell(QEMUFile *f);
+void qemu_fflush(QEMUFile *f);
void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size);
void qemu_put_byte(QEMUFile *f, int v);
@@ -113,6 +114,7 @@ int qemu_file_rate_limit(QEMUFile *f);
int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate);
int64_t qemu_file_get_rate_limit(QEMUFile *f);
int qemu_file_get_error(QEMUFile *f);
+void qemu_file_set_error(QEMUFile *f, int ret);
static inline void qemu_put_be64s(QEMUFile *f, const uint64_t *pv)
{
diff --git a/savevm.c b/savevm.c
index a1690b4..e10a045 100644
--- a/savevm.c
+++ b/savevm.c
@@ -443,7 +443,7 @@ int qemu_file_get_error(QEMUFile *f)
return f->last_error;
}
-static void qemu_file_set_error(QEMUFile *f, int ret)
+void qemu_file_set_error(QEMUFile *f, int ret)
{
if (f->last_error == 0) {
f->last_error = ret;
@@ -453,7 +453,7 @@ static void qemu_file_set_error(QEMUFile *f, int ret)
/** Flushes QEMUFile buffer
*
*/
-static void qemu_fflush(QEMUFile *f)
+void qemu_fflush(QEMUFile *f)
{
int ret = 0;

View File

@ -1,29 +0,0 @@
From 015c261bdbb06a737b14600d62c37fef28ea9d22 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:15 +0100
Subject: [PATCH] migration: flush all data to fd when buffered_flush is called
Including data that resided in the QEMUFile's own buffer.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit f5821518ed6d49aae9fd0aa6169d2d74bb83054c)
---
migration.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/migration.c b/migration.c
index 739e38c..1027b40 100644
--- a/migration.c
+++ b/migration.c
@@ -525,6 +525,8 @@ static ssize_t buffered_flush(MigrationState *s)
DPRINTF("flushing %zu byte(s) of data\n", s->buffer_size);
+ qemu_fflush(s->file);
+
while (s->bytes_xfer < s->xfer_limit && offset < s->buffer_size) {
size_t to_send = MIN(s->buffer_size - offset, s->xfer_limit - s->bytes_xfer);
ret = migrate_fd_put_buffer(s, s->buffer + offset, to_send);

View File

@ -1,80 +0,0 @@
From 7f2725d2a64c533129504a9c9ea610169abd72f8 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:16 +0100
Subject: [PATCH] migration: use qemu_file_set_error
Remove the return value of buffered_flush, pass it via the error code
of s->file. Once this is done, the error can be retrieved simply
via migrate_fd_close's call to qemu_fclose.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 63dfbd7ee03185c181a0791958ec9c8337089b55)
---
migration.c | 22 ++++++----------------
1 file changed, 6 insertions(+), 16 deletions(-)
diff --git a/migration.c b/migration.c
index 1027b40..da5f175 100644
--- a/migration.c
+++ b/migration.c
@@ -518,7 +518,7 @@ int64_t migrate_xbzrle_cache_size(void)
/* migration thread support */
-static ssize_t buffered_flush(MigrationState *s)
+static void buffered_flush(MigrationState *s)
{
size_t offset = 0;
ssize_t ret = 0;
@@ -545,9 +545,8 @@ static ssize_t buffered_flush(MigrationState *s)
s->buffer_size -= offset;
if (ret < 0) {
- return ret;
+ qemu_file_set_error(s->file, ret);
}
- return offset;
}
static int buffered_put_buffer(void *opaque, const uint8_t *buf,
@@ -586,25 +585,15 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf,
static int buffered_close(void *opaque)
{
MigrationState *s = opaque;
- ssize_t ret = 0;
- int ret2;
DPRINTF("closing\n");
s->xfer_limit = INT_MAX;
while (!qemu_file_get_error(s->file) && s->buffer_size) {
- ret = buffered_flush(s);
- if (ret < 0) {
- break;
- }
- }
-
- ret2 = migrate_fd_close(s);
- if (ret >= 0) {
- ret = ret2;
+ buffered_flush(s);
}
s->complete = true;
- return ret;
+ return migrate_fd_close(s);
}
static int buffered_get_fd(void *opaque)
@@ -750,7 +739,8 @@ static void *buffered_file_thread(void *opaque)
g_usleep((initial_time + BUFFER_DELAY - current_time)*1000);
sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
}
- ret = buffered_flush(s);
+ buffered_flush(s);
+ ret = qemu_file_get_error(s->file);
}
if (ret < 0) {

View File

@ -1,140 +0,0 @@
From 67f17b78f85bfa766ba9bde63148c3c171ef3426 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:17 +0100
Subject: [PATCH] migration: simplify error handling
Always use qemu_file_get_error to detect errors, since that is how
QEMUFile itself drops I/O after an error occurs. There is no need
to propagate and check return values all the time.
Also remove the "complete" member, since we know that it is set (via
migrate_fd_cleanup) only when the state changes.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit dba433c03a0f5dc22a459435dd89557886298921)
---
include/migration/migration.h | 1 -
migration.c | 46 +++++++++++++------------------------------
2 files changed, 14 insertions(+), 33 deletions(-)
diff --git a/include/migration/migration.h b/include/migration/migration.h
index d121409..3e680af 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -54,7 +54,6 @@ struct MigrationState
int64_t dirty_bytes_rate;
bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
int64_t xbzrle_cache_size;
- bool complete;
};
void process_incoming_migration(QEMUFile *f);
diff --git a/migration.c b/migration.c
index da5f175..41a592c 100644
--- a/migration.c
+++ b/migration.c
@@ -525,6 +525,10 @@ static void buffered_flush(MigrationState *s)
DPRINTF("flushing %zu byte(s) of data\n", s->buffer_size);
+ if (qemu_file_get_error(s->file)) {
+ s->buffer_size = 0;
+ return;
+ }
qemu_fflush(s->file);
while (s->bytes_xfer < s->xfer_limit && offset < s->buffer_size) {
@@ -592,7 +596,6 @@ static int buffered_close(void *opaque)
while (!qemu_file_get_error(s->file) && s->buffer_size) {
buffered_flush(s);
}
- s->complete = true;
return migrate_fd_close(s);
}
@@ -656,37 +659,21 @@ static void *buffered_file_thread(void *opaque)
int64_t sleep_time = 0;
int64_t max_size = 0;
bool last_round = false;
- int ret;
qemu_mutex_lock_iothread();
DPRINTF("beginning savevm\n");
- ret = qemu_savevm_state_begin(s->file, &s->params);
- qemu_mutex_unlock_iothread();
+ qemu_savevm_state_begin(s->file, &s->params);
- while (ret >= 0) {
+ while (s->state == MIG_STATE_ACTIVE) {
int64_t current_time;
uint64_t pending_size;
- qemu_mutex_lock_iothread();
- if (s->state != MIG_STATE_ACTIVE) {
- DPRINTF("put_ready returning because of non-active state\n");
- qemu_mutex_unlock_iothread();
- break;
- }
- if (s->complete) {
- qemu_mutex_unlock_iothread();
- break;
- }
if (s->bytes_xfer < s->xfer_limit) {
DPRINTF("iterate\n");
pending_size = qemu_savevm_state_pending(s->file, max_size);
DPRINTF("pending size %lu max %lu\n", pending_size, max_size);
if (pending_size && pending_size >= max_size) {
- ret = qemu_savevm_state_iterate(s->file);
- if (ret < 0) {
- qemu_mutex_unlock_iothread();
- break;
- }
+ qemu_savevm_state_iterate(s->file);
} else {
int old_vm_running = runstate_is_running();
int64_t start_time, end_time;
@@ -695,13 +682,8 @@ static void *buffered_file_thread(void *opaque)
start_time = qemu_get_clock_ms(rt_clock);
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
- ret = qemu_savevm_state_complete(s->file);
- if (ret < 0) {
- qemu_mutex_unlock_iothread();
- break;
- } else {
- migrate_fd_completed(s);
- }
+ qemu_savevm_state_complete(s->file);
+ migrate_fd_completed(s);
end_time = qemu_get_clock_ms(rt_clock);
s->total_time = end_time - s->total_time;
s->downtime = end_time - start_time;
@@ -740,12 +722,13 @@ static void *buffered_file_thread(void *opaque)
sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
}
buffered_flush(s);
- ret = qemu_file_get_error(s->file);
+ qemu_mutex_lock_iothread();
+ if (qemu_file_get_error(s->file)) {
+ migrate_fd_error(s);
+ }
}
- if (ret < 0) {
- migrate_fd_error(s);
- }
+ qemu_mutex_unlock_iothread();
g_free(s->buffer);
return NULL;
}
@@ -770,7 +753,6 @@ void migrate_fd_connect(MigrationState *s)
s->expected_downtime = max_downtime/1000000;
s->xfer_limit = s->bandwidth_limit / XFER_LIMIT_RATIO;
- s->complete = false;
s->file = qemu_fopen_ops(s, &buffered_file_ops);

View File

@ -1,152 +0,0 @@
From 907358d71215fdc486c6e70de9b16cfefc88303b Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:18 +0100
Subject: [PATCH] migration: do not nest flushing of device data
Completion of migration is currently done with a "nested" loop that
invokes buffered_flush: migrate_fd_completed is called by
buffered_file_thread, which calls migrate_fd_cleanup, which calls
buffered_close (via qemu_fclose), which flushes the buffer.
Simplify this, by reusing the buffered_flush call of buffered_file_thread.
Then if qemu_savevm_state_complete was called, and the buffer is empty
(including the QEMUFile buffer, for which we need the previous patch), we
are done.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit a3fa1d78cbae2259491b17689812edcb643a3b30)
---
migration.c | 55 ++++++++++++++++++++++++-------------------------------
1 file changed, 24 insertions(+), 31 deletions(-)
diff --git a/migration.c b/migration.c
index 41a592c..57fceb6d 100644
--- a/migration.c
+++ b/migration.c
@@ -262,41 +262,34 @@ void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
static void migrate_fd_cleanup(MigrationState *s)
{
- int ret = 0;
-
if (s->file) {
DPRINTF("closing file\n");
- ret = qemu_fclose(s->file);
+ qemu_fclose(s->file);
s->file = NULL;
}
assert(s->fd == -1);
- if (ret < 0 && s->state == MIG_STATE_ACTIVE) {
- s->state = MIG_STATE_ERROR;
- }
+ assert(s->state != MIG_STATE_ACTIVE);
- if (s->state != MIG_STATE_ACTIVE) {
+ if (s->state != MIG_STATE_COMPLETED) {
qemu_savevm_state_cancel();
}
+
+ notifier_list_notify(&migration_state_notifiers, s);
}
void migrate_fd_error(MigrationState *s)
{
DPRINTF("setting error state\n");
s->state = MIG_STATE_ERROR;
- notifier_list_notify(&migration_state_notifiers, s);
migrate_fd_cleanup(s);
}
static void migrate_fd_completed(MigrationState *s)
{
DPRINTF("setting completed state\n");
+ s->state = MIG_STATE_COMPLETED;
migrate_fd_cleanup(s);
- if (s->state == MIG_STATE_ACTIVE) {
- s->state = MIG_STATE_COMPLETED;
- runstate_set(RUN_STATE_POSTMIGRATE);
- }
- notifier_list_notify(&migration_state_notifiers, s);
}
static ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data,
@@ -326,8 +319,6 @@ static void migrate_fd_cancel(MigrationState *s)
DPRINTF("cancelling migration\n");
s->state = MIG_STATE_CANCELLED;
- notifier_list_notify(&migration_state_notifiers, s);
-
migrate_fd_cleanup(s);
}
@@ -592,10 +583,6 @@ static int buffered_close(void *opaque)
DPRINTF("closing\n");
- s->xfer_limit = INT_MAX;
- while (!qemu_file_get_error(s->file) && s->buffer_size) {
- buffered_flush(s);
- }
return migrate_fd_close(s);
}
@@ -658,6 +645,8 @@ static void *buffered_file_thread(void *opaque)
int64_t initial_time = qemu_get_clock_ms(rt_clock);
int64_t sleep_time = 0;
int64_t max_size = 0;
+ int64_t start_time = initial_time;
+ bool old_vm_running = false;
bool last_round = false;
qemu_mutex_lock_iothread();
@@ -675,23 +664,13 @@ static void *buffered_file_thread(void *opaque)
if (pending_size && pending_size >= max_size) {
qemu_savevm_state_iterate(s->file);
} else {
- int old_vm_running = runstate_is_running();
- int64_t start_time, end_time;
-
DPRINTF("done iterating\n");
start_time = qemu_get_clock_ms(rt_clock);
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
+ old_vm_running = runstate_is_running();
vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
+ s->xfer_limit = INT_MAX;
qemu_savevm_state_complete(s->file);
- migrate_fd_completed(s);
- end_time = qemu_get_clock_ms(rt_clock);
- s->total_time = end_time - s->total_time;
- s->downtime = end_time - start_time;
- if (s->state != MIG_STATE_COMPLETED) {
- if (old_vm_running) {
- vm_start();
- }
- }
last_round = true;
}
}
@@ -725,6 +704,20 @@ static void *buffered_file_thread(void *opaque)
qemu_mutex_lock_iothread();
if (qemu_file_get_error(s->file)) {
migrate_fd_error(s);
+ } else if (last_round && s->buffer_size == 0) {
+ migrate_fd_completed(s);
+ }
+ }
+
+ if (s->state == MIG_STATE_COMPLETED) {
+ int64_t end_time = qemu_get_clock_ms(rt_clock);
+ s->total_time = end_time - s->total_time;
+ s->downtime = end_time - start_time;
+ runstate_set(RUN_STATE_POSTMIGRATE);
+ } else {
+ if (old_vm_running) {
+ assert(last_round);
+ vm_start();
}
}

View File

@ -1,81 +0,0 @@
From 12a2075cf44c3234ba3efd7afb7a924ff39ba441 Mon Sep 17 00:00:00 2001
From: Kazuya Saito <saito.kazuya@jp.fujitsu.com>
Date: Fri, 22 Feb 2013 17:36:19 +0100
Subject: [PATCH] migration: add migrate_set_state tracepoint
Signed-off-by: Kazuya Saito <saito.kazuya@jp.fujitsu.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit c09e5bb1d88ef38986bac7c6ed59dbd732cc4771)
---
migration.c | 9 ++++++++-
trace-events | 3 +++
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/migration.c b/migration.c
index 57fceb6d..c0a9239 100644
--- a/migration.c
+++ b/migration.c
@@ -23,6 +23,7 @@
#include "migration/block.h"
#include "qemu/thread.h"
#include "qmp-commands.h"
+#include "trace.h"
//#define DEBUG_MIGRATION
@@ -282,6 +283,7 @@ void migrate_fd_error(MigrationState *s)
{
DPRINTF("setting error state\n");
s->state = MIG_STATE_ERROR;
+ trace_migrate_set_state(MIG_STATE_ERROR);
migrate_fd_cleanup(s);
}
@@ -289,6 +291,7 @@ static void migrate_fd_completed(MigrationState *s)
{
DPRINTF("setting completed state\n");
s->state = MIG_STATE_COMPLETED;
+ trace_migrate_set_state(MIG_STATE_COMPLETED);
migrate_fd_cleanup(s);
}
@@ -319,6 +322,7 @@ static void migrate_fd_cancel(MigrationState *s)
DPRINTF("cancelling migration\n");
s->state = MIG_STATE_CANCELLED;
+ trace_migrate_set_state(MIG_STATE_CANCELLED);
migrate_fd_cleanup(s);
}
@@ -377,8 +381,9 @@ static MigrationState *migrate_init(const MigrationParams *params)
s->bandwidth_limit = bandwidth_limit;
s->state = MIG_STATE_SETUP;
- s->total_time = qemu_get_clock_ms(rt_clock);
+ trace_migrate_set_state(MIG_STATE_SETUP);
+ s->total_time = qemu_get_clock_ms(rt_clock);
return s;
}
@@ -738,6 +743,8 @@ static const QEMUFileOps buffered_file_ops = {
void migrate_fd_connect(MigrationState *s)
{
s->state = MIG_STATE_ACTIVE;
+ trace_migrate_set_state(MIG_STATE_ACTIVE);
+
s->bytes_xfer = 0;
s->buffer = NULL;
s->buffer_size = 0;
diff --git a/trace-events b/trace-events
index 167f481..614c4ef 100644
--- a/trace-events
+++ b/trace-events
@@ -1091,3 +1091,6 @@ css_io_interrupt(int cssid, int ssid, int schid, uint32_t intparm, uint8_t isc,
# hw/s390x/virtio-ccw.c
virtio_ccw_interpret_ccw(int cssid, int ssid, int schid, int cmd_code) "VIRTIO-CCW: %x.%x.%04x: interpret command %x"
virtio_ccw_new_device(int cssid, int ssid, int schid, int devno, const char *devno_mode) "VIRTIO-CCW: add subchannel %x.%x.%04x, devno %04x (%s)"
+
+# migration.c
+migrate_set_state(int new_state) "new state %d"

View File

@ -1,126 +0,0 @@
From b61e15d1ead74c97c9fa709f6d2868529bae1098 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:20 +0100
Subject: [PATCH] migration: prepare to access s->state outside critical
sections
Accessing s->state outside the big QEMU lock will simplify a bit the
locking/unlocking of the iothread lock.
We need to keep the lock in migrate_fd_error and migrate_fd_completed,
however, because they call migrate_fd_cleanup.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit f4410a5d9926886c36d9fa9fdd969d0469d62724)
---
migration.c | 33 +++++++++++++++++++++------------
1 file changed, 21 insertions(+), 12 deletions(-)
diff --git a/migration.c b/migration.c
index c0a9239..e844b2c 100644
--- a/migration.c
+++ b/migration.c
@@ -279,19 +279,25 @@ static void migrate_fd_cleanup(MigrationState *s)
notifier_list_notify(&migration_state_notifiers, s);
}
+static void migrate_finish_set_state(MigrationState *s, int new_state)
+{
+ if (__sync_val_compare_and_swap(&s->state, MIG_STATE_ACTIVE,
+ new_state) == new_state) {
+ trace_migrate_set_state(new_state);
+ }
+}
+
void migrate_fd_error(MigrationState *s)
{
DPRINTF("setting error state\n");
- s->state = MIG_STATE_ERROR;
- trace_migrate_set_state(MIG_STATE_ERROR);
+ migrate_finish_set_state(s, MIG_STATE_ERROR);
migrate_fd_cleanup(s);
}
static void migrate_fd_completed(MigrationState *s)
{
DPRINTF("setting completed state\n");
- s->state = MIG_STATE_COMPLETED;
- trace_migrate_set_state(MIG_STATE_COMPLETED);
+ migrate_finish_set_state(s, MIG_STATE_COMPLETED);
migrate_fd_cleanup(s);
}
@@ -316,13 +322,9 @@ static ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data,
static void migrate_fd_cancel(MigrationState *s)
{
- if (s->state != MIG_STATE_ACTIVE)
- return;
-
DPRINTF("cancelling migration\n");
- s->state = MIG_STATE_CANCELLED;
- trace_migrate_set_state(MIG_STATE_CANCELLED);
+ migrate_finish_set_state(s, MIG_STATE_CANCELLED);
migrate_fd_cleanup(s);
}
@@ -657,12 +659,14 @@ static void *buffered_file_thread(void *opaque)
qemu_mutex_lock_iothread();
DPRINTF("beginning savevm\n");
qemu_savevm_state_begin(s->file, &s->params);
+ qemu_mutex_unlock_iothread();
while (s->state == MIG_STATE_ACTIVE) {
int64_t current_time;
uint64_t pending_size;
if (s->bytes_xfer < s->xfer_limit) {
+ qemu_mutex_lock_iothread();
DPRINTF("iterate\n");
pending_size = qemu_savevm_state_pending(s->file, max_size);
DPRINTF("pending size %lu max %lu\n", pending_size, max_size);
@@ -678,8 +682,9 @@ static void *buffered_file_thread(void *opaque)
qemu_savevm_state_complete(s->file);
last_round = true;
}
+ qemu_mutex_unlock_iothread();
}
- qemu_mutex_unlock_iothread();
+
current_time = qemu_get_clock_ms(rt_clock);
if (current_time >= initial_time + BUFFER_DELAY) {
uint64_t transferred_bytes = s->bytes_xfer;
@@ -706,14 +711,18 @@ static void *buffered_file_thread(void *opaque)
sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
}
buffered_flush(s);
- qemu_mutex_lock_iothread();
if (qemu_file_get_error(s->file)) {
+ qemu_mutex_lock_iothread();
migrate_fd_error(s);
+ qemu_mutex_unlock_iothread();
} else if (last_round && s->buffer_size == 0) {
+ qemu_mutex_lock_iothread();
migrate_fd_completed(s);
+ qemu_mutex_unlock_iothread();
}
}
+ qemu_mutex_lock_iothread();
if (s->state == MIG_STATE_COMPLETED) {
int64_t end_time = qemu_get_clock_ms(rt_clock);
s->total_time = end_time - s->total_time;
@@ -725,8 +734,8 @@ static void *buffered_file_thread(void *opaque)
vm_start();
}
}
-
qemu_mutex_unlock_iothread();
+
g_free(s->buffer);
return NULL;
}

View File

@ -1,129 +0,0 @@
From bce1e693cdf25a98c120882197c9fcce975fb039 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:21 +0100
Subject: [PATCH] migration: cleanup migration (including thread) in the
iothread
Perform final cleanup in a bottom half, and add joining the thread to
the series of cleanup actions.
migrate_fd_error remains for connection error, but it doesn't need
to cleanup anything anymore.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit bb1fadc444ff967554c41d96cb9dde110e8aece9)
---
include/migration/migration.h | 1 +
migration.c | 38 ++++++++++++++++++++------------------
2 files changed, 21 insertions(+), 18 deletions(-)
diff --git a/include/migration/migration.h b/include/migration/migration.h
index 3e680af..ed20bed 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -38,6 +38,7 @@ struct MigrationState
size_t buffer_size;
size_t buffer_capacity;
QemuThread thread;
+ QEMUBH *cleanup_bh;
QEMUFile *file;
int fd;
diff --git a/migration.c b/migration.c
index e844b2c..437475b 100644
--- a/migration.c
+++ b/migration.c
@@ -261,8 +261,13 @@ void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
/* shared migration helpers */
-static void migrate_fd_cleanup(MigrationState *s)
+static void migrate_fd_cleanup(void *opaque)
{
+ MigrationState *s = opaque;
+
+ qemu_bh_delete(s->cleanup_bh);
+ s->cleanup_bh = NULL;
+
if (s->file) {
DPRINTF("closing file\n");
qemu_fclose(s->file);
@@ -290,15 +295,10 @@ static void migrate_finish_set_state(MigrationState *s, int new_state)
void migrate_fd_error(MigrationState *s)
{
DPRINTF("setting error state\n");
- migrate_finish_set_state(s, MIG_STATE_ERROR);
- migrate_fd_cleanup(s);
-}
-
-static void migrate_fd_completed(MigrationState *s)
-{
- DPRINTF("setting completed state\n");
- migrate_finish_set_state(s, MIG_STATE_COMPLETED);
- migrate_fd_cleanup(s);
+ assert(s->file == NULL);
+ s->state = MIG_STATE_ERROR;
+ trace_migrate_set_state(MIG_STATE_ERROR);
+ notifier_list_notify(&migration_state_notifiers, s);
}
static ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data,
@@ -325,7 +325,6 @@ static void migrate_fd_cancel(MigrationState *s)
DPRINTF("cancelling migration\n");
migrate_finish_set_state(s, MIG_STATE_CANCELLED);
- migrate_fd_cleanup(s);
}
int migrate_fd_close(MigrationState *s)
@@ -590,6 +589,11 @@ static int buffered_close(void *opaque)
DPRINTF("closing\n");
+ qemu_mutex_unlock_iothread();
+ qemu_thread_join(&s->thread);
+ qemu_mutex_lock_iothread();
+ assert(s->state != MIG_STATE_ACTIVE);
+
return migrate_fd_close(s);
}
@@ -712,13 +716,9 @@ static void *buffered_file_thread(void *opaque)
}
buffered_flush(s);
if (qemu_file_get_error(s->file)) {
- qemu_mutex_lock_iothread();
- migrate_fd_error(s);
- qemu_mutex_unlock_iothread();
+ migrate_finish_set_state(s, MIG_STATE_ERROR);
} else if (last_round && s->buffer_size == 0) {
- qemu_mutex_lock_iothread();
- migrate_fd_completed(s);
- qemu_mutex_unlock_iothread();
+ migrate_finish_set_state(s, MIG_STATE_COMPLETED);
}
}
@@ -734,6 +734,7 @@ static void *buffered_file_thread(void *opaque)
vm_start();
}
}
+ qemu_bh_schedule(s->cleanup_bh);
qemu_mutex_unlock_iothread();
g_free(s->buffer);
@@ -763,9 +764,10 @@ void migrate_fd_connect(MigrationState *s)
s->xfer_limit = s->bandwidth_limit / XFER_LIMIT_RATIO;
+ s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s);
s->file = qemu_fopen_ops(s, &buffered_file_ops);
qemu_thread_create(&s->thread, buffered_file_thread, s,
- QEMU_THREAD_DETACHED);
+ QEMU_THREAD_JOINABLE);
notifier_list_notify(&migration_state_notifiers, s);
}

View File

@ -1,70 +0,0 @@
From b4800390037c71ffa12d691d3410327bc3eb826e Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:22 +0100
Subject: [PATCH] block-migration: remove variables that are never read
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit a55ce1c851b5802569fb00b2a645a73c03fd7c86)
---
block-migration.c | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/block-migration.c b/block-migration.c
index e6c917d..e72f322 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -50,7 +50,6 @@ typedef struct BlkMigDevState {
int64_t cur_dirty;
int64_t completed_sectors;
int64_t total_sectors;
- int64_t dirty;
QSIMPLEQ_ENTRY(BlkMigDevState) entry;
unsigned long *aio_bitmap;
} BlkMigDevState;
@@ -78,7 +77,6 @@ typedef struct BlkMigState {
int64_t total_sector_sum;
int prev_progress;
int bulk_completed;
- long double prev_time_offset;
} BlkMigState;
static BlkMigState block_mig_state;
@@ -179,13 +177,10 @@ static void alloc_aio_bitmap(BlkMigDevState *bmds)
static void blk_mig_read_cb(void *opaque, int ret)
{
- long double curr_time = qemu_get_clock_ns(rt_clock);
BlkMigBlock *blk = opaque;
blk->ret = ret;
- block_mig_state.prev_time_offset = curr_time;
-
QSIMPLEQ_INSERT_TAIL(&block_mig_state.blk_list, blk, entry);
bmds_set_aio_inflight(blk->bmds, blk->sector, blk->nr_sectors, 0);
@@ -236,10 +231,6 @@ static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
- if (block_mig_state.submitted == 0) {
- block_mig_state.prev_time_offset = qemu_get_clock_ns(rt_clock);
- }
-
blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov,
nr_sectors, blk_mig_read_cb, blk);
block_mig_state.submitted++;
@@ -382,10 +373,6 @@ static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
- if (block_mig_state.submitted == 0) {
- block_mig_state.prev_time_offset = qemu_get_clock_ns(rt_clock);
- }
-
blk->aiocb = bdrv_aio_readv(bmds->bs, sector, &blk->qiov,
nr_sectors, blk_mig_read_cb, blk);
block_mig_state.submitted++;

View File

@ -1,88 +0,0 @@
From b91507ad365c4672fb8c8217b9f37ce5c151e229 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:23 +0100
Subject: [PATCH] block-migration: small preparatory changes for locking
Some small changes that will simplify the positioning of lock/unlock
primitives.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 13197e3cbaba0ba693dd2855a32182ca584fa97e)
---
block-migration.c | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/block-migration.c b/block-migration.c
index e72f322..9a40edd 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -231,9 +231,10 @@ static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
+ block_mig_state.submitted++;
+
blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov,
nr_sectors, blk_mig_read_cb, blk);
- block_mig_state.submitted++;
bdrv_reset_dirty(bs, cur_sector, nr_sectors);
bmds->cur_sector = cur_sector + nr_sectors;
@@ -440,9 +441,10 @@ static int flush_blks(QEMUFile *f)
ret = blk->ret;
break;
}
- blk_send(f, blk);
QSIMPLEQ_REMOVE_HEAD(&block_mig_state.blk_list, entry);
+ blk_send(f, blk);
+
g_free(blk->buf);
g_free(blk);
@@ -542,15 +544,16 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
/* finished saving bulk on all devices */
block_mig_state.bulk_completed = 1;
}
+ ret = 0;
} else {
ret = blk_mig_save_dirty_block(f, 1);
- if (ret < 0) {
- return ret;
- }
- if (ret != 0) {
- /* no more dirty blocks */
- break;
- }
+ }
+ if (ret < 0) {
+ return ret;
+ }
+ if (ret != 0) {
+ /* no more dirty blocks */
+ break;
}
}
@@ -560,7 +563,6 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
}
qemu_put_be64(f, BLK_MIG_FLAG_EOS);
-
return qemu_ftell(f) - last_ftell;
}
@@ -603,7 +605,9 @@ static int block_save_complete(QEMUFile *f, void *opaque)
static uint64_t block_save_pending(QEMUFile *f, void *opaque, uint64_t max_size)
{
/* Estimate pending number of bytes to send */
- uint64_t pending = get_remaining_dirty() +
+ uint64_t pending;
+
+ pending = get_remaining_dirty() +
block_mig_state.submitted * BLOCK_SIZE +
block_mig_state.read_done * BLOCK_SIZE;

View File

@ -1,75 +0,0 @@
From 4c62f3e4b8f0c014306c4e5dae4eb8c59289d562 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:24 +0100
Subject: [PATCH] block-migration: document usage of state across threads
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 323920c4eac01de74cf2b5e941c97ca9b2d36b7f)
---
block-migration.c | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/block-migration.c b/block-migration.c
index 9a40edd..d62a8b8 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -43,18 +43,24 @@
#endif
typedef struct BlkMigDevState {
+ /* Written during setup phase. Can be read without a lock. */
BlockDriverState *bs;
- int bulk_completed;
int shared_base;
- int64_t cur_sector;
- int64_t cur_dirty;
- int64_t completed_sectors;
int64_t total_sectors;
QSIMPLEQ_ENTRY(BlkMigDevState) entry;
+
+ /* Only used by migration thread. Does not need a lock. */
+ int bulk_completed;
+ int64_t cur_sector;
+ int64_t cur_dirty;
+
+ /* Protected by iothread lock. */
unsigned long *aio_bitmap;
+ int64_t completed_sectors;
} BlkMigDevState;
typedef struct BlkMigBlock {
+ /* Only used by migration thread. */
uint8_t *buf;
BlkMigDevState *bmds;
int64_t sector;
@@ -62,19 +68,26 @@ typedef struct BlkMigBlock {
struct iovec iov;
QEMUIOVector qiov;
BlockDriverAIOCB *aiocb;
+
+ /* Protected by iothread lock. */
int ret;
QSIMPLEQ_ENTRY(BlkMigBlock) entry;
} BlkMigBlock;
typedef struct BlkMigState {
+ /* Written during setup phase. Can be read without a lock. */
int blk_enable;
int shared_base;
QSIMPLEQ_HEAD(bmds_list, BlkMigDevState) bmds_list;
+ int64_t total_sector_sum;
+
+ /* Protected by iothread lock. */
QSIMPLEQ_HEAD(blk_list, BlkMigBlock) blk_list;
int submitted;
int read_done;
+
+ /* Only used by migration thread. Does not need a lock. */
int transferred;
- int64_t total_sector_sum;
int prev_progress;
int bulk_completed;
} BlkMigState;

View File

@ -1,279 +0,0 @@
From f53959ca0d677a2ff0bf7243faeb2174f83268dc Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:25 +0100
Subject: [PATCH] block-migration: add lock
Some state is shared between the block migration code and its AIO
callbacks. Once block migration will run outside the iothread,
the block migration code and the AIO callbacks will be able to
run concurrently. Protect the critical sections with a separate
lock. Do the same for completed_sectors, which can be used from
the monitor.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 52e850dea988585c3d693fd9cd4a4c38968d89b8)
---
block-migration.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++---
include/qemu/atomic.h | 1 +
2 files changed, 52 insertions(+), 3 deletions(-)
diff --git a/block-migration.c b/block-migration.c
index d62a8b8..b726c6c 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -54,7 +54,7 @@ typedef struct BlkMigDevState {
int64_t cur_sector;
int64_t cur_dirty;
- /* Protected by iothread lock. */
+ /* Protected by block migration lock. */
unsigned long *aio_bitmap;
int64_t completed_sectors;
} BlkMigDevState;
@@ -69,7 +69,7 @@ typedef struct BlkMigBlock {
QEMUIOVector qiov;
BlockDriverAIOCB *aiocb;
- /* Protected by iothread lock. */
+ /* Protected by block migration lock. */
int ret;
QSIMPLEQ_ENTRY(BlkMigBlock) entry;
} BlkMigBlock;
@@ -81,7 +81,7 @@ typedef struct BlkMigState {
QSIMPLEQ_HEAD(bmds_list, BlkMigDevState) bmds_list;
int64_t total_sector_sum;
- /* Protected by iothread lock. */
+ /* Protected by lock. */
QSIMPLEQ_HEAD(blk_list, BlkMigBlock) blk_list;
int submitted;
int read_done;
@@ -90,10 +90,23 @@ typedef struct BlkMigState {
int transferred;
int prev_progress;
int bulk_completed;
+
+ /* Lock must be taken _inside_ the iothread lock. */
+ QemuMutex lock;
} BlkMigState;
static BlkMigState block_mig_state;
+static void blk_mig_lock(void)
+{
+ qemu_mutex_lock(&block_mig_state.lock);
+}
+
+static void blk_mig_unlock(void)
+{
+ qemu_mutex_unlock(&block_mig_state.lock);
+}
+
static void blk_send(QEMUFile *f, BlkMigBlock * blk)
{
int len;
@@ -120,9 +133,11 @@ uint64_t blk_mig_bytes_transferred(void)
BlkMigDevState *bmds;
uint64_t sum = 0;
+ blk_mig_lock();
QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
sum += bmds->completed_sectors;
}
+ blk_mig_unlock();
return sum << BDRV_SECTOR_BITS;
}
@@ -142,6 +157,9 @@ uint64_t blk_mig_bytes_total(void)
return sum << BDRV_SECTOR_BITS;
}
+
+/* Called with migration lock held. */
+
static int bmds_aio_inflight(BlkMigDevState *bmds, int64_t sector)
{
int64_t chunk = sector / (int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK;
@@ -154,6 +172,8 @@ static int bmds_aio_inflight(BlkMigDevState *bmds, int64_t sector)
}
}
+/* Called with migration lock held. */
+
static void bmds_set_aio_inflight(BlkMigDevState *bmds, int64_t sector_num,
int nb_sectors, int set)
{
@@ -188,10 +208,13 @@ static void alloc_aio_bitmap(BlkMigDevState *bmds)
bmds->aio_bitmap = g_malloc0(bitmap_size);
}
+/* Never hold migration lock when yielding to the main loop! */
+
static void blk_mig_read_cb(void *opaque, int ret)
{
BlkMigBlock *blk = opaque;
+ blk_mig_lock();
blk->ret = ret;
QSIMPLEQ_INSERT_TAIL(&block_mig_state.blk_list, blk, entry);
@@ -200,6 +223,7 @@ static void blk_mig_read_cb(void *opaque, int ret)
block_mig_state.submitted--;
block_mig_state.read_done++;
assert(block_mig_state.submitted >= 0);
+ blk_mig_unlock();
}
static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
@@ -244,7 +268,9 @@ static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
+ blk_mig_lock();
block_mig_state.submitted++;
+ blk_mig_unlock();
blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov,
nr_sectors, blk_mig_read_cb, blk);
@@ -366,8 +392,12 @@ static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
int ret = -EIO;
for (sector = bmds->cur_dirty; sector < bmds->total_sectors;) {
+ blk_mig_lock();
if (bmds_aio_inflight(bmds, sector)) {
+ blk_mig_unlock();
bdrv_drain_all();
+ } else {
+ blk_mig_unlock();
}
if (bdrv_get_dirty(bmds->bs, sector)) {
@@ -389,8 +419,11 @@ static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
blk->aiocb = bdrv_aio_readv(bmds->bs, sector, &blk->qiov,
nr_sectors, blk_mig_read_cb, blk);
+
+ blk_mig_lock();
block_mig_state.submitted++;
bmds_set_aio_inflight(bmds, sector, nr_sectors, 1);
+ blk_mig_unlock();
} else {
ret = bdrv_read(bmds->bs, sector, blk->buf, nr_sectors);
if (ret < 0) {
@@ -446,6 +479,7 @@ static int flush_blks(QEMUFile *f)
__FUNCTION__, block_mig_state.submitted, block_mig_state.read_done,
block_mig_state.transferred);
+ blk_mig_lock();
while ((blk = QSIMPLEQ_FIRST(&block_mig_state.blk_list)) != NULL) {
if (qemu_file_rate_limit(f)) {
break;
@@ -456,7 +490,9 @@ static int flush_blks(QEMUFile *f)
}
QSIMPLEQ_REMOVE_HEAD(&block_mig_state.blk_list, entry);
+ blk_mig_unlock();
blk_send(f, blk);
+ blk_mig_lock();
g_free(blk->buf);
g_free(blk);
@@ -465,6 +501,7 @@ static int flush_blks(QEMUFile *f)
block_mig_state.transferred++;
assert(block_mig_state.read_done >= 0);
}
+ blk_mig_unlock();
DPRINTF("%s Exit submitted %d read_done %d transferred %d\n", __FUNCTION__,
block_mig_state.submitted, block_mig_state.read_done,
@@ -493,6 +530,7 @@ static void blk_mig_cleanup(void)
set_dirty_tracking(0);
+ blk_mig_lock();
while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) {
QSIMPLEQ_REMOVE_HEAD(&block_mig_state.bmds_list, entry);
bdrv_set_in_use(bmds->bs, 0);
@@ -506,6 +544,7 @@ static void blk_mig_cleanup(void)
g_free(blk->buf);
g_free(blk);
}
+ blk_mig_unlock();
}
static void block_migration_cancel(void *opaque)
@@ -548,9 +587,11 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
blk_mig_reset_dirty_cursor();
/* control the rate of transfer */
+ blk_mig_lock();
while ((block_mig_state.submitted +
block_mig_state.read_done) * BLOCK_SIZE <
qemu_file_get_rate_limit(f)) {
+ blk_mig_unlock();
if (block_mig_state.bulk_completed == 0) {
/* first finish the bulk phase */
if (blk_mig_save_bulked_block(f) == 0) {
@@ -564,11 +605,13 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
if (ret < 0) {
return ret;
}
+ blk_mig_lock();
if (ret != 0) {
/* no more dirty blocks */
break;
}
}
+ blk_mig_unlock();
ret = flush_blks(f);
if (ret) {
@@ -595,7 +638,9 @@ static int block_save_complete(QEMUFile *f, void *opaque)
/* we know for sure that save bulk is completed and
all async read completed */
+ blk_mig_lock();
assert(block_mig_state.submitted == 0);
+ blk_mig_unlock();
do {
ret = blk_mig_save_dirty_block(f, 0);
@@ -620,6 +665,7 @@ static uint64_t block_save_pending(QEMUFile *f, void *opaque, uint64_t max_size)
/* Estimate pending number of bytes to send */
uint64_t pending;
+ blk_mig_lock();
pending = get_remaining_dirty() +
block_mig_state.submitted * BLOCK_SIZE +
block_mig_state.read_done * BLOCK_SIZE;
@@ -628,6 +674,7 @@ static uint64_t block_save_pending(QEMUFile *f, void *opaque, uint64_t max_size)
if (pending == 0 && !block_mig_state.bulk_completed) {
pending = BLOCK_SIZE;
}
+ blk_mig_unlock();
DPRINTF("Enter save live pending %" PRIu64 "\n", pending);
return pending;
@@ -739,6 +786,7 @@ void blk_mig_init(void)
{
QSIMPLEQ_INIT(&block_mig_state.bmds_list);
QSIMPLEQ_INIT(&block_mig_state.blk_list);
+ qemu_mutex_init(&block_mig_state.lock);
register_savevm_live(NULL, "block", 0, 1, &savevm_block_handlers,
&block_mig_state);
diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h
index 96a194b..10becb6 100644
--- a/include/qemu/atomic.h
+++ b/include/qemu/atomic.h
@@ -16,6 +16,7 @@
*/
#define smp_wmb() barrier()
#define smp_rmb() barrier()
+
/*
* We use GCC builtin if it's available, as that can use
* mfence on 32 bit as well, e.g. if built with -march=pentium-m.

View File

@ -1,40 +0,0 @@
From aa1e411294714429d6d4eb66bdb4266f65a01d1f Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:26 +0100
Subject: [PATCH] migration: reorder SaveVMHandlers members
This groups together the callbacks that later will have similar
locking rules.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 8c8de19d93444536d3291e6ab83e2bcf61dd2d0c)
---
include/migration/vmstate.h | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index f27276c..6229569 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -32,13 +32,15 @@ typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id);
typedef struct SaveVMHandlers {
void (*set_params)(const MigrationParams *params, void * opaque);
SaveStateHandler *save_state;
+
int (*save_live_setup)(QEMUFile *f, void *opaque);
- int (*save_live_iterate)(QEMUFile *f, void *opaque);
+ void (*cancel)(void *opaque);
int (*save_live_complete)(QEMUFile *f, void *opaque);
+ bool (*is_active)(void *opaque);
+ int (*save_live_iterate)(QEMUFile *f, void *opaque);
uint64_t (*save_live_pending)(QEMUFile *f, void *opaque, uint64_t max_size);
- void (*cancel)(void *opaque);
+
LoadStateHandler *load_state;
- bool (*is_active)(void *opaque);
} SaveVMHandlers;
int register_savevm(DeviceState *dev,

View File

@ -1,265 +0,0 @@
From efb8ea48a730325b4bb4cfd1b624e697b1522536 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:27 +0100
Subject: [PATCH] migration: run pending/iterate callbacks out of big lock
This makes it possible to do blocking writes directly to the socket,
with no buffer in the middle. For RAM, only the migration_bitmap_sync()
call needs the iothread lock. For block migration, it is needed by
the block layer (including bdrv_drain_all and dirty bitmap access),
but because some code is shared between iterate and complete, all of
mig_save_device_dirty is run with the lock taken.
In the savevm case, the iterate callback runs within the big lock.
This is annoying because it complicates the rules. Luckily we do not
need to do anything about it: the RAM iterate callback does not need
the iothread lock, and block migration never runs during savevm.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 32c835ba3984728c22d4e73cdb595090a60f437e)
---
arch_init.c | 4 ++++
block-migration.c | 37 +++++++++++++++++++++++++++++++++++--
include/migration/vmstate.h | 11 +++++++++++
migration.c | 4 ++--
4 files changed, 52 insertions(+), 4 deletions(-)
diff --git a/arch_init.c b/arch_init.c
index 8daeafa..32b4378 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -379,6 +379,8 @@ static inline bool migration_bitmap_set_dirty(MemoryRegion *mr,
return ret;
}
+/* Needs iothread lock! */
+
static void migration_bitmap_sync(void)
{
RAMBlock *block;
@@ -690,7 +692,9 @@ static uint64_t ram_save_pending(QEMUFile *f, void *opaque, uint64_t max_size)
remaining_size = ram_save_remaining() * TARGET_PAGE_SIZE;
if (remaining_size < max_size) {
+ qemu_mutex_lock_iothread();
migration_bitmap_sync();
+ qemu_mutex_unlock_iothread();
remaining_size = ram_save_remaining() * TARGET_PAGE_SIZE;
}
return remaining_size;
diff --git a/block-migration.c b/block-migration.c
index b726c6c..8da5f86 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -107,6 +107,10 @@ static void blk_mig_unlock(void)
qemu_mutex_unlock(&block_mig_state.lock);
}
+/* Must run outside of the iothread lock during the bulk phase,
+ * or the VM will stall.
+ */
+
static void blk_send(QEMUFile *f, BlkMigBlock * blk)
{
int len;
@@ -226,6 +230,8 @@ static void blk_mig_read_cb(void *opaque, int ret)
blk_mig_unlock();
}
+/* Called with no lock taken. */
+
static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
{
int64_t total_sectors = bmds->total_sectors;
@@ -235,11 +241,13 @@ static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
int nr_sectors;
if (bmds->shared_base) {
+ qemu_mutex_lock_iothread();
while (cur_sector < total_sectors &&
!bdrv_is_allocated(bs, cur_sector, MAX_IS_ALLOCATED_SEARCH,
&nr_sectors)) {
cur_sector += nr_sectors;
}
+ qemu_mutex_unlock_iothread();
}
if (cur_sector >= total_sectors) {
@@ -272,15 +280,19 @@ static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
block_mig_state.submitted++;
blk_mig_unlock();
+ qemu_mutex_lock_iothread();
blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov,
nr_sectors, blk_mig_read_cb, blk);
bdrv_reset_dirty(bs, cur_sector, nr_sectors);
- bmds->cur_sector = cur_sector + nr_sectors;
+ qemu_mutex_unlock_iothread();
+ bmds->cur_sector = cur_sector + nr_sectors;
return (bmds->cur_sector >= total_sectors);
}
+/* Called with iothread lock taken. */
+
static void set_dirty_tracking(int enable)
{
BlkMigDevState *bmds;
@@ -336,6 +348,8 @@ static void init_blk_migration(QEMUFile *f)
bdrv_iterate(init_blk_migration_it, NULL);
}
+/* Called with no lock taken. */
+
static int blk_mig_save_bulked_block(QEMUFile *f)
{
int64_t completed_sector_sum = 0;
@@ -382,6 +396,8 @@ static void blk_mig_reset_dirty_cursor(void)
}
}
+/* Called with iothread lock taken. */
+
static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
int is_async)
{
@@ -451,7 +467,9 @@ error:
return ret;
}
-/* return value:
+/* Called with iothread lock taken.
+ *
+ * return value:
* 0: too much data for max_downtime
* 1: few enough data for max_downtime
*/
@@ -470,6 +488,8 @@ static int blk_mig_save_dirty_block(QEMUFile *f, int is_async)
return ret;
}
+/* Called with no locks taken. */
+
static int flush_blks(QEMUFile *f)
{
BlkMigBlock *blk;
@@ -509,6 +529,8 @@ static int flush_blks(QEMUFile *f)
return ret;
}
+/* Called with iothread lock taken. */
+
static int64_t get_remaining_dirty(void)
{
BlkMigDevState *bmds;
@@ -521,6 +543,8 @@ static int64_t get_remaining_dirty(void)
return dirty << BDRV_SECTOR_BITS;
}
+/* Called with iothread lock taken. */
+
static void blk_mig_cleanup(void)
{
BlkMigDevState *bmds;
@@ -600,7 +624,12 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
}
ret = 0;
} else {
+ /* Always called with iothread lock taken for
+ * simplicity, block_save_complete also calls it.
+ */
+ qemu_mutex_lock_iothread();
ret = blk_mig_save_dirty_block(f, 1);
+ qemu_mutex_unlock_iothread();
}
if (ret < 0) {
return ret;
@@ -622,6 +651,8 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
return qemu_ftell(f) - last_ftell;
}
+/* Called with iothread lock taken. */
+
static int block_save_complete(QEMUFile *f, void *opaque)
{
int ret;
@@ -665,6 +696,7 @@ static uint64_t block_save_pending(QEMUFile *f, void *opaque, uint64_t max_size)
/* Estimate pending number of bytes to send */
uint64_t pending;
+ qemu_mutex_lock_iothread();
blk_mig_lock();
pending = get_remaining_dirty() +
block_mig_state.submitted * BLOCK_SIZE +
@@ -675,6 +707,7 @@ static uint64_t block_save_pending(QEMUFile *f, void *opaque, uint64_t max_size)
pending = BLOCK_SIZE;
}
blk_mig_unlock();
+ qemu_mutex_unlock_iothread();
DPRINTF("Enter save live pending %" PRIu64 "\n", pending);
return pending;
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 6229569..5f803f5 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -30,14 +30,25 @@ typedef void SaveStateHandler(QEMUFile *f, void *opaque);
typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id);
typedef struct SaveVMHandlers {
+ /* This runs inside the iothread lock. */
void (*set_params)(const MigrationParams *params, void * opaque);
SaveStateHandler *save_state;
int (*save_live_setup)(QEMUFile *f, void *opaque);
void (*cancel)(void *opaque);
int (*save_live_complete)(QEMUFile *f, void *opaque);
+
+ /* This runs both outside and inside the iothread lock. */
bool (*is_active)(void *opaque);
+
+ /* This runs outside the iothread lock in the migration case, and
+ * within the lock in the savevm case. The callback had better only
+ * use data that is local to the migration thread or protected
+ * by other locks.
+ */
int (*save_live_iterate)(QEMUFile *f, void *opaque);
+
+ /* This runs outside the iothread lock! */
uint64_t (*save_live_pending)(QEMUFile *f, void *opaque, uint64_t max_size);
LoadStateHandler *load_state;
diff --git a/migration.c b/migration.c
index 437475b..87b5009 100644
--- a/migration.c
+++ b/migration.c
@@ -670,7 +670,6 @@ static void *buffered_file_thread(void *opaque)
uint64_t pending_size;
if (s->bytes_xfer < s->xfer_limit) {
- qemu_mutex_lock_iothread();
DPRINTF("iterate\n");
pending_size = qemu_savevm_state_pending(s->file, max_size);
DPRINTF("pending size %lu max %lu\n", pending_size, max_size);
@@ -678,6 +677,7 @@ static void *buffered_file_thread(void *opaque)
qemu_savevm_state_iterate(s->file);
} else {
DPRINTF("done iterating\n");
+ qemu_mutex_lock_iothread();
start_time = qemu_get_clock_ms(rt_clock);
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
old_vm_running = runstate_is_running();
@@ -685,8 +685,8 @@ static void *buffered_file_thread(void *opaque)
s->xfer_limit = INT_MAX;
qemu_savevm_state_complete(s->file);
last_round = true;
+ qemu_mutex_unlock_iothread();
}
- qemu_mutex_unlock_iothread();
}
current_time = qemu_get_clock_ms(rt_clock);

View File

@ -1,117 +0,0 @@
From ffe95e1c4daef0e563b8d70a8f456f9e7037818d Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:28 +0100
Subject: [PATCH] migration: run setup callbacks out of big lock
Only the migration_bitmap_sync() call needs the iothread lock.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 9b0950375277467fd74a9075624477ae43b9bb22)
---
arch_init.c | 10 ++++++----
block-migration.c | 2 ++
include/migration/vmstate.h | 2 +-
migration.c | 2 --
savevm.c | 3 +++
5 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/arch_init.c b/arch_init.c
index 32b4378..6089c53 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -570,10 +570,6 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
bitmap_set(migration_bitmap, 0, ram_pages);
migration_dirty_pages = ram_pages;
- qemu_mutex_lock_ramlist();
- bytes_transferred = 0;
- reset_ram_globals();
-
if (migrate_use_xbzrle()) {
XBZRLE.cache = cache_init(migrate_xbzrle_cache_size() /
TARGET_PAGE_SIZE,
@@ -587,8 +583,14 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
acct_clear();
}
+ qemu_mutex_lock_iothread();
+ qemu_mutex_lock_ramlist();
+ bytes_transferred = 0;
+ reset_ram_globals();
+
memory_global_dirty_log_start();
migration_bitmap_sync();
+ qemu_mutex_unlock_iothread();
qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE);
diff --git a/block-migration.c b/block-migration.c
index 8da5f86..2fd7699 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -583,10 +583,12 @@ static int block_save_setup(QEMUFile *f, void *opaque)
DPRINTF("Enter save live setup submitted %d transferred %d\n",
block_mig_state.submitted, block_mig_state.transferred);
+ qemu_mutex_lock_iothread();
init_blk_migration(f);
/* start track dirty blocks */
set_dirty_tracking(1);
+ qemu_mutex_unlock_iothread();
ret = flush_blks(f);
blk_mig_reset_dirty_cursor();
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 5f803f5..abc3b47 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -34,7 +34,6 @@ typedef struct SaveVMHandlers {
void (*set_params)(const MigrationParams *params, void * opaque);
SaveStateHandler *save_state;
- int (*save_live_setup)(QEMUFile *f, void *opaque);
void (*cancel)(void *opaque);
int (*save_live_complete)(QEMUFile *f, void *opaque);
@@ -49,6 +48,7 @@ typedef struct SaveVMHandlers {
int (*save_live_iterate)(QEMUFile *f, void *opaque);
/* This runs outside the iothread lock! */
+ int (*save_live_setup)(QEMUFile *f, void *opaque);
uint64_t (*save_live_pending)(QEMUFile *f, void *opaque, uint64_t max_size);
LoadStateHandler *load_state;
diff --git a/migration.c b/migration.c
index 87b5009..7c1d4df 100644
--- a/migration.c
+++ b/migration.c
@@ -660,10 +660,8 @@ static void *buffered_file_thread(void *opaque)
bool old_vm_running = false;
bool last_round = false;
- qemu_mutex_lock_iothread();
DPRINTF("beginning savevm\n");
qemu_savevm_state_begin(s->file, &s->params);
- qemu_mutex_unlock_iothread();
while (s->state == MIG_STATE_ACTIVE) {
int64_t current_time;
diff --git a/savevm.c b/savevm.c
index e10a045..7c7774e 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1768,7 +1768,10 @@ static int qemu_savevm_state(QEMUFile *f)
return -EINVAL;
}
+ qemu_mutex_unlock_iothread();
qemu_savevm_state_begin(f, &params);
+ qemu_mutex_lock_iothread();
+
while (qemu_file_get_error(f) == 0) {
if (qemu_savevm_state_iterate(f) > 0) {
break;

View File

@ -1,176 +0,0 @@
From 4354cf42b4976ffc12b930cae1a4e9d8f9f71f08 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:29 +0100
Subject: [PATCH] migration: yay, buffering is gone
Buffering was needed because blocking writes could take a long time
and starve other threads seeking to grab the big QEMU mutex.
Now that all writes (except within _complete callbacks) are done
outside the big QEMU mutex, we do not need buffering at all.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit edaae611f6df0d66a8b5a90c84123b72980c7a22)
---
include/migration/migration.h | 3 --
migration.c | 79 ++++++++++++-------------------------------
savevm.c | 1 +
3 files changed, 22 insertions(+), 61 deletions(-)
diff --git a/include/migration/migration.h b/include/migration/migration.h
index ed20bed..cec8643 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -34,9 +34,6 @@ struct MigrationState
int64_t bandwidth_limit;
size_t bytes_xfer;
size_t xfer_limit;
- uint8_t *buffer;
- size_t buffer_size;
- size_t buffer_capacity;
QemuThread thread;
QEMUBH *cleanup_bh;
diff --git a/migration.c b/migration.c
index 7c1d4df..62a7f8e 100644
--- a/migration.c
+++ b/migration.c
@@ -514,73 +514,41 @@ int64_t migrate_xbzrle_cache_size(void)
/* migration thread support */
-
-static void buffered_flush(MigrationState *s)
-{
- size_t offset = 0;
- ssize_t ret = 0;
-
- DPRINTF("flushing %zu byte(s) of data\n", s->buffer_size);
-
- if (qemu_file_get_error(s->file)) {
- s->buffer_size = 0;
- return;
- }
- qemu_fflush(s->file);
-
- while (s->bytes_xfer < s->xfer_limit && offset < s->buffer_size) {
- size_t to_send = MIN(s->buffer_size - offset, s->xfer_limit - s->bytes_xfer);
- ret = migrate_fd_put_buffer(s, s->buffer + offset, to_send);
- if (ret <= 0) {
- DPRINTF("error flushing data, %zd\n", ret);
- break;
- } else {
- DPRINTF("flushed %zd byte(s)\n", ret);
- offset += ret;
- s->bytes_xfer += ret;
- }
- }
-
- DPRINTF("flushed %zu of %zu byte(s)\n", offset, s->buffer_size);
- memmove(s->buffer, s->buffer + offset, s->buffer_size - offset);
- s->buffer_size -= offset;
-
- if (ret < 0) {
- qemu_file_set_error(s->file, ret);
- }
-}
-
static int buffered_put_buffer(void *opaque, const uint8_t *buf,
int64_t pos, int size)
{
MigrationState *s = opaque;
- ssize_t error;
+ ssize_t ret;
+ size_t sent;
DPRINTF("putting %d bytes at %" PRId64 "\n", size, pos);
- error = qemu_file_get_error(s->file);
- if (error) {
- DPRINTF("flush when error, bailing: %s\n", strerror(-error));
- return error;
+ ret = qemu_file_get_error(s->file);
+ if (ret) {
+ DPRINTF("flush when error, bailing: %s\n", strerror(-ret));
+ return ret;
}
if (size <= 0) {
return size;
}
- if (size > (s->buffer_capacity - s->buffer_size)) {
- DPRINTF("increasing buffer capacity from %zu by %zu\n",
- s->buffer_capacity, size + 1024);
-
- s->buffer_capacity += size + 1024;
-
- s->buffer = g_realloc(s->buffer, s->buffer_capacity);
+ sent = 0;
+ while (size) {
+ ret = migrate_fd_put_buffer(s, buf, size);
+ if (ret <= 0) {
+ DPRINTF("error flushing data, %zd\n", ret);
+ return ret;
+ } else {
+ DPRINTF("flushed %zd byte(s)\n", ret);
+ sent += ret;
+ buf += ret;
+ size -= ret;
+ s->bytes_xfer += ret;
+ }
}
- memcpy(s->buffer + s->buffer_size, buf, size);
- s->buffer_size += size;
-
- return size;
+ return sent;
}
static int buffered_close(void *opaque)
@@ -712,10 +680,9 @@ static void *buffered_file_thread(void *opaque)
g_usleep((initial_time + BUFFER_DELAY - current_time)*1000);
sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
}
- buffered_flush(s);
if (qemu_file_get_error(s->file)) {
migrate_finish_set_state(s, MIG_STATE_ERROR);
- } else if (last_round && s->buffer_size == 0) {
+ } else if (last_round) {
migrate_finish_set_state(s, MIG_STATE_COMPLETED);
}
}
@@ -735,7 +702,6 @@ static void *buffered_file_thread(void *opaque)
qemu_bh_schedule(s->cleanup_bh);
qemu_mutex_unlock_iothread();
- g_free(s->buffer);
return NULL;
}
@@ -754,9 +720,6 @@ void migrate_fd_connect(MigrationState *s)
trace_migrate_set_state(MIG_STATE_ACTIVE);
s->bytes_xfer = 0;
- s->buffer = NULL;
- s->buffer_size = 0;
- s->buffer_capacity = 0;
/* This is a best 1st approximation. ns to ms */
s->expected_downtime = max_downtime/1000000;
diff --git a/savevm.c b/savevm.c
index 7c7774e..ce10295 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1724,6 +1724,7 @@ void qemu_savevm_state_complete(QEMUFile *f)
}
qemu_put_byte(f, QEMU_VM_EOF);
+ qemu_fflush(f);
}
uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size)

View File

@ -1,114 +0,0 @@
From 1b49e3073fada9243cb16e24aaa09e19a6675881 Mon Sep 17 00:00:00 2001
From: Juan Quintela <quintela@redhat.com>
Date: Fri, 22 Feb 2013 17:36:30 +0100
Subject: [PATCH] Rename buffered_ to migration_
This is consistent once that we have moved everything to migration.c
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 5f496a1be3d15f192be1ab1fed3a3278fd5a91a1)
---
migration.c | 32 ++++++++++++++++----------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/migration.c b/migration.c
index 62a7f8e..71c6c10 100644
--- a/migration.c
+++ b/migration.c
@@ -514,7 +514,7 @@ int64_t migrate_xbzrle_cache_size(void)
/* migration thread support */
-static int buffered_put_buffer(void *opaque, const uint8_t *buf,
+static int migration_put_buffer(void *opaque, const uint8_t *buf,
int64_t pos, int size)
{
MigrationState *s = opaque;
@@ -551,7 +551,7 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf,
return sent;
}
-static int buffered_close(void *opaque)
+static int migration_close(void *opaque)
{
MigrationState *s = opaque;
@@ -565,7 +565,7 @@ static int buffered_close(void *opaque)
return migrate_fd_close(s);
}
-static int buffered_get_fd(void *opaque)
+static int migration_get_fd(void *opaque)
{
MigrationState *s = opaque;
@@ -578,7 +578,7 @@ static int buffered_get_fd(void *opaque)
* 1: Time to stop
* negative: There has been an error
*/
-static int buffered_rate_limit(void *opaque)
+static int migration_rate_limit(void *opaque)
{
MigrationState *s = opaque;
int ret;
@@ -595,7 +595,7 @@ static int buffered_rate_limit(void *opaque)
return 0;
}
-static int64_t buffered_set_rate_limit(void *opaque, int64_t new_rate)
+static int64_t migration_set_rate_limit(void *opaque, int64_t new_rate)
{
MigrationState *s = opaque;
if (qemu_file_get_error(s->file)) {
@@ -611,14 +611,14 @@ out:
return s->xfer_limit;
}
-static int64_t buffered_get_rate_limit(void *opaque)
+static int64_t migration_get_rate_limit(void *opaque)
{
MigrationState *s = opaque;
return s->xfer_limit;
}
-static void *buffered_file_thread(void *opaque)
+static void *migration_thread(void *opaque)
{
MigrationState *s = opaque;
int64_t initial_time = qemu_get_clock_ms(rt_clock);
@@ -705,13 +705,13 @@ static void *buffered_file_thread(void *opaque)
return NULL;
}
-static const QEMUFileOps buffered_file_ops = {
- .get_fd = buffered_get_fd,
- .put_buffer = buffered_put_buffer,
- .close = buffered_close,
- .rate_limit = buffered_rate_limit,
- .get_rate_limit = buffered_get_rate_limit,
- .set_rate_limit = buffered_set_rate_limit,
+static const QEMUFileOps migration_file_ops = {
+ .get_fd = migration_get_fd,
+ .put_buffer = migration_put_buffer,
+ .close = migration_close,
+ .rate_limit = migration_rate_limit,
+ .get_rate_limit = migration_get_rate_limit,
+ .set_rate_limit = migration_set_rate_limit,
};
void migrate_fd_connect(MigrationState *s)
@@ -726,9 +726,9 @@ void migrate_fd_connect(MigrationState *s)
s->xfer_limit = s->bandwidth_limit / XFER_LIMIT_RATIO;
s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s);
- s->file = qemu_fopen_ops(s, &buffered_file_ops);
+ s->file = qemu_fopen_ops(s, &migration_file_ops);
- qemu_thread_create(&s->thread, buffered_file_thread, s,
+ qemu_thread_create(&s->thread, migration_thread, s,
QEMU_THREAD_JOINABLE);
notifier_list_notify(&migration_state_notifiers, s);
}

View File

@ -1,58 +0,0 @@
From d1e45898016eb902411abe5c5b377a490e2b03b2 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:31 +0100
Subject: [PATCH] qemu-file: make qemu_fflush and qemu_file_set_error private
again
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 05f28b837c6bd6124abab2496ce15c07a334a5ad)
---
include/migration/qemu-file.h | 2 --
savevm.c | 4 ++--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
index 5e0c287..46fc11d 100644
--- a/include/migration/qemu-file.h
+++ b/include/migration/qemu-file.h
@@ -82,7 +82,6 @@ QEMUFile *qemu_popen_cmd(const char *command, const char *mode);
int qemu_get_fd(QEMUFile *f);
int qemu_fclose(QEMUFile *f);
int64_t qemu_ftell(QEMUFile *f);
-void qemu_fflush(QEMUFile *f);
void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size);
void qemu_put_byte(QEMUFile *f, int v);
@@ -114,7 +113,6 @@ int qemu_file_rate_limit(QEMUFile *f);
int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate);
int64_t qemu_file_get_rate_limit(QEMUFile *f);
int qemu_file_get_error(QEMUFile *f);
-void qemu_file_set_error(QEMUFile *f, int ret);
static inline void qemu_put_be64s(QEMUFile *f, const uint64_t *pv)
{
diff --git a/savevm.c b/savevm.c
index ce10295..fef2ab9 100644
--- a/savevm.c
+++ b/savevm.c
@@ -443,7 +443,7 @@ int qemu_file_get_error(QEMUFile *f)
return f->last_error;
}
-void qemu_file_set_error(QEMUFile *f, int ret)
+static void qemu_file_set_error(QEMUFile *f, int ret)
{
if (f->last_error == 0) {
f->last_error = ret;
@@ -453,7 +453,7 @@ void qemu_file_set_error(QEMUFile *f, int ret)
/** Flushes QEMUFile buffer
*
*/
-void qemu_fflush(QEMUFile *f)
+static void qemu_fflush(QEMUFile *f)
{
int ret = 0;

View File

@ -1,67 +0,0 @@
From cc3b3656b4fcca8dcdfe6d174615333d7486ce69 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:32 +0100
Subject: [PATCH] migration: eliminate last_round
We will go around the loop exactly once after setting last_round.
Eliminate the variable altogether.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 059f896cefb2776181e39d9ba69345bd9d07d52b)
---
migration.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/migration.c b/migration.c
index 71c6c10..a888f36 100644
--- a/migration.c
+++ b/migration.c
@@ -626,7 +626,6 @@ static void *migration_thread(void *opaque)
int64_t max_size = 0;
int64_t start_time = initial_time;
bool old_vm_running = false;
- bool last_round = false;
DPRINTF("beginning savevm\n");
qemu_savevm_state_begin(s->file, &s->params);
@@ -650,8 +649,11 @@ static void *migration_thread(void *opaque)
vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
s->xfer_limit = INT_MAX;
qemu_savevm_state_complete(s->file);
- last_round = true;
qemu_mutex_unlock_iothread();
+ if (!qemu_file_get_error(s->file)) {
+ migrate_finish_set_state(s, MIG_STATE_COMPLETED);
+ break;
+ }
}
}
@@ -675,15 +677,13 @@ static void *migration_thread(void *opaque)
sleep_time = 0;
initial_time = current_time;
}
- if (!last_round && (s->bytes_xfer >= s->xfer_limit)) {
+ if (s->bytes_xfer >= s->xfer_limit) {
/* usleep expects microseconds */
g_usleep((initial_time + BUFFER_DELAY - current_time)*1000);
sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
}
if (qemu_file_get_error(s->file)) {
migrate_finish_set_state(s, MIG_STATE_ERROR);
- } else if (last_round) {
- migrate_finish_set_state(s, MIG_STATE_COMPLETED);
}
}
@@ -695,7 +695,6 @@ static void *migration_thread(void *opaque)
runstate_set(RUN_STATE_POSTMIGRATE);
} else {
if (old_vm_running) {
- assert(last_round);
vm_start();
}
}

View File

@ -1,39 +0,0 @@
From 409d6af88505169acec3bf3ae005eba79a981688 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:33 +0100
Subject: [PATCH] migration: detect error before sleeping
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit fd45ee2c643bb3d55de5c54b50c23859ca631a9f)
---
migration.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/migration.c b/migration.c
index a888f36..35c3455 100644
--- a/migration.c
+++ b/migration.c
@@ -657,6 +657,10 @@ static void *migration_thread(void *opaque)
}
}
+ if (qemu_file_get_error(s->file)) {
+ migrate_finish_set_state(s, MIG_STATE_ERROR);
+ break;
+ }
current_time = qemu_get_clock_ms(rt_clock);
if (current_time >= initial_time + BUFFER_DELAY) {
uint64_t transferred_bytes = s->bytes_xfer;
@@ -682,9 +686,6 @@ static void *migration_thread(void *opaque)
g_usleep((initial_time + BUFFER_DELAY - current_time)*1000);
sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
}
- if (qemu_file_get_error(s->file)) {
- migrate_finish_set_state(s, MIG_STATE_ERROR);
- }
}
qemu_mutex_lock_iothread();

View File

@ -1,33 +0,0 @@
From 8469b1f717180ae0ca4e764afcbaa61c931ab8d4 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:34 +0100
Subject: [PATCH] migration: remove useless qemu_file_get_error check
migration_put_buffer is never called if there has been an error.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit db2f25309af1af0f27e0ddec4acc3b66837fa668)
---
migration.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/migration.c b/migration.c
index 35c3455..d75beca 100644
--- a/migration.c
+++ b/migration.c
@@ -523,12 +523,6 @@ static int migration_put_buffer(void *opaque, const uint8_t *buf,
DPRINTF("putting %d bytes at %" PRId64 "\n", size, pos);
- ret = qemu_file_get_error(s->file);
- if (ret) {
- DPRINTF("flush when error, bailing: %s\n", strerror(-ret));
- return ret;
- }
-
if (size <= 0) {
return size;
}

View File

@ -1,36 +0,0 @@
From 59df9d30f0f54158975a3d3642a1d655b177cdfe Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:35 +0100
Subject: [PATCH] migration: use qemu_file_rate_limit consistently
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit a0ff044b8ea81908cd8fe5819ce33780f53f58ee)
---
migration.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/migration.c b/migration.c
index d75beca..ae2c83c 100644
--- a/migration.c
+++ b/migration.c
@@ -628,7 +628,7 @@ static void *migration_thread(void *opaque)
int64_t current_time;
uint64_t pending_size;
- if (s->bytes_xfer < s->xfer_limit) {
+ if (!qemu_file_rate_limit(s->file)) {
DPRINTF("iterate\n");
pending_size = qemu_savevm_state_pending(s->file, max_size);
DPRINTF("pending size %lu max %lu\n", pending_size, max_size);
@@ -675,7 +675,7 @@ static void *migration_thread(void *opaque)
sleep_time = 0;
initial_time = current_time;
}
- if (s->bytes_xfer >= s->xfer_limit) {
+ if (qemu_file_rate_limit(s->file)) {
/* usleep expects microseconds */
g_usleep((initial_time + BUFFER_DELAY - current_time)*1000);
sleep_time += qemu_get_clock_ms(rt_clock) - current_time;

View File

@ -1,103 +0,0 @@
From 4f88dd44aa288f1ded954850a9a222f4ecdf00b8 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:36 +0100
Subject: [PATCH] migration: merge qemu_popen_cmd with qemu_popen
There is no reason for outgoing exec migration to do popen manually
anymore (the reason used to be that we needed the FILE* to make it
non-blocking). Use qemu_popen_cmd.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 817b9ed5eb300dbb434d752da416441028539a96)
---
include/migration/qemu-file.h | 1 -
migration-exec.c | 10 ++++------
savevm.c | 22 ++++++++--------------
3 files changed, 12 insertions(+), 21 deletions(-)
diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
index 46fc11d..987e719 100644
--- a/include/migration/qemu-file.h
+++ b/include/migration/qemu-file.h
@@ -77,7 +77,6 @@ QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops);
QEMUFile *qemu_fopen(const char *filename, const char *mode);
QEMUFile *qemu_fdopen(int fd, const char *mode);
QEMUFile *qemu_fopen_socket(int fd);
-QEMUFile *qemu_popen(FILE *popen_file, const char *mode);
QEMUFile *qemu_popen_cmd(const char *command, const char *mode);
int qemu_get_fd(QEMUFile *f);
int qemu_fclose(QEMUFile *f);
diff --git a/migration-exec.c b/migration-exec.c
index a051a6e..5dc7313 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -59,19 +59,17 @@ static int exec_close(MigrationState *s)
void exec_start_outgoing_migration(MigrationState *s, const char *command, Error **errp)
{
- FILE *f;
-
- f = popen(command, "w");
+ QEMUFile *f;
+ f = qemu_popen_cmd(command, "w");
if (f == NULL) {
error_setg_errno(errp, errno, "failed to popen the migration target");
return;
}
- s->fd = fileno(f);
+ s->opaque = f;
+ s->fd = qemu_get_fd(f);
assert(s->fd != -1);
- s->opaque = qemu_popen(f, "w");
-
s->close = exec_close;
s->get_error = file_errno;
s->write = file_write;
diff --git a/savevm.c b/savevm.c
index fef2ab9..38699de 100644
--- a/savevm.c
+++ b/savevm.c
@@ -275,11 +275,17 @@ static const QEMUFileOps stdio_pipe_write_ops = {
.close = stdio_pclose
};
-QEMUFile *qemu_popen(FILE *stdio_file, const char *mode)
+QEMUFile *qemu_popen_cmd(const char *command, const char *mode)
{
+ FILE *stdio_file;
QEMUFileStdio *s;
- if (stdio_file == NULL || mode == NULL || (mode[0] != 'r' && mode[0] != 'w') || mode[1] != 0) {
+ stdio_file = popen(command, mode);
+ if (stdio_file == NULL) {
+ return NULL;
+ }
+
+ if (mode == NULL || (mode[0] != 'r' && mode[0] != 'w') || mode[1] != 0) {
fprintf(stderr, "qemu_popen: Argument validity check failed\n");
return NULL;
}
@@ -296,18 +302,6 @@ QEMUFile *qemu_popen(FILE *stdio_file, const char *mode)
return s->file;
}
-QEMUFile *qemu_popen_cmd(const char *command, const char *mode)
-{
- FILE *popen_file;
-
- popen_file = popen(command, mode);
- if(popen_file == NULL) {
- return NULL;
- }
-
- return qemu_popen(popen_file, mode);
-}
-
static const QEMUFileOps stdio_file_read_ops = {
.get_fd = stdio_get_fd,
.get_buffer = stdio_get_buffer,

View File

@ -1,45 +0,0 @@
From 701731a81e40d7321f619020b9062a5d88f7466a Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:37 +0100
Subject: [PATCH] qemu-file: fsync a writable stdio QEMUFile
This is what fd_close does. Prepare for switching to a QEMUFile.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit ce39ee3184a02eca7f9529cc19b1582f6f704c70)
---
savevm.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/savevm.c b/savevm.c
index 38699de..1d49fde 100644
--- a/savevm.c
+++ b/savevm.c
@@ -256,6 +256,24 @@ static int stdio_fclose(void *opaque)
{
QEMUFileStdio *s = opaque;
int ret = 0;
+
+ if (s->file->ops->put_buffer) {
+ int fd = fileno(s->stdio_file);
+ struct stat st;
+
+ ret = fstat(fd, &st);
+ if (ret == 0 && S_ISREG(st.st_mode)) {
+ /*
+ * If the file handle is a regular file make sure the
+ * data is flushed to disk before signaling success.
+ */
+ ret = fsync(fd);
+ if (ret != 0) {
+ ret = -errno;
+ return ret;
+ }
+ }
+ }
if (fclose(s->stdio_file) == EOF) {
ret = -errno;
}

View File

@ -1,65 +0,0 @@
From ba58f61422bff38da15331a092adfd2cfaadc8d5 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:38 +0100
Subject: [PATCH] qemu-file: check exit status when closing a pipe QEMUFile
This is what exec_close does. Move this to the underlying QEMUFile.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 13c7b2da073ec83cb47f9582149c8d28bb038e73)
---
include/qemu/osdep.h | 7 +++++++
migration-exec.c | 4 ----
savevm.c | 3 +++
3 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index 87d3b9c..df24400 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -9,6 +9,13 @@
#include <sys/signal.h>
#endif
+#ifndef _WIN32
+#include <sys/wait.h>
+#else
+#define WIFEXITED(x) 1
+#define WEXITSTATUS(x) (x)
+#endif
+
#include <sys/time.h>
#if defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10
diff --git a/migration-exec.c b/migration-exec.c
index 5dc7313..a2b5f8d 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -50,10 +50,6 @@ static int exec_close(MigrationState *s)
ret = qemu_fclose(s->opaque);
s->opaque = NULL;
s->fd = -1;
- if (ret >= 0 && !(WIFEXITED(ret) && WEXITSTATUS(ret) == 0)) {
- /* close succeeded, but non-zero exit code: */
- ret = -EIO; /* fake errno value */
- }
return ret;
}
diff --git a/savevm.c b/savevm.c
index 1d49fde..6d6f1f1 100644
--- a/savevm.c
+++ b/savevm.c
@@ -247,6 +247,9 @@ static int stdio_pclose(void *opaque)
ret = pclose(s->stdio_file);
if (ret == -1) {
ret = -errno;
+ } else if (!WIFEXITED(ret) || WEXITSTATUS(ret) != 0) {
+ /* close succeeded, but non-zero exit code: */
+ ret = -EIO; /* fake errno value */
}
g_free(s);
return ret;

View File

@ -1,111 +0,0 @@
From b38aa57a296bd4fdc31a9ebf3f28ffb612ad6e32 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:39 +0100
Subject: [PATCH] qemu-file: add writable socket QEMUFile
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 0cc3f3ccc9d29acc94b995430518bda1c7c01bef)
---
include/migration/qemu-file.h | 2 +-
migration-tcp.c | 2 +-
migration-unix.c | 2 +-
savevm.c | 33 +++++++++++++++++++++++++++++++--
4 files changed, 34 insertions(+), 5 deletions(-)
diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
index 987e719..25e8461 100644
--- a/include/migration/qemu-file.h
+++ b/include/migration/qemu-file.h
@@ -76,7 +76,7 @@ typedef struct QEMUFileOps {
QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops);
QEMUFile *qemu_fopen(const char *filename, const char *mode);
QEMUFile *qemu_fdopen(int fd, const char *mode);
-QEMUFile *qemu_fopen_socket(int fd);
+QEMUFile *qemu_fopen_socket(int fd, const char *mode);
QEMUFile *qemu_popen_cmd(const char *command, const char *mode);
int qemu_get_fd(QEMUFile *f);
int qemu_fclose(QEMUFile *f);
diff --git a/migration-tcp.c b/migration-tcp.c
index 59e3b7e..a748195 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -95,7 +95,7 @@ static void tcp_accept_incoming_migration(void *opaque)
goto out;
}
- f = qemu_fopen_socket(c);
+ f = qemu_fopen_socket(c, "rb");
if (f == NULL) {
fprintf(stderr, "could not qemu_fopen socket\n");
goto out;
diff --git a/migration-unix.c b/migration-unix.c
index 0ca2a21..d078f43 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -95,7 +95,7 @@ static void unix_accept_incoming_migration(void *opaque)
goto out;
}
- f = qemu_fopen_socket(c);
+ f = qemu_fopen_socket(c, "rb");
if (f == NULL) {
fprintf(stderr, "could not qemu_fopen socket\n");
goto out;
diff --git a/savevm.c b/savevm.c
index 6d6f1f1..76c88c7 100644
--- a/savevm.c
+++ b/savevm.c
@@ -198,6 +198,18 @@ static int socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
return len;
}
+static int socket_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size)
+{
+ QEMUFileSocket *s = opaque;
+ ssize_t len;
+
+ len = qemu_send_full(s->fd, buf, size, 0);
+ if (len < size) {
+ len = -socket_error();
+ }
+ return len;
+}
+
static int socket_close(void *opaque)
{
QEMUFileSocket *s = opaque;
@@ -369,12 +381,29 @@ static const QEMUFileOps socket_read_ops = {
.close = socket_close
};
-QEMUFile *qemu_fopen_socket(int fd)
+static const QEMUFileOps socket_write_ops = {
+ .get_fd = socket_get_fd,
+ .put_buffer = socket_put_buffer,
+ .close = socket_close
+};
+
+QEMUFile *qemu_fopen_socket(int fd, const char *mode)
{
QEMUFileSocket *s = g_malloc0(sizeof(QEMUFileSocket));
+ if (mode == NULL ||
+ (mode[0] != 'r' && mode[0] != 'w') ||
+ mode[1] != 'b' || mode[2] != 0) {
+ fprintf(stderr, "qemu_fopen: Argument validity check failed\n");
+ return NULL;
+ }
+
s->fd = fd;
- s->file = qemu_fopen_ops(s, &socket_read_ops);
+ if (mode[0] == 'w') {
+ s->file = qemu_fopen_ops(s, &socket_write_ops);
+ } else {
+ s->file = qemu_fopen_ops(s, &socket_read_ops);
+ }
return s->file;
}

View File

@ -1,73 +0,0 @@
From 6afaa318d59f4532dd9a6682704bfbfef280c86e Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:40 +0100
Subject: [PATCH] qemu-file: simplify and export qemu_ftell
Force a flush when qemu_ftell is called. This simplifies the buffer magic
(it also breaks qemu_ftell for input QEMUFiles, but we never use it).
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 3f2d38faab97f4d676c41868a8243997b2aab7cb)
---
savevm.c | 20 ++++++++------------
1 file changed, 8 insertions(+), 12 deletions(-)
diff --git a/savevm.c b/savevm.c
index 76c88c7..c60ace3 100644
--- a/savevm.c
+++ b/savevm.c
@@ -119,8 +119,8 @@ struct QEMUFile {
void *opaque;
int is_write;
- int64_t buf_offset; /* start of buffer when writing, end of buffer
- when reading */
+ int64_t pos; /* start of buffer when writing, end of buffer
+ when reading */
int buf_index;
int buf_size; /* 0 when writing */
uint8_t buf[IO_BUF_SIZE];
@@ -505,9 +505,9 @@ static void qemu_fflush(QEMUFile *f)
return;
}
if (f->is_write && f->buf_index > 0) {
- ret = f->ops->put_buffer(f->opaque, f->buf, f->buf_offset, f->buf_index);
+ ret = f->ops->put_buffer(f->opaque, f->buf, f->pos, f->buf_index);
if (ret >= 0) {
- f->buf_offset += f->buf_index;
+ f->pos += f->buf_index;
}
f->buf_index = 0;
}
@@ -534,11 +534,11 @@ static void qemu_fill_buffer(QEMUFile *f)
f->buf_index = 0;
f->buf_size = pending;
- len = f->ops->get_buffer(f->opaque, f->buf + pending, f->buf_offset,
+ len = f->ops->get_buffer(f->opaque, f->buf + pending, f->pos,
IO_BUF_SIZE - pending);
if (len > 0) {
f->buf_size += len;
- f->buf_offset += len;
+ f->pos += len;
} else if (len == 0) {
qemu_file_set_error(f, -EIO);
} else if (len != -EAGAIN)
@@ -718,12 +718,8 @@ int qemu_get_byte(QEMUFile *f)
int64_t qemu_ftell(QEMUFile *f)
{
- /* buf_offset excludes buffer for writing but includes it for reading */
- if (f->is_write) {
- return f->buf_offset + f->buf_index;
- } else {
- return f->buf_offset - f->buf_size + f->buf_index;
- }
+ qemu_fflush(f);
+ return f->pos;
}
int qemu_file_rate_limit(QEMUFile *f)

View File

@ -1,280 +0,0 @@
From 163a01830d0dbdb57f332915ebe298f86be84cb0 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:41 +0100
Subject: [PATCH] migration: use QEMUFile for migration channel lifetime
As a start, use QEMUFile to store the destination and close it.
qemu_get_fd gets a file descriptor that will be used by the write
callbacks.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit f8bbc1286337a8506162b5785babe6f2a7de2476)
Conflicts:
migration-tcp.c
migration-unix.c
savevm.c
---
include/migration/migration.h | 7 ++++---
migration-exec.c | 21 ++-------------------
migration-fd.c | 35 +++--------------------------------
migration-tcp.c | 19 +++----------------
migration-unix.c | 19 +++----------------
migration.c | 8 +++++---
savevm.c | 1 +
7 files changed, 21 insertions(+), 89 deletions(-)
diff --git a/include/migration/migration.h b/include/migration/migration.h
index cec8643..1f8f305 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -38,12 +38,13 @@ struct MigrationState
QEMUBH *cleanup_bh;
QEMUFile *file;
+ QEMUFile *migration_file;
+
int fd;
- int state;
int (*get_error)(MigrationState *s);
- int (*close)(MigrationState *s);
int (*write)(MigrationState *s, const void *buff, size_t size);
- void *opaque;
+
+ int state;
MigrationParams params;
int64_t total_time;
int64_t downtime;
diff --git a/migration-exec.c b/migration-exec.c
index a2b5f8d..8c3f720 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -43,33 +43,16 @@ static int file_write(MigrationState *s, const void * buf, size_t size)
return write(s->fd, buf, size);
}
-static int exec_close(MigrationState *s)
-{
- int ret = 0;
- DPRINTF("exec_close\n");
- ret = qemu_fclose(s->opaque);
- s->opaque = NULL;
- s->fd = -1;
- return ret;
-}
-
void exec_start_outgoing_migration(MigrationState *s, const char *command, Error **errp)
{
- QEMUFile *f;
- f = qemu_popen_cmd(command, "w");
- if (f == NULL) {
+ s->migration_file = qemu_popen_cmd(command, "w");
+ if (s->migration_file == NULL) {
error_setg_errno(errp, errno, "failed to popen the migration target");
return;
}
- s->opaque = f;
- s->fd = qemu_get_fd(f);
- assert(s->fd != -1);
-
- s->close = exec_close;
s->get_error = file_errno;
s->write = file_write;
-
migrate_fd_connect(s);
}
diff --git a/migration-fd.c b/migration-fd.c
index a99e0e3..4636457 100644
--- a/migration-fd.c
+++ b/migration-fd.c
@@ -40,45 +40,16 @@ static int fd_write(MigrationState *s, const void * buf, size_t size)
return write(s->fd, buf, size);
}
-static int fd_close(MigrationState *s)
-{
- struct stat st;
- int ret;
-
- DPRINTF("fd_close\n");
- ret = fstat(s->fd, &st);
- if (ret == 0 && S_ISREG(st.st_mode)) {
- /*
- * If the file handle is a regular file make sure the
- * data is flushed to disk before signaling success.
- */
- ret = fsync(s->fd);
- if (ret != 0) {
- ret = -errno;
- perror("migration-fd: fsync");
- return ret;
- }
- }
- ret = close(s->fd);
- s->fd = -1;
- if (ret != 0) {
- ret = -errno;
- perror("migration-fd: close");
- }
- return ret;
-}
-
void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **errp)
{
- s->fd = monitor_get_fd(cur_mon, fdname, errp);
- if (s->fd == -1) {
+ int fd = monitor_get_fd(cur_mon, fdname, errp);
+ if (fd == -1) {
return;
}
+ s->migration_file = qemu_fdopen(fd, "wb");
s->get_error = fd_errno;
s->write = fd_write;
- s->close = fd_close;
-
migrate_fd_connect(s);
}
diff --git a/migration-tcp.c b/migration-tcp.c
index a748195..1e8e004 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -39,28 +39,17 @@ static int socket_write(MigrationState *s, const void * buf, size_t size)
return send(s->fd, buf, size, 0);
}
-static int tcp_close(MigrationState *s)
-{
- int r = 0;
- DPRINTF("tcp_close\n");
- if (closesocket(s->fd) < 0) {
- r = -socket_error();
- }
- return r;
-}
-
static void tcp_wait_for_connect(int fd, void *opaque)
{
MigrationState *s = opaque;
if (fd < 0) {
DPRINTF("migrate connect error\n");
- s->fd = -1;
+ s->migration_file = NULL;
migrate_fd_error(s);
} else {
DPRINTF("migrate connect success\n");
- s->fd = fd;
- qemu_set_block(s->fd);
+ s->migration_file = qemu_fopen_socket(fd, "wb");
migrate_fd_connect(s);
}
}
@@ -69,9 +58,7 @@ void tcp_start_outgoing_migration(MigrationState *s, const char *host_port, Erro
{
s->get_error = socket_errno;
s->write = socket_write;
- s->close = tcp_close;
-
- s->fd = inet_nonblocking_connect(host_port, tcp_wait_for_connect, s, errp);
+ inet_nonblocking_connect(host_port, tcp_wait_for_connect, s, errp);
}
static void tcp_accept_incoming_migration(void *opaque)
diff --git a/migration-unix.c b/migration-unix.c
index d078f43..11917f4 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -39,28 +39,17 @@ static int unix_write(MigrationState *s, const void * buf, size_t size)
return write(s->fd, buf, size);
}
-static int unix_close(MigrationState *s)
-{
- int r = 0;
- DPRINTF("unix_close\n");
- if (close(s->fd) < 0) {
- r = -errno;
- }
- return r;
-}
-
static void unix_wait_for_connect(int fd, void *opaque)
{
MigrationState *s = opaque;
if (fd < 0) {
DPRINTF("migrate connect error\n");
- s->fd = -1;
+ s->migration_file = NULL;
migrate_fd_error(s);
} else {
DPRINTF("migrate connect success\n");
- s->fd = fd;
- qemu_set_block(s->fd);
+ s->migration_file = qemu_fopen_socket(fd, "wb");
migrate_fd_connect(s);
}
}
@@ -69,9 +58,7 @@ void unix_start_outgoing_migration(MigrationState *s, const char *path, Error **
{
s->get_error = unix_errno;
s->write = unix_write;
- s->close = unix_close;
-
- s->fd = unix_nonblocking_connect(path, unix_wait_for_connect, s, errp);
+ unix_nonblocking_connect(path, unix_wait_for_connect, s, errp);
}
static void unix_accept_incoming_migration(void *opaque)
diff --git a/migration.c b/migration.c
index ae2c83c..fa630ed 100644
--- a/migration.c
+++ b/migration.c
@@ -274,7 +274,7 @@ static void migrate_fd_cleanup(void *opaque)
s->file = NULL;
}
- assert(s->fd == -1);
+ assert(s->migration_file == NULL);
assert(s->state != MIG_STATE_ACTIVE);
if (s->state != MIG_STATE_COMPLETED) {
@@ -330,8 +330,9 @@ static void migrate_fd_cancel(MigrationState *s)
int migrate_fd_close(MigrationState *s)
{
int rc = 0;
- if (s->fd != -1) {
- rc = s->close(s);
+ if (s->migration_file != NULL) {
+ rc = qemu_fclose(s->migration_file);
+ s->migration_file = NULL;
s->fd = -1;
}
return rc;
@@ -720,6 +721,7 @@ void migrate_fd_connect(MigrationState *s)
s->xfer_limit = s->bandwidth_limit / XFER_LIMIT_RATIO;
s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s);
+ s->fd = qemu_get_fd(s->migration_file);
s->file = qemu_fopen_ops(s, &migration_file_ops);
qemu_thread_create(&s->thread, migration_thread, s,
diff --git a/savevm.c b/savevm.c
index c60ace3..43963ce 100644
--- a/savevm.c
+++ b/savevm.c
@@ -400,6 +400,7 @@ QEMUFile *qemu_fopen_socket(int fd, const char *mode)
s->fd = fd;
if (mode[0] == 'w') {
+ qemu_set_block(s->fd);
s->file = qemu_fopen_ops(s, &socket_write_ops);
} else {
s->file = qemu_fopen_ops(s, &socket_read_ops);

View File

@ -1,251 +0,0 @@
From e15601079ef83c1fed53fb82d938bb2e4d6104ca Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:42 +0100
Subject: [PATCH] migration: use QEMUFile for writing outgoing migration data
Second, drop the file descriptor indirection, and write directly to the
QEMUFile.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit e6a1cf21328802f3a83e84e893b8cb8a468141cc)
---
include/migration/migration.h | 4 ----
migration-exec.c | 12 -----------
migration-fd.c | 12 -----------
migration-tcp.c | 12 -----------
migration-unix.c | 12 -----------
migration.c | 46 ++++++++-----------------------------------
6 files changed, 8 insertions(+), 90 deletions(-)
diff --git a/include/migration/migration.h b/include/migration/migration.h
index 1f8f305..ae94706 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -40,10 +40,6 @@ struct MigrationState
QEMUFile *file;
QEMUFile *migration_file;
- int fd;
- int (*get_error)(MigrationState *s);
- int (*write)(MigrationState *s, const void *buff, size_t size);
-
int state;
MigrationParams params;
int64_t total_time;
diff --git a/migration-exec.c b/migration-exec.c
index 8c3f720..1c539de 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -33,16 +33,6 @@
do { } while (0)
#endif
-static int file_errno(MigrationState *s)
-{
- return errno;
-}
-
-static int file_write(MigrationState *s, const void * buf, size_t size)
-{
- return write(s->fd, buf, size);
-}
-
void exec_start_outgoing_migration(MigrationState *s, const char *command, Error **errp)
{
s->migration_file = qemu_popen_cmd(command, "w");
@@ -51,8 +41,6 @@ void exec_start_outgoing_migration(MigrationState *s, const char *command, Error
return;
}
- s->get_error = file_errno;
- s->write = file_write;
migrate_fd_connect(s);
}
diff --git a/migration-fd.c b/migration-fd.c
index 4636457..07c758a 100644
--- a/migration-fd.c
+++ b/migration-fd.c
@@ -30,16 +30,6 @@
do { } while (0)
#endif
-static int fd_errno(MigrationState *s)
-{
- return errno;
-}
-
-static int fd_write(MigrationState *s, const void * buf, size_t size)
-{
- return write(s->fd, buf, size);
-}
-
void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **errp)
{
int fd = monitor_get_fd(cur_mon, fdname, errp);
@@ -48,8 +38,6 @@ void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **
}
s->migration_file = qemu_fdopen(fd, "wb");
- s->get_error = fd_errno;
- s->write = fd_write;
migrate_fd_connect(s);
}
diff --git a/migration-tcp.c b/migration-tcp.c
index 1e8e004..5ea4f3d 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -29,16 +29,6 @@
do { } while (0)
#endif
-static int socket_errno(MigrationState *s)
-{
- return socket_error();
-}
-
-static int socket_write(MigrationState *s, const void * buf, size_t size)
-{
- return send(s->fd, buf, size, 0);
-}
-
static void tcp_wait_for_connect(int fd, void *opaque)
{
MigrationState *s = opaque;
@@ -56,8 +46,6 @@ static void tcp_wait_for_connect(int fd, void *opaque)
void tcp_start_outgoing_migration(MigrationState *s, const char *host_port, Error **errp)
{
- s->get_error = socket_errno;
- s->write = socket_write;
inet_nonblocking_connect(host_port, tcp_wait_for_connect, s, errp);
}
diff --git a/migration-unix.c b/migration-unix.c
index 11917f4..64bfa31 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -29,16 +29,6 @@
do { } while (0)
#endif
-static int unix_errno(MigrationState *s)
-{
- return errno;
-}
-
-static int unix_write(MigrationState *s, const void * buf, size_t size)
-{
- return write(s->fd, buf, size);
-}
-
static void unix_wait_for_connect(int fd, void *opaque)
{
MigrationState *s = opaque;
@@ -56,8 +46,6 @@ static void unix_wait_for_connect(int fd, void *opaque)
void unix_start_outgoing_migration(MigrationState *s, const char *path, Error **errp)
{
- s->get_error = unix_errno;
- s->write = unix_write;
unix_nonblocking_connect(path, unix_wait_for_connect, s, errp);
}
diff --git a/migration.c b/migration.c
index fa630ed..26ba6c9 100644
--- a/migration.c
+++ b/migration.c
@@ -301,25 +301,6 @@ void migrate_fd_error(MigrationState *s)
notifier_list_notify(&migration_state_notifiers, s);
}
-static ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data,
- size_t size)
-{
- ssize_t ret;
-
- if (s->state != MIG_STATE_ACTIVE) {
- return -EIO;
- }
-
- do {
- ret = s->write(s, data, size);
- } while (ret == -1 && ((s->get_error(s)) == EINTR));
-
- if (ret == -1)
- ret = -(s->get_error(s));
-
- return ret;
-}
-
static void migrate_fd_cancel(MigrationState *s)
{
DPRINTF("cancelling migration\n");
@@ -333,7 +314,6 @@ int migrate_fd_close(MigrationState *s)
if (s->migration_file != NULL) {
rc = qemu_fclose(s->migration_file);
s->migration_file = NULL;
- s->fd = -1;
}
return rc;
}
@@ -519,8 +499,7 @@ static int migration_put_buffer(void *opaque, const uint8_t *buf,
int64_t pos, int size)
{
MigrationState *s = opaque;
- ssize_t ret;
- size_t sent;
+ int ret;
DPRINTF("putting %d bytes at %" PRId64 "\n", size, pos);
@@ -528,22 +507,14 @@ static int migration_put_buffer(void *opaque, const uint8_t *buf,
return size;
}
- sent = 0;
- while (size) {
- ret = migrate_fd_put_buffer(s, buf, size);
- if (ret <= 0) {
- DPRINTF("error flushing data, %zd\n", ret);
- return ret;
- } else {
- DPRINTF("flushed %zd byte(s)\n", ret);
- sent += ret;
- buf += ret;
- size -= ret;
- s->bytes_xfer += ret;
- }
+ qemu_put_buffer(s->migration_file, buf, size);
+ ret = qemu_file_get_error(s->migration_file);
+ if (ret) {
+ return ret;
}
- return sent;
+ s->bytes_xfer += size;
+ return size;
}
static int migration_close(void *opaque)
@@ -564,7 +535,7 @@ static int migration_get_fd(void *opaque)
{
MigrationState *s = opaque;
- return s->fd;
+ return qemu_get_fd(s->migration_file);
}
/*
@@ -721,7 +692,6 @@ void migrate_fd_connect(MigrationState *s)
s->xfer_limit = s->bandwidth_limit / XFER_LIMIT_RATIO;
s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s);
- s->fd = qemu_get_fd(s->migration_file);
s->file = qemu_fopen_ops(s, &migration_file_ops);
qemu_thread_create(&s->thread, migration_thread, s,

View File

@ -1,45 +0,0 @@
From c6c8a4fa26f5aa2f687a779997a2bd040cd01ff4 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:43 +0100
Subject: [PATCH] migration: use qemu_ftell to compute bandwidth
Prepare for when s->bytes_xfer will be removed.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit be7172e22a9c3bc448894e57f6c2d1af6ffd47fd)
---
migration.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/migration.c b/migration.c
index 26ba6c9..def1e9e 100644
--- a/migration.c
+++ b/migration.c
@@ -589,6 +589,7 @@ static void *migration_thread(void *opaque)
MigrationState *s = opaque;
int64_t initial_time = qemu_get_clock_ms(rt_clock);
int64_t sleep_time = 0;
+ int64_t initial_bytes = 0;
int64_t max_size = 0;
int64_t start_time = initial_time;
bool old_vm_running = false;
@@ -629,7 +630,7 @@ static void *migration_thread(void *opaque)
}
current_time = qemu_get_clock_ms(rt_clock);
if (current_time >= initial_time + BUFFER_DELAY) {
- uint64_t transferred_bytes = s->bytes_xfer;
+ uint64_t transferred_bytes = qemu_ftell(s->file) - initial_bytes;
uint64_t time_spent = current_time - initial_time - sleep_time;
double bandwidth = transferred_bytes / time_spent;
max_size = bandwidth * migrate_max_downtime() / 1000000;
@@ -646,6 +647,7 @@ static void *migration_thread(void *opaque)
s->bytes_xfer = 0;
sleep_time = 0;
initial_time = current_time;
+ initial_bytes = qemu_ftell(s->file);
}
if (qemu_file_rate_limit(s->file)) {
/* usleep expects microseconds */

View File

@ -1,78 +0,0 @@
From 6709fac663d343a1f34178da389001d46df3cac9 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:44 +0100
Subject: [PATCH] migration: small changes around rate-limiting
This patch extracts a few small changes from the next patch, which
are unrelated to adding generic rate-limiting functionality to
QEMUFile. Make migration_set_rate_limit a simple accessor, and
use qemu_file_set_rate_limit consistently. Also fix a typo where
INT_MAX should have been SIZE_MAX.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 442773cef15092b5927851237850760345d2cf16)
---
migration.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/migration.c b/migration.c
index def1e9e..5c7d04f 100644
--- a/migration.c
+++ b/migration.c
@@ -462,10 +462,15 @@ void qmp_migrate_set_speed(int64_t value, Error **errp)
if (value < 0) {
value = 0;
}
+ if (value > SIZE_MAX) {
+ value = SIZE_MAX;
+ }
s = migrate_get_current();
s->bandwidth_limit = value;
- qemu_file_set_rate_limit(s->file, s->bandwidth_limit);
+ if (s->file) {
+ qemu_file_set_rate_limit(s->file, s->bandwidth_limit / XFER_LIMIT_RATIO);
+ }
}
void qmp_migrate_set_downtime(double value, Error **errp)
@@ -567,11 +572,8 @@ static int64_t migration_set_rate_limit(void *opaque, int64_t new_rate)
if (qemu_file_get_error(s->file)) {
goto out;
}
- if (new_rate > SIZE_MAX) {
- new_rate = SIZE_MAX;
- }
- s->xfer_limit = new_rate / XFER_LIMIT_RATIO;
+ s->xfer_limit = new_rate;
out:
return s->xfer_limit;
@@ -614,7 +616,7 @@ static void *migration_thread(void *opaque)
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
old_vm_running = runstate_is_running();
vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
- s->xfer_limit = INT_MAX;
+ qemu_file_set_rate_limit(s->file, INT_MAX);
qemu_savevm_state_complete(s->file);
qemu_mutex_unlock_iothread();
if (!qemu_file_get_error(s->file)) {
@@ -691,11 +693,12 @@ void migrate_fd_connect(MigrationState *s)
/* This is a best 1st approximation. ns to ms */
s->expected_downtime = max_downtime/1000000;
- s->xfer_limit = s->bandwidth_limit / XFER_LIMIT_RATIO;
-
s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s);
s->file = qemu_fopen_ops(s, &migration_file_ops);
+ qemu_file_set_rate_limit(s->file,
+ s->bandwidth_limit / XFER_LIMIT_RATIO);
+
qemu_thread_create(&s->thread, migration_thread, s,
QEMU_THREAD_JOINABLE);
notifier_list_notify(&migration_state_notifiers, s);

View File

@ -1,270 +0,0 @@
From 9324971693642bf648f60b3598a8b588bef000e8 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:45 +0100
Subject: [PATCH] migration: move rate limiting to QEMUFile
Rate limiting is now simply a byte counter; client call
qemu_file_rate_limit() manually to determine if they have to exit.
So it is possible and simple to move the functionality to QEMUFile.
This makes the remaining functionality of s->file redundant;
in the next patch we can remove it and write directly to s->migration_file.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 1964a397063967acc5ce71a2a24ed26e74824ee1)
---
docs/migration.txt | 20 +----------------
include/migration/qemu-file.h | 18 ++-------------
migration.c | 51 +------------------------------------------
savevm.c | 31 ++++++++++++++------------
4 files changed, 21 insertions(+), 99 deletions(-)
diff --git a/docs/migration.txt b/docs/migration.txt
index f3ddd2f..0719a55 100644
--- a/docs/migration.txt
+++ b/docs/migration.txt
@@ -55,10 +55,7 @@ QEMUFile with:
QEMUFile *qemu_fopen_ops(void *opaque,
QEMUFilePutBufferFunc *put_buffer,
QEMUFileGetBufferFunc *get_buffer,
- QEMUFileCloseFunc *close,
- QEMUFileRateLimit *rate_limit,
- QEMUFileSetRateLimit *set_rate_limit,
- QEMUFileGetRateLimit *get_rate_limit);
+ QEMUFileCloseFunc *close);
The functions have the following functionality:
@@ -80,24 +77,9 @@ Close a file and return an error code.
typedef int (QEMUFileCloseFunc)(void *opaque);
-Called to determine if the file has exceeded its bandwidth allocation. The
-bandwidth capping is a soft limit, not a hard limit.
-
-typedef int (QEMUFileRateLimit)(void *opaque);
-
-Called to change the current bandwidth allocation. This function must return
-the new actual bandwidth. It should be new_rate if everything goes OK, and
-the old rate otherwise.
-
-typedef size_t (QEMUFileSetRateLimit)(void *opaque, size_t new_rate);
-typedef size_t (QEMUFileGetRateLimit)(void *opaque);
-
You can use any internal state that you need using the opaque void *
pointer that is passed to all functions.
-The rate limiting functions are used to limit the bandwidth used by
-QEMU migration.
-
The important functions for us are put_buffer()/get_buffer() that
allow to write/read a buffer into the QEMUFile.
diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
index 25e8461..df81261 100644
--- a/include/migration/qemu-file.h
+++ b/include/migration/qemu-file.h
@@ -51,26 +51,11 @@ typedef int (QEMUFileCloseFunc)(void *opaque);
*/
typedef int (QEMUFileGetFD)(void *opaque);
-/* Called to determine if the file has exceeded its bandwidth allocation. The
- * bandwidth capping is a soft limit, not a hard limit.
- */
-typedef int (QEMUFileRateLimit)(void *opaque);
-
-/* Called to change the current bandwidth allocation. This function must return
- * the new actual bandwidth. It should be new_rate if everything goes ok, and
- * the old rate otherwise
- */
-typedef int64_t (QEMUFileSetRateLimit)(void *opaque, int64_t new_rate);
-typedef int64_t (QEMUFileGetRateLimit)(void *opaque);
-
typedef struct QEMUFileOps {
QEMUFilePutBufferFunc *put_buffer;
QEMUFileGetBufferFunc *get_buffer;
QEMUFileCloseFunc *close;
QEMUFileGetFD *get_fd;
- QEMUFileRateLimit *rate_limit;
- QEMUFileSetRateLimit *set_rate_limit;
- QEMUFileGetRateLimit *get_rate_limit;
} QEMUFileOps;
QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops);
@@ -109,7 +94,8 @@ unsigned int qemu_get_be32(QEMUFile *f);
uint64_t qemu_get_be64(QEMUFile *f);
int qemu_file_rate_limit(QEMUFile *f);
-int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate);
+void qemu_file_reset_rate_limit(QEMUFile *f);
+void qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate);
int64_t qemu_file_get_rate_limit(QEMUFile *f);
int qemu_file_get_error(QEMUFile *f);
diff --git a/migration.c b/migration.c
index 5c7d04f..ea84008 100644
--- a/migration.c
+++ b/migration.c
@@ -518,7 +518,6 @@ static int migration_put_buffer(void *opaque, const uint8_t *buf,
return ret;
}
- s->bytes_xfer += size;
return size;
}
@@ -543,49 +542,6 @@ static int migration_get_fd(void *opaque)
return qemu_get_fd(s->migration_file);
}
-/*
- * The meaning of the return values is:
- * 0: We can continue sending
- * 1: Time to stop
- * negative: There has been an error
- */
-static int migration_rate_limit(void *opaque)
-{
- MigrationState *s = opaque;
- int ret;
-
- ret = qemu_file_get_error(s->file);
- if (ret) {
- return ret;
- }
-
- if (s->bytes_xfer >= s->xfer_limit) {
- return 1;
- }
-
- return 0;
-}
-
-static int64_t migration_set_rate_limit(void *opaque, int64_t new_rate)
-{
- MigrationState *s = opaque;
- if (qemu_file_get_error(s->file)) {
- goto out;
- }
-
- s->xfer_limit = new_rate;
-
-out:
- return s->xfer_limit;
-}
-
-static int64_t migration_get_rate_limit(void *opaque)
-{
- MigrationState *s = opaque;
-
- return s->xfer_limit;
-}
-
static void *migration_thread(void *opaque)
{
MigrationState *s = opaque;
@@ -646,7 +602,7 @@ static void *migration_thread(void *opaque)
s->expected_downtime = s->dirty_bytes_rate / bandwidth;
}
- s->bytes_xfer = 0;
+ qemu_file_reset_rate_limit(s->file);
sleep_time = 0;
initial_time = current_time;
initial_bytes = qemu_ftell(s->file);
@@ -679,9 +635,6 @@ static const QEMUFileOps migration_file_ops = {
.get_fd = migration_get_fd,
.put_buffer = migration_put_buffer,
.close = migration_close,
- .rate_limit = migration_rate_limit,
- .get_rate_limit = migration_get_rate_limit,
- .set_rate_limit = migration_set_rate_limit,
};
void migrate_fd_connect(MigrationState *s)
@@ -689,10 +642,8 @@ void migrate_fd_connect(MigrationState *s)
s->state = MIG_STATE_ACTIVE;
trace_migrate_set_state(MIG_STATE_ACTIVE);
- s->bytes_xfer = 0;
/* This is a best 1st approximation. ns to ms */
s->expected_downtime = max_downtime/1000000;
-
s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s);
s->file = qemu_fopen_ops(s, &migration_file_ops);
diff --git a/savevm.c b/savevm.c
index 43963ce..e9471a5 100644
--- a/savevm.c
+++ b/savevm.c
@@ -119,6 +119,9 @@ struct QEMUFile {
void *opaque;
int is_write;
+ int64_t bytes_xfer;
+ int64_t xfer_limit;
+
int64_t pos; /* start of buffer when writing, end of buffer
when reading */
int buf_index;
@@ -479,7 +482,6 @@ QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops)
f->opaque = opaque;
f->ops = ops;
f->is_write = 0;
-
return f;
}
@@ -605,6 +607,7 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
memcpy(f->buf + f->buf_index, buf, l);
f->is_write = 1;
f->buf_index += l;
+ f->bytes_xfer += l;
buf += l;
size -= l;
if (f->buf_index >= IO_BUF_SIZE) {
@@ -725,28 +728,28 @@ int64_t qemu_ftell(QEMUFile *f)
int qemu_file_rate_limit(QEMUFile *f)
{
- if (f->ops->rate_limit)
- return f->ops->rate_limit(f->opaque);
-
+ if (qemu_file_get_error(f)) {
+ return 1;
+ }
+ if (f->xfer_limit > 0 && f->bytes_xfer > f->xfer_limit) {
+ return 1;
+ }
return 0;
}
int64_t qemu_file_get_rate_limit(QEMUFile *f)
{
- if (f->ops->get_rate_limit)
- return f->ops->get_rate_limit(f->opaque);
-
- return 0;
+ return f->xfer_limit;
}
-int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate)
+void qemu_file_set_rate_limit(QEMUFile *f, int64_t limit)
{
- /* any failed or completed migration keeps its state to allow probing of
- * migration data, but has no associated file anymore */
- if (f && f->ops->set_rate_limit)
- return f->ops->set_rate_limit(f->opaque, new_rate);
+ f->xfer_limit = limit;
+}
- return 0;
+void qemu_file_reset_rate_limit(QEMUFile *f)
+{
+ f->bytes_xfer = 0;
}
void qemu_put_be16(QEMUFile *f, unsigned int v)

View File

@ -1,52 +0,0 @@
From 2b2c8310a60981dfe3bb37cdd007016f285d1b8a Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:46 +0100
Subject: [PATCH] migration: move contents of migration_close to
migrate_fd_cleanup
With this patch, the migration_file is not needed anymore.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 404a7c05bcc20c51fe1a9bf2deaeb4d6b658d3a3)
---
migration.c | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/migration.c b/migration.c
index ea84008..949a5bc 100644
--- a/migration.c
+++ b/migration.c
@@ -272,6 +272,12 @@ static void migrate_fd_cleanup(void *opaque)
DPRINTF("closing file\n");
qemu_fclose(s->file);
s->file = NULL;
+
+ qemu_mutex_unlock_iothread();
+ qemu_thread_join(&s->thread);
+ qemu_mutex_lock_iothread();
+
+ migrate_fd_close(s);
}
assert(s->migration_file == NULL);
@@ -523,16 +529,7 @@ static int migration_put_buffer(void *opaque, const uint8_t *buf,
static int migration_close(void *opaque)
{
- MigrationState *s = opaque;
-
- DPRINTF("closing\n");
-
- qemu_mutex_unlock_iothread();
- qemu_thread_join(&s->thread);
- qemu_mutex_lock_iothread();
- assert(s->state != MIG_STATE_ACTIVE);
-
- return migrate_fd_close(s);
+ return 0;
}
static int migration_get_fd(void *opaque)

View File

@ -1,196 +0,0 @@
From 2e690b6127da765a58b4f69e7bc79c8abfa03551 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:47 +0100
Subject: [PATCH] migration: eliminate s->migration_file
The indirection is useless now. Backends can open s->file directly.
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit b352365f5abec075dede0222f1bc37674d64117c)
---
include/migration/migration.h | 2 --
migration-exec.c | 4 ++--
migration-fd.c | 2 +-
migration-tcp.c | 4 ++--
migration-unix.c | 4 ++--
migration.c | 51 ++++---------------------------------------
6 files changed, 11 insertions(+), 56 deletions(-)
diff --git a/include/migration/migration.h b/include/migration/migration.h
index ae94706..bb617fd 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -36,9 +36,7 @@ struct MigrationState
size_t xfer_limit;
QemuThread thread;
QEMUBH *cleanup_bh;
-
QEMUFile *file;
- QEMUFile *migration_file;
int state;
MigrationParams params;
diff --git a/migration-exec.c b/migration-exec.c
index 1c539de..deab4e3 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -35,8 +35,8 @@
void exec_start_outgoing_migration(MigrationState *s, const char *command, Error **errp)
{
- s->migration_file = qemu_popen_cmd(command, "w");
- if (s->migration_file == NULL) {
+ s->file = qemu_popen_cmd(command, "w");
+ if (s->file == NULL) {
error_setg_errno(errp, errno, "failed to popen the migration target");
return;
}
diff --git a/migration-fd.c b/migration-fd.c
index 07c758a..3d4613c 100644
--- a/migration-fd.c
+++ b/migration-fd.c
@@ -36,7 +36,7 @@ void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **
if (fd == -1) {
return;
}
- s->migration_file = qemu_fdopen(fd, "wb");
+ s->file = qemu_fdopen(fd, "wb");
migrate_fd_connect(s);
}
diff --git a/migration-tcp.c b/migration-tcp.c
index 5ea4f3d..b20ee58 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -35,11 +35,11 @@ static void tcp_wait_for_connect(int fd, void *opaque)
if (fd < 0) {
DPRINTF("migrate connect error\n");
- s->migration_file = NULL;
+ s->file = NULL;
migrate_fd_error(s);
} else {
DPRINTF("migrate connect success\n");
- s->migration_file = qemu_fopen_socket(fd, "wb");
+ s->file = qemu_fopen_socket(fd, "wb");
migrate_fd_connect(s);
}
}
diff --git a/migration-unix.c b/migration-unix.c
index 64bfa31..94b7022 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -35,11 +35,11 @@ static void unix_wait_for_connect(int fd, void *opaque)
if (fd < 0) {
DPRINTF("migrate connect error\n");
- s->migration_file = NULL;
+ s->file = NULL;
migrate_fd_error(s);
} else {
DPRINTF("migrate connect success\n");
- s->migration_file = qemu_fopen_socket(fd, "wb");
+ s->file = qemu_fopen_socket(fd, "wb");
migrate_fd_connect(s);
}
}
diff --git a/migration.c b/migration.c
index 949a5bc..68ce4c9 100644
--- a/migration.c
+++ b/migration.c
@@ -270,9 +270,6 @@ static void migrate_fd_cleanup(void *opaque)
if (s->file) {
DPRINTF("closing file\n");
- qemu_fclose(s->file);
- s->file = NULL;
-
qemu_mutex_unlock_iothread();
qemu_thread_join(&s->thread);
qemu_mutex_lock_iothread();
@@ -280,7 +277,7 @@ static void migrate_fd_cleanup(void *opaque)
migrate_fd_close(s);
}
- assert(s->migration_file == NULL);
+ assert(s->file == NULL);
assert(s->state != MIG_STATE_ACTIVE);
if (s->state != MIG_STATE_COMPLETED) {
@@ -317,9 +314,9 @@ static void migrate_fd_cancel(MigrationState *s)
int migrate_fd_close(MigrationState *s)
{
int rc = 0;
- if (s->migration_file != NULL) {
- rc = qemu_fclose(s->migration_file);
- s->migration_file = NULL;
+ if (s->file != NULL) {
+ rc = qemu_fclose(s->file);
+ s->file = NULL;
}
return rc;
}
@@ -506,39 +503,6 @@ int64_t migrate_xbzrle_cache_size(void)
/* migration thread support */
-static int migration_put_buffer(void *opaque, const uint8_t *buf,
- int64_t pos, int size)
-{
- MigrationState *s = opaque;
- int ret;
-
- DPRINTF("putting %d bytes at %" PRId64 "\n", size, pos);
-
- if (size <= 0) {
- return size;
- }
-
- qemu_put_buffer(s->migration_file, buf, size);
- ret = qemu_file_get_error(s->migration_file);
- if (ret) {
- return ret;
- }
-
- return size;
-}
-
-static int migration_close(void *opaque)
-{
- return 0;
-}
-
-static int migration_get_fd(void *opaque)
-{
- MigrationState *s = opaque;
-
- return qemu_get_fd(s->migration_file);
-}
-
static void *migration_thread(void *opaque)
{
MigrationState *s = opaque;
@@ -628,12 +592,6 @@ static void *migration_thread(void *opaque)
return NULL;
}
-static const QEMUFileOps migration_file_ops = {
- .get_fd = migration_get_fd,
- .put_buffer = migration_put_buffer,
- .close = migration_close,
-};
-
void migrate_fd_connect(MigrationState *s)
{
s->state = MIG_STATE_ACTIVE;
@@ -642,7 +600,6 @@ void migrate_fd_connect(MigrationState *s)
/* This is a best 1st approximation. ns to ms */
s->expected_downtime = max_downtime/1000000;
s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s);
- s->file = qemu_fopen_ops(s, &migration_file_ops);
qemu_file_set_rate_limit(s->file,
s->bandwidth_limit / XFER_LIMIT_RATIO);

View File

@ -1,48 +0,0 @@
From 4c0d468f2aed75305117ea9860af21c32a915041 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:48 +0100
Subject: [PATCH] migration: inline migrate_fd_close
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit 6f190a0641f5b06a462b62955c15c77b8fb3990c)
---
migration.c | 14 ++------------
1 file changed, 2 insertions(+), 12 deletions(-)
diff --git a/migration.c b/migration.c
index 68ce4c9..0aff06d 100644
--- a/migration.c
+++ b/migration.c
@@ -274,10 +274,10 @@ static void migrate_fd_cleanup(void *opaque)
qemu_thread_join(&s->thread);
qemu_mutex_lock_iothread();
- migrate_fd_close(s);
+ qemu_fclose(s->file);
+ s->file = NULL;
}
- assert(s->file == NULL);
assert(s->state != MIG_STATE_ACTIVE);
if (s->state != MIG_STATE_COMPLETED) {
@@ -311,16 +311,6 @@ static void migrate_fd_cancel(MigrationState *s)
migrate_finish_set_state(s, MIG_STATE_CANCELLED);
}
-int migrate_fd_close(MigrationState *s)
-{
- int rc = 0;
- if (s->file != NULL) {
- rc = qemu_fclose(s->file);
- s->file = NULL;
- }
- return rc;
-}
-
void add_migration_state_change_notifier(Notifier *notify)
{
notifier_list_add(&migration_state_notifiers, notify);

View File

@ -1,91 +0,0 @@
From 45d723c48255328fbd5128c4c70c91103e420590 Mon Sep 17 00:00:00 2001
From: Michael Roth <mdroth@linux.vnet.ibm.com>
Date: Thu, 16 May 2013 16:25:44 -0500
Subject: [PATCH] Revert "migration: don't account sleep time for calculating
bandwidth"
This reverts commit 7161082c8d8cf167c508976887a0a63f4db92b51.
Reverting this patch fixes a divide-by-zero error in qemu that can be
fairly reliably triggered by doing block migration. In this case, the
configuration/error was:
source: temp/x86_64-softmmu/qemu-system-x86_64 -enable-kvm -L temp-bios
-M pc-i440fx-1.4 -m 512M -kernel boot/vmlinuz-x86_64 -initrd
boot/test-initramfs-x86_64.img.gz -vga std -append seed=1234 -drive
file=disk1.img,if=virtio -drive file=disk2.img,if=virtio -device
virtio-net-pci,netdev=net0 -netdev user,id=net0 -monitor
unix:/tmp/vm-hmp.sock,server,nowait -qmp
unix:/tmp/vm-qmp.sock,server,nowait -vnc :100
16837 Floating point exception(core dumped)
target: temp/x86_64-softmmu/qemu-system-x86_64 -enable-kvm -L temp-bios
-M pc-i440fx-1.4 -m 512M -kernel boot/vmlinuz-x86_64 -initrd
boot/test-initramfs-x86_64.img.gz -vga std -append seed=1234 -drive
file=target_disk1.img,if=virtio -drive file=target_disk2.img,if=virtio
-device virtio-net-pci,netdev=net0 -netdev user,id=net0 -incoming
unix:/tmp/migrate.sock -monitor
unix:/tmp/vm-hmp-incoming.sock,server,nowait -qmp
unix:/tmp/vm-qmp-incoming.sock,server,nowait -vnc :101
Receiving block device images
20 %
21 %
load of migration failed
This revert potentially re-introduces a bug that was present in 1.4,
but fixes a prevalent issue with block migration so we should revert
it for now and take an updated patch later.
Conflicts:
migration.c
* fixed up to remove logic introduced in 7161082c while leaving
changes in HEAD intact
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Message-id: 1368739544-31021-1-git-send-email-mdroth@linux.vnet.ibm.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 77417f10701d330c7005b0f0a2c0cef9e05d430d)
---
migration.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/migration.c b/migration.c
index 0aff06d..cca6df6 100644
--- a/migration.c
+++ b/migration.c
@@ -497,7 +497,6 @@ static void *migration_thread(void *opaque)
{
MigrationState *s = opaque;
int64_t initial_time = qemu_get_clock_ms(rt_clock);
- int64_t sleep_time = 0;
int64_t initial_bytes = 0;
int64_t max_size = 0;
int64_t start_time = initial_time;
@@ -540,7 +539,7 @@ static void *migration_thread(void *opaque)
current_time = qemu_get_clock_ms(rt_clock);
if (current_time >= initial_time + BUFFER_DELAY) {
uint64_t transferred_bytes = qemu_ftell(s->file) - initial_bytes;
- uint64_t time_spent = current_time - initial_time - sleep_time;
+ uint64_t time_spent = current_time - initial_time;
double bandwidth = transferred_bytes / time_spent;
max_size = bandwidth * migrate_max_downtime() / 1000000;
@@ -554,14 +553,12 @@ static void *migration_thread(void *opaque)
}
qemu_file_reset_rate_limit(s->file);
- sleep_time = 0;
initial_time = current_time;
initial_bytes = qemu_ftell(s->file);
}
if (qemu_file_rate_limit(s->file)) {
/* usleep expects microseconds */
g_usleep((initial_time + BUFFER_DELAY - current_time)*1000);
- sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
}
}

View File

@ -1,66 +0,0 @@
From 7daeb79e054ba552bd598557a3373325727d2231 Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso@redhat.com>
Date: Tue, 19 Feb 2013 14:39:05 -0500
Subject: [PATCH] configure: Add --enable-migration-from-qemu-kvm
This switch will turn on all the migration compat bits needed to
perform migration from qemu-kvm to qemu. It's just a stub for now.
This compat will break incoming migration from qemu < 1.3, but for
distros where qemu-kvm was the only shipped package for years it's
not a big loss (and I don't know any way to avoid it).
Signed-off-by: Cole Robinson <crobinso@redhat.com>
---
configure | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/configure b/configure
index f4097ef..bc2870b 100755
--- a/configure
+++ b/configure
@@ -170,6 +170,7 @@ xfs=""
vhost_net="no"
kvm="no"
+migrate_from_kvm="no"
gprof="no"
debug_tcg="no"
debug="no"
@@ -759,6 +760,8 @@ for opt do
;;
--enable-kvm) kvm="yes"
;;
+ --enable-migration-from-qemu-kvm) migrate_from_kvm="yes"
+ ;;
--disable-tcg-interpreter) tcg_interpreter="no"
;;
--enable-tcg-interpreter) tcg_interpreter="yes"
@@ -1087,6 +1090,9 @@ echo " --enable-bluez enable bluez stack connectivity"
echo " --disable-slirp disable SLIRP userspace network connectivity"
echo " --disable-kvm disable KVM acceleration support"
echo " --enable-kvm enable KVM acceleration support"
+echo " --enable-migration-from-qemu-kvm Allow migration from qemu-kvm."
+echo " This will break migration from "
+echo " qemu < 1.3 in most cases"
echo " --enable-tcg-interpreter enable TCG with bytecode interpreter (TCI)"
echo " --disable-nptl disable usermode NPTL support"
echo " --enable-nptl enable usermode NPTL support"
@@ -3358,6 +3364,7 @@ echo "Linux AIO support $linux_aio"
echo "ATTR/XATTR support $attr"
echo "Install blobs $blobs"
echo "KVM support $kvm"
+echo "Migrate from qemu-kvm $migrate_from_kvm"
echo "TCG interpreter $tcg_interpreter"
echo "fdt support $fdt"
echo "preadv support $preadv"
@@ -3646,6 +3653,9 @@ fi
if test "$signalfd" = "yes" ; then
echo "CONFIG_SIGNALFD=y" >> $config_host_mak
fi
+if test "$migrate_from_kvm" = "yes"; then
+ echo "CONFIG_MIGRATE_FROM_QEMU_KVM=y" >> $config_host_mak
+fi
if test "$tcg_interpreter" = "yes" ; then
echo "CONFIG_TCG_INTERPRETER=y" >> $config_host_mak
fi

View File

@ -1,53 +0,0 @@
From b94ccea34cf71689a751fcec9fb7afb417ce7442 Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso@redhat.com>
Date: Tue, 19 Feb 2013 14:44:49 -0500
Subject: [PATCH] acpi_piix4: Drop minimum_version_id to handle qemu-kvm
migration
qemu-kvm 1.2 advertised version_id=2, but it was not the same
format as qemu.git version_id=2.
commit b0b873a07872f7ab7f66f259c73fb9dd42aa66a9 added the qemu-kvm
format to qemu.git, but was forced to call it version_id=3, and
bumped minimum_version_id to 3. This breaks incoming migration from
qemu-kvm.
If --enable-migration-from-qemu-kvm is enabled, drop minimum_version_id
to 2. Migration from qemu-kvm version_id=2 and qemu 1.3+ version_id=3
works, but migration from qemu < 1.3 is broken.
Signed-off-by: Cole Robinson <crobinso@redhat.com>
---
hw/acpi_piix4.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 1beac21..2abcc9d 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -257,16 +257,19 @@ static int acpi_load_old(QEMUFile *f, void *opaque, int version_id)
return ret;
}
-/* qemu-kvm 1.2 uses version 3 but advertised as 2
- * To support incoming qemu-kvm 1.2 migration, change version_id
- * and minimum_version_id to 2 below (which breaks migration from
- * qemu 1.2).
- *
- */
static const VMStateDescription vmstate_acpi = {
.name = "piix4_pm",
.version_id = 3,
+#ifdef CONFIG_MIGRATE_FROM_QEMU_KVM
+ /*
+ * qemu-kvm 1.2 uses qemu.git version 3 format, but advertised as 2.
+ * This allows incoming migration from qemu-kvm, but breaks incoming
+ * migration from qemu < 1.3.
+ */
+ .minimum_version_id = 2,
+#else
.minimum_version_id = 3,
+#endif
.minimum_version_id_old = 1,
.load_state_old = acpi_load_old,
.post_load = vmstate_acpi_post_load,

View File

@ -1,36 +0,0 @@
From fb124a30d5b7eff071122fd6236ebbcf8cbeaf46 Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso@redhat.com>
Date: Tue, 19 Feb 2013 15:04:59 -0500
Subject: [PATCH] i8254: Fix migration from qemu-kvm < 1.1
qemu-kvm commit 81bdec908fb2be0ccaff1d4ee67956c509e440ad did this,
but the logic can't be carried unconditionally in qemu.git without
breaking migration from qemu < 1.1.
Conditionalize it with --enable-migrate-from-qemu-kvm
Signed-off-by: Cole Robinson <crobinso@redhat.com>
---
hw/i8254_common.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/hw/i8254_common.c b/hw/i8254_common.c
index 8c2e45a..072fa09 100644
--- a/hw/i8254_common.c
+++ b/hw/i8254_common.c
@@ -275,7 +275,15 @@ static const VMStateDescription vmstate_pit_common = {
.pre_save = pit_dispatch_pre_save,
.post_load = pit_dispatch_post_load,
.fields = (VMStateField[]) {
+#ifdef CONFIG_MIGRATE_FROM_QEMU_KVM
+ /* qemu-kvm version_id=2 had 'flags' here which is equivalent
+ * This fixes incoming migration from qemu-kvm 1.0, but breaks
+ * incoming migration from qemu < 1.1
+ */
+ VMSTATE_UINT32(channels[0].irq_disabled, PITCommonState),
+#else
VMSTATE_UINT32_V(channels[0].irq_disabled, PITCommonState, 3),
+#endif
VMSTATE_STRUCT_ARRAY(channels, PITCommonState, 3, 2,
vmstate_pit_channel, PITChannelState),
VMSTATE_INT64(channels[0].next_transition_time,

View File

@ -1,83 +0,0 @@
From 296b2d495cca8331481939dce7f2c04f4d640366 Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso@redhat.com>
Date: Tue, 19 Feb 2013 15:35:40 -0500
Subject: [PATCH] pc_piix: Add compat handling for qemu-kvm VGA mem size
Paolo outlines this here:
https://lists.gnu.org/archive/html/qemu-devel/2013-01/msg02540.html
qemu-kvm defaulted to vgamem=16MB since at least 0.15, while qemu used
8MB. For qemu 1.2, the default was changed to 16MB for all devices
except cirrus.
If --enable-migration-from-qemu-kvm is specified, make sure cirrus
uses 16MB for <= pc-1.2 (the qemu-kvm merge), and 16MB always for
all others. This will break incoming qemu migration for qemu < 1.3.
Signed-off-by: Cole Robinson <crobinso@redhat.com>
---
hw/pc_piix.c | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 0af436c..e3f8e96 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -331,6 +331,13 @@ static QEMUMachine pc_machine_v1_3 = {
DEFAULT_MACHINE_OPTIONS,
};
+#ifdef CONFIG_MIGRATE_FROM_QEMU_KVM
+/* qemu-kvm defaulted to 16MB video memory since 0.15 at least. */
+# define OLD_VGA_MEM stringify(16)
+#else
+# define OLD_VGA_MEM stringify(8)
+#endif
+
#define PC_COMPAT_1_2 \
PC_COMPAT_1_3,\
{\
@@ -354,6 +361,10 @@ static QEMUMachine pc_machine_v1_3 = {
.property = "revision",\
.value = stringify(3),\
},{\
+ .driver = "cirrus-vga",\
+ .property = "vgamem_mb",\
+ .value = OLD_VGA_MEM,\
+ },{\
.driver = "VGA",\
.property = "mmio",\
.value = "off",\
@@ -371,6 +382,7 @@ static QEMUMachine pc_machine_v1_2 = {
DEFAULT_MACHINE_OPTIONS,
};
+
#define PC_COMPAT_1_1 \
PC_COMPAT_1_2,\
{\
@@ -384,19 +396,19 @@ static QEMUMachine pc_machine_v1_2 = {
},{\
.driver = "VGA",\
.property = "vgamem_mb",\
- .value = stringify(8),\
+ .value = OLD_VGA_MEM,\
},{\
.driver = "vmware-svga",\
.property = "vgamem_mb",\
- .value = stringify(8),\
+ .value = OLD_VGA_MEM,\
},{\
.driver = "qxl-vga",\
.property = "vgamem_mb",\
- .value = stringify(8),\
+ .value = OLD_VGA_MEM,\
},{\
.driver = "qxl",\
.property = "vgamem_mb",\
- .value = stringify(8),\
+ .value = OLD_VGA_MEM,\
},{\
.driver = "virtio-blk-pci",\
.property = "config-wce",\

View File

@ -1,101 +0,0 @@
From 59d4955ec7fd78cabb8d2a2460d742580de180f1 Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso@redhat.com>
Date: Tue, 19 Feb 2013 16:19:02 -0500
Subject: [PATCH] qxl: Add rom_size compat property, fix migration from 1.2
Commit 038c1879a00153b14bce113315b693e8c2944fa9 changed the qxl rom
size to 8192, which fixes incoming migration from qemu 1.0. However
from qemu 1.2 and 1.3 had rom size 16384, so incoming migration
from those versions is now broken.
Add a rom_size compat property. 1.2 and 1.3 get 16384, everything
else is 8192.
This isn't actually fool proof, since rom_size can be dependent on
the version of spice qemu is built against:
https://lists.gnu.org/archive/html/qemu-devel/2013-02/msg03154.html
However these sizes match what native Fedora packages get, so it's
good enough for now.
Signed-off-by: Cole Robinson <crobinso@redhat.com>
---
hw/pc_piix.c | 16 ++++++++++++++++
hw/qxl.c | 9 ++++-----
2 files changed, 20 insertions(+), 5 deletions(-)
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index e3f8e96..a1a6794 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -317,6 +317,14 @@ static QEMUMachine pc_i440fx_machine_v1_4 = {
.driver = "virtio-net-pci", \
.property = "mq", \
.value = "off", \
+ },{ \
+ .driver = "qxl", \
+ .property = "rom_size", \
+ .value = stringify(16384), \
+ },{\
+ .driver = "qxl-vga", \
+ .property = "rom_size", \
+ .value = stringify(16384), \
}
static QEMUMachine pc_machine_v1_3 = {
@@ -413,6 +421,14 @@ static QEMUMachine pc_machine_v1_2 = {
.driver = "virtio-blk-pci",\
.property = "config-wce",\
.value = "off",\
+ },{ \
+ .driver = "qxl", \
+ .property = "rom_size", \
+ .value = stringify(8192), \
+ },{\
+ .driver = "qxl-vga", \
+ .property = "rom_size", \
+ .value = stringify(8192), \
}
static QEMUMachine pc_machine_v1_1 = {
diff --git a/hw/qxl.c b/hw/qxl.c
index ca094e6..80bd92a 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -302,16 +302,14 @@ static inline uint32_t msb_mask(uint32_t val)
return mask;
}
-static ram_addr_t qxl_rom_size(void)
+static void check_qxl_rom_size(PCIQXLDevice *d)
{
uint32_t required_rom_size = sizeof(QXLRom) + sizeof(QXLModes) +
sizeof(qxl_modes);
- uint32_t rom_size = 8192; /* two pages */
required_rom_size = MAX(required_rom_size, TARGET_PAGE_SIZE);
required_rom_size = msb_mask(required_rom_size * 2 - 1);
- assert(required_rom_size <= rom_size);
- return rom_size;
+ assert(required_rom_size <= d->rom_size);
}
static void init_qxl_rom(PCIQXLDevice *d)
@@ -1979,7 +1977,7 @@ static int qxl_init_common(PCIQXLDevice *qxl)
pci_set_byte(&config[PCI_REVISION_ID], pci_device_rev);
pci_set_byte(&config[PCI_INTERRUPT_PIN], 1);
- qxl->rom_size = qxl_rom_size();
+ check_qxl_rom_size(qxl);
memory_region_init_ram(&qxl->rom_bar, "qxl.vrom", qxl->rom_size);
vmstate_register_ram(&qxl->rom_bar, &qxl->pci.qdev);
init_qxl_rom(qxl);
@@ -2296,6 +2294,7 @@ static Property qxl_properties[] = {
DEFINE_PROP_UINT32("vram64_size_mb", PCIQXLDevice, vram_size_mb, -1),
DEFINE_PROP_UINT32("vgamem_mb", PCIQXLDevice, vgamem_size_mb, 16),
DEFINE_PROP_INT32("surfaces", PCIQXLDevice, ssd.num_surfaces, 1024),
+ DEFINE_PROP_UINT32("rom_size", PCIQXLDevice, rom_size, 8192),
DEFINE_PROP_END_OF_LIST(),
};

View File

@ -1,47 +0,0 @@
From e5cdc492ec39f777b0bd877ca794f3b2ccdcffec Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi <stefanha@redhat.com>
Date: Wed, 22 May 2013 14:50:18 +0200
Subject: [PATCH] rtl8139: flush queued packets when RxBufPtr is written
Net queues support efficient "receive disable". For example, tap's file
descriptor will not be polled while its peer has receive disabled. This
saves CPU cycles for needlessly copying and then dropping packets which
the peer cannot receive.
rtl8139 is missing the qemu_flush_queued_packets() call that wakes the
queue up when receive becomes possible again.
As a result, the Windows 7 guest driver reaches a state where the
rtl8139 cannot receive packets. The driver has actually refilled the
receive buffer but we never resume reception.
The bug can be reproduced by running a large FTP 'get' inside a Windows
7 guest:
$ qemu -netdev tap,id=tap0,...
-device rtl8139,netdev=tap0
The Linux guest driver does not trigger the bug, probably due to a
different buffer management strategy.
Reported-by: Oliver Francke <oliver.francke@filoo.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 00b7ade807b5ce6779ddd86ce29c5521ec5c529a)
---
hw/rtl8139.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index d7716be..2c4d9bd 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -2575,6 +2575,9 @@ static void rtl8139_RxBufPtr_write(RTL8139State *s, uint32_t val)
/* this value is off by 16 */
s->RxBufPtr = MOD2(val + 0x10, s->RxBufferSize);
+ /* more buffer space may be available so try to receive */
+ qemu_flush_queued_packets(qemu_get_queue(s->nic));
+
DPRINTF(" CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n",
s->RxBufferSize, s->RxBufAddr, s->RxBufPtr);
}

View File

@ -1,44 +0,0 @@
From ad0343a9c903b79c6dd3ecdafb05a704c14514b9 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Fri, 5 Apr 2013 11:30:24 +0200
Subject: [PATCH] spice-qemu-char: vmc_write: Don't write more bytes then we're
asked too
This one took me eons to debug, but I've finally found it now, oh well.
The usage of the MIN macro in this line:
last_out = MIN(len, qemu_chr_be_can_write(scd->chr));
Causes qemu_chr_be_can_write to be called *twice*, since the MIN macro
evaluates its arguments twice (bad MIN macro, bad!). And the result of
the call can change between the 2 calls since the guest may have consumed
some data from the virtio ringbuffer between the calls!
When this happens it is possible for qemu_chr_be_can_write to return less
then len in the call made for the comparision, and then to return more then
len in the actual call for the return-value of MIN, after which we will end
up writing len data + some extra garbage, not good.
This patch fixes this by only calling qemu_chr_be_can_write once.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 75c439bc65c07d76f5e74c734ed5432bc6114a3b)
---
spice-qemu-char.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index 5065240..82f3f77 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -41,7 +41,8 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
uint8_t* p = (uint8_t*)buf;
while (len > 0) {
- last_out = MIN(len, qemu_chr_be_can_write(scd->chr));
+ int can_write = qemu_chr_be_can_write(scd->chr);
+ last_out = MIN(len, can_write);
if (last_out <= 0) {
break;
}

View File

@ -1,85 +0,0 @@
From 70ef52a74f40710757ade876f1ae9ebeb9d9094c Mon Sep 17 00:00:00 2001
From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Date: Mon, 27 May 2013 14:20:57 +1000
Subject: [PATCH] configure: dtc: Probe for libfdt_env.h
Currently QEMU provides a local clone of the file libfdt_env.h in
/include. This file is supposed to come with the libfdt package and is
only needed for broken installs of libfdt. Now that we have submodule
dtc, just ignore these broken installs and prompt for the dtc submodule
install instead. QEMU's local libfdt_env.h is removed accordingly.
Manifests as a bug when building QEMU with modern libfdt. The new
version of libfdt does not compile when QEMUs libfdt_env.h takes
precedence over the hosts.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Acked-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Message-id: 9b6a3a52e3f46cfbc1ded9ab56385ec045e46705.1369628289.git.peter.crosthwaite@xilinx.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 96ce65457690561417ae8e6f0e85f3c6f135018b)
---
configure | 2 ++
include/libfdt_env.h | 36 ------------------------------------
2 files changed, 2 insertions(+), 36 deletions(-)
delete mode 100644 include/libfdt_env.h
diff --git a/configure b/configure
index bc2870b..2996e1d 100755
--- a/configure
+++ b/configure
@@ -2378,7 +2378,9 @@ fi
# fdt probe
if test "$fdt" != "no" ; then
fdt_libs="-lfdt"
+ # explicitly check for libfdt_env.h as it is missing in some stable installs
cat > $TMPC << EOF
+#include <libfdt_env.h>
int main(void) { return 0; }
EOF
if compile_prog "" "$fdt_libs" ; then
diff --git a/include/libfdt_env.h b/include/libfdt_env.h
deleted file mode 100644
index 3667d4c..0000000
--- a/include/libfdt_env.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- * Copyright IBM Corp. 2008
- * Authors: Hollis Blanchard <hollisb@us.ibm.com>
- *
- */
-
-#ifndef _LIBFDT_ENV_H
-#define _LIBFDT_ENV_H
-
-#include "qemu/bswap.h"
-
-#ifdef HOST_WORDS_BIGENDIAN
-#define fdt32_to_cpu(x) (x)
-#define cpu_to_fdt32(x) (x)
-#define fdt64_to_cpu(x) (x)
-#define cpu_to_fdt64(x) (x)
-#else
-#define fdt32_to_cpu(x) bswap32(x)
-#define cpu_to_fdt32(x) bswap32(x)
-#define fdt64_to_cpu(x) bswap64(x)
-#define cpu_to_fdt64(x) bswap64(x)
-#endif
-
-#endif /* _LIBFDT_ENV_H */

View File

@ -1,29 +0,0 @@
From e787bef7d85fdbb6a8d5b07bb84542e81d14cb8d Mon Sep 17 00:00:00 2001
From: Michael Marineau <mike@marineau.org>
Date: Sun, 12 May 2013 19:19:37 -0400
Subject: [PATCH] Fix usage of USB_DEV_FLAG_IS_HOST flag.
USB_DEV_FLAG_IS_HOST is the bit number, not value. Booting with a
"Fitbit Base Station" USB dongle was triggering this assert.
Signed-off-by: Michael Marineau <mike@marineau.org>
Cc: qemu-stable@nongnu.org
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 756335292f2b46775992c314cc70b54480a46d26)
---
hw/usb/core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/usb/core.c b/hw/usb/core.c
index d057aab..67c41cd 100644
--- a/hw/usb/core.c
+++ b/hw/usb/core.c
@@ -410,7 +410,7 @@ void usb_handle_packet(USBDevice *dev, USBPacket *p)
assert(p->ep->type != USB_ENDPOINT_XFER_ISOC);
/* using async for interrupt packets breaks migration */
assert(p->ep->type != USB_ENDPOINT_XFER_INT ||
- (dev->flags & USB_DEV_FLAG_IS_HOST));
+ (dev->flags & (1 << USB_DEV_FLAG_IS_HOST)));
usb_packet_set_state(p, USB_PACKET_ASYNC);
QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
} else if (p->status == USB_RET_ADD_TO_QUEUE) {

View File

@ -1,31 +0,0 @@
From dadbf35f465f3423faa797a73c9a3caf5c6ab984 Mon Sep 17 00:00:00 2001
From: Anthony PERARD <anthony.perard@citrix.com>
Date: Mon, 17 Jun 2013 17:38:26 +0100
Subject: [PATCH] qxl: Fix QXLRam initialisation.
The qxl driver expect NULL for QXLRam.memory_configs, but this is never
initialized.
If memory is set to 0xc2c2.., it leads to a spice-critical error when
trying to start qxl.
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
(cherry picked from commit 329f97fc4ff4b533fcd2d8f4eab6c9c2568aed27)
---
hw/qxl.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/hw/qxl.c b/hw/qxl.c
index 80bd92a..5f52950 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -381,6 +381,7 @@ static void init_qxl_ram(PCIQXLDevice *d)
d->ram->int_pending = cpu_to_le32(0);
d->ram->int_mask = cpu_to_le32(0);
d->ram->update_surface = 0;
+ d->ram->monitors_config = 0;
SPICE_RING_INIT(&d->ram->cmd_ring);
SPICE_RING_INIT(&d->ram->cursor_ring);
SPICE_RING_INIT(&d->ram->release_ring);

View File

@ -1,110 +0,0 @@
From 0d298cfe215b2e09debb62978eb77d7be4f37e1f Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Fri, 15 Mar 2013 17:14:24 +0100
Subject: [PATCH] qemu-socket: Make socket_optslist public
Allow other users to create the QemuOpts needed for inet_connect_opts().
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit e62be8888a83aa0ab7f50eeb954deb2ec4e7201d)
---
include/qemu/sockets.h | 2 ++
util/qemu-sockets.c | 22 +++++++++++-----------
2 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index 42ca690..6eed34e 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -31,6 +31,8 @@ int inet_aton(const char *cp, struct in_addr *ia);
#include "qapi/qmp/qerror.h"
#include "char/char.h"
+extern QemuOptsList socket_optslist;
+
/* misc helpers */
int qemu_socket(int domain, int type, int protocol);
int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index cd54fb4..b32510a 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -33,10 +33,10 @@
static const int on=1, off=0;
-/* used temporarely until all users are converted to QemuOpts */
-static QemuOptsList dummy_opts = {
- .name = "dummy",
- .head = QTAILQ_HEAD_INITIALIZER(dummy_opts.head),
+/* used temporarily until all users are converted to QemuOpts */
+QemuOptsList socket_optslist = {
+ .name = "socket",
+ .head = QTAILQ_HEAD_INITIALIZER(socket_optslist.head),
.desc = {
{
.name = "path",
@@ -579,7 +579,7 @@ int inet_listen(const char *str, char *ostr, int olen,
addr = inet_parse(str, errp);
if (addr != NULL) {
- opts = qemu_opts_create_nofail(&dummy_opts);
+ opts = qemu_opts_create_nofail(&socket_optslist);
inet_addr_to_opts(opts, addr);
qapi_free_InetSocketAddress(addr);
sock = inet_listen_opts(opts, port_offset, errp);
@@ -652,7 +652,7 @@ int inet_nonblocking_connect(const char *str,
addr = inet_parse(str, errp);
if (addr != NULL) {
- opts = qemu_opts_create_nofail(&dummy_opts);
+ opts = qemu_opts_create_nofail(&socket_optslist);
inet_addr_to_opts(opts, addr);
qapi_free_InetSocketAddress(addr);
sock = inet_connect_opts(opts, errp, callback, opaque);
@@ -795,7 +795,7 @@ int unix_listen(const char *str, char *ostr, int olen, Error **errp)
char *path, *optstr;
int sock, len;
- opts = qemu_opts_create_nofail(&dummy_opts);
+ opts = qemu_opts_create_nofail(&socket_optslist);
optstr = strchr(str, ',');
if (optstr) {
@@ -823,7 +823,7 @@ int unix_connect(const char *path, Error **errp)
QemuOpts *opts;
int sock;
- opts = qemu_opts_create_nofail(&dummy_opts);
+ opts = qemu_opts_create_nofail(&socket_optslist);
qemu_opt_set(opts, "path", path);
sock = unix_connect_opts(opts, errp, NULL, NULL);
qemu_opts_del(opts);
@@ -840,7 +840,7 @@ int unix_nonblocking_connect(const char *path,
g_assert(callback != NULL);
- opts = qemu_opts_create_nofail(&dummy_opts);
+ opts = qemu_opts_create_nofail(&socket_optslist);
qemu_opt_set(opts, "path", path);
sock = unix_connect_opts(opts, errp, callback, opaque);
qemu_opts_del(opts);
@@ -891,7 +891,7 @@ int socket_connect(SocketAddress *addr, Error **errp,
QemuOpts *opts;
int fd;
- opts = qemu_opts_create_nofail(&dummy_opts);
+ opts = qemu_opts_create_nofail(&socket_optslist);
switch (addr->kind) {
case SOCKET_ADDRESS_KIND_INET:
inet_addr_to_opts(opts, addr->inet);
@@ -923,7 +923,7 @@ int socket_listen(SocketAddress *addr, Error **errp)
QemuOpts *opts;
int fd;
- opts = qemu_opts_create_nofail(&dummy_opts);
+ opts = qemu_opts_create_nofail(&socket_optslist);
switch (addr->kind) {
case SOCKET_ADDRESS_KIND_INET:
inet_addr_to_opts(opts, addr->inet);

View File

@ -1,35 +0,0 @@
From 82ba8008f0c6d7328872421e4d9d4f9868d74b11 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <mlureau@redhat.com>
Date: Sun, 2 Dec 2012 22:00:55 +0100
Subject: [PATCH] libcacard: correct T0 historical bytes size
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The VCARD_ATR_PREFIX macro adds a prefix of 6 characters only.
pcsc_scan was complaining before the patch:
+ Historical bytes: 56 43 41 52 44 5F 4E 53 53
ERROR! ATR is truncated: 2 byte(s) is/are missing
Signed-off-by: Marc-André Lureau <mlureau@redhat.com>
Reviewed-by: Alon Levy <alevy@redhat.com>
(cherry picked from commit e2fd2115ce26049335d66ae0ae5e5c0ad06fb498)
---
libcacard/vcardt.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcacard/vcardt.h b/libcacard/vcardt.h
index d3e9522..538bdde 100644
--- a/libcacard/vcardt.h
+++ b/libcacard/vcardt.h
@@ -26,7 +26,7 @@ typedef struct VCardEmulStruct VCardEmul;
#define MAX_CHANNEL 4
/* create an ATR with appropriate historical bytes */
-#define VCARD_ATR_PREFIX(size) 0x3b, 0x68+(size), 0x00, 0xff, \
+#define VCARD_ATR_PREFIX(size) 0x3b, 0x66+(size), 0x00, 0xff, \
'V', 'C', 'A', 'R', 'D', '_'

View File

@ -1,36 +0,0 @@
From ab2662a8074e329e15d92ee5bdce741b84901c4a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <mlureau@redhat.com>
Date: Wed, 21 Nov 2012 14:16:08 +0100
Subject: [PATCH] ccid-card-emul: do not crash if backend is not provided
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Program received signal SIGSEGV, Segmentation fault.
__strcmp_sse42 () at ../sysdeps/x86_64/multiarch/strcmp-sse42.S:164
164 movdqu (%rsi), %xmm2
(gdb) bt
at /home/elmarco/320g/src/qemu/hw/ccid-card-emulated.c:477
at /home/elmarco/320g/src/qemu/hw/ccid-card-emulated.c:503
Signed-off-by: Marc-André Lureau <mlureau@redhat.com>
Reviewed-by: Alon Levy <alevy@redhat.com>
(cherry picked from commit d0ebd78890fba2ab458ec34763dae8566ccb1b72)
---
hw/ccid-card-emulated.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/hw/ccid-card-emulated.c b/hw/ccid-card-emulated.c
index c8f8ba3..210433e 100644
--- a/hw/ccid-card-emulated.c
+++ b/hw/ccid-card-emulated.c
@@ -473,6 +473,9 @@ static uint32_t parse_enumeration(char *str,
{
uint32_t ret = not_found_value;
+ if (str == NULL)
+ return 0;
+
while (table->name != NULL) {
if (strcmp(table->name, str) == 0) {
ret = table->value;

View File

@ -1,46 +0,0 @@
From c05bf7d253830527dbb6f4280f50e805c188bb57 Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering@redhat.com>
Date: Mon, 21 May 2012 21:56:20 +0200
Subject: [PATCH] ccid: make backend_enum_table "static const" and adjust users
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Jim Meyering <meyering@redhat.com>
Reviewed-by: Alon Levy <alevy@redhat.com>
Reviewed-by: Marc-André Lureau <mlureau@redhat.com>
(cherry picked from commit d18c7117467aa5fae95a7c6eaffcf50618197e79)
---
hw/ccid-card-emulated.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/hw/ccid-card-emulated.c b/hw/ccid-card-emulated.c
index 210433e..cb9ef10 100644
--- a/hw/ccid-card-emulated.c
+++ b/hw/ccid-card-emulated.c
@@ -462,14 +462,14 @@ typedef struct EnumTable {
uint32_t value;
} EnumTable;
-EnumTable backend_enum_table[] = {
+static const EnumTable backend_enum_table[] = {
{BACKEND_NSS_EMULATED_NAME, BACKEND_NSS_EMULATED},
{BACKEND_CERTIFICATES_NAME, BACKEND_CERTIFICATES},
{NULL, 0},
};
static uint32_t parse_enumeration(char *str,
- EnumTable *table, uint32_t not_found_value)
+ const EnumTable *table, uint32_t not_found_value)
{
uint32_t ret = not_found_value;
@@ -490,7 +490,7 @@ static int emulated_initfn(CCIDCardState *base)
{
EmulatedState *card = DO_UPCAST(EmulatedState, base, base);
VCardEmulError ret;
- EnumTable *ptable;
+ const EnumTable *ptable;
QSIMPLEQ_INIT(&card->event_list);
QSIMPLEQ_INIT(&card->guest_apdu_list);

View File

@ -1,29 +0,0 @@
From f45224daee28b04543bf913e4d544c77ba9751a4 Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering@redhat.com>
Date: Mon, 21 May 2012 21:51:33 +0200
Subject: [PATCH] ccid: declare DEFAULT_ATR table to be "static const"
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Jim Meyering <meyering@redhat.com>
Reviewed-by: Alon Levy <alevy@redhat.com>
Reviewed-by: Marc-André Lureau <mlureau@redhat.com>
(cherry picked from commit da000a4867749434e03896a5072321771736352a)
---
hw/ccid-card-passthru.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c
index 0dde761..62070db 100644
--- a/hw/ccid-card-passthru.c
+++ b/hw/ccid-card-passthru.c
@@ -27,7 +27,7 @@ do { \
#define D_VERBOSE 4
/* TODO: do we still need this? */
-uint8_t DEFAULT_ATR[] = {
+static const uint8_t DEFAULT_ATR[] = {
/*
* From some example somewhere
* 0x3B, 0xB0, 0x18, 0x00, 0xD1, 0x81, 0x05, 0xB1, 0x40, 0x38, 0x1F, 0x03, 0x28

View File

@ -1,47 +0,0 @@
From 55f9a7671661393885ed67a5fdbd54a2bf8fed48 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <mlureau@redhat.com>
Date: Wed, 27 Feb 2013 21:08:06 +0100
Subject: [PATCH] libcacard: use system config directory for nss db on win32
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
It's a bit nicer to look for default database under
CSIDL_COMMON_APPDATA\pki\nss rather that /etc/pki/nss.
Signed-off-by: Marc-André Lureau <mlureau@redhat.com>
Reviewed-by: Alon Levy <alevy@redhat.com>
(cherry picked from commit e2d9c5e769d59f2bca649b8286892d49bdcfc2b1)
---
libcacard/vcard_emul_nss.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
index df79476..21d4689 100644
--- a/libcacard/vcard_emul_nss.c
+++ b/libcacard/vcard_emul_nss.c
@@ -893,7 +893,23 @@ vcard_emul_init(const VCardEmulOptions *options)
if (options->nss_db) {
rv = NSS_Init(options->nss_db);
} else {
- rv = NSS_Init("sql:/etc/pki/nssdb");
+ gchar *path, *db;
+#ifndef _WIN32
+ path = g_strdup("/etc/pki/nssdb");
+#else
+ if (g_get_system_config_dirs() == NULL ||
+ g_get_system_config_dirs()[0] == NULL) {
+ return VCARD_EMUL_FAIL;
+ }
+
+ path = g_build_filename(
+ g_get_system_config_dirs()[0], "pki", "nssdb", NULL);
+#endif
+ db = g_strdup_printf("sql:%s", path);
+
+ rv = NSS_Init(db);
+ g_free(db);
+ g_free(path);
}
if (rv != SECSuccess) {
return VCARD_EMUL_FAIL;

View File

@ -1,94 +0,0 @@
From 9819cebc4010a996b466669022e78dfedd4f0b9f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
Date: Mon, 25 Feb 2013 23:31:11 +0100
Subject: [PATCH] util: move socket_init() to osdep.c
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
vscclient needs to call socket_init() for portability.
Moving to osdep.c since it has no internal dependency.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Alon Levy <alevy@redhat.com>
(cherry picked from commit d3bf825e59125bc6a0accec0dca119ea0155cb82)
Conflicts:
util/qemu-sockets.c
---
util/osdep.c | 23 +++++++++++++++++++++++
util/qemu-sockets.c | 26 +-------------------------
2 files changed, 24 insertions(+), 25 deletions(-)
diff --git a/util/osdep.c b/util/osdep.c
index 5b51a03..3c1a0a3 100644
--- a/util/osdep.c
+++ b/util/osdep.c
@@ -400,3 +400,26 @@ bool fips_get_state(void)
return fips_enabled;
}
+#ifdef _WIN32
+static void socket_cleanup(void)
+{
+ WSACleanup();
+}
+#endif
+
+int socket_init(void)
+{
+#ifdef _WIN32
+ WSADATA Data;
+ int ret, err;
+
+ ret = WSAStartup(MAKEWORD(2, 2), &Data);
+ if (ret != 0) {
+ err = WSAGetLastError();
+ fprintf(stderr, "WSAStartup: %d\n", err);
+ return -1;
+ }
+ atexit(socket_cleanup);
+#endif
+ return 0;
+}
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index b32510a..7909381 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -618,7 +618,7 @@ int inet_connect(const char *str, Error **errp)
addr = inet_parse(str, errp);
if (addr != NULL) {
- opts = qemu_opts_create_nofail(&dummy_opts);
+ opts = qemu_opts_create_nofail(&socket_optslist);
inet_addr_to_opts(opts, addr);
qapi_free_InetSocketAddress(addr);
sock = inet_connect_opts(opts, errp, NULL, NULL);
@@ -945,27 +945,3 @@ int socket_listen(SocketAddress *addr, Error **errp)
qemu_opts_del(opts);
return fd;
}
-
-#ifdef _WIN32
-static void socket_cleanup(void)
-{
- WSACleanup();
-}
-#endif
-
-int socket_init(void)
-{
-#ifdef _WIN32
- WSADATA Data;
- int ret, err;
-
- ret = WSAStartup(MAKEWORD(2,2), &Data);
- if (ret != 0) {
- err = WSAGetLastError();
- fprintf(stderr, "WSAStartup: %d\n", err);
- return -1;
- }
- atexit(socket_cleanup);
-#endif
- return 0;
-}

View File

@ -1,70 +0,0 @@
From 2772b3db795ff963a6dc9fade6e561b6e23dea9a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <mlureau@redhat.com>
Date: Mon, 25 Feb 2013 23:31:12 +0100
Subject: [PATCH] build-sys: must link with -fstack-protector
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
It is needed to give that flag to the linker as well, but latest
libtool 2.4.2 still swallows that argument, so let's pass it with
libtool -Wc argument.
qemu-1.4.0/stubs/arch-query-cpu-def.c:6: undefined reference to `__stack_chk_guard'
Signed-off-by: Marc-André Lureau <mlureau@redhat.com>
Reviewed-by: Alon Levy <alevy@redhat.com>
(cherry picked from commit 37746c5eacf309fa019ea0fa45f776c36c561457)
Conflicts:
configure
---
configure | 8 +++++++-
rules.mak | 1 +
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/configure b/configure
index 2996e1d..e8633c5 100755
--- a/configure
+++ b/configure
@@ -1197,7 +1197,7 @@ fi
gcc_flags="-Wold-style-declaration -Wold-style-definition -Wtype-limits"
gcc_flags="-Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers $gcc_flags"
gcc_flags="-Wmissing-include-dirs -Wempty-body -Wnested-externs $gcc_flags"
-gcc_flags="-fstack-protector-all -Wendif-labels $gcc_flags"
+gcc_flags="-Wendif-labels $gcc_flags"
gcc_flags="-Wno-initializer-overrides $gcc_flags"
# Note that we do not add -Werror to gcc_flags here, because that would
# enable it for all configure tests. If a configure test failed due
@@ -1216,6 +1216,11 @@ for flag in $gcc_flags; do
fi
done
+if compile_prog "-Werror -fstack-protector-all" "" ; then
+ QEMU_CFLAGS="$QEMU_CFLAGS -fstack-protector-all"
+ LIBTOOLFLAGS="$LIBTOOLFLAGS -Wc,-fstack-protector-all"
+fi
+
# Workaround for http://gcc.gnu.org/PR55489. Happens with -fPIE/-fPIC and
# large functions that use global variables. The bug is in all releases of
# GCC, but it became particularly acute in 4.6.x and 4.7.x. It is fixed in
@@ -3832,6 +3837,7 @@ fi
echo "LDFLAGS=$LDFLAGS" >> $config_host_mak
echo "ARLIBS_BEGIN=$arlibs_begin" >> $config_host_mak
echo "ARLIBS_END=$arlibs_end" >> $config_host_mak
+echo "LIBTOOLFLAGS=$LIBTOOLFLAGS" >> $config_host_mak
echo "LIBS+=$LIBS" >> $config_host_mak
echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak
echo "EXESUF=$EXESUF" >> $config_host_mak
diff --git a/rules.mak b/rules.mak
index edc2552..36aba2d 100644
--- a/rules.mak
+++ b/rules.mak
@@ -36,6 +36,7 @@ LINK = $(call quiet-command,\
$(if $(filter %.lo %.la,$^),$(LIBTOOL) --mode=link --tag=CC \
)$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \
$(sort $(filter %.o, $1)) $(filter-out %.o, $1) $(version-obj-y) \
+ $(if $(filter %.lo %.la,$^),$(LIBTOOLFLAGS)) \
$(LIBS),$(if $(filter %.lo %.la,$^),"lt LINK ", " LINK ")"$(TARGET_DIR)$@")
endif

View File

@ -1,54 +0,0 @@
From c47df42d06e9bbc8bd7e7a40754f6245f4bea83f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <mlureau@redhat.com>
Date: Mon, 25 Feb 2013 23:31:13 +0100
Subject: [PATCH] libcacard: fix mingw64 cross-compilation
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Compile and link with version.lo
Signed-off-by: Marc-André Lureau <mlureau@redhat.com>
Reviewed-by: Alon Levy <alevy@redhat.com>
(cherry picked from commit 5354e4d242175e067bb70732f694ae9322a81351)
---
Makefile | 8 ++++++--
rules.mak | 3 ++-
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/Makefile b/Makefile
index 0d9099a..751cf1d 100644
--- a/Makefile
+++ b/Makefile
@@ -148,11 +148,15 @@ recurse-all: $(SUBDIR_RULES) $(ROMSUBDIR_RULES)
bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS)
-version.o: $(SRC_PATH)/version.rc config-host.h
+version.o: $(SRC_PATH)/version.rc config-host.h | version.lo
$(call quiet-command,$(WINDRES) -I. -o $@ $<," RC $(TARGET_DIR)$@")
+version.lo: $(SRC_PATH)/version.rc config-host.h
+ $(call quiet-command,$(LIBTOOL) --mode=compile --tag=RC $(WINDRES) -I. -o $@ $<,"lt RC $(TARGET_DIR)$@")
version-obj-$(CONFIG_WIN32) += version.o
-Makefile: $(version-obj-y)
+version-lobj-$(CONFIG_WIN32) += $(if $(LIBTOOL),version.lo)
+Makefile: $(version-obj-y) $(version-lobj-y)
+
######################################################################
# Build libraries
diff --git a/rules.mak b/rules.mak
index 36aba2d..292a422 100644
--- a/rules.mak
+++ b/rules.mak
@@ -35,7 +35,8 @@ LIBTOOL += $(if $(V),,--quiet)
LINK = $(call quiet-command,\
$(if $(filter %.lo %.la,$^),$(LIBTOOL) --mode=link --tag=CC \
)$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \
- $(sort $(filter %.o, $1)) $(filter-out %.o, $1) $(version-obj-y) \
+ $(sort $(filter %.o, $1)) $(filter-out %.o, $1) \
+ $(if $(filter %.lo %.la,$^),$(version-lobj-y),$(version-obj-y)) \
$(if $(filter %.lo %.la,$^),$(LIBTOOLFLAGS)) \
$(LIBS),$(if $(filter %.lo %.la,$^),"lt LINK ", " LINK ")"$(TARGET_DIR)$@")
endif

View File

@ -1,374 +0,0 @@
From 6a7a90c34f62ffca270db3dbe3653f4eb2145c32 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
Date: Mon, 25 Feb 2013 23:31:14 +0100
Subject: [PATCH] libcacard: split vscclient main() from socket reading
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Alon Levy <alevy@redhat.com>
(cherry picked from commit a50b831ae1fe039b7c22793f307e0b8afdf50589)
---
libcacard/vscclient.c | 314 ++++++++++++++++++++++++++------------------------
1 file changed, 162 insertions(+), 152 deletions(-)
diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c
index 9b744f2..5e00db3 100644
--- a/libcacard/vscclient.c
+++ b/libcacard/vscclient.c
@@ -211,6 +211,166 @@ get_id_from_string(char *string, unsigned int default_id)
return id;
}
+static int
+on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming)
+{
+ uint32_t *capabilities = (incoming->capabilities);
+ int num_capabilities =
+ 1 + ((mhHeader->length - sizeof(VSCMsgInit)) / sizeof(uint32_t));
+ int i;
+ int rv;
+ pthread_t thread_id;
+
+ incoming->version = ntohl(incoming->version);
+ if (incoming->version != VSCARD_VERSION) {
+ if (verbose > 0) {
+ printf("warning: host has version %d, we have %d\n",
+ verbose, VSCARD_VERSION);
+ }
+ }
+ if (incoming->magic != VSCARD_MAGIC) {
+ printf("unexpected magic: got %d, expected %d\n",
+ incoming->magic, VSCARD_MAGIC);
+ return -1;
+ }
+ for (i = 0 ; i < num_capabilities; ++i) {
+ capabilities[i] = ntohl(capabilities[i]);
+ }
+ /* Future: check capabilities */
+ /* remove whatever reader might be left in qemu,
+ * in case of an unclean previous exit. */
+ send_msg(VSC_ReaderRemove, VSCARD_MINIMAL_READER_ID, NULL, 0);
+ /* launch the event_thread. This will trigger reader adds for all the
+ * existing readers */
+ rv = pthread_create(&thread_id, NULL, event_thread, NULL);
+ if (rv < 0) {
+ perror("pthread_create");
+ return rv;
+ }
+ return 0;
+}
+
+#define APDUBufSize 270
+
+static int
+do_socket_read(void)
+{
+ int rv;
+ int dwSendLength;
+ int dwRecvLength;
+ uint8_t pbRecvBuffer[APDUBufSize];
+ uint8_t pbSendBuffer[APDUBufSize];
+ VReaderStatus reader_status;
+ VReader *reader = NULL;
+ VSCMsgHeader mhHeader;
+ VSCMsgError *error_msg;
+
+ rv = read(sock, &mhHeader, sizeof(mhHeader));
+ if (rv < sizeof(mhHeader)) {
+ /* Error */
+ if (rv < 0) {
+ perror("header read error\n");
+ } else {
+ fprintf(stderr, "header short read %d\n", rv);
+ }
+ return -1;
+ }
+ mhHeader.type = ntohl(mhHeader.type);
+ mhHeader.reader_id = ntohl(mhHeader.reader_id);
+ mhHeader.length = ntohl(mhHeader.length);
+ if (verbose) {
+ printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n",
+ mhHeader.type, mhHeader.reader_id, mhHeader.length,
+ mhHeader.length);
+ }
+ switch (mhHeader.type) {
+ case VSC_APDU:
+ case VSC_Flush:
+ case VSC_Error:
+ case VSC_Init:
+ rv = read(sock, pbSendBuffer, mhHeader.length);
+ break;
+ default:
+ fprintf(stderr, "Unexpected message of type 0x%X\n", mhHeader.type);
+ return -1;
+ }
+ switch (mhHeader.type) {
+ case VSC_APDU:
+ if (rv < 0) {
+ /* Error */
+ fprintf(stderr, "read error\n");
+ close(sock);
+ return -1;
+ }
+ if (verbose) {
+ printf(" recv APDU: ");
+ print_byte_array(pbSendBuffer, mhHeader.length);
+ }
+ /* Transmit received APDU */
+ dwSendLength = mhHeader.length;
+ dwRecvLength = sizeof(pbRecvBuffer);
+ reader = vreader_get_reader_by_id(mhHeader.reader_id);
+ reader_status = vreader_xfr_bytes(reader,
+ pbSendBuffer, dwSendLength,
+ pbRecvBuffer, &dwRecvLength);
+ if (reader_status == VREADER_OK) {
+ mhHeader.length = dwRecvLength;
+ if (verbose) {
+ printf(" send response: ");
+ print_byte_array(pbRecvBuffer, mhHeader.length);
+ }
+ send_msg(VSC_APDU, mhHeader.reader_id,
+ pbRecvBuffer, dwRecvLength);
+ } else {
+ rv = reader_status; /* warning: not meaningful */
+ send_msg(VSC_Error, mhHeader.reader_id, &rv, sizeof(uint32_t));
+ }
+ vreader_free(reader);
+ reader = NULL; /* we've freed it, don't use it by accident
+ again */
+ break;
+ case VSC_Flush:
+ /* TODO: actually flush */
+ send_msg(VSC_FlushComplete, mhHeader.reader_id, NULL, 0);
+ break;
+ case VSC_Error:
+ error_msg = (VSCMsgError *) pbSendBuffer;
+ if (error_msg->code == VSC_SUCCESS) {
+ qemu_mutex_lock(&pending_reader_lock);
+ if (pending_reader) {
+ vreader_set_id(pending_reader, mhHeader.reader_id);
+ vreader_free(pending_reader);
+ pending_reader = NULL;
+ qemu_cond_signal(&pending_reader_condition);
+ }
+ qemu_mutex_unlock(&pending_reader_lock);
+ break;
+ }
+ printf("warning: qemu refused to add reader\n");
+ if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) {
+ /* clear pending reader, qemu can't handle any more */
+ qemu_mutex_lock(&pending_reader_lock);
+ if (pending_reader) {
+ pending_reader = NULL;
+ /* make sure the event loop doesn't hang */
+ qemu_cond_signal(&pending_reader_condition);
+ }
+ qemu_mutex_unlock(&pending_reader_lock);
+ }
+ break;
+ case VSC_Init:
+ if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) {
+ return -1;
+ }
+ break;
+ default:
+ printf("Default\n");
+ return -1;
+ }
+
+ return 0;
+}
+
static void
do_command(void)
{
@@ -339,8 +499,6 @@ do_command(void)
}
-#define APDUBufSize 270
-
/* just for ease of parsing command line arguments. */
#define MAX_CERTS 100
@@ -385,44 +543,6 @@ connect_to_qemu(
return sock;
}
-static int on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming)
-{
- uint32_t *capabilities = (incoming->capabilities);
- int num_capabilities =
- 1 + ((mhHeader->length - sizeof(VSCMsgInit)) / sizeof(uint32_t));
- int i;
- int rv;
- pthread_t thread_id;
-
- incoming->version = ntohl(incoming->version);
- if (incoming->version != VSCARD_VERSION) {
- if (verbose > 0) {
- printf("warning: host has version %d, we have %d\n",
- verbose, VSCARD_VERSION);
- }
- }
- if (incoming->magic != VSCARD_MAGIC) {
- printf("unexpected magic: got %d, expected %d\n",
- incoming->magic, VSCARD_MAGIC);
- return -1;
- }
- for (i = 0 ; i < num_capabilities; ++i) {
- capabilities[i] = ntohl(capabilities[i]);
- }
- /* Future: check capabilities */
- /* remove whatever reader might be left in qemu,
- * in case of an unclean previous exit. */
- send_msg(VSC_ReaderRemove, VSCARD_MINIMAL_READER_ID, NULL, 0);
- /* launch the event_thread. This will trigger reader adds for all the
- * existing readers */
- rv = pthread_create(&thread_id, NULL, event_thread, NULL);
- if (rv < 0) {
- perror("pthread_create");
- return rv;
- }
- return 0;
-}
-
int
main(
int argc,
@@ -431,21 +551,13 @@ main(
char *qemu_host;
char *qemu_port;
VSCMsgHeader mhHeader;
- VSCMsgError *error_msg;
- int rv;
- int dwSendLength;
- int dwRecvLength;
- uint8_t pbRecvBuffer[APDUBufSize];
- uint8_t pbSendBuffer[APDUBufSize];
- VReaderStatus reader_status;
- VReader *reader = NULL;
VCardEmulOptions *command_line_options = NULL;
char *cert_names[MAX_CERTS];
char *emul_args = NULL;
int cert_count = 0;
- int c;
+ int c, rv;
while ((c = getopt(argc, argv, "c:e:pd:")) != -1) {
switch (c) {
@@ -548,109 +660,7 @@ main(
if (!FD_ISSET(sock, &fds)) {
continue;
}
-
- rv = read(sock, &mhHeader, sizeof(mhHeader));
- if (rv < sizeof(mhHeader)) {
- /* Error */
- if (rv < 0) {
- perror("header read error\n");
- } else {
- fprintf(stderr, "header short read %d\n", rv);
- }
- return 8;
- }
- mhHeader.type = ntohl(mhHeader.type);
- mhHeader.reader_id = ntohl(mhHeader.reader_id);
- mhHeader.length = ntohl(mhHeader.length);
- if (verbose) {
- printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n",
- mhHeader.type, mhHeader.reader_id, mhHeader.length,
- mhHeader.length);
- }
- switch (mhHeader.type) {
- case VSC_APDU:
- case VSC_Flush:
- case VSC_Error:
- case VSC_Init:
- rv = read(sock, pbSendBuffer, mhHeader.length);
- break;
- default:
- fprintf(stderr, "Unexpected message of type 0x%X\n", mhHeader.type);
- return 0;
- }
- switch (mhHeader.type) {
- case VSC_APDU:
- if (rv < 0) {
- /* Error */
- fprintf(stderr, "read error\n");
- close(sock);
- return 8;
- }
- if (verbose) {
- printf(" recv APDU: ");
- print_byte_array(pbSendBuffer, mhHeader.length);
- }
- /* Transmit received APDU */
- dwSendLength = mhHeader.length;
- dwRecvLength = sizeof(pbRecvBuffer);
- reader = vreader_get_reader_by_id(mhHeader.reader_id);
- reader_status = vreader_xfr_bytes(reader,
- pbSendBuffer, dwSendLength,
- pbRecvBuffer, &dwRecvLength);
- if (reader_status == VREADER_OK) {
- mhHeader.length = dwRecvLength;
- if (verbose) {
- printf(" send response: ");
- print_byte_array(pbRecvBuffer, mhHeader.length);
- }
- send_msg(VSC_APDU, mhHeader.reader_id,
- pbRecvBuffer, dwRecvLength);
- } else {
- rv = reader_status; /* warning: not meaningful */
- send_msg(VSC_Error, mhHeader.reader_id, &rv, sizeof(uint32_t));
- }
- vreader_free(reader);
- reader = NULL; /* we've freed it, don't use it by accident
- again */
- break;
- case VSC_Flush:
- /* TODO: actually flush */
- send_msg(VSC_FlushComplete, mhHeader.reader_id, NULL, 0);
- break;
- case VSC_Error:
- error_msg = (VSCMsgError *) pbSendBuffer;
- if (error_msg->code == VSC_SUCCESS) {
- qemu_mutex_lock(&pending_reader_lock);
- if (pending_reader) {
- vreader_set_id(pending_reader, mhHeader.reader_id);
- vreader_free(pending_reader);
- pending_reader = NULL;
- qemu_cond_signal(&pending_reader_condition);
- }
- qemu_mutex_unlock(&pending_reader_lock);
- break;
- }
- printf("warning: qemu refused to add reader\n");
- if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) {
- /* clear pending reader, qemu can't handle any more */
- qemu_mutex_lock(&pending_reader_lock);
- if (pending_reader) {
- pending_reader = NULL;
- /* make sure the event loop doesn't hang */
- qemu_cond_signal(&pending_reader_condition);
- }
- qemu_mutex_unlock(&pending_reader_lock);
- }
- break;
- case VSC_Init:
- if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) {
- return -1;
- }
- break;
- default:
- printf("Default\n");
- return 0;
- }
+ rv = do_socket_read();
} while (rv >= 0);
return 0;

Some files were not shown because too many files have changed in this diff Show More