Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/dgilbert/tags/pull-migration-20…
Browse files Browse the repository at this point in the history
…180615a' into staging

Migration pull 2018-06-15

# gpg: Signature made Fri 15 Jun 2018 16:13:17 BST
# gpg:                using RSA key 0516331EBC5BFDE7
# gpg: Good signature from "Dr. David Alan Gilbert (RH2) <[email protected]>"
# Primary key fingerprint: 45F5 C71B 4A0C B7FB 977A  9FA9 0516 331E BC5B FDE7

* remotes/dgilbert/tags/pull-migration-20180615a:
  migration: calculate expected_downtime with ram_bytes_remaining()
  migration/postcopy: Wake rate limit sleep on postcopy request
  migration: Wake rate limiting for urgent requests
  migration/postcopy: Add max-postcopy-bandwidth parameter
  migration: introduce migration_update_rates
  migration: fix counting xbzrle cache_miss_rate
  migration/block-dirty-bitmap: fix dirty_bitmap_load
  migration: Poison ramblock loops in migration
  migration: Fixes for non-migratable RAMBlocks
  typedefs: add QJSON

Signed-off-by: Peter Maydell <[email protected]>
  • Loading branch information
pm215 committed Jun 15, 2018
2 parents 42747d6 + 650af89 commit 2ef2f16
Show file tree
Hide file tree
Showing 12 changed files with 146 additions and 33 deletions.
7 changes: 7 additions & 0 deletions hmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,9 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict)
monitor_printf(mon, "%s: %" PRIu64 "\n",
MigrationParameter_str(MIGRATION_PARAMETER_XBZRLE_CACHE_SIZE),
params->xbzrle_cache_size);
monitor_printf(mon, "%s: %" PRIu64 "\n",
MigrationParameter_str(MIGRATION_PARAMETER_MAX_POSTCOPY_BANDWIDTH),
params->max_postcopy_bandwidth);
}

qapi_free_MigrationParameters(params);
Expand Down Expand Up @@ -1676,6 +1679,10 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
}
p->xbzrle_cache_size = cache_size;
break;
case MIGRATION_PARAMETER_MAX_POSTCOPY_BANDWIDTH:
p->has_max_postcopy_bandwidth = true;
visit_type_size(v, param, &p->max_postcopy_bandwidth, &err);
break;
default:
assert(0);
}
Expand Down
4 changes: 3 additions & 1 deletion include/exec/ramlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,10 @@ typedef struct RAMList {
extern RAMList ram_list;

/* Should be holding either ram_list.mutex, or the RCU lock. */
#define RAMBLOCK_FOREACH(block) \
#define INTERNAL_RAMBLOCK_FOREACH(block) \
QLIST_FOREACH_RCU(block, &ram_list.blocks, next)
/* Never use the INTERNAL_ version except for defining other macros */
#define RAMBLOCK_FOREACH(block) INTERNAL_RAMBLOCK_FOREACH(block)

void qemu_mutex_lock_ramlist(void);
void qemu_mutex_unlock_ramlist(void);
Expand Down
2 changes: 0 additions & 2 deletions include/migration/vmstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@
#ifndef QEMU_VMSTATE_H
#define QEMU_VMSTATE_H

typedef struct QJSON QJSON;

typedef struct VMStateInfo VMStateInfo;
typedef struct VMStateDescription VMStateDescription;
typedef struct VMStateField VMStateField;
Expand Down
1 change: 1 addition & 0 deletions include/qemu/typedefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ typedef struct QEMUTimer QEMUTimer;
typedef struct QEMUTimerListGroup QEMUTimerListGroup;
typedef struct QBool QBool;
typedef struct QDict QDict;
typedef struct QJSON QJSON;
typedef struct QList QList;
typedef struct QNull QNull;
typedef struct QNum QNum;
Expand Down
3 changes: 3 additions & 0 deletions migration/block-dirty-bitmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,9 @@ static int dirty_bitmap_load(QEMUFile *f, void *opaque, int version_id)

do {
ret = dirty_bitmap_load_header(f, &s);
if (ret < 0) {
return ret;
}

if (s.flags & DIRTY_BITMAP_MIG_FLAG_START) {
ret = dirty_bitmap_load_start(f, &s);
Expand Down
73 changes: 66 additions & 7 deletions migration/migration.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@
#define DEFAULT_MIGRATE_MULTIFD_CHANNELS 2
#define DEFAULT_MIGRATE_MULTIFD_PAGE_COUNT 16

/* Background transfer rate for postcopy, 0 means unlimited, note
* that page requests can still exceed this limit.
*/
#define DEFAULT_MIGRATE_MAX_POSTCOPY_BANDWIDTH 0

static NotifierList migration_state_notifiers =
NOTIFIER_LIST_INITIALIZER(migration_state_notifiers);

Expand Down Expand Up @@ -659,6 +664,8 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp)
params->x_multifd_page_count = s->parameters.x_multifd_page_count;
params->has_xbzrle_cache_size = true;
params->xbzrle_cache_size = s->parameters.xbzrle_cache_size;
params->has_max_postcopy_bandwidth = true;
params->max_postcopy_bandwidth = s->parameters.max_postcopy_bandwidth;

return params;
}
Expand Down Expand Up @@ -1066,6 +1073,9 @@ static void migrate_params_test_apply(MigrateSetParameters *params,
if (params->has_xbzrle_cache_size) {
dest->xbzrle_cache_size = params->xbzrle_cache_size;
}
if (params->has_max_postcopy_bandwidth) {
dest->max_postcopy_bandwidth = params->max_postcopy_bandwidth;
}
}

static void migrate_params_apply(MigrateSetParameters *params, Error **errp)
Expand Down Expand Up @@ -1138,6 +1148,9 @@ static void migrate_params_apply(MigrateSetParameters *params, Error **errp)
s->parameters.xbzrle_cache_size = params->xbzrle_cache_size;
xbzrle_cache_resize(params->xbzrle_cache_size, errp);
}
if (params->has_max_postcopy_bandwidth) {
s->parameters.max_postcopy_bandwidth = params->max_postcopy_bandwidth;
}
}

void qmp_migrate_set_parameters(MigrateSetParameters *params, Error **errp)
Expand Down Expand Up @@ -1887,6 +1900,16 @@ int64_t migrate_xbzrle_cache_size(void)
return s->parameters.xbzrle_cache_size;
}

static int64_t migrate_max_postcopy_bandwidth(void)
{
MigrationState *s;

s = migrate_get_current();

return s->parameters.max_postcopy_bandwidth;
}


bool migrate_use_block(void)
{
MigrationState *s;
Expand Down Expand Up @@ -2226,6 +2249,7 @@ static int postcopy_start(MigrationState *ms)
QIOChannelBuffer *bioc;
QEMUFile *fb;
int64_t time_at_stop = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
int64_t bandwidth = migrate_max_postcopy_bandwidth();
bool restart_block = false;
int cur_state = MIGRATION_STATUS_ACTIVE;
if (!migrate_pause_before_switchover()) {
Expand Down Expand Up @@ -2280,7 +2304,12 @@ static int postcopy_start(MigrationState *ms)
* will notice we're in POSTCOPY_ACTIVE and not actually
* wrap their state up here
*/
qemu_file_set_rate_limit(ms->to_dst_file, INT64_MAX);
/* 0 max-postcopy-bandwidth means unlimited */
if (!bandwidth) {
qemu_file_set_rate_limit(ms->to_dst_file, INT64_MAX);
} else {
qemu_file_set_rate_limit(ms->to_dst_file, bandwidth / XFER_LIMIT_RATIO);
}
if (migrate_postcopy_ram()) {
/* Ping just for debugging, helps line traces up */
qemu_savevm_send_ping(ms->to_dst_file, 2);
Expand Down Expand Up @@ -2717,8 +2746,7 @@ static void migration_update_counters(MigrationState *s,
* recalculate. 10000 is a small enough number for our purposes
*/
if (ram_counters.dirty_pages_rate && transferred > 10000) {
s->expected_downtime = ram_counters.dirty_pages_rate *
qemu_target_page_size() / bandwidth;
s->expected_downtime = ram_counters.remaining / bandwidth;
}

qemu_file_reset_rate_limit(s->to_dst_file);
Expand Down Expand Up @@ -2823,6 +2851,16 @@ static void migration_iteration_finish(MigrationState *s)
qemu_mutex_unlock_iothread();
}

void migration_make_urgent_request(void)
{
qemu_sem_post(&migrate_get_current()->rate_limit_sem);
}

void migration_consume_urgent_request(void)
{
qemu_sem_wait(&migrate_get_current()->rate_limit_sem);
}

/*
* Master migration thread on the source VM.
* It drives the migration and pumps the data down the outgoing channel.
Expand All @@ -2832,6 +2870,7 @@ static void *migration_thread(void *opaque)
MigrationState *s = opaque;
int64_t setup_start = qemu_clock_get_ms(QEMU_CLOCK_HOST);
MigThrError thr_error;
bool urgent = false;

rcu_register_thread();

Expand Down Expand Up @@ -2872,7 +2911,7 @@ static void *migration_thread(void *opaque)
s->state == MIGRATION_STATUS_POSTCOPY_ACTIVE) {
int64_t current_time;

if (!qemu_file_rate_limit(s->to_dst_file)) {
if (urgent || !qemu_file_rate_limit(s->to_dst_file)) {
MigIterateState iter_state = migration_iteration_run(s);
if (iter_state == MIG_ITERATE_SKIP) {
continue;
Expand Down Expand Up @@ -2903,10 +2942,24 @@ static void *migration_thread(void *opaque)

migration_update_counters(s, current_time);

urgent = false;
if (qemu_file_rate_limit(s->to_dst_file)) {
/* usleep expects microseconds */
g_usleep((s->iteration_start_time + BUFFER_DELAY -
current_time) * 1000);
/* Wait for a delay to do rate limiting OR
* something urgent to post the semaphore.
*/
int ms = s->iteration_start_time + BUFFER_DELAY - current_time;
trace_migration_thread_ratelimit_pre(ms);
if (qemu_sem_timedwait(&s->rate_limit_sem, ms) == 0) {
/* We were worken by one or more urgent things but
* the timedwait will have consumed one of them.
* The service routine for the urgent wake will dec
* the semaphore itself for each item it consumes,
* so add this one we just eat back.
*/
qemu_sem_post(&s->rate_limit_sem);
urgent = true;
}
trace_migration_thread_ratelimit_post(urgent);
}
}

Expand Down Expand Up @@ -3042,6 +3095,9 @@ static Property migration_properties[] = {
DEFINE_PROP_SIZE("xbzrle-cache-size", MigrationState,
parameters.xbzrle_cache_size,
DEFAULT_MIGRATE_XBZRLE_CACHE_SIZE),
DEFINE_PROP_SIZE("max-postcopy-bandwidth", MigrationState,
parameters.max_postcopy_bandwidth,
DEFAULT_MIGRATE_MAX_POSTCOPY_BANDWIDTH),

/* Migration capabilities */
DEFINE_PROP_MIG_CAP("x-xbzrle", MIGRATION_CAPABILITY_XBZRLE),
Expand Down Expand Up @@ -3077,6 +3133,7 @@ static void migration_instance_finalize(Object *obj)
qemu_mutex_destroy(&ms->qemu_file_lock);
g_free(params->tls_hostname);
g_free(params->tls_creds);
qemu_sem_destroy(&ms->rate_limit_sem);
qemu_sem_destroy(&ms->pause_sem);
qemu_sem_destroy(&ms->postcopy_pause_sem);
qemu_sem_destroy(&ms->postcopy_pause_rp_sem);
Expand Down Expand Up @@ -3110,10 +3167,12 @@ static void migration_instance_init(Object *obj)
params->has_x_multifd_channels = true;
params->has_x_multifd_page_count = true;
params->has_xbzrle_cache_size = true;
params->has_max_postcopy_bandwidth = true;

qemu_sem_init(&ms->postcopy_pause_sem, 0);
qemu_sem_init(&ms->postcopy_pause_rp_sem, 0);
qemu_sem_init(&ms->rp_state.rp_sem, 0);
qemu_sem_init(&ms->rate_limit_sem, 0);
qemu_mutex_init(&ms->qemu_file_lock);
}

Expand Down
11 changes: 11 additions & 0 deletions migration/migration.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ struct MigrationState
*/
QemuMutex qemu_file_lock;

/*
* Used to allow urgent requests to override rate limiting.
*/
QemuSemaphore rate_limit_sem;

/* bytes already send at the beggining of current interation */
uint64_t iteration_initial_bytes;
/* time at the start of current iteration */
Expand Down Expand Up @@ -284,4 +289,10 @@ void migrate_send_rp_resume_ack(MigrationIncomingState *mis, uint32_t value);
void dirty_bitmap_mig_before_vm_start(void);
void init_dirty_bitmap_incoming_migration(void);

#define qemu_ram_foreach_block \
#warning "Use qemu_ram_foreach_block_migratable in migration code"

void migration_make_urgent_request(void);
void migration_consume_urgent_request(void);

#endif
2 changes: 0 additions & 2 deletions migration/qjson.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
#ifndef QEMU_QJSON_H
#define QEMU_QJSON_H

typedef struct QJSON QJSON;

QJSON *qjson_new(void);
void qjson_destroy(QJSON *json);
void json_prop_str(QJSON *json, const char *name, const char *str);
Expand Down
Loading

0 comments on commit 2ef2f16

Please sign in to comment.