migration/next for 20151015

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABCAAGBQJWH0bXAAoJEPSH7xhYctcjCSYP/jxMPlLpmTWCAJra++buJ77d
 qgU/MWSIf3/9AGYrbz8Y5KUGlfMeB7ZYDICnFH9vF69fnHHwV9kgMqIS8yC8coih
 JeKT4pWQzhleIz5lFmHr7Krt5i5U0Q+SJ0aWQv489UkKEXlIDz2YM23yvaIQjMP4
 Ue6FkiHqoENsUznhnxsCjPMkR3a0zuVRqEseIUD+1lCjnLzgrYQks/lwXNtlX8HF
 7HbQl4MAKi3vRSxy0Tx1cyCOoJ8zdmIhwwlBL3dS8TYDODXFWYuJDWNqvNjoQiit
 lQ2M9TgsvPxjwaoujnP8/dUCcvnVNaDnAPwTxs/FjUCSQ1i4gzBOg3KNExs5Rhn4
 SHWMjgffDMWoHXLSQScz+qpVIPBgK4ETJk4TG0vgi7ZA0/XAE45R8fbMf66vpmhT
 F2s00UwCvZ14E614sdnCrhYPafb2f+HMRrpM6Rr5Yt1Q6EP30ZK1RKE6+SvGN6KJ
 kQFzNvXJn9F7ClXzuVmtBKRw3hgEJWv1wPqf+RXpotTc9IDxCFIk1YwD4FofgkdT
 A8sYcw1S3W0bcYHB/l85AW+1L+Mkwl3qtaOh3Y7orF/NwQfSfVTXxTMCrOqAXhBA
 zg9WsLJlTjVVdGUnEiqPFuDu/LaVUTd8A+qiNsqyiImw/WJnf8qFrmpDafbMq1YH
 zQichbdN7s7GVswYL6qC
 =IZs3
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/juanquintela/tags/migration/20151015' into staging

migration/next for 20151015

# gpg: Signature made Thu 15 Oct 2015 07:25:27 BST using RSA key ID 5872D723
# gpg: Good signature from "Juan Quintela <quintela@redhat.com>"
# gpg:                 aka "Juan Quintela <quintela@trasno.org>"

* remotes/juanquintela/tags/migration/20151015:
  migration: fix deadlock
  migration: announce VM's new home just before VM is runnable
  Migration: Generate the completed event only when we complete

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2015-10-16 15:47:59 +01:00
commit e95bdb4341
2 changed files with 40 additions and 19 deletions

View File

@ -294,17 +294,22 @@ static void process_incoming_migration_co(void *opaque)
migrate_decompress_threads_join(); migrate_decompress_threads_join();
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
migrate_generate_event(MIGRATION_STATUS_COMPLETED);
qemu_announce_self();
/* Make sure all file formats flush their mutable metadata */ /* Make sure all file formats flush their mutable metadata */
bdrv_invalidate_cache_all(&local_err); bdrv_invalidate_cache_all(&local_err);
if (local_err) { if (local_err) {
migrate_generate_event(MIGRATION_STATUS_FAILED);
error_report_err(local_err); error_report_err(local_err);
migrate_decompress_threads_join(); migrate_decompress_threads_join();
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/*
* This must happen after all error conditions are dealt with and
* we're sure the VM is going to be running on this host.
*/
qemu_announce_self();
/* If global state section was not received or we are in running /* If global state section was not received or we are in running
state, we need to obey autostart. Any other state is set with state, we need to obey autostart. Any other state is set with
runstate_set. */ runstate_set. */
@ -320,6 +325,12 @@ static void process_incoming_migration_co(void *opaque)
runstate_set(global_state_get_runstate()); runstate_set(global_state_get_runstate());
} }
migrate_decompress_threads_join(); migrate_decompress_threads_join();
/*
* This must happen after any state changes since as soon as an external
* observer sees this event they might start to prod at the VM assuming
* it's ready to use.
*/
migrate_generate_event(MIGRATION_STATUS_COMPLETED);
} }
void process_incoming_migration(QEMUFile *f) void process_incoming_migration(QEMUFile *f)

View File

@ -219,7 +219,6 @@ static RAMBlock *last_seen_block;
/* This is the last block from where we have sent data */ /* This is the last block from where we have sent data */
static RAMBlock *last_sent_block; static RAMBlock *last_sent_block;
static ram_addr_t last_offset; static ram_addr_t last_offset;
static unsigned long *migration_bitmap;
static QemuMutex migration_bitmap_mutex; static QemuMutex migration_bitmap_mutex;
static uint64_t migration_dirty_pages; static uint64_t migration_dirty_pages;
static uint32_t last_version; static uint32_t last_version;
@ -236,6 +235,11 @@ struct PageSearchStatus {
}; };
typedef struct PageSearchStatus PageSearchStatus; typedef struct PageSearchStatus PageSearchStatus;
static struct BitmapRcu {
struct rcu_head rcu;
unsigned long *bmap;
} *migration_bitmap_rcu;
struct CompressParam { struct CompressParam {
bool start; bool start;
bool done; bool done;
@ -540,7 +544,7 @@ ram_addr_t migration_bitmap_find_and_reset_dirty(RAMBlock *rb,
unsigned long next; unsigned long next;
bitmap = atomic_rcu_read(&migration_bitmap); bitmap = atomic_rcu_read(&migration_bitmap_rcu)->bmap;
if (ram_bulk_stage && nr > base) { if (ram_bulk_stage && nr > base) {
next = nr + 1; next = nr + 1;
} else { } else {
@ -558,7 +562,7 @@ ram_addr_t migration_bitmap_find_and_reset_dirty(RAMBlock *rb,
static void migration_bitmap_sync_range(ram_addr_t start, ram_addr_t length) static void migration_bitmap_sync_range(ram_addr_t start, ram_addr_t length)
{ {
unsigned long *bitmap; unsigned long *bitmap;
bitmap = atomic_rcu_read(&migration_bitmap); bitmap = atomic_rcu_read(&migration_bitmap_rcu)->bmap;
migration_dirty_pages += migration_dirty_pages +=
cpu_physical_memory_sync_dirty_bitmap(bitmap, start, length); cpu_physical_memory_sync_dirty_bitmap(bitmap, start, length);
} }
@ -1090,17 +1094,22 @@ void free_xbzrle_decoded_buf(void)
xbzrle_decoded_buf = NULL; xbzrle_decoded_buf = NULL;
} }
static void migration_bitmap_free(struct BitmapRcu *bmap)
{
g_free(bmap->bmap);
g_free(bmap);
}
static void migration_end(void) static void migration_end(void)
{ {
/* caller have hold iothread lock or is in a bh, so there is /* caller have hold iothread lock or is in a bh, so there is
* no writing race against this migration_bitmap * no writing race against this migration_bitmap
*/ */
unsigned long *bitmap = migration_bitmap; struct BitmapRcu *bitmap = migration_bitmap_rcu;
atomic_rcu_set(&migration_bitmap, NULL); atomic_rcu_set(&migration_bitmap_rcu, NULL);
if (bitmap) { if (bitmap) {
memory_global_dirty_log_stop(); memory_global_dirty_log_stop();
synchronize_rcu(); call_rcu(bitmap, migration_bitmap_free, rcu);
g_free(bitmap);
} }
XBZRLE_cache_lock(); XBZRLE_cache_lock();
@ -1136,9 +1145,10 @@ void migration_bitmap_extend(ram_addr_t old, ram_addr_t new)
/* called in qemu main thread, so there is /* called in qemu main thread, so there is
* no writing race against this migration_bitmap * no writing race against this migration_bitmap
*/ */
if (migration_bitmap) { if (migration_bitmap_rcu) {
unsigned long *old_bitmap = migration_bitmap, *bitmap; struct BitmapRcu *old_bitmap = migration_bitmap_rcu, *bitmap;
bitmap = bitmap_new(new); bitmap = g_new(struct BitmapRcu, 1);
bitmap->bmap = bitmap_new(new);
/* prevent migration_bitmap content from being set bit /* prevent migration_bitmap content from being set bit
* by migration_bitmap_sync_range() at the same time. * by migration_bitmap_sync_range() at the same time.
@ -1146,13 +1156,12 @@ void migration_bitmap_extend(ram_addr_t old, ram_addr_t new)
* at the same time. * at the same time.
*/ */
qemu_mutex_lock(&migration_bitmap_mutex); qemu_mutex_lock(&migration_bitmap_mutex);
bitmap_copy(bitmap, old_bitmap, old); bitmap_copy(bitmap->bmap, old_bitmap->bmap, old);
bitmap_set(bitmap, old, new - old); bitmap_set(bitmap->bmap, old, new - old);
atomic_rcu_set(&migration_bitmap, bitmap); atomic_rcu_set(&migration_bitmap_rcu, bitmap);
qemu_mutex_unlock(&migration_bitmap_mutex); qemu_mutex_unlock(&migration_bitmap_mutex);
migration_dirty_pages += new - old; migration_dirty_pages += new - old;
synchronize_rcu(); call_rcu(old_bitmap, migration_bitmap_free, rcu);
g_free(old_bitmap);
} }
} }
@ -1210,8 +1219,9 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
reset_ram_globals(); reset_ram_globals();
ram_bitmap_pages = last_ram_offset() >> TARGET_PAGE_BITS; ram_bitmap_pages = last_ram_offset() >> TARGET_PAGE_BITS;
migration_bitmap = bitmap_new(ram_bitmap_pages); migration_bitmap_rcu = g_new(struct BitmapRcu, 1);
bitmap_set(migration_bitmap, 0, ram_bitmap_pages); migration_bitmap_rcu->bmap = bitmap_new(ram_bitmap_pages);
bitmap_set(migration_bitmap_rcu->bmap, 0, ram_bitmap_pages);
/* /*
* Count the total number of pages used by ram blocks not including any * Count the total number of pages used by ram blocks not including any