backport migration cleanup (bz #962954)

This commit is contained in:
Alon Levy 2013-05-22 21:48:57 -04:00
parent d8d9ba50c6
commit 408bdb5e74
48 changed files with 4865 additions and 1 deletions

View File

@ -0,0 +1,45 @@
From ad2bca6903af3d02737b893679396343cd598a3e Mon Sep 17 00:00:00 2001
From: Alon Levy <alevy@redhat.com>
Date: Wed, 22 May 2013 19:22:26 -0400
Subject: [PATCH 200/246] ui/vnc-tls.c: fix gnutls warning
---
ui/vnc-tls.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/ui/vnc-tls.c b/ui/vnc-tls.c
index 5629263..2d01982 100644
--- a/ui/vnc-tls.c
+++ b/ui/vnc-tls.c
@@ -99,9 +99,13 @@ 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)
{
+#if GNUTLS_VERSION_MAJOR < 3
gnutls_anon_server_credentials anon_cred;
+#else
+ gnutls_anon_server_credentials_t anon_cred;
+#endif
int ret;
if ((ret = gnutls_anon_allocate_server_credentials(&anon_cred)) < 0) {
@@ -382,7 +386,12 @@ int vnc_tls_client_setup(struct VncState *vs,
}
} else {
- gnutls_anon_server_credentials anon_cred = vnc_tls_initialize_anon_cred();
+#if GNUTLS_VERSION_MAJOR < 2
+ gnutls_anon_server_credentials
+#else
+ gnutls_anon_server_credentials_t
+#endif
+ anon_cred = vnc_tls_initialize_anon_cred();
if (!anon_cred) {
gnutls_deinit(vs->tls.session);
vs->tls.session = NULL;
--
1.8.2.1

View File

@ -0,0 +1,31 @@
From c30be405e8d7344268900de953df863667950217 Mon Sep 17 00:00:00 2001
From: Juan Quintela <quintela@redhat.com>
Date: Fri, 1 Feb 2013 11:12:26 +0100
Subject: [PATCH 201/246] 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>
---
migration.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/migration.c b/migration.c
index 98c7696..3584a24 100644
--- a/migration.c
+++ b/migration.c
@@ -774,6 +774,8 @@ void migrate_fd_connect(MigrationState *s)
s->buffer = NULL;
s->buffer_size = 0;
s->buffer_capacity = 0;
+ /* This is a best 1st approximation. ns to ms */
+ s->expected_downtime = max_downtime/1000000;
s->xfer_limit = s->bandwidth_limit / XFER_LIMIT_RATIO;
s->complete = false;
--
1.8.2.1

View File

@ -0,0 +1,37 @@
From 306e49f278d465051e83253022252b1c69737eb1 Mon Sep 17 00:00:00 2001
From: Juan Quintela <quintela@redhat.com>
Date: Fri, 1 Feb 2013 12:39:08 +0100
Subject: [PATCH 202/246] 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>
---
migration.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/migration.c b/migration.c
index 3584a24..0026f08 100644
--- a/migration.c
+++ b/migration.c
@@ -673,7 +673,7 @@ static void *buffered_file_thread(void *opaque)
qemu_mutex_unlock_iothread();
while (true) {
- int64_t current_time = qemu_get_clock_ms(rt_clock);
+ int64_t current_time;
uint64_t pending_size;
qemu_mutex_lock_iothread();
@@ -727,6 +727,7 @@ static void *buffered_file_thread(void *opaque)
}
}
qemu_mutex_unlock_iothread();
+ current_time = qemu_get_clock_ms(rt_clock);
if (current_time >= initial_time + BUFFER_DELAY) {
uint64_t transferred_bytes = s->bytes_xfer;
uint64_t time_spent = current_time - initial_time;
--
1.8.2.1

View File

@ -0,0 +1,54 @@
From abda6f8a1cd72a04737ebd9e814a8eb427783a21 Mon Sep 17 00:00:00 2001
From: Juan Quintela <quintela@redhat.com>
Date: Fri, 1 Feb 2013 12:41:38 +0100
Subject: [PATCH 203/246] 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>
---
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) {
--
1.8.2.1

View File

@ -0,0 +1,63 @@
From 5b6a7544893648bc29dee219a634bfa7d2ca857a Mon Sep 17 00:00:00 2001
From: Juan Quintela <quintela@redhat.com>
Date: Fri, 1 Feb 2013 13:22:37 +0100
Subject: [PATCH 204/246] 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>
---
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;
--
1.8.2.1

View File

@ -0,0 +1,50 @@
From 9c9566a75a88ff2db9d747ab24cbb7a3d71c4d8b Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:07 +0100
Subject: [PATCH 205/246] 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>
---
migration.c | 11 +----------
1 file changed, 1 insertion(+), 10 deletions(-)
diff --git a/migration.c b/migration.c
index 59e479d..71c0eec 100644
--- a/migration.c
+++ b/migration.c
@@ -666,14 +666,9 @@ static void *buffered_file_thread(void *opaque)
qemu_mutex_lock_iothread();
DPRINTF("beginning savevm\n");
ret = qemu_savevm_state_begin(s->file, &s->params);
- if (ret < 0) {
- DPRINTF("failed, %d\n", ret);
- qemu_mutex_unlock_iothread();
- goto out;
- }
qemu_mutex_unlock_iothread();
- while (true) {
+ while (ret >= 0) {
int64_t current_time;
uint64_t pending_size;
@@ -754,12 +749,8 @@ static void *buffered_file_thread(void *opaque)
sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
}
ret = buffered_flush(s);
- if (ret < 0) {
- break;
- }
}
-out:
if (ret < 0) {
migrate_fd_error(s);
}
--
1.8.2.1

View File

@ -0,0 +1,52 @@
From 9a914ea26d69de42b55e70c6d330eeec0cb7ccfe Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:08 +0100
Subject: [PATCH 206/246] 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>
---
migration.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/migration.c b/migration.c
index 71c0eec..d601641 100644
--- a/migration.c
+++ b/migration.c
@@ -699,11 +699,7 @@ static void *buffered_file_thread(void *opaque)
DPRINTF("done iterating\n");
start_time = qemu_get_clock_ms(rt_clock);
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
- if (old_vm_running) {
- vm_stop(RUN_STATE_FINISH_MIGRATE);
- } else {
- vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
- }
+ vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
ret = qemu_savevm_state_complete(s->file);
if (ret < 0) {
qemu_mutex_unlock_iothread();
--
1.8.2.1

View File

@ -0,0 +1,69 @@
From fa25441af918e5e19c181cd5aac537a6bb8799ed Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:09 +0100
Subject: [PATCH 207/246] 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>
---
migration.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/migration.c b/migration.c
index d601641..739e38c 100644
--- a/migration.c
+++ b/migration.c
@@ -260,7 +260,7 @@ void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
/* shared migration helpers */
-static int migrate_fd_cleanup(MigrationState *s)
+static void migrate_fd_cleanup(MigrationState *s)
{
int ret = 0;
@@ -271,7 +271,13 @@ static int migrate_fd_cleanup(MigrationState *s)
}
assert(s->fd == -1);
- return ret;
+ if (ret < 0 && s->state == MIG_STATE_ACTIVE) {
+ s->state = MIG_STATE_ERROR;
+ }
+
+ if (s->state != MIG_STATE_ACTIVE) {
+ qemu_savevm_state_cancel();
+ }
}
void migrate_fd_error(MigrationState *s)
@@ -285,9 +291,8 @@ void migrate_fd_error(MigrationState *s)
static void migrate_fd_completed(MigrationState *s)
{
DPRINTF("setting completed state\n");
- if (migrate_fd_cleanup(s) < 0) {
- s->state = MIG_STATE_ERROR;
- } else {
+ migrate_fd_cleanup(s);
+ if (s->state == MIG_STATE_ACTIVE) {
s->state = MIG_STATE_COMPLETED;
runstate_set(RUN_STATE_POSTMIGRATE);
}
@@ -322,7 +327,6 @@ static void migrate_fd_cancel(MigrationState *s)
s->state = MIG_STATE_CANCELLED;
notifier_list_notify(&migration_state_notifiers, s);
- qemu_savevm_state_cancel();
migrate_fd_cleanup(s);
}
--
1.8.2.1

View File

@ -0,0 +1,72 @@
From af258e54dc3654dbe326dcdf022b277e8872072a Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:10 +0100
Subject: [PATCH 208/246] 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>
---
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;
}
--
1.8.2.1

View File

@ -0,0 +1,106 @@
From d00dba1bf360ad47957774923dfd2c07ee9cdec0 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:11 +0100
Subject: [PATCH 209/246] 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>
---
block-migration.c | 26 ++++++++------------------
1 file changed, 8 insertions(+), 18 deletions(-)
diff --git a/block-migration.c b/block-migration.c
index 43ab202..e6c917d 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -524,16 +524,10 @@ static int block_save_setup(QEMUFile *f, void *opaque)
set_dirty_tracking(1);
ret = flush_blks(f);
- if (ret) {
- blk_mig_cleanup();
- return ret;
- }
-
blk_mig_reset_dirty_cursor();
-
qemu_put_be64(f, BLK_MIG_FLAG_EOS);
- return 0;
+ return ret;
}
static int block_save_iterate(QEMUFile *f, void *opaque)
@@ -546,7 +540,6 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
ret = flush_blks(f);
if (ret) {
- blk_mig_cleanup();
return ret;
}
@@ -564,20 +557,18 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
}
} else {
ret = blk_mig_save_dirty_block(f, 1);
+ if (ret < 0) {
+ return ret;
+ }
if (ret != 0) {
/* no more dirty blocks */
break;
}
}
}
- if (ret < 0) {
- blk_mig_cleanup();
- return ret;
- }
ret = flush_blks(f);
if (ret) {
- blk_mig_cleanup();
return ret;
}
@@ -595,7 +586,6 @@ static int block_save_complete(QEMUFile *f, void *opaque)
ret = flush_blks(f);
if (ret) {
- blk_mig_cleanup();
return ret;
}
@@ -607,12 +597,11 @@ static int block_save_complete(QEMUFile *f, void *opaque)
do {
ret = blk_mig_save_dirty_block(f, 0);
+ if (ret < 0) {
+ return ret;
+ }
} while (ret == 0);
- blk_mig_cleanup();
- if (ret < 0) {
- return ret;
- }
/* report completion */
qemu_put_be64(f, (100 << BDRV_SECTOR_BITS) | BLK_MIG_FLAG_PROGRESS);
@@ -620,6 +609,7 @@ static int block_save_complete(QEMUFile *f, void *opaque)
qemu_put_be64(f, BLK_MIG_FLAG_EOS);
+ blk_mig_cleanup();
return 0;
}
--
1.8.2.1

View File

@ -0,0 +1,87 @@
From 64774c81205e77bd55d69b6a116f0ef5f61929ba Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:12 +0100
Subject: [PATCH 210/246] 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>
---
savevm.c | 25 ++++++++++++-------------
1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/savevm.c b/savevm.c
index 4302903..a681177 100644
--- a/savevm.c
+++ b/savevm.c
@@ -453,13 +453,13 @@ static void qemu_file_set_error(QEMUFile *f, int ret)
/** Flushes QEMUFile buffer
*
*/
-static int qemu_fflush(QEMUFile *f)
+static void qemu_fflush(QEMUFile *f)
{
int ret = 0;
- if (!f->ops->put_buffer)
- return 0;
-
+ if (!f->ops->put_buffer) {
+ return;
+ }
if (f->is_write && f->buf_index > 0) {
ret = f->ops->put_buffer(f->opaque, f->buf, f->buf_offset, f->buf_index);
if (ret >= 0) {
@@ -467,7 +467,9 @@ static int qemu_fflush(QEMUFile *f)
}
f->buf_index = 0;
}
- return ret;
+ if (ret < 0) {
+ qemu_file_set_error(f, ret);
+ }
}
static void qemu_fill_buffer(QEMUFile *f)
@@ -518,7 +520,8 @@ int qemu_get_fd(QEMUFile *f)
int qemu_fclose(QEMUFile *f)
{
int ret;
- ret = qemu_fflush(f);
+ qemu_fflush(f);
+ ret = qemu_file_get_error(f);
if (f->ops->close) {
int ret2 = f->ops->close(f->opaque);
@@ -560,9 +563,8 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
buf += l;
size -= l;
if (f->buf_index >= IO_BUF_SIZE) {
- int ret = qemu_fflush(f);
- if (ret < 0) {
- qemu_file_set_error(f, ret);
+ qemu_fflush(f);
+ if (qemu_file_get_error(f)) {
break;
}
}
@@ -584,10 +586,7 @@ void qemu_put_byte(QEMUFile *f, int v)
f->buf[f->buf_index++] = v;
f->is_write = 1;
if (f->buf_index >= IO_BUF_SIZE) {
- int ret = qemu_fflush(f);
- if (ret < 0) {
- qemu_file_set_error(f, ret);
- }
+ qemu_fflush(f);
}
}
--
1.8.2.1

View File

@ -0,0 +1,145 @@
From 8b3e57abc68b37922399034c92dd4a10890c2c0e Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:13 +0100
Subject: [PATCH 211/246] 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>
---
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;
}
--
1.8.2.1

View File

@ -0,0 +1,71 @@
From 5d4b7aa9dee156a613086d343987220c99adddd9 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:14 +0100
Subject: [PATCH 212/246] 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>
---
include/migration/qemu-file.h | 2 ++
savevm.c | 4 ++--
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
index 46fc11d..5e0c287 100644
--- a/include/migration/qemu-file.h
+++ b/include/migration/qemu-file.h
@@ -82,6 +82,7 @@ QEMUFile *qemu_popen_cmd(const char *command, const char *mode);
int qemu_get_fd(QEMUFile *f);
int qemu_fclose(QEMUFile *f);
int64_t qemu_ftell(QEMUFile *f);
+void qemu_fflush(QEMUFile *f);
void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size);
void qemu_put_byte(QEMUFile *f, int v);
@@ -113,6 +114,7 @@ int qemu_file_rate_limit(QEMUFile *f);
int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate);
int64_t qemu_file_get_rate_limit(QEMUFile *f);
int qemu_file_get_error(QEMUFile *f);
+void qemu_file_set_error(QEMUFile *f, int ret);
static inline void qemu_put_be64s(QEMUFile *f, const uint64_t *pv)
{
diff --git a/savevm.c b/savevm.c
index a1690b4..e10a045 100644
--- a/savevm.c
+++ b/savevm.c
@@ -443,7 +443,7 @@ int qemu_file_get_error(QEMUFile *f)
return f->last_error;
}
-static void qemu_file_set_error(QEMUFile *f, int ret)
+void qemu_file_set_error(QEMUFile *f, int ret)
{
if (f->last_error == 0) {
f->last_error = ret;
@@ -453,7 +453,7 @@ static void qemu_file_set_error(QEMUFile *f, int ret)
/** Flushes QEMUFile buffer
*
*/
-static void qemu_fflush(QEMUFile *f)
+void qemu_fflush(QEMUFile *f)
{
int ret = 0;
--
1.8.2.1

View File

@ -0,0 +1,32 @@
From 0c1da6466596bc25328f896161f06622899cce48 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:15 +0100
Subject: [PATCH 213/246] 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>
---
migration.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/migration.c b/migration.c
index 739e38c..1027b40 100644
--- a/migration.c
+++ b/migration.c
@@ -525,6 +525,8 @@ static ssize_t buffered_flush(MigrationState *s)
DPRINTF("flushing %zu byte(s) of data\n", s->buffer_size);
+ qemu_fflush(s->file);
+
while (s->bytes_xfer < s->xfer_limit && offset < s->buffer_size) {
size_t to_send = MIN(s->buffer_size - offset, s->xfer_limit - s->bytes_xfer);
ret = migrate_fd_put_buffer(s, s->buffer + offset, to_send);
--
1.8.2.1

View File

@ -0,0 +1,82 @@
From a00d2c8014dbf2553c7bbd69a025f7e3992d25be Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:16 +0100
Subject: [PATCH 214/246] 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>
---
migration.c | 22 ++++++----------------
1 file changed, 6 insertions(+), 16 deletions(-)
diff --git a/migration.c b/migration.c
index 1027b40..da5f175 100644
--- a/migration.c
+++ b/migration.c
@@ -518,7 +518,7 @@ int64_t migrate_xbzrle_cache_size(void)
/* migration thread support */
-static ssize_t buffered_flush(MigrationState *s)
+static void buffered_flush(MigrationState *s)
{
size_t offset = 0;
ssize_t ret = 0;
@@ -545,9 +545,8 @@ static ssize_t buffered_flush(MigrationState *s)
s->buffer_size -= offset;
if (ret < 0) {
- return ret;
+ qemu_file_set_error(s->file, ret);
}
- return offset;
}
static int buffered_put_buffer(void *opaque, const uint8_t *buf,
@@ -586,25 +585,15 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf,
static int buffered_close(void *opaque)
{
MigrationState *s = opaque;
- ssize_t ret = 0;
- int ret2;
DPRINTF("closing\n");
s->xfer_limit = INT_MAX;
while (!qemu_file_get_error(s->file) && s->buffer_size) {
- ret = buffered_flush(s);
- if (ret < 0) {
- break;
- }
- }
-
- ret2 = migrate_fd_close(s);
- if (ret >= 0) {
- ret = ret2;
+ buffered_flush(s);
}
s->complete = true;
- return ret;
+ return migrate_fd_close(s);
}
static int buffered_get_fd(void *opaque)
@@ -750,7 +739,8 @@ static void *buffered_file_thread(void *opaque)
g_usleep((initial_time + BUFFER_DELAY - current_time)*1000);
sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
}
- ret = buffered_flush(s);
+ buffered_flush(s);
+ ret = qemu_file_get_error(s->file);
}
if (ret < 0) {
--
1.8.2.1

View File

@ -0,0 +1,142 @@
From fd038161f3313522eb0faea2a58adcb3766e5efd Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:17 +0100
Subject: [PATCH 215/246] 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>
---
include/migration/migration.h | 1 -
migration.c | 46 +++++++++++++------------------------------
2 files changed, 14 insertions(+), 33 deletions(-)
diff --git a/include/migration/migration.h b/include/migration/migration.h
index d121409..3e680af 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -54,7 +54,6 @@ struct MigrationState
int64_t dirty_bytes_rate;
bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
int64_t xbzrle_cache_size;
- bool complete;
};
void process_incoming_migration(QEMUFile *f);
diff --git a/migration.c b/migration.c
index da5f175..41a592c 100644
--- a/migration.c
+++ b/migration.c
@@ -525,6 +525,10 @@ static void buffered_flush(MigrationState *s)
DPRINTF("flushing %zu byte(s) of data\n", s->buffer_size);
+ if (qemu_file_get_error(s->file)) {
+ s->buffer_size = 0;
+ return;
+ }
qemu_fflush(s->file);
while (s->bytes_xfer < s->xfer_limit && offset < s->buffer_size) {
@@ -592,7 +596,6 @@ static int buffered_close(void *opaque)
while (!qemu_file_get_error(s->file) && s->buffer_size) {
buffered_flush(s);
}
- s->complete = true;
return migrate_fd_close(s);
}
@@ -656,37 +659,21 @@ static void *buffered_file_thread(void *opaque)
int64_t sleep_time = 0;
int64_t max_size = 0;
bool last_round = false;
- int ret;
qemu_mutex_lock_iothread();
DPRINTF("beginning savevm\n");
- ret = qemu_savevm_state_begin(s->file, &s->params);
- qemu_mutex_unlock_iothread();
+ qemu_savevm_state_begin(s->file, &s->params);
- while (ret >= 0) {
+ while (s->state == MIG_STATE_ACTIVE) {
int64_t current_time;
uint64_t pending_size;
- qemu_mutex_lock_iothread();
- if (s->state != MIG_STATE_ACTIVE) {
- DPRINTF("put_ready returning because of non-active state\n");
- qemu_mutex_unlock_iothread();
- break;
- }
- if (s->complete) {
- qemu_mutex_unlock_iothread();
- break;
- }
if (s->bytes_xfer < s->xfer_limit) {
DPRINTF("iterate\n");
pending_size = qemu_savevm_state_pending(s->file, max_size);
DPRINTF("pending size %lu max %lu\n", pending_size, max_size);
if (pending_size && pending_size >= max_size) {
- ret = qemu_savevm_state_iterate(s->file);
- if (ret < 0) {
- qemu_mutex_unlock_iothread();
- break;
- }
+ qemu_savevm_state_iterate(s->file);
} else {
int old_vm_running = runstate_is_running();
int64_t start_time, end_time;
@@ -695,13 +682,8 @@ static void *buffered_file_thread(void *opaque)
start_time = qemu_get_clock_ms(rt_clock);
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
- ret = qemu_savevm_state_complete(s->file);
- if (ret < 0) {
- qemu_mutex_unlock_iothread();
- break;
- } else {
- migrate_fd_completed(s);
- }
+ qemu_savevm_state_complete(s->file);
+ migrate_fd_completed(s);
end_time = qemu_get_clock_ms(rt_clock);
s->total_time = end_time - s->total_time;
s->downtime = end_time - start_time;
@@ -740,12 +722,13 @@ static void *buffered_file_thread(void *opaque)
sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
}
buffered_flush(s);
- ret = qemu_file_get_error(s->file);
+ qemu_mutex_lock_iothread();
+ if (qemu_file_get_error(s->file)) {
+ migrate_fd_error(s);
+ }
}
- if (ret < 0) {
- migrate_fd_error(s);
- }
+ qemu_mutex_unlock_iothread();
g_free(s->buffer);
return NULL;
}
@@ -770,7 +753,6 @@ void migrate_fd_connect(MigrationState *s)
s->expected_downtime = max_downtime/1000000;
s->xfer_limit = s->bandwidth_limit / XFER_LIMIT_RATIO;
- s->complete = false;
s->file = qemu_fopen_ops(s, &buffered_file_ops);
--
1.8.2.1

View File

@ -0,0 +1,154 @@
From 10a7d96875e75f249789c4e66578360740b6277f Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:18 +0100
Subject: [PATCH 216/246] 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>
---
migration.c | 55 ++++++++++++++++++++++++-------------------------------
1 file changed, 24 insertions(+), 31 deletions(-)
diff --git a/migration.c b/migration.c
index 41a592c..57fceb6d 100644
--- a/migration.c
+++ b/migration.c
@@ -262,41 +262,34 @@ void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
static void migrate_fd_cleanup(MigrationState *s)
{
- int ret = 0;
-
if (s->file) {
DPRINTF("closing file\n");
- ret = qemu_fclose(s->file);
+ qemu_fclose(s->file);
s->file = NULL;
}
assert(s->fd == -1);
- if (ret < 0 && s->state == MIG_STATE_ACTIVE) {
- s->state = MIG_STATE_ERROR;
- }
+ assert(s->state != MIG_STATE_ACTIVE);
- if (s->state != MIG_STATE_ACTIVE) {
+ if (s->state != MIG_STATE_COMPLETED) {
qemu_savevm_state_cancel();
}
+
+ notifier_list_notify(&migration_state_notifiers, s);
}
void migrate_fd_error(MigrationState *s)
{
DPRINTF("setting error state\n");
s->state = MIG_STATE_ERROR;
- notifier_list_notify(&migration_state_notifiers, s);
migrate_fd_cleanup(s);
}
static void migrate_fd_completed(MigrationState *s)
{
DPRINTF("setting completed state\n");
+ s->state = MIG_STATE_COMPLETED;
migrate_fd_cleanup(s);
- if (s->state == MIG_STATE_ACTIVE) {
- s->state = MIG_STATE_COMPLETED;
- runstate_set(RUN_STATE_POSTMIGRATE);
- }
- notifier_list_notify(&migration_state_notifiers, s);
}
static ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data,
@@ -326,8 +319,6 @@ static void migrate_fd_cancel(MigrationState *s)
DPRINTF("cancelling migration\n");
s->state = MIG_STATE_CANCELLED;
- notifier_list_notify(&migration_state_notifiers, s);
-
migrate_fd_cleanup(s);
}
@@ -592,10 +583,6 @@ static int buffered_close(void *opaque)
DPRINTF("closing\n");
- s->xfer_limit = INT_MAX;
- while (!qemu_file_get_error(s->file) && s->buffer_size) {
- buffered_flush(s);
- }
return migrate_fd_close(s);
}
@@ -658,6 +645,8 @@ static void *buffered_file_thread(void *opaque)
int64_t initial_time = qemu_get_clock_ms(rt_clock);
int64_t sleep_time = 0;
int64_t max_size = 0;
+ int64_t start_time = initial_time;
+ bool old_vm_running = false;
bool last_round = false;
qemu_mutex_lock_iothread();
@@ -675,23 +664,13 @@ static void *buffered_file_thread(void *opaque)
if (pending_size && pending_size >= max_size) {
qemu_savevm_state_iterate(s->file);
} else {
- int old_vm_running = runstate_is_running();
- int64_t start_time, end_time;
-
DPRINTF("done iterating\n");
start_time = qemu_get_clock_ms(rt_clock);
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
+ old_vm_running = runstate_is_running();
vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
+ s->xfer_limit = INT_MAX;
qemu_savevm_state_complete(s->file);
- migrate_fd_completed(s);
- end_time = qemu_get_clock_ms(rt_clock);
- s->total_time = end_time - s->total_time;
- s->downtime = end_time - start_time;
- if (s->state != MIG_STATE_COMPLETED) {
- if (old_vm_running) {
- vm_start();
- }
- }
last_round = true;
}
}
@@ -725,6 +704,20 @@ static void *buffered_file_thread(void *opaque)
qemu_mutex_lock_iothread();
if (qemu_file_get_error(s->file)) {
migrate_fd_error(s);
+ } else if (last_round && s->buffer_size == 0) {
+ migrate_fd_completed(s);
+ }
+ }
+
+ if (s->state == MIG_STATE_COMPLETED) {
+ int64_t end_time = qemu_get_clock_ms(rt_clock);
+ s->total_time = end_time - s->total_time;
+ s->downtime = end_time - start_time;
+ runstate_set(RUN_STATE_POSTMIGRATE);
+ } else {
+ if (old_vm_running) {
+ assert(last_round);
+ vm_start();
}
}
--
1.8.2.1

View File

@ -0,0 +1,83 @@
From 00c79950d1190667daf58d4aa536aede816376a1 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 217/246] 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>
---
migration.c | 9 ++++++++-
trace-events | 3 +++
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/migration.c b/migration.c
index 57fceb6d..c0a9239 100644
--- a/migration.c
+++ b/migration.c
@@ -23,6 +23,7 @@
#include "migration/block.h"
#include "qemu/thread.h"
#include "qmp-commands.h"
+#include "trace.h"
//#define DEBUG_MIGRATION
@@ -282,6 +283,7 @@ void migrate_fd_error(MigrationState *s)
{
DPRINTF("setting error state\n");
s->state = MIG_STATE_ERROR;
+ trace_migrate_set_state(MIG_STATE_ERROR);
migrate_fd_cleanup(s);
}
@@ -289,6 +291,7 @@ static void migrate_fd_completed(MigrationState *s)
{
DPRINTF("setting completed state\n");
s->state = MIG_STATE_COMPLETED;
+ trace_migrate_set_state(MIG_STATE_COMPLETED);
migrate_fd_cleanup(s);
}
@@ -319,6 +322,7 @@ static void migrate_fd_cancel(MigrationState *s)
DPRINTF("cancelling migration\n");
s->state = MIG_STATE_CANCELLED;
+ trace_migrate_set_state(MIG_STATE_CANCELLED);
migrate_fd_cleanup(s);
}
@@ -377,8 +381,9 @@ static MigrationState *migrate_init(const MigrationParams *params)
s->bandwidth_limit = bandwidth_limit;
s->state = MIG_STATE_SETUP;
- s->total_time = qemu_get_clock_ms(rt_clock);
+ trace_migrate_set_state(MIG_STATE_SETUP);
+ s->total_time = qemu_get_clock_ms(rt_clock);
return s;
}
@@ -738,6 +743,8 @@ static const QEMUFileOps buffered_file_ops = {
void migrate_fd_connect(MigrationState *s)
{
s->state = MIG_STATE_ACTIVE;
+ trace_migrate_set_state(MIG_STATE_ACTIVE);
+
s->bytes_xfer = 0;
s->buffer = NULL;
s->buffer_size = 0;
diff --git a/trace-events b/trace-events
index 167f481..614c4ef 100644
--- a/trace-events
+++ b/trace-events
@@ -1091,3 +1091,6 @@ css_io_interrupt(int cssid, int ssid, int schid, uint32_t intparm, uint8_t isc,
# hw/s390x/virtio-ccw.c
virtio_ccw_interpret_ccw(int cssid, int ssid, int schid, int cmd_code) "VIRTIO-CCW: %x.%x.%04x: interpret command %x"
virtio_ccw_new_device(int cssid, int ssid, int schid, int devno, const char *devno_mode) "VIRTIO-CCW: add subchannel %x.%x.%04x, devno %04x (%s)"
+
+# migration.c
+migrate_set_state(int new_state) "new state %d"
--
1.8.2.1

View File

@ -0,0 +1,128 @@
From 5378a79abf77509ea47d75d8984644f3ba2ff209 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:20 +0100
Subject: [PATCH 218/246] 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>
---
migration.c | 33 +++++++++++++++++++++------------
1 file changed, 21 insertions(+), 12 deletions(-)
diff --git a/migration.c b/migration.c
index c0a9239..e844b2c 100644
--- a/migration.c
+++ b/migration.c
@@ -279,19 +279,25 @@ static void migrate_fd_cleanup(MigrationState *s)
notifier_list_notify(&migration_state_notifiers, s);
}
+static void migrate_finish_set_state(MigrationState *s, int new_state)
+{
+ if (__sync_val_compare_and_swap(&s->state, MIG_STATE_ACTIVE,
+ new_state) == new_state) {
+ trace_migrate_set_state(new_state);
+ }
+}
+
void migrate_fd_error(MigrationState *s)
{
DPRINTF("setting error state\n");
- s->state = MIG_STATE_ERROR;
- trace_migrate_set_state(MIG_STATE_ERROR);
+ migrate_finish_set_state(s, MIG_STATE_ERROR);
migrate_fd_cleanup(s);
}
static void migrate_fd_completed(MigrationState *s)
{
DPRINTF("setting completed state\n");
- s->state = MIG_STATE_COMPLETED;
- trace_migrate_set_state(MIG_STATE_COMPLETED);
+ migrate_finish_set_state(s, MIG_STATE_COMPLETED);
migrate_fd_cleanup(s);
}
@@ -316,13 +322,9 @@ static ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data,
static void migrate_fd_cancel(MigrationState *s)
{
- if (s->state != MIG_STATE_ACTIVE)
- return;
-
DPRINTF("cancelling migration\n");
- s->state = MIG_STATE_CANCELLED;
- trace_migrate_set_state(MIG_STATE_CANCELLED);
+ migrate_finish_set_state(s, MIG_STATE_CANCELLED);
migrate_fd_cleanup(s);
}
@@ -657,12 +659,14 @@ static void *buffered_file_thread(void *opaque)
qemu_mutex_lock_iothread();
DPRINTF("beginning savevm\n");
qemu_savevm_state_begin(s->file, &s->params);
+ qemu_mutex_unlock_iothread();
while (s->state == MIG_STATE_ACTIVE) {
int64_t current_time;
uint64_t pending_size;
if (s->bytes_xfer < s->xfer_limit) {
+ qemu_mutex_lock_iothread();
DPRINTF("iterate\n");
pending_size = qemu_savevm_state_pending(s->file, max_size);
DPRINTF("pending size %lu max %lu\n", pending_size, max_size);
@@ -678,8 +682,9 @@ static void *buffered_file_thread(void *opaque)
qemu_savevm_state_complete(s->file);
last_round = true;
}
+ qemu_mutex_unlock_iothread();
}
- qemu_mutex_unlock_iothread();
+
current_time = qemu_get_clock_ms(rt_clock);
if (current_time >= initial_time + BUFFER_DELAY) {
uint64_t transferred_bytes = s->bytes_xfer;
@@ -706,14 +711,18 @@ static void *buffered_file_thread(void *opaque)
sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
}
buffered_flush(s);
- qemu_mutex_lock_iothread();
if (qemu_file_get_error(s->file)) {
+ qemu_mutex_lock_iothread();
migrate_fd_error(s);
+ qemu_mutex_unlock_iothread();
} else if (last_round && s->buffer_size == 0) {
+ qemu_mutex_lock_iothread();
migrate_fd_completed(s);
+ qemu_mutex_unlock_iothread();
}
}
+ qemu_mutex_lock_iothread();
if (s->state == MIG_STATE_COMPLETED) {
int64_t end_time = qemu_get_clock_ms(rt_clock);
s->total_time = end_time - s->total_time;
@@ -725,8 +734,8 @@ static void *buffered_file_thread(void *opaque)
vm_start();
}
}
-
qemu_mutex_unlock_iothread();
+
g_free(s->buffer);
return NULL;
}
--
1.8.2.1

View File

@ -0,0 +1,131 @@
From f3940c04a0436c4d2291df4118494154ea7463b5 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:21 +0100
Subject: [PATCH 219/246] 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>
---
include/migration/migration.h | 1 +
migration.c | 38 ++++++++++++++++++++------------------
2 files changed, 21 insertions(+), 18 deletions(-)
diff --git a/include/migration/migration.h b/include/migration/migration.h
index 3e680af..ed20bed 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -38,6 +38,7 @@ struct MigrationState
size_t buffer_size;
size_t buffer_capacity;
QemuThread thread;
+ QEMUBH *cleanup_bh;
QEMUFile *file;
int fd;
diff --git a/migration.c b/migration.c
index e844b2c..437475b 100644
--- a/migration.c
+++ b/migration.c
@@ -261,8 +261,13 @@ void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
/* shared migration helpers */
-static void migrate_fd_cleanup(MigrationState *s)
+static void migrate_fd_cleanup(void *opaque)
{
+ MigrationState *s = opaque;
+
+ qemu_bh_delete(s->cleanup_bh);
+ s->cleanup_bh = NULL;
+
if (s->file) {
DPRINTF("closing file\n");
qemu_fclose(s->file);
@@ -290,15 +295,10 @@ static void migrate_finish_set_state(MigrationState *s, int new_state)
void migrate_fd_error(MigrationState *s)
{
DPRINTF("setting error state\n");
- migrate_finish_set_state(s, MIG_STATE_ERROR);
- migrate_fd_cleanup(s);
-}
-
-static void migrate_fd_completed(MigrationState *s)
-{
- DPRINTF("setting completed state\n");
- migrate_finish_set_state(s, MIG_STATE_COMPLETED);
- migrate_fd_cleanup(s);
+ assert(s->file == NULL);
+ s->state = MIG_STATE_ERROR;
+ trace_migrate_set_state(MIG_STATE_ERROR);
+ notifier_list_notify(&migration_state_notifiers, s);
}
static ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data,
@@ -325,7 +325,6 @@ static void migrate_fd_cancel(MigrationState *s)
DPRINTF("cancelling migration\n");
migrate_finish_set_state(s, MIG_STATE_CANCELLED);
- migrate_fd_cleanup(s);
}
int migrate_fd_close(MigrationState *s)
@@ -590,6 +589,11 @@ static int buffered_close(void *opaque)
DPRINTF("closing\n");
+ qemu_mutex_unlock_iothread();
+ qemu_thread_join(&s->thread);
+ qemu_mutex_lock_iothread();
+ assert(s->state != MIG_STATE_ACTIVE);
+
return migrate_fd_close(s);
}
@@ -712,13 +716,9 @@ static void *buffered_file_thread(void *opaque)
}
buffered_flush(s);
if (qemu_file_get_error(s->file)) {
- qemu_mutex_lock_iothread();
- migrate_fd_error(s);
- qemu_mutex_unlock_iothread();
+ migrate_finish_set_state(s, MIG_STATE_ERROR);
} else if (last_round && s->buffer_size == 0) {
- qemu_mutex_lock_iothread();
- migrate_fd_completed(s);
- qemu_mutex_unlock_iothread();
+ migrate_finish_set_state(s, MIG_STATE_COMPLETED);
}
}
@@ -734,6 +734,7 @@ static void *buffered_file_thread(void *opaque)
vm_start();
}
}
+ qemu_bh_schedule(s->cleanup_bh);
qemu_mutex_unlock_iothread();
g_free(s->buffer);
@@ -763,9 +764,10 @@ void migrate_fd_connect(MigrationState *s)
s->xfer_limit = s->bandwidth_limit / XFER_LIMIT_RATIO;
+ s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s);
s->file = qemu_fopen_ops(s, &buffered_file_ops);
qemu_thread_create(&s->thread, buffered_file_thread, s,
- QEMU_THREAD_DETACHED);
+ QEMU_THREAD_JOINABLE);
notifier_list_notify(&migration_state_notifiers, s);
}
--
1.8.2.1

View File

@ -0,0 +1,72 @@
From 9fdbad6e2d4c5bc85daddabe74b3e26337c11219 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:22 +0100
Subject: [PATCH 220/246] 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>
---
block-migration.c | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/block-migration.c b/block-migration.c
index e6c917d..e72f322 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -50,7 +50,6 @@ typedef struct BlkMigDevState {
int64_t cur_dirty;
int64_t completed_sectors;
int64_t total_sectors;
- int64_t dirty;
QSIMPLEQ_ENTRY(BlkMigDevState) entry;
unsigned long *aio_bitmap;
} BlkMigDevState;
@@ -78,7 +77,6 @@ typedef struct BlkMigState {
int64_t total_sector_sum;
int prev_progress;
int bulk_completed;
- long double prev_time_offset;
} BlkMigState;
static BlkMigState block_mig_state;
@@ -179,13 +177,10 @@ static void alloc_aio_bitmap(BlkMigDevState *bmds)
static void blk_mig_read_cb(void *opaque, int ret)
{
- long double curr_time = qemu_get_clock_ns(rt_clock);
BlkMigBlock *blk = opaque;
blk->ret = ret;
- block_mig_state.prev_time_offset = curr_time;
-
QSIMPLEQ_INSERT_TAIL(&block_mig_state.blk_list, blk, entry);
bmds_set_aio_inflight(blk->bmds, blk->sector, blk->nr_sectors, 0);
@@ -236,10 +231,6 @@ static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
- if (block_mig_state.submitted == 0) {
- block_mig_state.prev_time_offset = qemu_get_clock_ns(rt_clock);
- }
-
blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov,
nr_sectors, blk_mig_read_cb, blk);
block_mig_state.submitted++;
@@ -382,10 +373,6 @@ static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
- if (block_mig_state.submitted == 0) {
- block_mig_state.prev_time_offset = qemu_get_clock_ns(rt_clock);
- }
-
blk->aiocb = bdrv_aio_readv(bmds->bs, sector, &blk->qiov,
nr_sectors, blk_mig_read_cb, blk);
block_mig_state.submitted++;
--
1.8.2.1

View File

@ -0,0 +1,91 @@
From 50897e0513dd4854402e3d26d3a95860cabba5d2 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:23 +0100
Subject: [PATCH 221/246] 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>
---
block-migration.c | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/block-migration.c b/block-migration.c
index e72f322..9a40edd 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -231,9 +231,10 @@ static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
+ block_mig_state.submitted++;
+
blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov,
nr_sectors, blk_mig_read_cb, blk);
- block_mig_state.submitted++;
bdrv_reset_dirty(bs, cur_sector, nr_sectors);
bmds->cur_sector = cur_sector + nr_sectors;
@@ -440,9 +441,10 @@ static int flush_blks(QEMUFile *f)
ret = blk->ret;
break;
}
- blk_send(f, blk);
QSIMPLEQ_REMOVE_HEAD(&block_mig_state.blk_list, entry);
+ blk_send(f, blk);
+
g_free(blk->buf);
g_free(blk);
@@ -542,15 +544,16 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
/* finished saving bulk on all devices */
block_mig_state.bulk_completed = 1;
}
+ ret = 0;
} else {
ret = blk_mig_save_dirty_block(f, 1);
- if (ret < 0) {
- return ret;
- }
- if (ret != 0) {
- /* no more dirty blocks */
- break;
- }
+ }
+ if (ret < 0) {
+ return ret;
+ }
+ if (ret != 0) {
+ /* no more dirty blocks */
+ break;
}
}
@@ -560,7 +563,6 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
}
qemu_put_be64(f, BLK_MIG_FLAG_EOS);
-
return qemu_ftell(f) - last_ftell;
}
@@ -603,7 +605,9 @@ static int block_save_complete(QEMUFile *f, void *opaque)
static uint64_t block_save_pending(QEMUFile *f, void *opaque, uint64_t max_size)
{
/* Estimate pending number of bytes to send */
- uint64_t pending = get_remaining_dirty() +
+ uint64_t pending;
+
+ pending = get_remaining_dirty() +
block_mig_state.submitted * BLOCK_SIZE +
block_mig_state.read_done * BLOCK_SIZE;
--
1.8.2.1

View File

@ -0,0 +1,78 @@
From 79d609fcbb20cd8fb41d61362778b4f491caa5c8 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:24 +0100
Subject: [PATCH 222/246] 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>
---
block-migration.c | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/block-migration.c b/block-migration.c
index 9a40edd..d62a8b8 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -43,18 +43,24 @@
#endif
typedef struct BlkMigDevState {
+ /* Written during setup phase. Can be read without a lock. */
BlockDriverState *bs;
- int bulk_completed;
int shared_base;
- int64_t cur_sector;
- int64_t cur_dirty;
- int64_t completed_sectors;
int64_t total_sectors;
QSIMPLEQ_ENTRY(BlkMigDevState) entry;
+
+ /* Only used by migration thread. Does not need a lock. */
+ int bulk_completed;
+ int64_t cur_sector;
+ int64_t cur_dirty;
+
+ /* Protected by iothread lock. */
unsigned long *aio_bitmap;
+ int64_t completed_sectors;
} BlkMigDevState;
typedef struct BlkMigBlock {
+ /* Only used by migration thread. */
uint8_t *buf;
BlkMigDevState *bmds;
int64_t sector;
@@ -62,19 +68,26 @@ typedef struct BlkMigBlock {
struct iovec iov;
QEMUIOVector qiov;
BlockDriverAIOCB *aiocb;
+
+ /* Protected by iothread lock. */
int ret;
QSIMPLEQ_ENTRY(BlkMigBlock) entry;
} BlkMigBlock;
typedef struct BlkMigState {
+ /* Written during setup phase. Can be read without a lock. */
int blk_enable;
int shared_base;
QSIMPLEQ_HEAD(bmds_list, BlkMigDevState) bmds_list;
+ int64_t total_sector_sum;
+
+ /* Protected by iothread lock. */
QSIMPLEQ_HEAD(blk_list, BlkMigBlock) blk_list;
int submitted;
int read_done;
+
+ /* Only used by migration thread. Does not need a lock. */
int transferred;
- int64_t total_sector_sum;
int prev_progress;
int bulk_completed;
} BlkMigState;
--
1.8.2.1

View File

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

View File

@ -0,0 +1,42 @@
From 3d91104155abc46db41f0588bdbcfbd34aa007af Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:26 +0100
Subject: [PATCH 224/246] 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>
---
include/migration/vmstate.h | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index f27276c..6229569 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -32,13 +32,15 @@ typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id);
typedef struct SaveVMHandlers {
void (*set_params)(const MigrationParams *params, void * opaque);
SaveStateHandler *save_state;
+
int (*save_live_setup)(QEMUFile *f, void *opaque);
- int (*save_live_iterate)(QEMUFile *f, void *opaque);
+ void (*cancel)(void *opaque);
int (*save_live_complete)(QEMUFile *f, void *opaque);
+ bool (*is_active)(void *opaque);
+ int (*save_live_iterate)(QEMUFile *f, void *opaque);
uint64_t (*save_live_pending)(QEMUFile *f, void *opaque, uint64_t max_size);
- void (*cancel)(void *opaque);
+
LoadStateHandler *load_state;
- bool (*is_active)(void *opaque);
} SaveVMHandlers;
int register_savevm(DeviceState *dev,
--
1.8.2.1

View File

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

View File

@ -0,0 +1,119 @@
From 4418176da1e72e62c06b87bc39f4dc3688e9a4cf Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:28 +0100
Subject: [PATCH 226/246] 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>
---
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;
--
1.8.2.1

View File

@ -0,0 +1,178 @@
From 7b88ce8fc64774035975391bbab68e59810fe07b Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:29 +0100
Subject: [PATCH 227/246] 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>
---
include/migration/migration.h | 3 --
migration.c | 79 ++++++++++++-------------------------------
savevm.c | 1 +
3 files changed, 22 insertions(+), 61 deletions(-)
diff --git a/include/migration/migration.h b/include/migration/migration.h
index ed20bed..cec8643 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -34,9 +34,6 @@ struct MigrationState
int64_t bandwidth_limit;
size_t bytes_xfer;
size_t xfer_limit;
- uint8_t *buffer;
- size_t buffer_size;
- size_t buffer_capacity;
QemuThread thread;
QEMUBH *cleanup_bh;
diff --git a/migration.c b/migration.c
index 7c1d4df..62a7f8e 100644
--- a/migration.c
+++ b/migration.c
@@ -514,73 +514,41 @@ int64_t migrate_xbzrle_cache_size(void)
/* migration thread support */
-
-static void buffered_flush(MigrationState *s)
-{
- size_t offset = 0;
- ssize_t ret = 0;
-
- DPRINTF("flushing %zu byte(s) of data\n", s->buffer_size);
-
- if (qemu_file_get_error(s->file)) {
- s->buffer_size = 0;
- return;
- }
- qemu_fflush(s->file);
-
- while (s->bytes_xfer < s->xfer_limit && offset < s->buffer_size) {
- size_t to_send = MIN(s->buffer_size - offset, s->xfer_limit - s->bytes_xfer);
- ret = migrate_fd_put_buffer(s, s->buffer + offset, to_send);
- if (ret <= 0) {
- DPRINTF("error flushing data, %zd\n", ret);
- break;
- } else {
- DPRINTF("flushed %zd byte(s)\n", ret);
- offset += ret;
- s->bytes_xfer += ret;
- }
- }
-
- DPRINTF("flushed %zu of %zu byte(s)\n", offset, s->buffer_size);
- memmove(s->buffer, s->buffer + offset, s->buffer_size - offset);
- s->buffer_size -= offset;
-
- if (ret < 0) {
- qemu_file_set_error(s->file, ret);
- }
-}
-
static int buffered_put_buffer(void *opaque, const uint8_t *buf,
int64_t pos, int size)
{
MigrationState *s = opaque;
- ssize_t error;
+ ssize_t ret;
+ size_t sent;
DPRINTF("putting %d bytes at %" PRId64 "\n", size, pos);
- error = qemu_file_get_error(s->file);
- if (error) {
- DPRINTF("flush when error, bailing: %s\n", strerror(-error));
- return error;
+ ret = qemu_file_get_error(s->file);
+ if (ret) {
+ DPRINTF("flush when error, bailing: %s\n", strerror(-ret));
+ return ret;
}
if (size <= 0) {
return size;
}
- if (size > (s->buffer_capacity - s->buffer_size)) {
- DPRINTF("increasing buffer capacity from %zu by %zu\n",
- s->buffer_capacity, size + 1024);
-
- s->buffer_capacity += size + 1024;
-
- s->buffer = g_realloc(s->buffer, s->buffer_capacity);
+ sent = 0;
+ while (size) {
+ ret = migrate_fd_put_buffer(s, buf, size);
+ if (ret <= 0) {
+ DPRINTF("error flushing data, %zd\n", ret);
+ return ret;
+ } else {
+ DPRINTF("flushed %zd byte(s)\n", ret);
+ sent += ret;
+ buf += ret;
+ size -= ret;
+ s->bytes_xfer += ret;
+ }
}
- memcpy(s->buffer + s->buffer_size, buf, size);
- s->buffer_size += size;
-
- return size;
+ return sent;
}
static int buffered_close(void *opaque)
@@ -712,10 +680,9 @@ static void *buffered_file_thread(void *opaque)
g_usleep((initial_time + BUFFER_DELAY - current_time)*1000);
sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
}
- buffered_flush(s);
if (qemu_file_get_error(s->file)) {
migrate_finish_set_state(s, MIG_STATE_ERROR);
- } else if (last_round && s->buffer_size == 0) {
+ } else if (last_round) {
migrate_finish_set_state(s, MIG_STATE_COMPLETED);
}
}
@@ -735,7 +702,6 @@ static void *buffered_file_thread(void *opaque)
qemu_bh_schedule(s->cleanup_bh);
qemu_mutex_unlock_iothread();
- g_free(s->buffer);
return NULL;
}
@@ -754,9 +720,6 @@ void migrate_fd_connect(MigrationState *s)
trace_migrate_set_state(MIG_STATE_ACTIVE);
s->bytes_xfer = 0;
- s->buffer = NULL;
- s->buffer_size = 0;
- s->buffer_capacity = 0;
/* This is a best 1st approximation. ns to ms */
s->expected_downtime = max_downtime/1000000;
diff --git a/savevm.c b/savevm.c
index 7c7774e..ce10295 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1724,6 +1724,7 @@ void qemu_savevm_state_complete(QEMUFile *f)
}
qemu_put_byte(f, QEMU_VM_EOF);
+ qemu_fflush(f);
}
uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size)
--
1.8.2.1

View File

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

View File

@ -0,0 +1,60 @@
From 6c3c2d1af9dbc147b7975e490cbf860502ed93e5 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:31 +0100
Subject: [PATCH 229/246] 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>
---
include/migration/qemu-file.h | 2 --
savevm.c | 4 ++--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
index 5e0c287..46fc11d 100644
--- a/include/migration/qemu-file.h
+++ b/include/migration/qemu-file.h
@@ -82,7 +82,6 @@ QEMUFile *qemu_popen_cmd(const char *command, const char *mode);
int qemu_get_fd(QEMUFile *f);
int qemu_fclose(QEMUFile *f);
int64_t qemu_ftell(QEMUFile *f);
-void qemu_fflush(QEMUFile *f);
void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size);
void qemu_put_byte(QEMUFile *f, int v);
@@ -114,7 +113,6 @@ int qemu_file_rate_limit(QEMUFile *f);
int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate);
int64_t qemu_file_get_rate_limit(QEMUFile *f);
int qemu_file_get_error(QEMUFile *f);
-void qemu_file_set_error(QEMUFile *f, int ret);
static inline void qemu_put_be64s(QEMUFile *f, const uint64_t *pv)
{
diff --git a/savevm.c b/savevm.c
index ce10295..fef2ab9 100644
--- a/savevm.c
+++ b/savevm.c
@@ -443,7 +443,7 @@ int qemu_file_get_error(QEMUFile *f)
return f->last_error;
}
-void qemu_file_set_error(QEMUFile *f, int ret)
+static void qemu_file_set_error(QEMUFile *f, int ret)
{
if (f->last_error == 0) {
f->last_error = ret;
@@ -453,7 +453,7 @@ void qemu_file_set_error(QEMUFile *f, int ret)
/** Flushes QEMUFile buffer
*
*/
-void qemu_fflush(QEMUFile *f)
+static void qemu_fflush(QEMUFile *f)
{
int ret = 0;
--
1.8.2.1

View File

@ -0,0 +1,69 @@
From 70ae4fa3b1eb5b327a8375bcdd04c5d837f16d6f Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:32 +0100
Subject: [PATCH 230/246] 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>
---
migration.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/migration.c b/migration.c
index 71c6c10..a888f36 100644
--- a/migration.c
+++ b/migration.c
@@ -626,7 +626,6 @@ static void *migration_thread(void *opaque)
int64_t max_size = 0;
int64_t start_time = initial_time;
bool old_vm_running = false;
- bool last_round = false;
DPRINTF("beginning savevm\n");
qemu_savevm_state_begin(s->file, &s->params);
@@ -650,8 +649,11 @@ static void *migration_thread(void *opaque)
vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
s->xfer_limit = INT_MAX;
qemu_savevm_state_complete(s->file);
- last_round = true;
qemu_mutex_unlock_iothread();
+ if (!qemu_file_get_error(s->file)) {
+ migrate_finish_set_state(s, MIG_STATE_COMPLETED);
+ break;
+ }
}
}
@@ -675,15 +677,13 @@ static void *migration_thread(void *opaque)
sleep_time = 0;
initial_time = current_time;
}
- if (!last_round && (s->bytes_xfer >= s->xfer_limit)) {
+ if (s->bytes_xfer >= s->xfer_limit) {
/* usleep expects microseconds */
g_usleep((initial_time + BUFFER_DELAY - current_time)*1000);
sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
}
if (qemu_file_get_error(s->file)) {
migrate_finish_set_state(s, MIG_STATE_ERROR);
- } else if (last_round) {
- migrate_finish_set_state(s, MIG_STATE_COMPLETED);
}
}
@@ -695,7 +695,6 @@ static void *migration_thread(void *opaque)
runstate_set(RUN_STATE_POSTMIGRATE);
} else {
if (old_vm_running) {
- assert(last_round);
vm_start();
}
}
--
1.8.2.1

View File

@ -0,0 +1,41 @@
From 853560d2513e360ca0dc690fba8a55ad7da31312 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:33 +0100
Subject: [PATCH 231/246] 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>
---
migration.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/migration.c b/migration.c
index a888f36..35c3455 100644
--- a/migration.c
+++ b/migration.c
@@ -657,6 +657,10 @@ static void *migration_thread(void *opaque)
}
}
+ if (qemu_file_get_error(s->file)) {
+ migrate_finish_set_state(s, MIG_STATE_ERROR);
+ break;
+ }
current_time = qemu_get_clock_ms(rt_clock);
if (current_time >= initial_time + BUFFER_DELAY) {
uint64_t transferred_bytes = s->bytes_xfer;
@@ -682,9 +686,6 @@ static void *migration_thread(void *opaque)
g_usleep((initial_time + BUFFER_DELAY - current_time)*1000);
sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
}
- if (qemu_file_get_error(s->file)) {
- migrate_finish_set_state(s, MIG_STATE_ERROR);
- }
}
qemu_mutex_lock_iothread();
--
1.8.2.1

View File

@ -0,0 +1,35 @@
From f4f1096175be8a34f16fb3e39dfde22e4566d0c6 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:34 +0100
Subject: [PATCH 232/246] 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>
---
migration.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/migration.c b/migration.c
index 35c3455..d75beca 100644
--- a/migration.c
+++ b/migration.c
@@ -523,12 +523,6 @@ static int migration_put_buffer(void *opaque, const uint8_t *buf,
DPRINTF("putting %d bytes at %" PRId64 "\n", size, pos);
- ret = qemu_file_get_error(s->file);
- if (ret) {
- DPRINTF("flush when error, bailing: %s\n", strerror(-ret));
- return ret;
- }
-
if (size <= 0) {
return size;
}
--
1.8.2.1

View File

@ -0,0 +1,38 @@
From b806155b3d8c4ba206d90d2337fb682a446ed08c Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:35 +0100
Subject: [PATCH 233/246] 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>
---
migration.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/migration.c b/migration.c
index d75beca..ae2c83c 100644
--- a/migration.c
+++ b/migration.c
@@ -628,7 +628,7 @@ static void *migration_thread(void *opaque)
int64_t current_time;
uint64_t pending_size;
- if (s->bytes_xfer < s->xfer_limit) {
+ if (!qemu_file_rate_limit(s->file)) {
DPRINTF("iterate\n");
pending_size = qemu_savevm_state_pending(s->file, max_size);
DPRINTF("pending size %lu max %lu\n", pending_size, max_size);
@@ -675,7 +675,7 @@ static void *migration_thread(void *opaque)
sleep_time = 0;
initial_time = current_time;
}
- if (s->bytes_xfer >= s->xfer_limit) {
+ if (qemu_file_rate_limit(s->file)) {
/* usleep expects microseconds */
g_usleep((initial_time + BUFFER_DELAY - current_time)*1000);
sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
--
1.8.2.1

View File

@ -0,0 +1,105 @@
From d168927f61149c211e156be639be1cf8399bf30e Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:36 +0100
Subject: [PATCH 234/246] 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>
---
include/migration/qemu-file.h | 1 -
migration-exec.c | 10 ++++------
savevm.c | 22 ++++++++--------------
3 files changed, 12 insertions(+), 21 deletions(-)
diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
index 46fc11d..987e719 100644
--- a/include/migration/qemu-file.h
+++ b/include/migration/qemu-file.h
@@ -77,7 +77,6 @@ QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops);
QEMUFile *qemu_fopen(const char *filename, const char *mode);
QEMUFile *qemu_fdopen(int fd, const char *mode);
QEMUFile *qemu_fopen_socket(int fd);
-QEMUFile *qemu_popen(FILE *popen_file, const char *mode);
QEMUFile *qemu_popen_cmd(const char *command, const char *mode);
int qemu_get_fd(QEMUFile *f);
int qemu_fclose(QEMUFile *f);
diff --git a/migration-exec.c b/migration-exec.c
index a051a6e..5dc7313 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -59,19 +59,17 @@ static int exec_close(MigrationState *s)
void exec_start_outgoing_migration(MigrationState *s, const char *command, Error **errp)
{
- FILE *f;
-
- f = popen(command, "w");
+ QEMUFile *f;
+ f = qemu_popen_cmd(command, "w");
if (f == NULL) {
error_setg_errno(errp, errno, "failed to popen the migration target");
return;
}
- s->fd = fileno(f);
+ s->opaque = f;
+ s->fd = qemu_get_fd(f);
assert(s->fd != -1);
- s->opaque = qemu_popen(f, "w");
-
s->close = exec_close;
s->get_error = file_errno;
s->write = file_write;
diff --git a/savevm.c b/savevm.c
index fef2ab9..38699de 100644
--- a/savevm.c
+++ b/savevm.c
@@ -275,11 +275,17 @@ static const QEMUFileOps stdio_pipe_write_ops = {
.close = stdio_pclose
};
-QEMUFile *qemu_popen(FILE *stdio_file, const char *mode)
+QEMUFile *qemu_popen_cmd(const char *command, const char *mode)
{
+ FILE *stdio_file;
QEMUFileStdio *s;
- if (stdio_file == NULL || mode == NULL || (mode[0] != 'r' && mode[0] != 'w') || mode[1] != 0) {
+ stdio_file = popen(command, mode);
+ if (stdio_file == NULL) {
+ return NULL;
+ }
+
+ if (mode == NULL || (mode[0] != 'r' && mode[0] != 'w') || mode[1] != 0) {
fprintf(stderr, "qemu_popen: Argument validity check failed\n");
return NULL;
}
@@ -296,18 +302,6 @@ QEMUFile *qemu_popen(FILE *stdio_file, const char *mode)
return s->file;
}
-QEMUFile *qemu_popen_cmd(const char *command, const char *mode)
-{
- FILE *popen_file;
-
- popen_file = popen(command, mode);
- if(popen_file == NULL) {
- return NULL;
- }
-
- return qemu_popen(popen_file, mode);
-}
-
static const QEMUFileOps stdio_file_read_ops = {
.get_fd = stdio_get_fd,
.get_buffer = stdio_get_buffer,
--
1.8.2.1

View File

@ -0,0 +1,47 @@
From 1b98be7980ca1ac4a5ea1b140e09594c74824204 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:37 +0100
Subject: [PATCH 235/246] 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>
---
savevm.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/savevm.c b/savevm.c
index 38699de..1d49fde 100644
--- a/savevm.c
+++ b/savevm.c
@@ -256,6 +256,24 @@ static int stdio_fclose(void *opaque)
{
QEMUFileStdio *s = opaque;
int ret = 0;
+
+ if (s->file->ops->put_buffer) {
+ int fd = fileno(s->stdio_file);
+ struct stat st;
+
+ ret = fstat(fd, &st);
+ if (ret == 0 && S_ISREG(st.st_mode)) {
+ /*
+ * If the file handle is a regular file make sure the
+ * data is flushed to disk before signaling success.
+ */
+ ret = fsync(fd);
+ if (ret != 0) {
+ ret = -errno;
+ return ret;
+ }
+ }
+ }
if (fclose(s->stdio_file) == EOF) {
ret = -errno;
}
--
1.8.2.1

View File

@ -0,0 +1,68 @@
From 0755b0d7d8d94d566945d1016ca7a61a5913f4ae Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:38 +0100
Subject: [PATCH 236/246] 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>
---
include/qemu/osdep.h | 7 +++++++
migration-exec.c | 4 ----
savevm.c | 3 +++
3 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index 87d3b9c..df24400 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -9,6 +9,13 @@
#include <sys/signal.h>
#endif
+#ifndef _WIN32
+#include <sys/wait.h>
+#else
+#define WIFEXITED(x) 1
+#define WEXITSTATUS(x) (x)
+#endif
+
#include <sys/time.h>
#if defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10
diff --git a/migration-exec.c b/migration-exec.c
index 5dc7313..a2b5f8d 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -50,10 +50,6 @@ static int exec_close(MigrationState *s)
ret = qemu_fclose(s->opaque);
s->opaque = NULL;
s->fd = -1;
- if (ret >= 0 && !(WIFEXITED(ret) && WEXITSTATUS(ret) == 0)) {
- /* close succeeded, but non-zero exit code: */
- ret = -EIO; /* fake errno value */
- }
return ret;
}
diff --git a/savevm.c b/savevm.c
index 1d49fde..6d6f1f1 100644
--- a/savevm.c
+++ b/savevm.c
@@ -247,6 +247,9 @@ static int stdio_pclose(void *opaque)
ret = pclose(s->stdio_file);
if (ret == -1) {
ret = -errno;
+ } else if (!WIFEXITED(ret) || WEXITSTATUS(ret) != 0) {
+ /* close succeeded, but non-zero exit code: */
+ ret = -EIO; /* fake errno value */
}
g_free(s);
return ret;
--
1.8.2.1

View File

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

View File

@ -0,0 +1,75 @@
From 6690c2eb2a183f2853742e20a0d2a6fb0c39ae65 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:40 +0100
Subject: [PATCH 238/246] 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>
---
savevm.c | 20 ++++++++------------
1 file changed, 8 insertions(+), 12 deletions(-)
diff --git a/savevm.c b/savevm.c
index 76c88c7..c60ace3 100644
--- a/savevm.c
+++ b/savevm.c
@@ -119,8 +119,8 @@ struct QEMUFile {
void *opaque;
int is_write;
- int64_t buf_offset; /* start of buffer when writing, end of buffer
- when reading */
+ int64_t pos; /* start of buffer when writing, end of buffer
+ when reading */
int buf_index;
int buf_size; /* 0 when writing */
uint8_t buf[IO_BUF_SIZE];
@@ -505,9 +505,9 @@ static void qemu_fflush(QEMUFile *f)
return;
}
if (f->is_write && f->buf_index > 0) {
- ret = f->ops->put_buffer(f->opaque, f->buf, f->buf_offset, f->buf_index);
+ ret = f->ops->put_buffer(f->opaque, f->buf, f->pos, f->buf_index);
if (ret >= 0) {
- f->buf_offset += f->buf_index;
+ f->pos += f->buf_index;
}
f->buf_index = 0;
}
@@ -534,11 +534,11 @@ static void qemu_fill_buffer(QEMUFile *f)
f->buf_index = 0;
f->buf_size = pending;
- len = f->ops->get_buffer(f->opaque, f->buf + pending, f->buf_offset,
+ len = f->ops->get_buffer(f->opaque, f->buf + pending, f->pos,
IO_BUF_SIZE - pending);
if (len > 0) {
f->buf_size += len;
- f->buf_offset += len;
+ f->pos += len;
} else if (len == 0) {
qemu_file_set_error(f, -EIO);
} else if (len != -EAGAIN)
@@ -718,12 +718,8 @@ int qemu_get_byte(QEMUFile *f)
int64_t qemu_ftell(QEMUFile *f)
{
- /* buf_offset excludes buffer for writing but includes it for reading */
- if (f->is_write) {
- return f->buf_offset + f->buf_index;
- } else {
- return f->buf_offset - f->buf_size + f->buf_index;
- }
+ qemu_fflush(f);
+ return f->pos;
}
int qemu_file_rate_limit(QEMUFile *f)
--
1.8.2.1

View File

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

View File

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

View File

@ -0,0 +1,47 @@
From 75a2c8fdbeb4eb8fbe66e6b12a13994bf80bb08b Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:43 +0100
Subject: [PATCH 241/246] 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>
---
migration.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/migration.c b/migration.c
index 26ba6c9..def1e9e 100644
--- a/migration.c
+++ b/migration.c
@@ -589,6 +589,7 @@ static void *migration_thread(void *opaque)
MigrationState *s = opaque;
int64_t initial_time = qemu_get_clock_ms(rt_clock);
int64_t sleep_time = 0;
+ int64_t initial_bytes = 0;
int64_t max_size = 0;
int64_t start_time = initial_time;
bool old_vm_running = false;
@@ -629,7 +630,7 @@ static void *migration_thread(void *opaque)
}
current_time = qemu_get_clock_ms(rt_clock);
if (current_time >= initial_time + BUFFER_DELAY) {
- uint64_t transferred_bytes = s->bytes_xfer;
+ uint64_t transferred_bytes = qemu_ftell(s->file) - initial_bytes;
uint64_t time_spent = current_time - initial_time - sleep_time;
double bandwidth = transferred_bytes / time_spent;
max_size = bandwidth * migrate_max_downtime() / 1000000;
@@ -646,6 +647,7 @@ static void *migration_thread(void *opaque)
s->bytes_xfer = 0;
sleep_time = 0;
initial_time = current_time;
+ initial_bytes = qemu_ftell(s->file);
}
if (qemu_file_rate_limit(s->file)) {
/* usleep expects microseconds */
--
1.8.2.1

View File

@ -0,0 +1,80 @@
From ac64f1634590c63facd49747946d4c90975ed7be Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:44 +0100
Subject: [PATCH 242/246] 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>
---
migration.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/migration.c b/migration.c
index def1e9e..5c7d04f 100644
--- a/migration.c
+++ b/migration.c
@@ -462,10 +462,15 @@ void qmp_migrate_set_speed(int64_t value, Error **errp)
if (value < 0) {
value = 0;
}
+ if (value > SIZE_MAX) {
+ value = SIZE_MAX;
+ }
s = migrate_get_current();
s->bandwidth_limit = value;
- qemu_file_set_rate_limit(s->file, s->bandwidth_limit);
+ if (s->file) {
+ qemu_file_set_rate_limit(s->file, s->bandwidth_limit / XFER_LIMIT_RATIO);
+ }
}
void qmp_migrate_set_downtime(double value, Error **errp)
@@ -567,11 +572,8 @@ static int64_t migration_set_rate_limit(void *opaque, int64_t new_rate)
if (qemu_file_get_error(s->file)) {
goto out;
}
- if (new_rate > SIZE_MAX) {
- new_rate = SIZE_MAX;
- }
- s->xfer_limit = new_rate / XFER_LIMIT_RATIO;
+ s->xfer_limit = new_rate;
out:
return s->xfer_limit;
@@ -614,7 +616,7 @@ static void *migration_thread(void *opaque)
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
old_vm_running = runstate_is_running();
vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
- s->xfer_limit = INT_MAX;
+ qemu_file_set_rate_limit(s->file, INT_MAX);
qemu_savevm_state_complete(s->file);
qemu_mutex_unlock_iothread();
if (!qemu_file_get_error(s->file)) {
@@ -691,11 +693,12 @@ void migrate_fd_connect(MigrationState *s)
/* This is a best 1st approximation. ns to ms */
s->expected_downtime = max_downtime/1000000;
- s->xfer_limit = s->bandwidth_limit / XFER_LIMIT_RATIO;
-
s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s);
s->file = qemu_fopen_ops(s, &migration_file_ops);
+ qemu_file_set_rate_limit(s->file,
+ s->bandwidth_limit / XFER_LIMIT_RATIO);
+
qemu_thread_create(&s->thread, migration_thread, s,
QEMU_THREAD_JOINABLE);
notifier_list_notify(&migration_state_notifiers, s);
--
1.8.2.1

View File

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

View File

@ -0,0 +1,54 @@
From 89c59de898603ea7ee0879f5e4244ab33dd4ec3d Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:46 +0100
Subject: [PATCH 244/246] 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>
---
migration.c | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/migration.c b/migration.c
index ea84008..949a5bc 100644
--- a/migration.c
+++ b/migration.c
@@ -272,6 +272,12 @@ static void migrate_fd_cleanup(void *opaque)
DPRINTF("closing file\n");
qemu_fclose(s->file);
s->file = NULL;
+
+ qemu_mutex_unlock_iothread();
+ qemu_thread_join(&s->thread);
+ qemu_mutex_lock_iothread();
+
+ migrate_fd_close(s);
}
assert(s->migration_file == NULL);
@@ -523,16 +529,7 @@ static int migration_put_buffer(void *opaque, const uint8_t *buf,
static int migration_close(void *opaque)
{
- MigrationState *s = opaque;
-
- DPRINTF("closing\n");
-
- qemu_mutex_unlock_iothread();
- qemu_thread_join(&s->thread);
- qemu_mutex_lock_iothread();
- assert(s->state != MIG_STATE_ACTIVE);
-
- return migrate_fd_close(s);
+ return 0;
}
static int migration_get_fd(void *opaque)
--
1.8.2.1

View File

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

View File

@ -0,0 +1,50 @@
From 9b421d01c4ffdf89ec93b84363357773d8e09083 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 22 Feb 2013 17:36:48 +0100
Subject: [PATCH 246/246] 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>
---
migration.c | 14 ++------------
1 file changed, 2 insertions(+), 12 deletions(-)
diff --git a/migration.c b/migration.c
index 68ce4c9..0aff06d 100644
--- a/migration.c
+++ b/migration.c
@@ -274,10 +274,10 @@ static void migrate_fd_cleanup(void *opaque)
qemu_thread_join(&s->thread);
qemu_mutex_lock_iothread();
- migrate_fd_close(s);
+ qemu_fclose(s->file);
+ s->file = NULL;
}
- assert(s->file == NULL);
assert(s->state != MIG_STATE_ACTIVE);
if (s->state != MIG_STATE_COMPLETED) {
@@ -311,16 +311,6 @@ static void migrate_fd_cancel(MigrationState *s)
migrate_finish_set_state(s, MIG_STATE_CANCELLED);
}
-int migrate_fd_close(MigrationState *s)
-{
- int rc = 0;
- if (s->file != NULL) {
- rc = qemu_fclose(s->file);
- s->file = NULL;
- }
- return rc;
-}
-
void add_migration_state_change_notifier(Notifier *notify)
{
notifier_list_add(&migration_state_notifiers, notify);
--
1.8.2.1

103
qemu.spec
View File

@ -131,7 +131,7 @@
Summary: QEMU is a FAST! processor emulator
Name: qemu
Version: 1.4.1
Release: 3%{?dist}
Release: 4%{?dist}
# Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped
Epoch: 2
License: GPLv2+ and LGPLv2+ and BSD
@ -199,6 +199,56 @@ 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
# qemu-km migration cleanup (bz #962954)
# Moves migration notifiers to iothread, fixing spice assert
Patch0200: 0200-ui-vnc-tls.c-fix-gnutls-warning.patch
Patch0201: 0201-migration-change-initial-value-of-expected_downtime.patch
Patch0202: 0202-migration-calculate-end-time-after-we-have-sent-the-.patch
Patch0203: 0203-migration-don-t-account-sleep-time-for-calculating-b.patch
Patch0204: 0204-migration-calculate-expected_downtime.patch
Patch0205: 0205-migration-simplify-while-loop.patch
Patch0206: 0206-migration-always-use-vm_stop_force_state.patch
Patch0207: 0207-migration-move-more-error-handling-to-migrate_fd_cle.patch
Patch0208: 0208-migration-push-qemu_savevm_state_cancel-out-of-qemu_.patch
Patch0209: 0209-block-migration-remove-useless-calls-to-blk_mig_clea.patch
Patch0210: 0210-qemu-file-pass-errno-from-qemu_fflush-via-f-last_err.patch
Patch0211: 0211-migration-use-qemu_file_set_error-to-pass-error-code.patch
Patch0212: 0212-qemu-file-temporarily-expose-qemu_file_set_error-and.patch
Patch0213: 0213-migration-flush-all-data-to-fd-when-buffered_flush-i.patch
Patch0214: 0214-migration-use-qemu_file_set_error.patch
Patch0215: 0215-migration-simplify-error-handling.patch
Patch0216: 0216-migration-do-not-nest-flushing-of-device-data.patch
Patch0217: 0217-migration-add-migrate_set_state-tracepoint.patch
Patch0218: 0218-migration-prepare-to-access-s-state-outside-critical.patch
Patch0219: 0219-migration-cleanup-migration-including-thread-in-the-.patch
Patch0220: 0220-block-migration-remove-variables-that-are-never-read.patch
Patch0221: 0221-block-migration-small-preparatory-changes-for-lockin.patch
Patch0222: 0222-block-migration-document-usage-of-state-across-threa.patch
Patch0223: 0223-block-migration-add-lock.patch
Patch0224: 0224-migration-reorder-SaveVMHandlers-members.patch
Patch0225: 0225-migration-run-pending-iterate-callbacks-out-of-big-l.patch
Patch0226: 0226-migration-run-setup-callbacks-out-of-big-lock.patch
Patch0227: 0227-migration-yay-buffering-is-gone.patch
Patch0228: 0228-Rename-buffered_-to-migration_.patch
Patch0229: 0229-qemu-file-make-qemu_fflush-and-qemu_file_set_error-p.patch
Patch0230: 0230-migration-eliminate-last_round.patch
Patch0231: 0231-migration-detect-error-before-sleeping.patch
Patch0232: 0232-migration-remove-useless-qemu_file_get_error-check.patch
Patch0233: 0233-migration-use-qemu_file_rate_limit-consistently.patch
Patch0234: 0234-migration-merge-qemu_popen_cmd-with-qemu_popen.patch
Patch0235: 0235-qemu-file-fsync-a-writable-stdio-QEMUFile.patch
Patch0236: 0236-qemu-file-check-exit-status-when-closing-a-pipe-QEMU.patch
Patch0237: 0237-qemu-file-add-writable-socket-QEMUFile.patch
Patch0238: 0238-qemu-file-simplify-and-export-qemu_ftell.patch
Patch0239: 0239-migration-use-QEMUFile-for-migration-channel-lifetim.patch
Patch0240: 0240-migration-use-QEMUFile-for-writing-outgoing-migratio.patch
Patch0241: 0241-migration-use-qemu_ftell-to-compute-bandwidth.patch
Patch0242: 0242-migration-small-changes-around-rate-limiting.patch
Patch0243: 0243-migration-move-rate-limiting-to-QEMUFile.patch
Patch0244: 0244-migration-move-contents-of-migration_close-to-migrat.patch
Patch0245: 0245-migration-eliminate-s-migration_file.patch
Patch0246: 0246-migration-inline-migrate_fd_close.patch
BuildRequires: SDL-devel
BuildRequires: zlib-devel
BuildRequires: which
@ -673,6 +723,54 @@ CAC emulation development files.
# Fix crash with usbredir (bz #962826)
%patch0107 -p1
# qemu-km migration cleanup (bz #962954)
%patch0200 -p1
%patch0201 -p1
%patch0202 -p1
%patch0203 -p1
%patch0204 -p1
%patch0205 -p1
%patch0206 -p1
%patch0207 -p1
%patch0208 -p1
%patch0209 -p1
%patch0210 -p1
%patch0211 -p1
%patch0212 -p1
%patch0213 -p1
%patch0214 -p1
%patch0215 -p1
%patch0216 -p1
%patch0217 -p1
%patch0218 -p1
%patch0219 -p1
%patch0220 -p1
%patch0221 -p1
%patch0222 -p1
%patch0223 -p1
%patch0224 -p1
%patch0225 -p1
%patch0226 -p1
%patch0227 -p1
%patch0228 -p1
%patch0229 -p1
%patch0230 -p1
%patch0231 -p1
%patch0232 -p1
%patch0233 -p1
%patch0234 -p1
%patch0235 -p1
%patch0236 -p1
%patch0237 -p1
%patch0238 -p1
%patch0239 -p1
%patch0240 -p1
%patch0241 -p1
%patch0242 -p1
%patch0243 -p1
%patch0244 -p1
%patch0245 -p1
%patch0246 -p1
%build
%if %{with kvmonly}
@ -1288,6 +1386,9 @@ getent passwd qemu >/dev/null || \
%endif
%changelog
* 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)