Skip to content

Commit 2ef2f16

Browse files
committed
Merge remote-tracking branch 'remotes/dgilbert/tags/pull-migration-20180615a' 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) <dgilbert@redhat.com>" # 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 <peter.maydell@linaro.org>
2 parents 42747d6 + 650af89 commit 2ef2f16

File tree

12 files changed

+146
-33
lines changed

12 files changed

+146
-33
lines changed

hmp.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,9 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict)
370370
monitor_printf(mon, "%s: %" PRIu64 "\n",
371371
MigrationParameter_str(MIGRATION_PARAMETER_XBZRLE_CACHE_SIZE),
372372
params->xbzrle_cache_size);
373+
monitor_printf(mon, "%s: %" PRIu64 "\n",
374+
MigrationParameter_str(MIGRATION_PARAMETER_MAX_POSTCOPY_BANDWIDTH),
375+
params->max_postcopy_bandwidth);
373376
}
374377

375378
qapi_free_MigrationParameters(params);
@@ -1676,6 +1679,10 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
16761679
}
16771680
p->xbzrle_cache_size = cache_size;
16781681
break;
1682+
case MIGRATION_PARAMETER_MAX_POSTCOPY_BANDWIDTH:
1683+
p->has_max_postcopy_bandwidth = true;
1684+
visit_type_size(v, param, &p->max_postcopy_bandwidth, &err);
1685+
break;
16791686
default:
16801687
assert(0);
16811688
}

include/exec/ramlist.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,10 @@ typedef struct RAMList {
5656
extern RAMList ram_list;
5757

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

6264
void qemu_mutex_lock_ramlist(void);
6365
void qemu_mutex_unlock_ramlist(void);

include/migration/vmstate.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@
2727
#ifndef QEMU_VMSTATE_H
2828
#define QEMU_VMSTATE_H
2929

30-
typedef struct QJSON QJSON;
31-
3230
typedef struct VMStateInfo VMStateInfo;
3331
typedef struct VMStateDescription VMStateDescription;
3432
typedef struct VMStateField VMStateField;

include/qemu/typedefs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ typedef struct QEMUTimer QEMUTimer;
9797
typedef struct QEMUTimerListGroup QEMUTimerListGroup;
9898
typedef struct QBool QBool;
9999
typedef struct QDict QDict;
100+
typedef struct QJSON QJSON;
100101
typedef struct QList QList;
101102
typedef struct QNull QNull;
102103
typedef struct QNum QNum;

migration/block-dirty-bitmap.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,9 @@ static int dirty_bitmap_load(QEMUFile *f, void *opaque, int version_id)
672672

673673
do {
674674
ret = dirty_bitmap_load_header(f, &s);
675+
if (ret < 0) {
676+
return ret;
677+
}
675678

676679
if (s.flags & DIRTY_BITMAP_MIG_FLAG_START) {
677680
ret = dirty_bitmap_load_start(f, &s);

migration/migration.c

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@
8282
#define DEFAULT_MIGRATE_MULTIFD_CHANNELS 2
8383
#define DEFAULT_MIGRATE_MULTIFD_PAGE_COUNT 16
8484

85+
/* Background transfer rate for postcopy, 0 means unlimited, note
86+
* that page requests can still exceed this limit.
87+
*/
88+
#define DEFAULT_MIGRATE_MAX_POSTCOPY_BANDWIDTH 0
89+
8590
static NotifierList migration_state_notifiers =
8691
NOTIFIER_LIST_INITIALIZER(migration_state_notifiers);
8792

@@ -659,6 +664,8 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp)
659664
params->x_multifd_page_count = s->parameters.x_multifd_page_count;
660665
params->has_xbzrle_cache_size = true;
661666
params->xbzrle_cache_size = s->parameters.xbzrle_cache_size;
667+
params->has_max_postcopy_bandwidth = true;
668+
params->max_postcopy_bandwidth = s->parameters.max_postcopy_bandwidth;
662669

663670
return params;
664671
}
@@ -1066,6 +1073,9 @@ static void migrate_params_test_apply(MigrateSetParameters *params,
10661073
if (params->has_xbzrle_cache_size) {
10671074
dest->xbzrle_cache_size = params->xbzrle_cache_size;
10681075
}
1076+
if (params->has_max_postcopy_bandwidth) {
1077+
dest->max_postcopy_bandwidth = params->max_postcopy_bandwidth;
1078+
}
10691079
}
10701080

10711081
static void migrate_params_apply(MigrateSetParameters *params, Error **errp)
@@ -1138,6 +1148,9 @@ static void migrate_params_apply(MigrateSetParameters *params, Error **errp)
11381148
s->parameters.xbzrle_cache_size = params->xbzrle_cache_size;
11391149
xbzrle_cache_resize(params->xbzrle_cache_size, errp);
11401150
}
1151+
if (params->has_max_postcopy_bandwidth) {
1152+
s->parameters.max_postcopy_bandwidth = params->max_postcopy_bandwidth;
1153+
}
11411154
}
11421155

11431156
void qmp_migrate_set_parameters(MigrateSetParameters *params, Error **errp)
@@ -1887,6 +1900,16 @@ int64_t migrate_xbzrle_cache_size(void)
18871900
return s->parameters.xbzrle_cache_size;
18881901
}
18891902

1903+
static int64_t migrate_max_postcopy_bandwidth(void)
1904+
{
1905+
MigrationState *s;
1906+
1907+
s = migrate_get_current();
1908+
1909+
return s->parameters.max_postcopy_bandwidth;
1910+
}
1911+
1912+
18901913
bool migrate_use_block(void)
18911914
{
18921915
MigrationState *s;
@@ -2226,6 +2249,7 @@ static int postcopy_start(MigrationState *ms)
22262249
QIOChannelBuffer *bioc;
22272250
QEMUFile *fb;
22282251
int64_t time_at_stop = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
2252+
int64_t bandwidth = migrate_max_postcopy_bandwidth();
22292253
bool restart_block = false;
22302254
int cur_state = MIGRATION_STATUS_ACTIVE;
22312255
if (!migrate_pause_before_switchover()) {
@@ -2280,7 +2304,12 @@ static int postcopy_start(MigrationState *ms)
22802304
* will notice we're in POSTCOPY_ACTIVE and not actually
22812305
* wrap their state up here
22822306
*/
2283-
qemu_file_set_rate_limit(ms->to_dst_file, INT64_MAX);
2307+
/* 0 max-postcopy-bandwidth means unlimited */
2308+
if (!bandwidth) {
2309+
qemu_file_set_rate_limit(ms->to_dst_file, INT64_MAX);
2310+
} else {
2311+
qemu_file_set_rate_limit(ms->to_dst_file, bandwidth / XFER_LIMIT_RATIO);
2312+
}
22842313
if (migrate_postcopy_ram()) {
22852314
/* Ping just for debugging, helps line traces up */
22862315
qemu_savevm_send_ping(ms->to_dst_file, 2);
@@ -2717,8 +2746,7 @@ static void migration_update_counters(MigrationState *s,
27172746
* recalculate. 10000 is a small enough number for our purposes
27182747
*/
27192748
if (ram_counters.dirty_pages_rate && transferred > 10000) {
2720-
s->expected_downtime = ram_counters.dirty_pages_rate *
2721-
qemu_target_page_size() / bandwidth;
2749+
s->expected_downtime = ram_counters.remaining / bandwidth;
27222750
}
27232751

27242752
qemu_file_reset_rate_limit(s->to_dst_file);
@@ -2823,6 +2851,16 @@ static void migration_iteration_finish(MigrationState *s)
28232851
qemu_mutex_unlock_iothread();
28242852
}
28252853

2854+
void migration_make_urgent_request(void)
2855+
{
2856+
qemu_sem_post(&migrate_get_current()->rate_limit_sem);
2857+
}
2858+
2859+
void migration_consume_urgent_request(void)
2860+
{
2861+
qemu_sem_wait(&migrate_get_current()->rate_limit_sem);
2862+
}
2863+
28262864
/*
28272865
* Master migration thread on the source VM.
28282866
* It drives the migration and pumps the data down the outgoing channel.
@@ -2832,6 +2870,7 @@ static void *migration_thread(void *opaque)
28322870
MigrationState *s = opaque;
28332871
int64_t setup_start = qemu_clock_get_ms(QEMU_CLOCK_HOST);
28342872
MigThrError thr_error;
2873+
bool urgent = false;
28352874

28362875
rcu_register_thread();
28372876

@@ -2872,7 +2911,7 @@ static void *migration_thread(void *opaque)
28722911
s->state == MIGRATION_STATUS_POSTCOPY_ACTIVE) {
28732912
int64_t current_time;
28742913

2875-
if (!qemu_file_rate_limit(s->to_dst_file)) {
2914+
if (urgent || !qemu_file_rate_limit(s->to_dst_file)) {
28762915
MigIterateState iter_state = migration_iteration_run(s);
28772916
if (iter_state == MIG_ITERATE_SKIP) {
28782917
continue;
@@ -2903,10 +2942,24 @@ static void *migration_thread(void *opaque)
29032942

29042943
migration_update_counters(s, current_time);
29052944

2945+
urgent = false;
29062946
if (qemu_file_rate_limit(s->to_dst_file)) {
2907-
/* usleep expects microseconds */
2908-
g_usleep((s->iteration_start_time + BUFFER_DELAY -
2909-
current_time) * 1000);
2947+
/* Wait for a delay to do rate limiting OR
2948+
* something urgent to post the semaphore.
2949+
*/
2950+
int ms = s->iteration_start_time + BUFFER_DELAY - current_time;
2951+
trace_migration_thread_ratelimit_pre(ms);
2952+
if (qemu_sem_timedwait(&s->rate_limit_sem, ms) == 0) {
2953+
/* We were worken by one or more urgent things but
2954+
* the timedwait will have consumed one of them.
2955+
* The service routine for the urgent wake will dec
2956+
* the semaphore itself for each item it consumes,
2957+
* so add this one we just eat back.
2958+
*/
2959+
qemu_sem_post(&s->rate_limit_sem);
2960+
urgent = true;
2961+
}
2962+
trace_migration_thread_ratelimit_post(urgent);
29102963
}
29112964
}
29122965

@@ -3042,6 +3095,9 @@ static Property migration_properties[] = {
30423095
DEFINE_PROP_SIZE("xbzrle-cache-size", MigrationState,
30433096
parameters.xbzrle_cache_size,
30443097
DEFAULT_MIGRATE_XBZRLE_CACHE_SIZE),
3098+
DEFINE_PROP_SIZE("max-postcopy-bandwidth", MigrationState,
3099+
parameters.max_postcopy_bandwidth,
3100+
DEFAULT_MIGRATE_MAX_POSTCOPY_BANDWIDTH),
30453101

30463102
/* Migration capabilities */
30473103
DEFINE_PROP_MIG_CAP("x-xbzrle", MIGRATION_CAPABILITY_XBZRLE),
@@ -3077,6 +3133,7 @@ static void migration_instance_finalize(Object *obj)
30773133
qemu_mutex_destroy(&ms->qemu_file_lock);
30783134
g_free(params->tls_hostname);
30793135
g_free(params->tls_creds);
3136+
qemu_sem_destroy(&ms->rate_limit_sem);
30803137
qemu_sem_destroy(&ms->pause_sem);
30813138
qemu_sem_destroy(&ms->postcopy_pause_sem);
30823139
qemu_sem_destroy(&ms->postcopy_pause_rp_sem);
@@ -3110,10 +3167,12 @@ static void migration_instance_init(Object *obj)
31103167
params->has_x_multifd_channels = true;
31113168
params->has_x_multifd_page_count = true;
31123169
params->has_xbzrle_cache_size = true;
3170+
params->has_max_postcopy_bandwidth = true;
31133171

31143172
qemu_sem_init(&ms->postcopy_pause_sem, 0);
31153173
qemu_sem_init(&ms->postcopy_pause_rp_sem, 0);
31163174
qemu_sem_init(&ms->rp_state.rp_sem, 0);
3175+
qemu_sem_init(&ms->rate_limit_sem, 0);
31173176
qemu_mutex_init(&ms->qemu_file_lock);
31183177
}
31193178

migration/migration.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,11 @@ struct MigrationState
121121
*/
122122
QemuMutex qemu_file_lock;
123123

124+
/*
125+
* Used to allow urgent requests to override rate limiting.
126+
*/
127+
QemuSemaphore rate_limit_sem;
128+
124129
/* bytes already send at the beggining of current interation */
125130
uint64_t iteration_initial_bytes;
126131
/* time at the start of current iteration */
@@ -284,4 +289,10 @@ void migrate_send_rp_resume_ack(MigrationIncomingState *mis, uint32_t value);
284289
void dirty_bitmap_mig_before_vm_start(void);
285290
void init_dirty_bitmap_incoming_migration(void);
286291

292+
#define qemu_ram_foreach_block \
293+
#warning "Use qemu_ram_foreach_block_migratable in migration code"
294+
295+
void migration_make_urgent_request(void);
296+
void migration_consume_urgent_request(void);
297+
287298
#endif

migration/qjson.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
#ifndef QEMU_QJSON_H
1414
#define QEMU_QJSON_H
1515

16-
typedef struct QJSON QJSON;
17-
1816
QJSON *qjson_new(void);
1917
void qjson_destroy(QJSON *json);
2018
void json_prop_str(QJSON *json, const char *name, const char *str);

0 commit comments

Comments
 (0)