From fe5971542cf8cf5ab79a13aef10483bbbb0bc05e Mon Sep 17 00:00:00 2001 From: Yaniv Kamay <yaniv@qumranet.com> Date: Wed, 18 Mar 2009 21:59:49 +0200 Subject: [PATCH 1/6] qemu: fix physical memory migration Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> Bugzilla: 492351 RH-Upstream-status: pending Acked-by: Juan Quintela <quintela@redhat.com> Acked-by: Amit Shah <amit.shah@redhat.com> --- qemu/hw/hw.h | 1 + qemu/migration.c | 5 +++++ qemu/savevm.c | 5 +++++ qemu/vl.c | 19 +++++++++++++++---- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/qemu/hw/hw.h b/qemu/hw/hw.h index eab7bb4..6aad964 100644 --- a/qemu/hw/hw.h +++ b/qemu/hw/hw.h @@ -67,6 +67,7 @@ unsigned int qemu_get_be32(QEMUFile *f); uint64_t qemu_get_be64(QEMUFile *f); int qemu_file_rate_limit(QEMUFile *f); int qemu_file_has_error(QEMUFile *f); +void qemu_file_set_has_error(QEMUFile *f); /* Try to send any outstanding data. This function is useful when output is * halted due to rate limiting or EAGAIN errors occur as it can be used to diff --git a/qemu/migration.c b/qemu/migration.c index 60d5ca0..688390d 100644 --- a/qemu/migration.c +++ b/qemu/migration.c @@ -219,6 +219,11 @@ void migrate_fd_put_ready(void *opaque) bdrv_flush_all(); qemu_savevm_state_complete(s->file); + if (qemu_file_has_error(s->file)) { + vm_start(); + s->done(s, MIG_STATE_ERROR); + return; + } s->done(s, MIG_STATE_COMPLETED); } } diff --git a/qemu/savevm.c b/qemu/savevm.c index 2c28b5d..be5b7b1 100644 --- a/qemu/savevm.c +++ b/qemu/savevm.c @@ -379,6 +379,11 @@ int qemu_file_has_error(QEMUFile *f) return f->has_error; } +void qemu_file_set_has_error(QEMUFile *f) +{ + f->has_error = 1; +} + void qemu_fflush(QEMUFile *f) { if (!f->put_buffer) diff --git a/qemu/vl.c b/qemu/vl.c index 4d2cf00..b2bb644 100644 --- a/qemu/vl.c +++ b/qemu/vl.c @@ -3231,8 +3231,14 @@ static int ram_save_block(QEMUFile *f) int found = 0; while (addr < phys_ram_size) { - if (kvm_enabled() && current_addr == 0) - kvm_update_dirty_pages_log(); /* FIXME: propagate errors */ + if (kvm_enabled() && current_addr == 0) { + int r; + if ((r = kvm_update_dirty_pages_log())) { + printf("%s: update dirty pages log failed %d\n", __FUNCTION__, r); + qemu_file_set_has_error(f); // for now: replacing FIXME with ugly hack + return 0; + } + } if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) { uint8_t ch; @@ -3303,10 +3309,15 @@ static int ram_save_live(QEMUFile *f, int stage, void *opaque) /* try transferring iterative blocks of memory */ if (stage == 3) { - cpu_physical_memory_set_dirty_tracking(0); - + int r; + if ((r = kvm_update_dirty_pages_log())) { + printf("%s: update dirty pages log failed %d\n", __FUNCTION__, r); + qemu_file_set_has_error(f); + return 0; + } /* flush all remaining blocks regardless of rate limiting */ while (ram_save_block(f) != 0); + cpu_physical_memory_set_dirty_tracking(0); } qemu_put_be64(f, RAM_SAVE_FLAG_EOS); -- 1.6.1