migration: Extend query-migrate to provide dirty page limit info

Extend query-migrate to provide throttle time and estimated
ring full time with dirty-limit capability enabled, through which
we can observe if dirty limit take effect during live migration.

Signed-off-by: Hyman Huang(黄勇) <yong.huang@smartx.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Message-ID: <168733225273.5845.15871826788879741674-8@git.sr.ht>
Signed-off-by: Juan Quintela <quintela@redhat.com>
This commit is contained in:
Hyman Huang(黄勇) 2023-06-08 00:21:58 +08:00 committed by Juan Quintela
parent acac51ba24
commit 15699cf542
5 changed files with 76 additions and 1 deletions

View File

@ -34,4 +34,6 @@ void dirtylimit_set_vcpu(int cpu_index,
void dirtylimit_set_all(uint64_t quota,
bool enable);
void dirtylimit_vcpu_execute(CPUState *cpu);
uint64_t dirtylimit_throttle_time_per_round(void);
uint64_t dirtylimit_ring_full_time(void);
#endif

View File

@ -190,6 +190,16 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict)
info->cpu_throttle_percentage);
}
if (info->has_dirty_limit_throttle_time_per_round) {
monitor_printf(mon, "dirty-limit throttle time: %" PRIu64 " us\n",
info->dirty_limit_throttle_time_per_round);
}
if (info->has_dirty_limit_ring_full_time) {
monitor_printf(mon, "dirty-limit ring full time: %" PRIu64 " us\n",
info->dirty_limit_ring_full_time);
}
if (info->has_postcopy_blocktime) {
monitor_printf(mon, "postcopy blocktime: %u\n",
info->postcopy_blocktime);

View File

@ -64,6 +64,7 @@
#include "yank_functions.h"
#include "sysemu/qtest.h"
#include "options.h"
#include "sysemu/dirtylimit.h"
static NotifierList migration_state_notifiers =
NOTIFIER_LIST_INITIALIZER(migration_state_notifiers);
@ -974,6 +975,15 @@ static void populate_ram_info(MigrationInfo *info, MigrationState *s)
info->ram->dirty_pages_rate =
stat64_get(&mig_stats.dirty_pages_rate);
}
if (migrate_dirty_limit() && dirtylimit_in_service()) {
info->has_dirty_limit_throttle_time_per_round = true;
info->dirty_limit_throttle_time_per_round =
dirtylimit_throttle_time_per_round();
info->has_dirty_limit_ring_full_time = true;
info->dirty_limit_ring_full_time = dirtylimit_ring_full_time();
}
}
static void populate_disk_info(MigrationInfo *info)

View File

@ -250,6 +250,18 @@
# blocked. Present and non-empty when migration is blocked.
# (since 6.0)
#
# @dirty-limit-throttle-time-per-round: Maximum throttle time (in microseconds) of virtual
# CPUs each dirty ring full round, which shows how
# MigrationCapability dirty-limit affects the guest
# during live migration. (since 8.1)
#
# @dirty-limit-ring-full-time: Estimated average dirty ring full time (in microseconds)
# each dirty ring full round, note that the value equals
# dirty ring memory size divided by average dirty page rate
# of virtual CPU, which can be used to observe the average
# memory load of virtual CPU indirectly. Note that zero
# means guest doesn't dirty memory (since 8.1)
#
# Since: 0.14
##
{ 'struct': 'MigrationInfo',
@ -267,7 +279,9 @@
'*postcopy-blocktime': 'uint32',
'*postcopy-vcpu-blocktime': ['uint32'],
'*compression': 'CompressionStats',
'*socket-address': ['SocketAddress'] } }
'*socket-address': ['SocketAddress'],
'*dirty-limit-throttle-time-per-round': 'uint64',
'*dirty-limit-ring-full-time': 'uint64'} }
##
# @query-migrate:

View File

@ -565,6 +565,45 @@ out:
hmp_handle_error(mon, err);
}
/* Return the max throttle time of each virtual CPU */
uint64_t dirtylimit_throttle_time_per_round(void)
{
CPUState *cpu;
int64_t max = 0;
CPU_FOREACH(cpu) {
if (cpu->throttle_us_per_full > max) {
max = cpu->throttle_us_per_full;
}
}
return max;
}
/*
* Estimate average dirty ring full time of each virtaul CPU.
* Return 0 if guest doesn't dirty memory.
*/
uint64_t dirtylimit_ring_full_time(void)
{
CPUState *cpu;
uint64_t curr_rate = 0;
int nvcpus = 0;
CPU_FOREACH(cpu) {
if (cpu->running) {
nvcpus++;
curr_rate += vcpu_dirty_rate_get(cpu->cpu_index);
}
}
if (!curr_rate || !nvcpus) {
return 0;
}
return dirtylimit_dirty_ring_full_time(curr_rate / nvcpus);
}
static struct DirtyLimitInfo *dirtylimit_query_vcpu(int cpu_index)
{
DirtyLimitInfo *info = NULL;