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:
commit
5f9089d1b5
8
.gitignore
vendored
8
.gitignore
vendored
@ -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
|
||||
|
@ -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);
|
@ -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 +-
|
||||
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
@ -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);
|
||||
|
||||
/**
|
@ -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(). */
|
@ -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/core/qdev.c | 6 +++---
|
||||
hw/pci/pci.c | 31 ++++++++++++++++---------------
|
||||
hw/qdev-core.h | 2 +-
|
||||
hw/qdev.c | 6 +++---
|
||||
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)
|
@ -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) {
|
248
0004-virtio-bus-remove-vdev-field.patch
Normal file
248
0004-virtio-bus-remove-vdev-field.patch
Normal 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 */
|
@ -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;
|
447
0005-virtio-pci-remove-vdev-field.patch
Normal file
447
0005-virtio-pci-remove-vdev-field.patch
Normal 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;
|
@ -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 {
|
293
0006-virtio-ccw-remove-vdev-field.patch
Normal file
293
0006-virtio-ccw-remove-vdev-field.patch
Normal 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++) {
|
148
0007-virtio-bus-cleanup-plug-unplug-interface.patch
Normal file
148
0007-virtio-bus-cleanup-plug-unplug-interface.patch
Normal 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);
|
@ -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)
|
@ -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);
|
||||
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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,
|
||||
};
|
||||
|
||||
/*
|
@ -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;
|
@ -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;
|
112
0011-virtio-scsi-switch-exit-callback-to-VirtioDeviceClas.patch
Normal file
112
0011-virtio-scsi-switch-exit-callback-to-VirtioDeviceClas.patch
Normal 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 */
|
@ -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);
|
@ -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;
|
@ -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;
|
||||
}
|
||||
|
59
0014-virtio-pci-add-device_unplugged-callback.patch
Normal file
59
0014-virtio-pci-add-device_unplugged-callback.patch
Normal 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 = {
|
72
0101-block-Close-backing-file-early-in-bdrv_img_create.patch
Normal file
72
0101-block-Close-backing-file-early-in-bdrv_img_create.patch
Normal 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);
|
||||
}
|
@ -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;
|
@ -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;
|
@ -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 },
|
@ -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;
|
@ -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);
|
@ -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) {
|
@ -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:
|
@ -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;
|
90
0105-scsi-disk-fix-VERIFY-emulation.patch
Normal file
90
0105-scsi-disk-fix-VERIFY-emulation.patch
Normal 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,
|
@ -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);
|
||||
}
|
@ -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();
|
@ -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);
|
||||
}
|
@ -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, ¶ms);
|
||||
@@ -1798,6 +1788,9 @@ out:
|
||||
if (ret == 0) {
|
||||
ret = qemu_file_get_error(f);
|
||||
}
|
||||
+ if (ret != 0) {
|
||||
+ qemu_savevm_state_cancel();
|
||||
+ }
|
||||
|
||||
return ret;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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, ¶ms);
|
||||
- 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, ¶ms);
|
||||
+ 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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
@ -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) {
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
@ -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++;
|
@ -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;
|
||||
|
@ -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;
|
@ -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.
|
@ -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,
|
@ -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);
|
@ -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, ¶ms);
|
||||
+ qemu_mutex_lock_iothread();
|
||||
+
|
||||
while (qemu_file_get_error(f) == 0) {
|
||||
if (qemu_savevm_state_iterate(f) > 0) {
|
||||
break;
|
@ -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)
|
@ -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);
|
||||
}
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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();
|
@ -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;
|
||||
}
|
@ -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;
|
@ -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,
|
@ -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;
|
||||
}
|
@ -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;
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
@ -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);
|
@ -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,
|
@ -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 */
|
@ -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);
|
@ -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)
|
@ -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)
|
@ -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);
|
@ -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);
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
@ -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,
|
@ -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,
|
@ -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",\
|
@ -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(),
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
@ -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 */
|
@ -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) {
|
@ -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);
|
@ -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);
|
@ -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', '_'
|
||||
|
||||
|
@ -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;
|
@ -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);
|
@ -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
|
@ -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;
|
@ -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;
|
||||
-}
|
@ -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
|
||||
|
@ -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
|
@ -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
Loading…
Reference in New Issue
Block a user