migration/next for 20180604
-----BEGIN PGP SIGNATURE----- iQIcBAABCAAGBQJbFLygAAoJEPSH7xhYctcjszUP/j7/21sHXwPyB5y4CQHsivLL 18MnXTkjgSlue3fuPKI9ZzD2VZq19AtwarLuW3IFf15adKfeV0hhZsIMUmu0XTAz jgol8YYgoYlk3/on8Ux8PWV9RWKHh7vWAF7hjwJOnI5CFF7gXz6kVjUx03A7RSnB 1a92lvgl5P8AbK5HZ/i08nOaAxCUWIVIoQeZf3BlZ5WdJE0j+d0Mvp/S8NEq5VPD P6oYJZy64QFGotmV1vtYD4G/Hqe8XBw2LoSVgjPSmQpd1m4CXiq0iyCxtC8HT+iq 0P0eHATRglc5oGhRV6Mi5ixH2K2MvpshdyMKVAbkJchKBHn4k3m6jefhnUXuucwC fq9x7VIYzQ80S+44wJri683yUWP3Qmbb6mWYBb1L0jgbTkY1wx431IYMtDVv5q4R oXtbe77G6lWKHH0SFrU8TY/fqJvBwpat+QwOoNsluHVjzAzpOpcVokB8pLj592/1 bHkDwvv7i+B37muOF3PFy++BoliwpRiNbVC5Btw4mnbOoY+AeJHMRBuhJHU6EyJv GOFiQ5w5XEXEu98giNqHcc0AC8w7iTRGI472UzpS0AG20wpc1/2jF0yM99stauwD oIu3MU4dQlz6QRy8KFnJShqjYNYuOs59USLiYM79ABa9J+JxJxxTAaqRbUFojQR6 KN2i0QQJ+6MO4Skjbu/3 =K0eJ -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/juanquintela/tags/migration/20180604' into staging migration/next for 20180604 # gpg: Signature made Mon 04 Jun 2018 05:14:24 BST # gpg: using RSA key F487EF185872D723 # gpg: Good signature from "Juan Quintela <quintela@redhat.com>" # gpg: aka "Juan Quintela <quintela@trasno.org>" # Primary key fingerprint: 1899 FF8E DEBF 58CC EE03 4B82 F487 EF18 5872 D723 * remotes/juanquintela/tags/migration/20180604: migration: not wait RDMA_CM_EVENT_DISCONNECTED event after rdma_disconnect migration: remove unnecessary variables len in QIOChannelRDMA migration: Don't activate block devices if using -S migration: discard non-migratable RAMBlocks migration: introduce decompress-error-check Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
b74588a493
38
exec.c
38
exec.c
@ -104,6 +104,9 @@ static MemoryRegion io_mem_unassigned;
|
|||||||
* (Set during postcopy)
|
* (Set during postcopy)
|
||||||
*/
|
*/
|
||||||
#define RAM_UF_ZEROPAGE (1 << 3)
|
#define RAM_UF_ZEROPAGE (1 << 3)
|
||||||
|
|
||||||
|
/* RAM can be migrated */
|
||||||
|
#define RAM_MIGRATABLE (1 << 4)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef TARGET_PAGE_BITS_VARY
|
#ifdef TARGET_PAGE_BITS_VARY
|
||||||
@ -1839,6 +1842,21 @@ void qemu_ram_set_uf_zeroable(RAMBlock *rb)
|
|||||||
rb->flags |= RAM_UF_ZEROPAGE;
|
rb->flags |= RAM_UF_ZEROPAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool qemu_ram_is_migratable(RAMBlock *rb)
|
||||||
|
{
|
||||||
|
return rb->flags & RAM_MIGRATABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qemu_ram_set_migratable(RAMBlock *rb)
|
||||||
|
{
|
||||||
|
rb->flags |= RAM_MIGRATABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qemu_ram_unset_migratable(RAMBlock *rb)
|
||||||
|
{
|
||||||
|
rb->flags &= ~RAM_MIGRATABLE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Called with iothread lock held. */
|
/* Called with iothread lock held. */
|
||||||
void qemu_ram_set_idstr(RAMBlock *new_block, const char *name, DeviceState *dev)
|
void qemu_ram_set_idstr(RAMBlock *new_block, const char *name, DeviceState *dev)
|
||||||
{
|
{
|
||||||
@ -3894,6 +3912,26 @@ int qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int qemu_ram_foreach_migratable_block(RAMBlockIterFunc func, void *opaque)
|
||||||
|
{
|
||||||
|
RAMBlock *block;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
RAMBLOCK_FOREACH(block) {
|
||||||
|
if (!qemu_ram_is_migratable(block)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ret = func(block->idstr, block->host, block->offset,
|
||||||
|
block->used_length, opaque);
|
||||||
|
if (ret) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unmap pages of memory from start to start+length such that
|
* Unmap pages of memory from start to start+length such that
|
||||||
* they a) read as 0, b) Trigger whatever fault mechanism
|
* they a) read as 0, b) Trigger whatever fault mechanism
|
||||||
|
@ -1692,6 +1692,9 @@ static void machvirt_machine_init(void)
|
|||||||
}
|
}
|
||||||
type_init(machvirt_machine_init);
|
type_init(machvirt_machine_init);
|
||||||
|
|
||||||
|
#define VIRT_COMPAT_2_12 \
|
||||||
|
HW_COMPAT_2_12
|
||||||
|
|
||||||
static void virt_2_12_instance_init(Object *obj)
|
static void virt_2_12_instance_init(Object *obj)
|
||||||
{
|
{
|
||||||
VirtMachineState *vms = VIRT_MACHINE(obj);
|
VirtMachineState *vms = VIRT_MACHINE(obj);
|
||||||
@ -1762,6 +1765,7 @@ static void virt_2_12_instance_init(Object *obj)
|
|||||||
|
|
||||||
static void virt_machine_2_12_options(MachineClass *mc)
|
static void virt_machine_2_12_options(MachineClass *mc)
|
||||||
{
|
{
|
||||||
|
SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_12);
|
||||||
}
|
}
|
||||||
DEFINE_VIRT_MACHINE_AS_LATEST(2, 12)
|
DEFINE_VIRT_MACHINE_AS_LATEST(2, 12)
|
||||||
|
|
||||||
|
@ -430,6 +430,7 @@ static void pc_i440fx_3_0_machine_options(MachineClass *m)
|
|||||||
pc_i440fx_machine_options(m);
|
pc_i440fx_machine_options(m);
|
||||||
m->alias = "pc";
|
m->alias = "pc";
|
||||||
m->is_default = 1;
|
m->is_default = 1;
|
||||||
|
SET_MACHINE_COMPAT(m, PC_COMPAT_2_12);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_I440FX_MACHINE(v3_0, "pc-i440fx-3.0", NULL,
|
DEFINE_I440FX_MACHINE(v3_0, "pc-i440fx-3.0", NULL,
|
||||||
|
@ -312,6 +312,7 @@ static void pc_q35_3_0_machine_options(MachineClass *m)
|
|||||||
{
|
{
|
||||||
pc_q35_machine_options(m);
|
pc_q35_machine_options(m);
|
||||||
m->alias = "q35";
|
m->alias = "q35";
|
||||||
|
SET_MACHINE_COMPAT(m, PC_COMPAT_2_12);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_Q35_MACHINE(v3_0, "pc-q35-3.0", NULL,
|
DEFINE_Q35_MACHINE(v3_0, "pc-q35-3.0", NULL,
|
||||||
|
@ -75,6 +75,9 @@ const char *qemu_ram_get_idstr(RAMBlock *rb);
|
|||||||
bool qemu_ram_is_shared(RAMBlock *rb);
|
bool qemu_ram_is_shared(RAMBlock *rb);
|
||||||
bool qemu_ram_is_uf_zeroable(RAMBlock *rb);
|
bool qemu_ram_is_uf_zeroable(RAMBlock *rb);
|
||||||
void qemu_ram_set_uf_zeroable(RAMBlock *rb);
|
void qemu_ram_set_uf_zeroable(RAMBlock *rb);
|
||||||
|
bool qemu_ram_is_migratable(RAMBlock *rb);
|
||||||
|
void qemu_ram_set_migratable(RAMBlock *rb);
|
||||||
|
void qemu_ram_unset_migratable(RAMBlock *rb);
|
||||||
|
|
||||||
size_t qemu_ram_pagesize(RAMBlock *block);
|
size_t qemu_ram_pagesize(RAMBlock *block);
|
||||||
size_t qemu_ram_pagesize_largest(void);
|
size_t qemu_ram_pagesize_largest(void);
|
||||||
@ -119,6 +122,7 @@ typedef int (RAMBlockIterFunc)(const char *block_name, void *host_addr,
|
|||||||
ram_addr_t offset, ram_addr_t length, void *opaque);
|
ram_addr_t offset, ram_addr_t length, void *opaque);
|
||||||
|
|
||||||
int qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque);
|
int qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque);
|
||||||
|
int qemu_ram_foreach_migratable_block(RAMBlockIterFunc func, void *opaque);
|
||||||
int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length);
|
int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
#ifndef HW_COMPAT_H
|
#ifndef HW_COMPAT_H
|
||||||
#define HW_COMPAT_H
|
#define HW_COMPAT_H
|
||||||
|
|
||||||
#define HW_COMPAT_2_12
|
#define HW_COMPAT_2_12 \
|
||||||
|
{\
|
||||||
|
.driver = "migration",\
|
||||||
|
.property = "decompress-error-check",\
|
||||||
|
.value = "off",\
|
||||||
|
},
|
||||||
|
|
||||||
#define HW_COMPAT_2_11 \
|
#define HW_COMPAT_2_11 \
|
||||||
{\
|
{\
|
||||||
|
@ -202,6 +202,16 @@ static void migrate_generate_event(int new_state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool migrate_late_block_activate(void)
|
||||||
|
{
|
||||||
|
MigrationState *s;
|
||||||
|
|
||||||
|
s = migrate_get_current();
|
||||||
|
|
||||||
|
return s->enabled_capabilities[
|
||||||
|
MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE];
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called on -incoming with a defer: uri.
|
* Called on -incoming with a defer: uri.
|
||||||
* The migration can be started later after any parameters have been
|
* The migration can be started later after any parameters have been
|
||||||
@ -311,13 +321,23 @@ static void process_incoming_migration_bh(void *opaque)
|
|||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
MigrationIncomingState *mis = opaque;
|
MigrationIncomingState *mis = opaque;
|
||||||
|
|
||||||
/* Make sure all file formats flush their mutable metadata.
|
/* If capability late_block_activate is set:
|
||||||
* If we get an error here, just don't restart the VM yet. */
|
* Only fire up the block code now if we're going to restart the
|
||||||
bdrv_invalidate_cache_all(&local_err);
|
* VM, else 'cont' will do it.
|
||||||
if (local_err) {
|
* This causes file locking to happen; so we don't want it to happen
|
||||||
error_report_err(local_err);
|
* unless we really are starting the VM.
|
||||||
local_err = NULL;
|
*/
|
||||||
autostart = false;
|
if (!migrate_late_block_activate() ||
|
||||||
|
(autostart && (!global_state_received() ||
|
||||||
|
global_state_get_runstate() == RUN_STATE_RUNNING))) {
|
||||||
|
/* Make sure all file formats flush their mutable metadata.
|
||||||
|
* If we get an error here, just don't restart the VM yet. */
|
||||||
|
bdrv_invalidate_cache_all(&local_err);
|
||||||
|
if (local_err) {
|
||||||
|
error_report_err(local_err);
|
||||||
|
local_err = NULL;
|
||||||
|
autostart = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2971,6 +2991,8 @@ void migration_global_dump(Monitor *mon)
|
|||||||
ms->send_configuration ? "on" : "off");
|
ms->send_configuration ? "on" : "off");
|
||||||
monitor_printf(mon, "send-section-footer: %s\n",
|
monitor_printf(mon, "send-section-footer: %s\n",
|
||||||
ms->send_section_footer ? "on" : "off");
|
ms->send_section_footer ? "on" : "off");
|
||||||
|
monitor_printf(mon, "decompress-error-check: %s\n",
|
||||||
|
ms->decompress_error_check ? "on" : "off");
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEFINE_PROP_MIG_CAP(name, x) \
|
#define DEFINE_PROP_MIG_CAP(name, x) \
|
||||||
@ -2984,6 +3006,8 @@ static Property migration_properties[] = {
|
|||||||
send_configuration, true),
|
send_configuration, true),
|
||||||
DEFINE_PROP_BOOL("send-section-footer", MigrationState,
|
DEFINE_PROP_BOOL("send-section-footer", MigrationState,
|
||||||
send_section_footer, true),
|
send_section_footer, true),
|
||||||
|
DEFINE_PROP_BOOL("decompress-error-check", MigrationState,
|
||||||
|
decompress_error_check, true),
|
||||||
|
|
||||||
/* Migration parameters */
|
/* Migration parameters */
|
||||||
DEFINE_PROP_UINT8("x-compress-level", MigrationState,
|
DEFINE_PROP_UINT8("x-compress-level", MigrationState,
|
||||||
|
@ -212,6 +212,13 @@ struct MigrationState
|
|||||||
/* Needed by postcopy-pause state */
|
/* Needed by postcopy-pause state */
|
||||||
QemuSemaphore postcopy_pause_sem;
|
QemuSemaphore postcopy_pause_sem;
|
||||||
QemuSemaphore postcopy_pause_rp_sem;
|
QemuSemaphore postcopy_pause_rp_sem;
|
||||||
|
/*
|
||||||
|
* Whether we abort the migration if decompression errors are
|
||||||
|
* detected at the destination. It is left at false for qemu
|
||||||
|
* older than 3.0, since only newer qemu sends streams that
|
||||||
|
* do not trigger spurious decompression errors.
|
||||||
|
*/
|
||||||
|
bool decompress_error_check;
|
||||||
};
|
};
|
||||||
|
|
||||||
void migrate_set_state(int *state, int old_state, int new_state);
|
void migrate_set_state(int *state, int old_state, int new_state);
|
||||||
|
@ -374,7 +374,7 @@ bool postcopy_ram_supported_by_host(MigrationIncomingState *mis)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* We don't support postcopy with shared RAM yet */
|
/* We don't support postcopy with shared RAM yet */
|
||||||
if (qemu_ram_foreach_block(test_ramblock_postcopiable, NULL)) {
|
if (qemu_ram_foreach_migratable_block(test_ramblock_postcopiable, NULL)) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -502,7 +502,7 @@ static int cleanup_range(const char *block_name, void *host_addr,
|
|||||||
*/
|
*/
|
||||||
int postcopy_ram_incoming_init(MigrationIncomingState *mis, size_t ram_pages)
|
int postcopy_ram_incoming_init(MigrationIncomingState *mis, size_t ram_pages)
|
||||||
{
|
{
|
||||||
if (qemu_ram_foreach_block(init_range, NULL)) {
|
if (qemu_ram_foreach_migratable_block(init_range, NULL)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -524,7 +524,7 @@ int postcopy_ram_incoming_cleanup(MigrationIncomingState *mis)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qemu_ram_foreach_block(cleanup_range, mis)) {
|
if (qemu_ram_foreach_migratable_block(cleanup_range, mis)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* Let the fault thread quit */
|
/* Let the fault thread quit */
|
||||||
@ -593,7 +593,7 @@ static int nhp_range(const char *block_name, void *host_addr,
|
|||||||
*/
|
*/
|
||||||
int postcopy_ram_prepare_discard(MigrationIncomingState *mis)
|
int postcopy_ram_prepare_discard(MigrationIncomingState *mis)
|
||||||
{
|
{
|
||||||
if (qemu_ram_foreach_block(nhp_range, mis)) {
|
if (qemu_ram_foreach_migratable_block(nhp_range, mis)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -604,7 +604,7 @@ int postcopy_ram_prepare_discard(MigrationIncomingState *mis)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Mark the given area of RAM as requiring notification to unwritten areas
|
* Mark the given area of RAM as requiring notification to unwritten areas
|
||||||
* Used as a callback on qemu_ram_foreach_block.
|
* Used as a callback on qemu_ram_foreach_migratable_block.
|
||||||
* host_addr: Base of area to mark
|
* host_addr: Base of area to mark
|
||||||
* offset: Offset in the whole ram arena
|
* offset: Offset in the whole ram arena
|
||||||
* length: Length of the section
|
* length: Length of the section
|
||||||
@ -1099,7 +1099,7 @@ int postcopy_ram_enable_notify(MigrationIncomingState *mis)
|
|||||||
mis->have_fault_thread = true;
|
mis->have_fault_thread = true;
|
||||||
|
|
||||||
/* Mark so that we get notified of accesses to unwritten areas */
|
/* Mark so that we get notified of accesses to unwritten areas */
|
||||||
if (qemu_ram_foreach_block(ram_block_enable_notify, mis)) {
|
if (qemu_ram_foreach_migratable_block(ram_block_enable_notify, mis)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,11 +157,16 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Should be holding either ram_list.mutex, or the RCU lock. */
|
||||||
|
#define RAMBLOCK_FOREACH_MIGRATABLE(block) \
|
||||||
|
RAMBLOCK_FOREACH(block) \
|
||||||
|
if (!qemu_ram_is_migratable(block)) {} else
|
||||||
|
|
||||||
static void ramblock_recv_map_init(void)
|
static void ramblock_recv_map_init(void)
|
||||||
{
|
{
|
||||||
RAMBlock *rb;
|
RAMBlock *rb;
|
||||||
|
|
||||||
RAMBLOCK_FOREACH(rb) {
|
RAMBLOCK_FOREACH_MIGRATABLE(rb) {
|
||||||
assert(!rb->receivedmap);
|
assert(!rb->receivedmap);
|
||||||
rb->receivedmap = bitmap_new(rb->max_length >> qemu_target_page_bits());
|
rb->receivedmap = bitmap_new(rb->max_length >> qemu_target_page_bits());
|
||||||
}
|
}
|
||||||
@ -1078,6 +1083,10 @@ unsigned long migration_bitmap_find_dirty(RAMState *rs, RAMBlock *rb,
|
|||||||
unsigned long *bitmap = rb->bmap;
|
unsigned long *bitmap = rb->bmap;
|
||||||
unsigned long next;
|
unsigned long next;
|
||||||
|
|
||||||
|
if (!qemu_ram_is_migratable(rb)) {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
if (rs->ram_bulk_stage && start > 0) {
|
if (rs->ram_bulk_stage && start > 0) {
|
||||||
next = start + 1;
|
next = start + 1;
|
||||||
} else {
|
} else {
|
||||||
@ -1123,7 +1132,7 @@ uint64_t ram_pagesize_summary(void)
|
|||||||
RAMBlock *block;
|
RAMBlock *block;
|
||||||
uint64_t summary = 0;
|
uint64_t summary = 0;
|
||||||
|
|
||||||
RAMBLOCK_FOREACH(block) {
|
RAMBLOCK_FOREACH_MIGRATABLE(block) {
|
||||||
summary |= block->page_size;
|
summary |= block->page_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1147,7 +1156,7 @@ static void migration_bitmap_sync(RAMState *rs)
|
|||||||
|
|
||||||
qemu_mutex_lock(&rs->bitmap_mutex);
|
qemu_mutex_lock(&rs->bitmap_mutex);
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
RAMBLOCK_FOREACH(block) {
|
RAMBLOCK_FOREACH_MIGRATABLE(block) {
|
||||||
migration_bitmap_sync_range(rs, block, 0, block->used_length);
|
migration_bitmap_sync_range(rs, block, 0, block->used_length);
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
@ -1786,6 +1795,11 @@ static int ram_save_host_page(RAMState *rs, PageSearchStatus *pss,
|
|||||||
size_t pagesize_bits =
|
size_t pagesize_bits =
|
||||||
qemu_ram_pagesize(pss->block) >> TARGET_PAGE_BITS;
|
qemu_ram_pagesize(pss->block) >> TARGET_PAGE_BITS;
|
||||||
|
|
||||||
|
if (!qemu_ram_is_migratable(pss->block)) {
|
||||||
|
error_report("block %s should not be migrated !", pss->block->idstr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
/* Check the pages is dirty and if it is send it */
|
/* Check the pages is dirty and if it is send it */
|
||||||
if (!migration_bitmap_clear_dirty(rs, pss->block, pss->page)) {
|
if (!migration_bitmap_clear_dirty(rs, pss->block, pss->page)) {
|
||||||
@ -1884,7 +1898,7 @@ uint64_t ram_bytes_total(void)
|
|||||||
uint64_t total = 0;
|
uint64_t total = 0;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
RAMBLOCK_FOREACH(block) {
|
RAMBLOCK_FOREACH_MIGRATABLE(block) {
|
||||||
total += block->used_length;
|
total += block->used_length;
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
@ -1939,7 +1953,7 @@ static void ram_save_cleanup(void *opaque)
|
|||||||
*/
|
*/
|
||||||
memory_global_dirty_log_stop();
|
memory_global_dirty_log_stop();
|
||||||
|
|
||||||
QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
|
RAMBLOCK_FOREACH_MIGRATABLE(block) {
|
||||||
g_free(block->bmap);
|
g_free(block->bmap);
|
||||||
block->bmap = NULL;
|
block->bmap = NULL;
|
||||||
g_free(block->unsentmap);
|
g_free(block->unsentmap);
|
||||||
@ -2002,7 +2016,7 @@ void ram_postcopy_migrated_memory_release(MigrationState *ms)
|
|||||||
{
|
{
|
||||||
struct RAMBlock *block;
|
struct RAMBlock *block;
|
||||||
|
|
||||||
RAMBLOCK_FOREACH(block) {
|
RAMBLOCK_FOREACH_MIGRATABLE(block) {
|
||||||
unsigned long *bitmap = block->bmap;
|
unsigned long *bitmap = block->bmap;
|
||||||
unsigned long range = block->used_length >> TARGET_PAGE_BITS;
|
unsigned long range = block->used_length >> TARGET_PAGE_BITS;
|
||||||
unsigned long run_start = find_next_zero_bit(bitmap, range, 0);
|
unsigned long run_start = find_next_zero_bit(bitmap, range, 0);
|
||||||
@ -2080,7 +2094,7 @@ static int postcopy_each_ram_send_discard(MigrationState *ms)
|
|||||||
struct RAMBlock *block;
|
struct RAMBlock *block;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
RAMBLOCK_FOREACH(block) {
|
RAMBLOCK_FOREACH_MIGRATABLE(block) {
|
||||||
PostcopyDiscardState *pds =
|
PostcopyDiscardState *pds =
|
||||||
postcopy_discard_send_init(ms, block->idstr);
|
postcopy_discard_send_init(ms, block->idstr);
|
||||||
|
|
||||||
@ -2288,7 +2302,7 @@ int ram_postcopy_send_discard_bitmap(MigrationState *ms)
|
|||||||
rs->last_sent_block = NULL;
|
rs->last_sent_block = NULL;
|
||||||
rs->last_page = 0;
|
rs->last_page = 0;
|
||||||
|
|
||||||
QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
|
RAMBLOCK_FOREACH_MIGRATABLE(block) {
|
||||||
unsigned long pages = block->used_length >> TARGET_PAGE_BITS;
|
unsigned long pages = block->used_length >> TARGET_PAGE_BITS;
|
||||||
unsigned long *bitmap = block->bmap;
|
unsigned long *bitmap = block->bmap;
|
||||||
unsigned long *unsentmap = block->unsentmap;
|
unsigned long *unsentmap = block->unsentmap;
|
||||||
@ -2447,7 +2461,7 @@ static void ram_list_init_bitmaps(void)
|
|||||||
|
|
||||||
/* Skip setting bitmap if there is no RAM */
|
/* Skip setting bitmap if there is no RAM */
|
||||||
if (ram_bytes_total()) {
|
if (ram_bytes_total()) {
|
||||||
QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
|
RAMBLOCK_FOREACH_MIGRATABLE(block) {
|
||||||
pages = block->max_length >> TARGET_PAGE_BITS;
|
pages = block->max_length >> TARGET_PAGE_BITS;
|
||||||
block->bmap = bitmap_new(pages);
|
block->bmap = bitmap_new(pages);
|
||||||
bitmap_set(block->bmap, 0, pages);
|
bitmap_set(block->bmap, 0, pages);
|
||||||
@ -2563,7 +2577,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
|
|||||||
|
|
||||||
qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE);
|
qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE);
|
||||||
|
|
||||||
RAMBLOCK_FOREACH(block) {
|
RAMBLOCK_FOREACH_MIGRATABLE(block) {
|
||||||
qemu_put_byte(f, strlen(block->idstr));
|
qemu_put_byte(f, strlen(block->idstr));
|
||||||
qemu_put_buffer(f, (uint8_t *)block->idstr, strlen(block->idstr));
|
qemu_put_buffer(f, (uint8_t *)block->idstr, strlen(block->idstr));
|
||||||
qemu_put_be64(f, block->used_length);
|
qemu_put_be64(f, block->used_length);
|
||||||
@ -2807,6 +2821,11 @@ static inline RAMBlock *ram_block_from_stream(QEMUFile *f, int flags)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!qemu_ram_is_migratable(block)) {
|
||||||
|
error_report("block %s should not be migrated !", id);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2881,7 +2900,7 @@ static void *do_data_decompress(void *opaque)
|
|||||||
|
|
||||||
ret = qemu_uncompress_data(¶m->stream, des, pagesize,
|
ret = qemu_uncompress_data(¶m->stream, des, pagesize,
|
||||||
param->compbuf, len);
|
param->compbuf, len);
|
||||||
if (ret < 0) {
|
if (ret < 0 && migrate_get_current()->decompress_error_check) {
|
||||||
error_report("decompress data failed");
|
error_report("decompress data failed");
|
||||||
qemu_file_set_error(decomp_file, ret);
|
qemu_file_set_error(decomp_file, ret);
|
||||||
}
|
}
|
||||||
@ -3049,7 +3068,7 @@ static int ram_load_cleanup(void *opaque)
|
|||||||
xbzrle_load_cleanup();
|
xbzrle_load_cleanup();
|
||||||
compress_threads_load_cleanup();
|
compress_threads_load_cleanup();
|
||||||
|
|
||||||
RAMBLOCK_FOREACH(rb) {
|
RAMBLOCK_FOREACH_MIGRATABLE(rb) {
|
||||||
g_free(rb->receivedmap);
|
g_free(rb->receivedmap);
|
||||||
rb->receivedmap = NULL;
|
rb->receivedmap = NULL;
|
||||||
}
|
}
|
||||||
@ -3311,7 +3330,10 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
|
|||||||
length = qemu_get_be64(f);
|
length = qemu_get_be64(f);
|
||||||
|
|
||||||
block = qemu_ram_block_by_name(id);
|
block = qemu_ram_block_by_name(id);
|
||||||
if (block) {
|
if (block && !qemu_ram_is_migratable(block)) {
|
||||||
|
error_report("block %s should not be migrated !", id);
|
||||||
|
ret = -EINVAL;
|
||||||
|
} else if (block) {
|
||||||
if (length != block->used_length) {
|
if (length != block->used_length) {
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
@ -400,7 +400,6 @@ struct QIOChannelRDMA {
|
|||||||
QIOChannel parent;
|
QIOChannel parent;
|
||||||
RDMAContext *rdma;
|
RDMAContext *rdma;
|
||||||
QEMUFile *file;
|
QEMUFile *file;
|
||||||
size_t len;
|
|
||||||
bool blocking; /* XXX we don't actually honour this yet */
|
bool blocking; /* XXX we don't actually honour this yet */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2268,8 +2267,7 @@ static int qemu_rdma_write(QEMUFile *f, RDMAContext *rdma,
|
|||||||
|
|
||||||
static void qemu_rdma_cleanup(RDMAContext *rdma)
|
static void qemu_rdma_cleanup(RDMAContext *rdma)
|
||||||
{
|
{
|
||||||
struct rdma_cm_event *cm_event;
|
int idx;
|
||||||
int ret, idx;
|
|
||||||
|
|
||||||
if (rdma->cm_id && rdma->connected) {
|
if (rdma->cm_id && rdma->connected) {
|
||||||
if ((rdma->error_state ||
|
if ((rdma->error_state ||
|
||||||
@ -2283,14 +2281,7 @@ static void qemu_rdma_cleanup(RDMAContext *rdma)
|
|||||||
qemu_rdma_post_send_control(rdma, NULL, &head);
|
qemu_rdma_post_send_control(rdma, NULL, &head);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = rdma_disconnect(rdma->cm_id);
|
rdma_disconnect(rdma->cm_id);
|
||||||
if (!ret) {
|
|
||||||
trace_qemu_rdma_cleanup_waiting_for_disconnect();
|
|
||||||
ret = rdma_get_cm_event(rdma->channel, &cm_event);
|
|
||||||
if (!ret) {
|
|
||||||
rdma_ack_cm_event(cm_event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
trace_qemu_rdma_cleanup_disconnect();
|
trace_qemu_rdma_cleanup_disconnect();
|
||||||
rdma->connected = false;
|
rdma->connected = false;
|
||||||
}
|
}
|
||||||
@ -2608,6 +2599,7 @@ static ssize_t qio_channel_rdma_writev(QIOChannel *ioc,
|
|||||||
int ret;
|
int ret;
|
||||||
ssize_t done = 0;
|
ssize_t done = 0;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
CHECK_ERROR_STATE();
|
CHECK_ERROR_STATE();
|
||||||
|
|
||||||
@ -2627,10 +2619,10 @@ static ssize_t qio_channel_rdma_writev(QIOChannel *ioc,
|
|||||||
while (remaining) {
|
while (remaining) {
|
||||||
RDMAControlHeader head;
|
RDMAControlHeader head;
|
||||||
|
|
||||||
rioc->len = MIN(remaining, RDMA_SEND_INCREMENT);
|
len = MIN(remaining, RDMA_SEND_INCREMENT);
|
||||||
remaining -= rioc->len;
|
remaining -= len;
|
||||||
|
|
||||||
head.len = rioc->len;
|
head.len = len;
|
||||||
head.type = RDMA_CONTROL_QEMU_FILE;
|
head.type = RDMA_CONTROL_QEMU_FILE;
|
||||||
|
|
||||||
ret = qemu_rdma_exchange_send(rdma, &head, data, NULL, NULL, NULL);
|
ret = qemu_rdma_exchange_send(rdma, &head, data, NULL, NULL, NULL);
|
||||||
@ -2640,8 +2632,8 @@ static ssize_t qio_channel_rdma_writev(QIOChannel *ioc,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
data += rioc->len;
|
data += len;
|
||||||
done += rioc->len;
|
done += len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2736,8 +2728,7 @@ static ssize_t qio_channel_rdma_readv(QIOChannel *ioc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rioc->len = done;
|
return done;
|
||||||
return rioc->len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2689,11 +2689,13 @@ void vmstate_register_ram(MemoryRegion *mr, DeviceState *dev)
|
|||||||
{
|
{
|
||||||
qemu_ram_set_idstr(mr->ram_block,
|
qemu_ram_set_idstr(mr->ram_block,
|
||||||
memory_region_name(mr), dev);
|
memory_region_name(mr), dev);
|
||||||
|
qemu_ram_set_migratable(mr->ram_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vmstate_unregister_ram(MemoryRegion *mr, DeviceState *dev)
|
void vmstate_unregister_ram(MemoryRegion *mr, DeviceState *dev)
|
||||||
{
|
{
|
||||||
qemu_ram_unset_idstr(mr->ram_block);
|
qemu_ram_unset_idstr(mr->ram_block);
|
||||||
|
qemu_ram_unset_migratable(mr->ram_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vmstate_register_ram_global(MemoryRegion *mr)
|
void vmstate_register_ram_global(MemoryRegion *mr)
|
||||||
|
@ -146,7 +146,6 @@ qemu_rdma_accept_pin_state(bool pin) "%d"
|
|||||||
qemu_rdma_accept_pin_verbsc(void *verbs) "Verbs context after listen: %p"
|
qemu_rdma_accept_pin_verbsc(void *verbs) "Verbs context after listen: %p"
|
||||||
qemu_rdma_block_for_wrid_miss(const char *wcompstr, int wcomp, const char *gcompstr, uint64_t req) "A Wanted wrid %s (%d) but got %s (%" PRIu64 ")"
|
qemu_rdma_block_for_wrid_miss(const char *wcompstr, int wcomp, const char *gcompstr, uint64_t req) "A Wanted wrid %s (%d) but got %s (%" PRIu64 ")"
|
||||||
qemu_rdma_cleanup_disconnect(void) ""
|
qemu_rdma_cleanup_disconnect(void) ""
|
||||||
qemu_rdma_cleanup_waiting_for_disconnect(void) ""
|
|
||||||
qemu_rdma_close(void) ""
|
qemu_rdma_close(void) ""
|
||||||
qemu_rdma_connect_pin_all_requested(void) ""
|
qemu_rdma_connect_pin_all_requested(void) ""
|
||||||
qemu_rdma_connect_pin_all_outcome(bool pin) "%d"
|
qemu_rdma_connect_pin_all_outcome(bool pin) "%d"
|
||||||
|
@ -376,13 +376,17 @@
|
|||||||
# @postcopy-blocktime: Calculate downtime for postcopy live migration
|
# @postcopy-blocktime: Calculate downtime for postcopy live migration
|
||||||
# (since 3.0)
|
# (since 3.0)
|
||||||
#
|
#
|
||||||
|
# @late-block-activate: If enabled, the destination will not activate block
|
||||||
|
# devices (and thus take locks) immediately at the end of migration.
|
||||||
|
# (since 3.0)
|
||||||
|
#
|
||||||
# Since: 1.2
|
# Since: 1.2
|
||||||
##
|
##
|
||||||
{ 'enum': 'MigrationCapability',
|
{ 'enum': 'MigrationCapability',
|
||||||
'data': ['xbzrle', 'rdma-pin-all', 'auto-converge', 'zero-blocks',
|
'data': ['xbzrle', 'rdma-pin-all', 'auto-converge', 'zero-blocks',
|
||||||
'compress', 'events', 'postcopy-ram', 'x-colo', 'release-ram',
|
'compress', 'events', 'postcopy-ram', 'x-colo', 'release-ram',
|
||||||
'block', 'return-path', 'pause-before-switchover', 'x-multifd',
|
'block', 'return-path', 'pause-before-switchover', 'x-multifd',
|
||||||
'dirty-bitmaps', 'postcopy-blocktime' ] }
|
'dirty-bitmaps', 'postcopy-blocktime', 'late-block-activate' ] }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @MigrationCapabilityStatus:
|
# @MigrationCapabilityStatus:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user