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+
8590static 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
10711081static 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
11431156void 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+
18901913bool 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
0 commit comments