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,
|
void dirtylimit_set_all(uint64_t quota,
|
||||||
bool enable);
|
bool enable);
|
||||||
void dirtylimit_vcpu_execute(CPUState *cpu);
|
void dirtylimit_vcpu_execute(CPUState *cpu);
|
||||||
|
uint64_t dirtylimit_throttle_time_per_round(void);
|
||||||
|
uint64_t dirtylimit_ring_full_time(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -190,6 +190,16 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict)
|
||||||
info->cpu_throttle_percentage);
|
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) {
|
if (info->has_postcopy_blocktime) {
|
||||||
monitor_printf(mon, "postcopy blocktime: %u\n",
|
monitor_printf(mon, "postcopy blocktime: %u\n",
|
||||||
info->postcopy_blocktime);
|
info->postcopy_blocktime);
|
||||||
|
|
|
@ -64,6 +64,7 @@
|
||||||
#include "yank_functions.h"
|
#include "yank_functions.h"
|
||||||
#include "sysemu/qtest.h"
|
#include "sysemu/qtest.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
#include "sysemu/dirtylimit.h"
|
||||||
|
|
||||||
static NotifierList migration_state_notifiers =
|
static NotifierList migration_state_notifiers =
|
||||||
NOTIFIER_LIST_INITIALIZER(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 =
|
info->ram->dirty_pages_rate =
|
||||||
stat64_get(&mig_stats.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)
|
static void populate_disk_info(MigrationInfo *info)
|
||||||
|
|
|
@ -250,6 +250,18 @@
|
||||||
# blocked. Present and non-empty when migration is blocked.
|
# blocked. Present and non-empty when migration is blocked.
|
||||||
# (since 6.0)
|
# (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
|
# Since: 0.14
|
||||||
##
|
##
|
||||||
{ 'struct': 'MigrationInfo',
|
{ 'struct': 'MigrationInfo',
|
||||||
|
@ -267,7 +279,9 @@
|
||||||
'*postcopy-blocktime': 'uint32',
|
'*postcopy-blocktime': 'uint32',
|
||||||
'*postcopy-vcpu-blocktime': ['uint32'],
|
'*postcopy-vcpu-blocktime': ['uint32'],
|
||||||
'*compression': 'CompressionStats',
|
'*compression': 'CompressionStats',
|
||||||
'*socket-address': ['SocketAddress'] } }
|
'*socket-address': ['SocketAddress'],
|
||||||
|
'*dirty-limit-throttle-time-per-round': 'uint64',
|
||||||
|
'*dirty-limit-ring-full-time': 'uint64'} }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @query-migrate:
|
# @query-migrate:
|
||||||
|
|
|
@ -565,6 +565,45 @@ out:
|
||||||
hmp_handle_error(mon, err);
|
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)
|
static struct DirtyLimitInfo *dirtylimit_query_vcpu(int cpu_index)
|
||||||
{
|
{
|
||||||
DirtyLimitInfo *info = NULL;
|
DirtyLimitInfo *info = NULL;
|
||||||
|
|
Loading…
Reference in a new issue