mirror of https://github.com/xemu-project/xemu.git
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:
parent
acac51ba24
commit
15699cf542
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue