Compare commits

...

5 Commits

Author SHA1 Message Date
Paolo Bonzini 04f3006c4f add fix-ipv6-brackets.patch 2013-06-04 23:40:27 +02:00
Dan Horák 742904e1a4 - Install the qemu-kvm.1 man page only on arches with kvm 2013-05-27 14:33:18 +02:00
Cole Robinson a7b9285033 Update to qemu stable 1.4.2
Alias qemu-system-* man page to qemu.1 (bz #907746)
Drop execute bit on service files (bz #963917)
Conditionalize KSM service on host virt support (bz #963681)
Split out KSM package, make it not pulled in by default
2013-05-25 15:13:26 -04:00
Alon Levy b37e2081e5 adding fix for div by zero introduced by migration cleanup rebase 2013-05-23 10:29:37 -04:00
Alon Levy 408bdb5e74 backport migration cleanup (bz #962954) 2013-05-22 21:48:57 -04:00
73 changed files with 5046 additions and 128 deletions

1
.gitignore vendored
View File

@ -19,3 +19,4 @@ 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

View File

@ -1,4 +1,4 @@
From bed754a15e27a3630681959cf1d3161084f29fe9 Mon Sep 17 00:00:00 2001
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

View File

@ -1,4 +1,4 @@
From de768f74c31d04063889c5dc588d55bc19cf7315 Mon Sep 17 00:00:00 2001
From 260acf7f716aa138138dc301b80a1bd10761b0bc Mon Sep 17 00:00:00 2001
From: Amit Shah <amit.shah@redhat.com>
Date: Mon, 21 Mar 2011 20:31:45 +0100
Subject: [PATCH] char: Add a QemuChrHandlers struct to initialise chardev
@ -764,7 +764,7 @@ index 47ac8c9..2f8757f 100644
if (s->cs->opened && !dev->attached) {
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 8c0ead0..bb07c62 100644
index 1406e3f..2ee9ad1 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -1227,6 +1227,12 @@ static void usbredir_chardev_event(void *opaque, int event)

View File

@ -1,4 +1,4 @@
From 64080f1b8983660b707ed8c0d10ace22e9b46f7a Mon Sep 17 00:00:00 2001
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

View File

@ -1,4 +1,4 @@
From 84877040f31425a8fecdbee19cb24fcc5a8212df Mon Sep 17 00:00:00 2001
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

View File

@ -1,4 +1,4 @@
From c7e9b2a5b981209f4e77b26562758663cc060900 Mon Sep 17 00:00:00 2001
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

View File

@ -1,4 +1,4 @@
From 6540bebbaa749d405df91516e1ca5a075e354628 Mon Sep 17 00:00:00 2001
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

View File

@ -1,4 +1,4 @@
From 33f3874dc760f0960d408be2f916d04373de543b Mon Sep 17 00:00:00 2001
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

View File

@ -1,4 +1,4 @@
From aa0a2c94c70ae5ed0fb215328c8ecebbef10cbe9 Mon Sep 17 00:00:00 2001
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

View File

@ -1,4 +1,4 @@
From de979c48aa4b5e7f3f8658f9ac69030f3de3c99c Mon Sep 17 00:00:00 2001
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

View File

@ -1,4 +1,4 @@
From 1e87b85766f9c18a2f9dffd289c0e56d640637c4 Mon Sep 17 00:00:00 2001
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
@ -9,7 +9,7 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index bb07c62..4d23b66 100644
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)

View File

@ -1,4 +1,4 @@
From 42931bebb2856307dcdc9babc5dd9954b60c8094 Mon Sep 17 00:00:00 2001
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

View File

@ -1,4 +1,4 @@
From 81ab56732f4990c288c88a545925dc4431c313d2 Mon Sep 17 00:00:00 2001
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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,46 +0,0 @@
From f76e7a03ac948a7649878d7ddbb02ace0f6e3625 Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso@redhat.com>
Date: Wed, 20 Feb 2013 11:14:45 -0500
Subject: [PATCH] docs: Fix generating qemu-doc.html with texinfo 5
LC_ALL=C makeinfo --no-headers --no-split --number-sections --html qemu-doc.texi -o qemu-doc.html
./qemu-options.texi:1521: unknown command `list'
./qemu-options.texi:1521: table requires an argument: the formatter for @item
./qemu-options.texi:1521: warning: @table has text but no @item
CC: qemu-stable@nongnu.org
Signed-off-by: Cole Robinson <crobinso@redhat.com>
---
qemu-options.hx | 19 +++++++------------
1 file changed, 7 insertions(+), 12 deletions(-)
diff --git a/qemu-options.hx b/qemu-options.hx
index 15dc29e..470c2b4 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2092,18 +2092,13 @@ QEMU supports using either local sheepdog devices or remote networked
devices.
Syntax for specifying a sheepdog device
-@table @list
-``sheepdog:<vdiname>''
-
-``sheepdog:<vdiname>:<snapid>''
-
-``sheepdog:<vdiname>:<tag>''
-
-``sheepdog:<host>:<port>:<vdiname>''
-
-``sheepdog:<host>:<port>:<vdiname>:<snapid>''
-
-``sheepdog:<host>:<port>:<vdiname>:<tag>''
+@table @code
+@item sheepdog:<vdiname>
+@item sheepdog:<vdiname>:<snapid>
+@item sheepdog:<vdiname>:<tag>
+@item sheepdog:<host>:<port>:<vdiname>
+@item sheepdog:<host>:<port>:<vdiname>:<snapid>
+@item sheepdog:<host>:<port>:<vdiname>:<tag>
@end table
Example

View File

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

View File

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

View File

@ -1,31 +0,0 @@
From 106a39c50211b7c7e96ffb47ad9deae5d9be6d84 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Fri, 15 Mar 2013 11:52:37 +0100
Subject: [PATCH] usb-redir: Fix crash on migration with no client connected
If no client is connected on the src side, then we won't receive a
parser during migrate, in this case usbredir_post_load() should be a nop,
rather then to try to derefefence the NULL dev->parser pointer.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 3713e1485e6eace7d48b9c790602cfd92c616e5f)
---
hw/usb/redirect.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 4d23b66..bf6aaf0 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -2008,6 +2008,10 @@ static int usbredir_post_load(void *priv, int version_id)
{
USBRedirDevice *dev = priv;
+ if (dev->parser == NULL) {
+ return 0;
+ }
+
switch (dev->device_info.speed) {
case usb_redir_speed_low:
dev->dev.speed = USB_SPEED_LOW;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
From c6c153bfd7f9da48eb541d78bf09bc03bcc337e5 Mon Sep 17 00:00:00 2001
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
@ -16,7 +16,7 @@ Signed-off-by: Cole Robinson <crobinso@redhat.com>
1 file changed, 10 insertions(+)
diff --git a/configure b/configure
index e7468a9..719e348 100755
index f4097ef..bc2870b 100755
--- a/configure
+++ b/configure
@@ -170,6 +170,7 @@ xfs=""
@ -46,7 +46,7 @@ index e7468a9..719e348 100755
echo " --enable-tcg-interpreter enable TCG with bytecode interpreter (TCI)"
echo " --disable-nptl disable usermode NPTL support"
echo " --enable-nptl enable usermode NPTL support"
@@ -3324,6 +3330,7 @@ echo "Linux AIO support $linux_aio"
@@ -3358,6 +3364,7 @@ echo "Linux AIO support $linux_aio"
echo "ATTR/XATTR support $attr"
echo "Install blobs $blobs"
echo "KVM support $kvm"
@ -54,7 +54,7 @@ index e7468a9..719e348 100755
echo "TCG interpreter $tcg_interpreter"
echo "fdt support $fdt"
echo "preadv support $preadv"
@@ -3612,6 +3619,9 @@ fi
@@ -3646,6 +3653,9 @@ fi
if test "$signalfd" = "yes" ; then
echo "CONFIG_SIGNALFD=y" >> $config_host_mak
fi

View File

@ -1,4 +1,4 @@
From 75e3acce2d9302a2344b3de381a49f6cd0fa04ad Mon Sep 17 00:00:00 2001
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

View File

@ -1,4 +1,4 @@
From c50ed212c0b0814a0edefb2d2a2fc7abc6aed2af Mon Sep 17 00:00:00 2001
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

View File

@ -1,4 +1,4 @@
From 271e4d924c39efd716cc3ad86a5f615660b13f22 Mon Sep 17 00:00:00 2001
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

View File

@ -1,4 +1,4 @@
From 66cc6383d6b1d934d22e9a16b432cacacd58c315 Mon Sep 17 00:00:00 2001
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

81
fix-ipv6-brackets.patch Normal file
View File

@ -0,0 +1,81 @@
needed for rh summit demo, jan tomko should get a better patch in 1.5.1.
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index fdd8dc4..e3051f3 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -61,6 +61,25 @@ QemuOptsList socket_optslist = {
},
};
+static int qemu_getaddrinfo(const char *node, const char *service,
+ const struct addrinfo *hints,
+ struct addrinfo **res)
+{
+ int ret;
+
+ if (node[0] == '[') {
+ int len = strlen(node);
+ if (node[len - 1] == ']') {
+ char *ipv6_node = g_strndup(node + 1, len - 2);
+ ret = getaddrinfo(ipv6_node, service, hints, res);
+ g_free(ipv6_node);
+ return ret;
+ }
+ }
+
+ return getaddrinfo(node, service, hints, res);
+}
+
static int inet_getport(struct addrinfo *e)
{
struct sockaddr_in *i4;
@@ -136,7 +155,7 @@ int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp)
/* lookup */
if (port_offset)
snprintf(port, sizeof(port), "%d", atoi(port) + port_offset);
- rc = getaddrinfo(strlen(addr) ? addr : NULL, port, &ai, &res);
+ rc = qemu_getaddrinfo(strlen(addr) ? addr : NULL, port, &ai, &res);
if (rc != 0) {
error_setg(errp, "address resolution failed for %s:%s: %s", addr, port,
gai_strerror(rc));
@@ -328,7 +347,7 @@ static struct addrinfo *inet_parse_connect_opts(QemuOpts *opts, Error **errp)
}
/* lookup */
- rc = getaddrinfo(addr, port, &ai, &res);
+ rc = qemu_getaddrinfo(addr, port, &ai, &res);
if (rc != 0) {
error_setg(errp, "address resolution failed for %s:%s: %s", addr, port,
gai_strerror(rc));
@@ -424,7 +443,7 @@ int inet_dgram_opts(QemuOpts *opts, Error **errp)
if (qemu_opt_get_bool(opts, "ipv6", 0))
ai.ai_family = PF_INET6;
- if (0 != (rc = getaddrinfo(addr, port, &ai, &peer))) {
+ if (0 != (rc = qemu_getaddrinfo(addr, port, &ai, &peer))) {
error_setg(errp, "address resolution failed for %s:%s: %s", addr, port,
gai_strerror(rc));
return -1;
@@ -444,7 +463,7 @@ int inet_dgram_opts(QemuOpts *opts, Error **errp)
if (!port || strlen(port) == 0)
port = "0";
- if (0 != (rc = getaddrinfo(addr, port, &ai, &local))) {
+ if (0 != (rc = qemu_getaddrinfo(addr, port, &ai, &local))) {
error_setg(errp, "address resolution failed for %s:%s: %s", addr, port,
gai_strerror(rc));
goto err;
@@ -506,10 +525,11 @@ InetSocketAddress *inet_parse(const char *str, Error **errp)
}
} else if (str[0] == '[') {
/* IPv6 addr */
- if (2 != sscanf(str, "[%64[^]]]:%32[^,]%n", host, port, &pos)) {
+ if (2 != sscanf(str, "%63[^]]]:%32[^,]%n", host, port, &pos)) {
error_setg(errp, "error parsing IPv6 address '%s'", str);
goto fail;
}
+ strcat(host, "]");
addr->ipv6 = addr->has_ipv6 = true;
} else if (qemu_isdigit(str[0])) {
/* IPv4 addr */

View File

@ -1,6 +1,7 @@
[Unit]
Description=Kernel Samepage Merging
ConditionPathExists=/sys/kernel/mm/ksm
ConditionVirtualization=no
[Service]
Type=oneshot

View File

@ -2,6 +2,7 @@
Description=Kernel Samepage Merging (KSM) Tuning Daemon
After=ksm.service
Requires=ksm.service
ConditionVirtualization=no
[Service]
ExecStart=/usr/sbin/ksmtuned

210
qemu.spec
View File

@ -130,7 +130,7 @@
Summary: QEMU is a FAST! processor emulator
Name: qemu
Version: 1.4.1
Version: 1.4.2
Release: 3%{?dist}
# Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped
Epoch: 2
@ -187,17 +187,64 @@ Patch0010: 0010-usb-redir-Add-flow-control-support.patch
Patch0011: 0011-char-Disable-write-callback-if-throttled-chardev-is-.patch
Patch0012: 0012-hw-virtio-serial-bus-replay-guest-open-on-destinatio.patch
# Fix migration crash with spice (bz #962954)
Patch0101: 0101-vnc-tls-Fix-compilation-with-newer-versions-of-GNU-T.patch
Patch0102: 0102-migration-change-initial-value-of-expected_downtime.patch
Patch0103: 0103-migration-calculate-end-time-after-we-have-sent-the-.patch
Patch0104: 0104-migration-don-t-account-sleep-time-for-calculating-b.patch
Patch0105: 0105-migration-calculate-expected_downtime.patch
Patch0106: 0106-migration-simplify-while-loop.patch
Patch0107: 0107-migration-always-use-vm_stop_force_state.patch
Patch0108: 0108-migration-move-more-error-handling-to-migrate_fd_cle.patch
Patch0109: 0109-migration-push-qemu_savevm_state_cancel-out-of-qemu_.patch
Patch0110: 0110-block-migration-remove-useless-calls-to-blk_mig_clea.patch
Patch0111: 0111-qemu-file-pass-errno-from-qemu_fflush-via-f-last_err.patch
Patch0112: 0112-migration-use-qemu_file_set_error-to-pass-error-code.patch
Patch0113: 0113-qemu-file-temporarily-expose-qemu_file_set_error-and.patch
Patch0114: 0114-migration-flush-all-data-to-fd-when-buffered_flush-i.patch
Patch0115: 0115-migration-use-qemu_file_set_error.patch
Patch0116: 0116-migration-simplify-error-handling.patch
Patch0117: 0117-migration-do-not-nest-flushing-of-device-data.patch
Patch0118: 0118-migration-add-migrate_set_state-tracepoint.patch
Patch0119: 0119-migration-prepare-to-access-s-state-outside-critical.patch
Patch0120: 0120-migration-cleanup-migration-including-thread-in-the-.patch
Patch0121: 0121-block-migration-remove-variables-that-are-never-read.patch
Patch0122: 0122-block-migration-small-preparatory-changes-for-lockin.patch
Patch0123: 0123-block-migration-document-usage-of-state-across-threa.patch
Patch0124: 0124-block-migration-add-lock.patch
Patch0125: 0125-migration-reorder-SaveVMHandlers-members.patch
Patch0126: 0126-migration-run-pending-iterate-callbacks-out-of-big-l.patch
Patch0127: 0127-migration-run-setup-callbacks-out-of-big-lock.patch
Patch0128: 0128-migration-yay-buffering-is-gone.patch
Patch0129: 0129-Rename-buffered_-to-migration_.patch
Patch0130: 0130-qemu-file-make-qemu_fflush-and-qemu_file_set_error-p.patch
Patch0131: 0131-migration-eliminate-last_round.patch
Patch0132: 0132-migration-detect-error-before-sleeping.patch
Patch0133: 0133-migration-remove-useless-qemu_file_get_error-check.patch
Patch0134: 0134-migration-use-qemu_file_rate_limit-consistently.patch
Patch0135: 0135-migration-merge-qemu_popen_cmd-with-qemu_popen.patch
Patch0136: 0136-qemu-file-fsync-a-writable-stdio-QEMUFile.patch
Patch0137: 0137-qemu-file-check-exit-status-when-closing-a-pipe-QEMU.patch
Patch0138: 0138-qemu-file-add-writable-socket-QEMUFile.patch
Patch0139: 0139-qemu-file-simplify-and-export-qemu_ftell.patch
Patch0140: 0140-migration-use-QEMUFile-for-migration-channel-lifetim.patch
Patch0141: 0141-migration-use-QEMUFile-for-writing-outgoing-migratio.patch
Patch0142: 0142-migration-use-qemu_ftell-to-compute-bandwidth.patch
Patch0143: 0143-migration-small-changes-around-rate-limiting.patch
Patch0144: 0144-migration-move-rate-limiting-to-QEMUFile.patch
Patch0145: 0145-migration-move-contents-of-migration_close-to-migrat.patch
Patch0146: 0146-migration-eliminate-s-migration_file.patch
Patch0147: 0147-migration-inline-migrate_fd_close.patch
Patch0148: 0148-Revert-migration-don-t-account-sleep-time-for-calcul.patch
# qemu-kvm migration compat (posted upstream)
Patch0101: 0101-configure-Add-enable-migration-from-qemu-kvm.patch
Patch0102: 0102-acpi_piix4-Drop-minimum_version_id-to-handle-qemu-kv.patch
Patch0103: 0103-i8254-Fix-migration-from-qemu-kvm-1.1.patch
Patch0104: 0104-pc_piix-Add-compat-handling-for-qemu-kvm-VGA-mem-siz.patch
# Fix migration w/ qxl from qemu-kvm 1.2 (solution pending upstream)
Patch0105: 0105-qxl-Add-rom_size-compat-property-fix-migration-from-.patch
# Fix generating docs with texinfo 5 (posted upstream)
Patch0106: 0106-docs-Fix-generating-qemu-doc.html-with-texinfo-5.patch
# Fix crash with usbredir (bz #962826)
Patch0107: 0107-usb-redir-Fix-crash-on-migration-with-no-client-conn.patch
Patch0201: 0201-configure-Add-enable-migration-from-qemu-kvm.patch
Patch0202: 0202-acpi_piix4-Drop-minimum_version_id-to-handle-qemu-kv.patch
Patch0203: 0203-i8254-Fix-migration-from-qemu-kvm-1.1.patch
Patch0204: 0204-pc_piix-Add-compat-handling-for-qemu-kvm-VGA-mem-siz.patch
Patch0205: 0205-qxl-Add-rom_size-compat-property-fix-migration-from-.patch
Patch0999: fix-ipv6-brackets.patch
BuildRequires: SDL-devel
BuildRequires: zlib-devel
@ -400,6 +447,19 @@ This package does not need to be installed on the host OS.
%systemd_postun_with_restart qemu-guest-agent.service
%package -n ksm
Summary: Kernel Samepage Merging services
Group: Development/Tools
Requires: %{name}-common = %{epoch}:%{version}-%{release}
Requires(post): systemd-units
Requires(postun): systemd-units
%description -n ksm
Kernel Samepage Merging (KSM) is a memory-saving de-duplication feature,
that merges anonymous (private) pages (not pagecache ones).
This package provides service files for disabling and tuning KSM.
%if 0%{?user:1}
%package %{user}
Summary: QEMU user mode emulation of qemu targets
@ -661,17 +721,64 @@ CAC emulation development files.
%patch0011 -p1
%patch0012 -p1
# qemu-kvm migration compat (posted upstream)
# Fix migration crash with spice (bz #962954)
%patch0101 -p1
%patch0102 -p1
%patch0103 -p1
%patch0104 -p1
# Fix migration w/ qxl from qemu-kvm 1.2 (solution pending upstream)
%patch0105 -p1
# Fix generating docs with texinfo 5 (posted upstream)
%patch0106 -p1
# Fix crash with usbredir (bz #962826)
%patch0107 -p1
%patch0108 -p1
%patch0109 -p1
%patch0110 -p1
%patch0111 -p1
%patch0112 -p1
%patch0113 -p1
%patch0114 -p1
%patch0115 -p1
%patch0116 -p1
%patch0117 -p1
%patch0118 -p1
%patch0119 -p1
%patch0120 -p1
%patch0121 -p1
%patch0122 -p1
%patch0123 -p1
%patch0124 -p1
%patch0125 -p1
%patch0126 -p1
%patch0127 -p1
%patch0128 -p1
%patch0129 -p1
%patch0130 -p1
%patch0131 -p1
%patch0132 -p1
%patch0133 -p1
%patch0134 -p1
%patch0135 -p1
%patch0136 -p1
%patch0137 -p1
%patch0138 -p1
%patch0139 -p1
%patch0140 -p1
%patch0141 -p1
%patch0142 -p1
%patch0143 -p1
%patch0144 -p1
%patch0145 -p1
%patch0146 -p1
%patch0147 -p1
%patch0148 -p1
# qemu-kvm migration compat (posted upstream)
%patch0201 -p1
%patch0202 -p1
%patch0203 -p1
%patch0204 -p1
%patch0205 -p1
%patch0999 -p1
%build
@ -755,11 +862,11 @@ gcc %{SOURCE6} -O2 -g -o ksmctl
%define _udevdir /lib/udev/rules.d
install -D -p -m 0755 %{SOURCE4} $RPM_BUILD_ROOT/lib/systemd/system/ksm.service
install -D -p -m 0744 %{SOURCE4} $RPM_BUILD_ROOT/lib/systemd/system/ksm.service
install -D -p -m 0644 %{SOURCE5} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/ksm
install -D -p -m 0755 ksmctl $RPM_BUILD_ROOT/lib/systemd/ksmctl
install -D -p -m 0755 %{SOURCE7} $RPM_BUILD_ROOT/lib/systemd/system/ksmtuned.service
install -D -p -m 0744 %{SOURCE7} $RPM_BUILD_ROOT/lib/systemd/system/ksmtuned.service
install -D -p -m 0755 %{SOURCE8} $RPM_BUILD_ROOT%{_sbindir}/ksmtuned
install -D -p -m 0644 %{SOURCE9} $RPM_BUILD_ROOT%{_sysconfdir}/ksmtuned.conf
@ -789,6 +896,12 @@ rm $RPM_BUILD_ROOT%{_datadir}/systemtap/tapset/qemu-system-%{kvm_target}.stp
chmod -x ${RPM_BUILD_ROOT}%{_mandir}/man1/*
install -D -p -m 0644 -t ${RPM_BUILD_ROOT}%{qemudocdir} Changelog README TODO COPYING COPYING.LIB LICENSE
for emu in $RPM_BUILD_ROOT%{_bindir}/qemu-system-*; do
ln -sf qemu.1.gz $RPM_BUILD_ROOT%{_mandir}/man1/$(basename $emu).1.gz
done
%if 0%{?need_qemu_kvm}
ln -sf qemu.1.gz $RPM_BUILD_ROOT%{_mandir}/man1/qemu-kvm.1.gz
%endif
install -D -p -m 0644 qemu.sasl $RPM_BUILD_ROOT%{_sysconfdir}/sasl2/qemu.conf
@ -951,22 +1064,19 @@ udevadm trigger --subsystem-match=misc --sysname-match=kvm --action=add || :
%if %{without separate_kvm}
%post common
%systemd_post ksm.service
%systemd_post ksmtuned.service
getent group kvm >/dev/null || groupadd -g 36 -r kvm
getent group qemu >/dev/null || groupadd -g 107 -r qemu
getent passwd qemu >/dev/null || \
useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \
-c "qemu user" qemu
%preun common
%post -n ksm
%systemd_post ksm.service
%systemd_post ksmtuned.service
%preun -n ksm
%systemd_preun ksm.service
%systemd_preun ksmtuned.service
%postun common
%postun -n ksm
%systemd_postun_with_restart ksm.service
%systemd_postun_with_restart ksmtuned.service
%endif
@ -988,7 +1098,8 @@ getent passwd qemu >/dev/null || \
%if 0%{?need_qemu_kvm}
%global qemu_kvm_files \
%{_bindir}/qemu-kvm
%{_bindir}/qemu-kvm \
%{_mandir}/man1/qemu-kvm.1*
%endif
%files
@ -1018,7 +1129,11 @@ getent passwd qemu >/dev/null || \
%{_bindir}/virtfs-proxy-helper
%{_libexecdir}/qemu-bridge-helper
%config(noreplace) %{_sysconfdir}/sasl2/qemu.conf
%dir %{_sysconfdir}/qemu
%config(noreplace) %{_sysconfdir}/qemu/bridge.conf
%if %{without separate_kvm}
%files -n ksm
/lib/systemd/system/ksm.service
/lib/systemd/ksmctl
%config(noreplace) %{_sysconfdir}/sysconfig/ksm
@ -1026,8 +1141,6 @@ getent passwd qemu >/dev/null || \
%{_sbindir}/ksmtuned
%config(noreplace) %{_sysconfdir}/ksmtuned.conf
%endif
%dir %{_sysconfdir}/qemu
%config(noreplace) %{_sysconfdir}/qemu/bridge.conf
%if %{without separate_kvm}
%files guest-agent
@ -1096,6 +1209,8 @@ getent passwd qemu >/dev/null || \
%{_bindir}/qemu-system-x86_64
%{_datadir}/systemtap/tapset/qemu-system-i386.stp
%{_datadir}/systemtap/tapset/qemu-system-x86_64.stp
%{_mandir}/man1/qemu-system-i386.1*
%{_mandir}/man1/qemu-system-x86_64.1*
%endif
%{_datadir}/%{name}/acpi-dsdt.aml
%{_datadir}/%{name}/q35-acpi-dsdt.aml
@ -1135,6 +1250,7 @@ getent passwd qemu >/dev/null || \
%defattr(-,root,root)
%{_bindir}/qemu-system-alpha
%{_datadir}/systemtap/tapset/qemu-system-alpha.stp
%{_mandir}/man1/qemu-system-alpha.1*
%{_datadir}/%{name}/palcode-clipper
%endif
@ -1143,6 +1259,7 @@ getent passwd qemu >/dev/null || \
%defattr(-,root,root)
%{_bindir}/qemu-system-arm
%{_datadir}/systemtap/tapset/qemu-system-arm.stp
%{_mandir}/man1/qemu-system-arm.1*
%endif
%if 0%{?system_mips:1}
@ -1156,6 +1273,10 @@ getent passwd qemu >/dev/null || \
%{_datadir}/systemtap/tapset/qemu-system-mipsel.stp
%{_datadir}/systemtap/tapset/qemu-system-mips64el.stp
%{_datadir}/systemtap/tapset/qemu-system-mips64.stp
%{_mandir}/man1/qemu-system-mips.1*
%{_mandir}/man1/qemu-system-mipsel.1*
%{_mandir}/man1/qemu-system-mips64el.1*
%{_mandir}/man1/qemu-system-mips64.1*
%endif
%if 0%{?system_cris:1}
@ -1163,6 +1284,7 @@ getent passwd qemu >/dev/null || \
%defattr(-,root,root)
%{_bindir}/qemu-system-cris
%{_datadir}/systemtap/tapset/qemu-system-cris.stp
%{_mandir}/man1/qemu-system-cris.1*
%endif
%if 0%{?system_lm32:1}
@ -1170,6 +1292,7 @@ getent passwd qemu >/dev/null || \
%defattr(-,root,root)
%{_bindir}/qemu-system-lm32
%{_datadir}/systemtap/tapset/qemu-system-lm32.stp
%{_mandir}/man1/qemu-system-lm32.1*
%endif
%if 0%{?system_m68k:1}
@ -1177,6 +1300,7 @@ getent passwd qemu >/dev/null || \
%defattr(-,root,root)
%{_bindir}/qemu-system-m68k
%{_datadir}/systemtap/tapset/qemu-system-m68k.stp
%{_mandir}/man1/qemu-system-m68k.1*
%endif
%if 0%{?system_microblaze:1}
@ -1186,6 +1310,8 @@ getent passwd qemu >/dev/null || \
%{_bindir}/qemu-system-microblazeel
%{_datadir}/systemtap/tapset/qemu-system-microblaze.stp
%{_datadir}/systemtap/tapset/qemu-system-microblazeel.stp
%{_mandir}/man1/qemu-system-microblaze.1*
%{_mandir}/man1/qemu-system-microblazeel.1*
%{_datadir}/%{name}/petalogix*.dtb
%endif
@ -1194,6 +1320,7 @@ getent passwd qemu >/dev/null || \
%defattr(-,root,root)
%{_bindir}/qemu-system-or32
%{_datadir}/systemtap/tapset/qemu-system-or32.stp
%{_mandir}/man1/qemu-system-or32.1*
%endif
%if 0%{?system_s390x:1}
@ -1201,6 +1328,7 @@ getent passwd qemu >/dev/null || \
%defattr(-,root,root)
%{_bindir}/qemu-system-s390x
%{_datadir}/systemtap/tapset/qemu-system-s390x.stp
%{_mandir}/man1/qemu-system-s390x.1*
%{_datadir}/%{name}/s390-zipl.rom
%ifarch s390x
%{?kvm_files:}
@ -1215,6 +1343,8 @@ getent passwd qemu >/dev/null || \
%{_bindir}/qemu-system-sh4eb
%{_datadir}/systemtap/tapset/qemu-system-sh4.stp
%{_datadir}/systemtap/tapset/qemu-system-sh4eb.stp
%{_mandir}/man1/qemu-system-sh4.1*
%{_mandir}/man1/qemu-system-sh4eb.1*
%endif
%if 0%{?system_sparc:1}
@ -1224,6 +1354,8 @@ getent passwd qemu >/dev/null || \
%{_bindir}/qemu-system-sparc64
%{_datadir}/systemtap/tapset/qemu-system-sparc.stp
%{_datadir}/systemtap/tapset/qemu-system-sparc64.stp
%{_mandir}/man1/qemu-system-sparc.1*
%{_mandir}/man1/qemu-system-sparc64.1*
%endif
%if 0%{?system_ppc:1}
@ -1236,6 +1368,9 @@ getent passwd qemu >/dev/null || \
%{_datadir}/systemtap/tapset/qemu-system-ppc.stp
%{_datadir}/systemtap/tapset/qemu-system-ppc64.stp
%{_datadir}/systemtap/tapset/qemu-system-ppcemb.stp
%{_mandir}/man1/qemu-system-ppc.1*
%{_mandir}/man1/qemu-system-ppc64.1*
%{_mandir}/man1/qemu-system-ppcemb.1*
%endif
%{_datadir}/%{name}/bamboo.dtb
%{_datadir}/%{name}/ppc_rom.bin
@ -1251,6 +1386,7 @@ getent passwd qemu >/dev/null || \
%defattr(-,root,root)
%{_bindir}/qemu-system-unicore32
%{_datadir}/systemtap/tapset/qemu-system-unicore32.stp
%{_mandir}/man1/qemu-system-unicore32.1*
%endif
%if 0%{?system_xtensa:1}
@ -1260,6 +1396,8 @@ getent passwd qemu >/dev/null || \
%{_bindir}/qemu-system-xtensaeb
%{_datadir}/systemtap/tapset/qemu-system-xtensa.stp
%{_datadir}/systemtap/tapset/qemu-system-xtensaeb.stp
%{_mandir}/man1/qemu-system-xtensa.1*
%{_mandir}/man1/qemu-system-xtensaeb.1*
%endif
%if %{without separate_kvm}
@ -1288,6 +1426,22 @@ getent passwd qemu >/dev/null || \
%endif
%changelog
* Tue Jun 4 2013 Paolo Bonzini <pbonzini@redhat.com> 2:1.5.0-5
- add fix-ipv6-brackets.patch
* Mon May 27 2013 Dan Horák <dan[at]danny.cz> - 2:1.5.0-3
- Install the qemu-kvm.1 man page only on arches with kvm
* Sat May 25 2013 Cole Robinson <crobinso@redhat.com> - 2:1.4.2-1
- Update to qemu stable 1.4.2
- Alias qemu-system-* man page to qemu.1 (bz #907746)
- Drop execute bit on service files (bz #963917)
- Conditionalize KSM service on host virt support (bz #963681)
- Split out KSM package, make it not pulled in by default
* Wed May 22 2013 Alon Levy <alevy@redhat.com> - 2:1.4.1-4
- Backport migration cleanup (bz #962954)
* Thu May 16 2013 Paolo Bonzini <pbonzini@redhat.com> - 2:1.4.1-3
- Drop loading of vhost-net module (bz #963198)

View File

@ -1 +1 @@
eb2d696956324722b5ecfa46e41f9a75 qemu-1.4.1.tar.bz2
b3eafa033ae4b8faba584f9f141b888f qemu-1.4.2.tar.bz2