Skip to content

Commit

Permalink
migration: add postcopy total blocktime into query-migrate
Browse files Browse the repository at this point in the history
Postcopy total blocktime is available on destination side only.
But query-migrate was possible only for source. This patch
adds ability to call query-migrate on destination.
To be able to see postcopy blocktime, need to request postcopy-blocktime
capability.

The query-migrate command will show following sample result:
{"return":
    "postcopy-vcpu-blocktime": [115, 100],
    "status": "completed",
    "postcopy-blocktime": 100
}}

postcopy_vcpu_blocktime contains list, where the first item is the first
vCPU in QEMU.

This patch has a drawback, it combines states of incoming and
outgoing migration. Ongoing migration state will overwrite incoming
state. Looks like better to separate query-migrate for incoming and
outgoing migration or add parameter to indicate type of migration.

Reviewed-by: Dr. David Alan Gilbert <[email protected]>
Signed-off-by: Alexey Perevalov <[email protected]>
Reviewed-by: Juan Quintela <[email protected]>
Signed-off-by: Juan Quintela <[email protected]>
Message-Id: <[email protected]>
Signed-off-by: Dr. David Alan Gilbert <[email protected]>
  • Loading branch information
Alexey Perevalov authored and dagrh committed Apr 25, 2018
1 parent 346f3da commit 65ace06
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 5 deletions.
15 changes: 15 additions & 0 deletions hmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,21 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict)
info->cpu_throttle_percentage);
}

if (info->has_postcopy_blocktime) {
monitor_printf(mon, "postcopy blocktime: %u\n",
info->postcopy_blocktime);
}

if (info->has_postcopy_vcpu_blocktime) {
Visitor *v;
char *str;
v = string_output_visitor_new(false, &str);
visit_type_uint32List(v, NULL, &info->postcopy_vcpu_blocktime, NULL);
visit_complete(v, &str);
monitor_printf(mon, "postcopy vcpu blocktime: %s\n", str);
g_free(str);
visit_free(v);
}
qapi_free_MigrationInfo(info);
qapi_free_MigrationCapabilityStatusList(caps);
}
Expand Down
42 changes: 38 additions & 4 deletions migration/migration.c
Original file line number Diff line number Diff line change
Expand Up @@ -630,14 +630,15 @@ static void populate_disk_info(MigrationInfo *info)
}
}

MigrationInfo *qmp_query_migrate(Error **errp)
static void fill_source_migration_info(MigrationInfo *info)
{
MigrationInfo *info = g_malloc0(sizeof(*info));
MigrationState *s = migrate_get_current();

switch (s->state) {
case MIGRATION_STATUS_NONE:
/* no migration has happened ever */
/* do not overwrite destination migration status */
return;
break;
case MIGRATION_STATUS_SETUP:
info->has_status = true;
Expand Down Expand Up @@ -688,8 +689,6 @@ MigrationInfo *qmp_query_migrate(Error **errp)
break;
}
info->status = s->state;

return info;
}

/**
Expand Down Expand Up @@ -753,6 +752,41 @@ static bool migrate_caps_check(bool *cap_list,
return true;
}

static void fill_destination_migration_info(MigrationInfo *info)
{
MigrationIncomingState *mis = migration_incoming_get_current();

switch (mis->state) {
case MIGRATION_STATUS_NONE:
return;
break;
case MIGRATION_STATUS_SETUP:
case MIGRATION_STATUS_CANCELLING:
case MIGRATION_STATUS_CANCELLED:
case MIGRATION_STATUS_ACTIVE:
case MIGRATION_STATUS_POSTCOPY_ACTIVE:
case MIGRATION_STATUS_FAILED:
case MIGRATION_STATUS_COLO:
info->has_status = true;
break;
case MIGRATION_STATUS_COMPLETED:
info->has_status = true;
fill_destination_postcopy_migration_info(info);
break;
}
info->status = mis->state;
}

MigrationInfo *qmp_query_migrate(Error **errp)
{
MigrationInfo *info = g_malloc0(sizeof(*info));

fill_destination_migration_info(info);
fill_source_migration_info(info);

return info;
}

void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
Error **errp)
{
Expand Down
4 changes: 4 additions & 0 deletions migration/migration.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ struct MigrationIncomingState {

MigrationIncomingState *migration_incoming_get_current(void);
void migration_incoming_state_destroy(void);
/*
* Functions to work with blocktime context
*/
void fill_destination_postcopy_migration_info(MigrationInfo *info);

#define TYPE_MIGRATION "migration"

Expand Down
56 changes: 56 additions & 0 deletions migration/postcopy-ram.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,55 @@ static struct PostcopyBlocktimeContext *blocktime_context_new(void)
return ctx;
}

static uint32List *get_vcpu_blocktime_list(PostcopyBlocktimeContext *ctx)
{
uint32List *list = NULL, *entry = NULL;
int i;

for (i = smp_cpus - 1; i >= 0; i--) {
entry = g_new0(uint32List, 1);
entry->value = ctx->vcpu_blocktime[i];
entry->next = list;
list = entry;
}

return list;
}

/*
* This function just populates MigrationInfo from postcopy's
* blocktime context. It will not populate MigrationInfo,
* unless postcopy-blocktime capability was set.
*
* @info: pointer to MigrationInfo to populate
*/
void fill_destination_postcopy_migration_info(MigrationInfo *info)
{
MigrationIncomingState *mis = migration_incoming_get_current();
PostcopyBlocktimeContext *bc = mis->blocktime_ctx;

if (!bc) {
return;
}

info->has_postcopy_blocktime = true;
info->postcopy_blocktime = bc->total_blocktime;
info->has_postcopy_vcpu_blocktime = true;
info->postcopy_vcpu_blocktime = get_vcpu_blocktime_list(bc);
}

static uint32_t get_postcopy_total_blocktime(void)
{
MigrationIncomingState *mis = migration_incoming_get_current();
PostcopyBlocktimeContext *bc = mis->blocktime_ctx;

if (!bc) {
return 0;
}

return bc->total_blocktime;
}

/**
* receive_ufd_features: check userfault fd features, to request only supported
* features in the future.
Expand Down Expand Up @@ -512,6 +561,9 @@ int postcopy_ram_incoming_cleanup(MigrationIncomingState *mis)
munmap(mis->postcopy_tmp_zero_page, mis->largest_page_size);
mis->postcopy_tmp_zero_page = NULL;
}
trace_postcopy_ram_incoming_cleanup_blocktime(
get_postcopy_total_blocktime());

trace_postcopy_ram_incoming_cleanup_exit();
return 0;
}
Expand Down Expand Up @@ -1157,6 +1209,10 @@ void *postcopy_get_tmp_page(MigrationIncomingState *mis)

#else
/* No target OS support, stubs just fail */
void fill_destination_postcopy_migration_info(MigrationInfo *info)
{
}

bool postcopy_ram_supported_by_host(MigrationIncomingState *mis)
{
error_report("%s: No OS support", __func__);
Expand Down
1 change: 1 addition & 0 deletions migration/trace-events
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ postcopy_ram_incoming_cleanup_closeuf(void) ""
postcopy_ram_incoming_cleanup_entry(void) ""
postcopy_ram_incoming_cleanup_exit(void) ""
postcopy_ram_incoming_cleanup_join(void) ""
postcopy_ram_incoming_cleanup_blocktime(uint64_t total) "total blocktime %" PRIu64
postcopy_request_shared_page(const char *sharer, const char *rb, uint64_t rb_offset) "for %s in %s offset 0x%"PRIx64
postcopy_request_shared_page_present(const char *sharer, const char *rb, uint64_t rb_offset) "%s already %s offset 0x%"PRIx64
postcopy_wake_shared(uint64_t client_addr, const char *rb) "at 0x%"PRIx64" in %s"
Expand Down
11 changes: 10 additions & 1 deletion qapi/migration.json
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,13 @@
# @error-desc: the human readable error description string, when
# @status is 'failed'. Clients should not attempt to parse the
# error strings. (Since 2.7)
#
# @postcopy-blocktime: total time when all vCPU were blocked during postcopy
# live migration (Since 2.13)
#
# @postcopy-vcpu-blocktime: list of the postcopy blocktime per vCPU (Since 2.13)
#

#
# Since: 0.14.0
##
Expand All @@ -167,7 +174,9 @@
'*downtime': 'int',
'*setup-time': 'int',
'*cpu-throttle-percentage': 'int',
'*error-desc': 'str'} }
'*error-desc': 'str',
'*postcopy-blocktime' : 'uint32',
'*postcopy-vcpu-blocktime': ['uint32']} }

##
# @query-migrate:
Expand Down

0 comments on commit 65ace06

Please sign in to comment.