diff --git a/hmp-commands.hx b/hmp-commands.hx index f3de4076471b65b55430912aa575935bba63083d..bb52e4d3bd435a68e2ba3f11976a98eedf6746d4 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1025,7 +1025,9 @@ ETEXI .name = "migrate_start_postcopy", .args_type = "", .params = "", - .help = "Switch migration to postcopy mode", + .help = "Followup to a migration command to switch the migration" + " to postcopy mode. The x-postcopy-ram capability must " + "be set before the original migration command.", .mhandler.cmd = hmp_migrate_start_postcopy, }, diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index f992494e108ac217ad350bb96661c880a74d0ca4..3bb8897727acc5657ce0b00ea3fcf43957fbf847 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -112,7 +112,7 @@ void qemu_savevm_state_header(QEMUFile *f); int qemu_savevm_state_iterate(QEMUFile *f, bool postcopy); void qemu_savevm_state_cleanup(void); void qemu_savevm_state_complete_postcopy(QEMUFile *f); -void qemu_savevm_state_complete_precopy(QEMUFile *f); +void qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_only); void qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size, uint64_t *res_non_postcopiable, uint64_t *res_postcopiable); diff --git a/migration/migration.c b/migration/migration.c index c5c977e7375298606b7421a5334cfd3e1d433328..7e4e27b57d4dcc54610b204ebd027c34d958bd91 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -768,7 +768,7 @@ void qmp_migrate_start_postcopy(Error **errp) MigrationState *s = migrate_get_current(); if (!migrate_postcopy_ram()) { - error_setg(errp, "Enable postcopy with migration_set_capability before" + error_setg(errp, "Enable postcopy with migrate_set_capability before" " the start of migration"); return; } @@ -902,38 +902,31 @@ bool migration_in_postcopy(MigrationState *s) MigrationState *migrate_init(const MigrationParams *params) { MigrationState *s = migrate_get_current(); - int64_t bandwidth_limit = s->bandwidth_limit; - bool enabled_capabilities[MIGRATION_CAPABILITY_MAX]; - int64_t xbzrle_cache_size = s->xbzrle_cache_size; - int compress_level = s->parameters[MIGRATION_PARAMETER_COMPRESS_LEVEL]; - int compress_thread_count = - s->parameters[MIGRATION_PARAMETER_COMPRESS_THREADS]; - int decompress_thread_count = - s->parameters[MIGRATION_PARAMETER_DECOMPRESS_THREADS]; - int x_cpu_throttle_initial = - s->parameters[MIGRATION_PARAMETER_X_CPU_THROTTLE_INITIAL]; - int x_cpu_throttle_increment = - s->parameters[MIGRATION_PARAMETER_X_CPU_THROTTLE_INCREMENT]; - - memcpy(enabled_capabilities, s->enabled_capabilities, - sizeof(enabled_capabilities)); - memset(s, 0, sizeof(*s)); + /* + * Reinitialise all migration state, except + * parameters/capabilities that the user set, and + * locks. + */ + s->bytes_xfer = 0; + s->xfer_limit = 0; + s->cleanup_bh = 0; + s->file = NULL; + s->state = MIGRATION_STATUS_NONE; s->params = *params; - memcpy(s->enabled_capabilities, enabled_capabilities, - sizeof(enabled_capabilities)); - s->xbzrle_cache_size = xbzrle_cache_size; - - s->parameters[MIGRATION_PARAMETER_COMPRESS_LEVEL] = compress_level; - s->parameters[MIGRATION_PARAMETER_COMPRESS_THREADS] = - compress_thread_count; - s->parameters[MIGRATION_PARAMETER_DECOMPRESS_THREADS] = - decompress_thread_count; - s->parameters[MIGRATION_PARAMETER_X_CPU_THROTTLE_INITIAL] = - x_cpu_throttle_initial; - s->parameters[MIGRATION_PARAMETER_X_CPU_THROTTLE_INCREMENT] = - x_cpu_throttle_increment; - s->bandwidth_limit = bandwidth_limit; + s->rp_state.from_dst_file = NULL; + s->rp_state.error = false; + s->mbps = 0.0; + s->downtime = 0; + s->expected_downtime = 0; + s->dirty_pages_rate = 0; + s->dirty_bytes_rate = 0; + s->setup_time = 0; + s->dirty_sync_count = 0; + s->start_postcopy = false; + s->migration_thread_running = false; + s->last_req_rb = NULL; + migrate_set_state(s, MIGRATION_STATUS_NONE, MIGRATION_STATUS_SETUP); QSIMPLEQ_INIT(&s->src_page_requests); @@ -1428,6 +1421,12 @@ static int postcopy_start(MigrationState *ms, bool *old_vm_running) goto fail; } + /* + * Cause any non-postcopiable, but iterative devices to + * send out their final data. + */ + qemu_savevm_state_complete_precopy(ms->file, true); + /* * in Finish migrate and with the io-lock held everything should * be quiet, but we've potentially still got dirty pages and we @@ -1471,7 +1470,7 @@ static int postcopy_start(MigrationState *ms, bool *old_vm_running) */ qemu_savevm_send_postcopy_listen(fb); - qemu_savevm_state_complete_precopy(fb); + qemu_savevm_state_complete_precopy(fb, false); qemu_savevm_send_ping(fb, 3); qemu_savevm_send_postcopy_run(fb); @@ -1538,7 +1537,7 @@ static void migration_completion(MigrationState *s, int current_active_state, ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE); if (ret >= 0) { qemu_file_set_rate_limit(s->file, INT64_MAX); - qemu_savevm_state_complete_precopy(s->file); + qemu_savevm_state_complete_precopy(s->file, false); } } qemu_mutex_unlock_iothread(); diff --git a/migration/ram.c b/migration/ram.c index 62cf42bfdbdc53a36fe1c0de8c28bd5a68999a1c..7f32696d7988f59ef5131bf546b4e4ff0171cfab 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -1184,7 +1184,8 @@ int ram_save_queue_pages(MigrationState *ms, const char *rbname, } trace_ram_save_queue_pages(ramblock->idstr, start, len); if (start+len > ramblock->used_length) { - error_report("%s request overrun start=%zx len=%zx blocklen=%zx", + error_report("%s request overrun start=" RAM_ADDR_FMT " len=" + RAM_ADDR_FMT " blocklen=" RAM_ADDR_FMT, __func__, start, len, ramblock->used_length); goto err; } @@ -1845,7 +1846,7 @@ int ram_discard_range(MigrationIncomingState *mis, ret = postcopy_ram_discard_range(mis, host_startaddr, length); } else { error_report("ram_discard_range: Overrun block '%s' (%" PRIu64 - "/%zu/%zu)", + "/%zx/" RAM_ADDR_FMT")", block_name, start, length, rb->used_length); } @@ -2273,6 +2274,7 @@ static int ram_load_postcopy(QEMUFile *f) /* Temporary page that is later 'placed' */ void *postcopy_host_page = postcopy_get_tmp_page(mis); void *last_host = NULL; + bool all_zero = false; while (!ret && !(flags & RAM_SAVE_FLAG_EOS)) { ram_addr_t addr; @@ -2280,7 +2282,6 @@ static int ram_load_postcopy(QEMUFile *f) void *page_buffer = NULL; void *place_source = NULL; uint8_t ch; - bool all_zero = false; addr = qemu_get_be64(f); flags = addr & ~TARGET_PAGE_MASK; diff --git a/migration/rdma.c b/migration/rdma.c index 553fbd7503cae257f0f6e9f33cd3e9740bc16df9..dcabb91005c6bf58ccc6023f0df17fa6b5547bb8 100644 --- a/migration/rdma.c +++ b/migration/rdma.c @@ -577,7 +577,7 @@ static int rdma_add_block(RDMAContext *rdma, const char *block_name, block->is_ram_block = local->init ? false : true; if (rdma->blockmap) { - g_hash_table_insert(rdma->blockmap, (void *) block_offset, block); + g_hash_table_insert(rdma->blockmap, (void *)(uintptr_t)block_offset, block); } trace_rdma_add_block(block_name, local->nb_blocks, diff --git a/migration/savevm.c b/migration/savevm.c index be52314a12dc7244b9b295d5fb5ada928900f2c9..d90e22856836d1b3e19b6276cd22c849ee04fde4 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -1026,7 +1026,7 @@ void qemu_savevm_state_complete_postcopy(QEMUFile *f) qemu_fflush(f); } -void qemu_savevm_state_complete_precopy(QEMUFile *f) +void qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_only) { QJSON *vmdesc; int vmdesc_len; @@ -1041,9 +1041,11 @@ void qemu_savevm_state_complete_precopy(QEMUFile *f) QTAILQ_FOREACH(se, &savevm_state.handlers, entry) { if (!se->ops || (in_postcopy && se->ops->save_live_complete_postcopy) || + (in_postcopy && !iterable_only) || !se->ops->save_live_complete_precopy) { continue; } + if (se->ops && se->ops->is_active) { if (!se->ops->is_active(se->opaque)) { continue; @@ -1062,6 +1064,10 @@ void qemu_savevm_state_complete_precopy(QEMUFile *f) } } + if (iterable_only) { + return; + } + vmdesc = qjson_new(); json_prop_int(vmdesc, "page_size", TARGET_PAGE_SIZE); json_start_array(vmdesc, "devices"); @@ -1176,7 +1182,7 @@ static int qemu_savevm_state(QEMUFile *f, Error **errp) ret = qemu_file_get_error(f); if (ret == 0) { - qemu_savevm_state_complete_precopy(f); + qemu_savevm_state_complete_precopy(f, false); ret = qemu_file_get_error(f); } qemu_savevm_state_cleanup(); diff --git a/qapi-schema.json b/qapi-schema.json index 36e59b8932211d8d85d9cd8cf771791cded75588..b65905f4d60e9fcd2f94d35aad9bb43aaef56868 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -706,7 +706,9 @@ ## # @migrate-start-postcopy # -# Switch migration to postcopy mode +# Followup to a migration command to switch the migration to postcopy mode. +# The x-postcopy-ram capability must be set before the original migration +# command. # # Since: 2.5 { 'command': 'migrate-start-postcopy' }