---
arch_init.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
hmp.c | 13 ++++++++++
migration.c | 12 +++++++++
migration.h | 9 +++++++
qapi-schema.json | 25 ++++++++++++++++++-
qmp-commands.hx | 28 ++++++++++++++++++++++
6 files changed, 153 insertions(+), 2 deletions(-)
diff --git a/arch_init.c b/arch_init.c
index af9fcc3..4d063b5 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -180,6 +180,64 @@ void xbzrle_cache_resize(int64_t new_size)
cache_resize(new_size);
}
+/* accounting */
+typedef struct AccountingInfo {
+ uint64_t dup_pages;
+ uint64_t norm_pages;
+ uint64_t xbzrle_bytes;
+ uint64_t xbzrle_pages;
+ uint64_t xbzrle_cache_miss;
+ uint64_t iterations;
+ uint64_t xbzrle_overflows;
+} AccountingInfo;
+
+static AccountingInfo acct_info;
+
+static void acct_clear(void)
+{
+ memset(&acct_info, 0, sizeof(acct_info));
+}
+
+uint64_t dup_mig_bytes_transferred(void)
+{
+ return acct_info.dup_pages * TARGET_PAGE_SIZE;
+}
+
+uint64_t dup_mig_pages_transferred(void)
+{
+ return acct_info.dup_pages;
+}
+
+uint64_t norm_mig_bytes_transferred(void)
+{
+ return acct_info.norm_pages * TARGET_PAGE_SIZE;
+}
+
+uint64_t norm_mig_pages_transferred(void)
+{
+ return acct_info.norm_pages;
+}
+
+uint64_t xbzrle_mig_bytes_transferred(void)
+{
+ return acct_info.xbzrle_bytes;
+}
+
+uint64_t xbzrle_mig_pages_transferred(void)
+{
+ return acct_info.xbzrle_pages;
+}
+
+uint64_t xbzrle_mig_pages_cache_miss(void)
+{
+ return acct_info.xbzrle_cache_miss;
+}
+
+uint64_t xbzrle_mig_pages_overflow(void)
+{
+ return acct_info.xbzrle_overflows;
+}
+
/***********************************************************/
/* XBRLE page cache implementation */
static CacheItem *cache_item_get(unsigned long pos, int item)
@@ -394,6 +452,7 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t
*current_data,
slot = cache_is_cached(current_addr);
if (slot == -1) {
cache_insert(current_addr, current_data, 0);
+ acct_info.xbzrle_cache_miss++;
goto done;
}
cache_location = cache_get_cache_pos(current_addr);
@@ -414,6 +473,9 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t
*current_data,
if (encoded_len< 0) {
DPRINTF("Unmodifed page - skipping\n");
goto done;
+ } else if (encoded_len == 0) {
+ DPRINTF("Overflow - sending orginal page\n");
+ acct_info.xbzrle_overflows++;
}
hdr.xh_len = encoded_len;
@@ -423,7 +485,9 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t
*current_data,
save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_XBZRLE);
qemu_put_buffer(f, (uint8_t *)&hdr, sizeof(hdr));
qemu_put_buffer(f, encoded_buf, encoded_len);
+ acct_info.xbzrle_pages++;
bytes_sent = encoded_len + sizeof(hdr);
+ acct_info.xbzrle_bytes += bytes_sent;
done:
g_free(encoded_buf);
@@ -463,6 +527,7 @@ static int ram_save_block(QEMUFile *f, int stage)
save_block_hdr(f, block, offset, cont,
RAM_SAVE_FLAG_COMPRESS);
qemu_put_byte(f, *p);
bytes_sent = 1;
+ acct_info.dup_pages++;
} else if (stage == 2&& use_xbzrle) {
bytes_sent = save_xbzrle_page(f, p, current_addr, block,
offset, cont);
@@ -474,6 +539,7 @@ static int ram_save_block(QEMUFile *f, int stage)
save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_PAGE);
qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
bytes_sent = TARGET_PAGE_SIZE;
+ acct_info.norm_pages++;
}
break;
@@ -591,6 +657,7 @@ int ram_save_live(QEMUFile *f, int stage, void *opaque)
if (migrate_use_xbzrle()) {
cache_init(migrate_xbzrle_cache_size());
+ acct_clear();
}
/* Make sure all dirty bits are set */
@@ -624,6 +691,7 @@ int ram_save_live(QEMUFile *f, int stage, void *opaque)
/* bytes_sent -1 represent unchanged page */
if (bytes_sent> 0) {
bytes_transferred += bytes_sent;
+ acct_info.iterations++;
} else if (bytes_sent == 0) { /* no more blocks */
break;
}
diff --git a/hmp.c b/hmp.c
index b569887..59d3275 100644
--- a/hmp.c
+++ b/hmp.c
@@ -153,6 +153,19 @@ void hmp_info_migrate(Monitor *mon)
info->disk->total>> 10);
}
+ if (info->has_cache) {
+ monitor_printf(mon, "cache size: %" PRIu64 " bytes\n",
+ info->cache->cache_size);
+ monitor_printf(mon, "xbzrle transferred: %" PRIu64 " kbytes\n",
+ info->cache->xbzrle_bytes>> 10);
+ monitor_printf(mon, "xbzrle pages: %" PRIu64 " pages\n",
+ info->cache->xbzrle_pages);
+ monitor_printf(mon, "xbzrle cache miss: %" PRIu64 "\n",
+ info->cache->xbzrle_cache_miss);
+ monitor_printf(mon, "xbzrle overflow : %" PRIu64 "\n",
+ info->cache->xbzrle_overflow);
+ }
+
qapi_free_MigrationInfo(info);
}
diff --git a/migration.c b/migration.c
index 071a1b9..ac6a533 100644
--- a/migration.c
+++ b/migration.c
@@ -136,6 +136,8 @@ MigrationInfo *qmp_query_migrate(Error **errp)
info->ram->transferred = ram_bytes_transferred();
info->ram->remaining = ram_bytes_remaining();
info->ram->total = ram_bytes_total();
+ info->ram->duplicate = dup_mig_pages_transferred();
+ info->ram->norm = norm_mig_pages_transferred();
if (blk_mig_active()) {
info->has_disk = true;
@@ -144,6 +146,16 @@ MigrationInfo *qmp_query_migrate(Error **errp)
info->disk->remaining = blk_mig_bytes_remaining();
info->disk->total = blk_mig_bytes_total();
}
+
+ if (s->params.use_xbzrle) {
+ info->has_cache = true;
+ info->cache = g_malloc0(sizeof(*info->cache));
+ Info->cache->cache_size = migrate_xbzrle_cache_size();
+ info->cache->xbzrle_bytes = xbzrle_mig_bytes_transferred();
+ info->cache->xbzrle_pages = xbzrle_mig_pages_transferred();
+ info->cache->xbzrle_cache_miss = xbzrle_mig_pages_cache_miss();
+ info->cache->xbzrle_overflow = xbzrle_mig_pages_overflow();
+ }
break;
case MIG_STATE_COMPLETED:
info->has_status = true;
diff --git a/migration.h b/migration.h
index 3426c94..03f116d 100644
--- a/migration.h
+++ b/migration.h
@@ -82,6 +82,15 @@ uint64_t ram_bytes_remaining(void);
uint64_t ram_bytes_transferred(void);
uint64_t ram_bytes_total(void);
+uint64_t dup_mig_bytes_transferred(void);
+uint64_t dup_mig_pages_transferred(void);
+uint64_t norm_mig_bytes_transferred(void);
+uint64_t norm_mig_pages_transferred(void);
+uint64_t xbzrle_mig_bytes_transferred(void);
+uint64_t xbzrle_mig_pages_transferred(void);
+uint64_t xbzrle_mig_pages_overflow(void);
+uint64_t xbzrle_mig_pages_cache_miss(void);
+
int ram_save_live(QEMUFile *f, int stage, void *opaque);
int ram_load(QEMUFile *f, void *opaque, int version_id);
diff --git a/qapi-schema.json b/qapi-schema.json
index 956caed..051d7a1 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -239,7 +239,28 @@
# Since: 0.14.0.
##
{ 'type': 'MigrationStats',
- 'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int' } }
+ 'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int',
'duplicate': 'int', 'norm': 'int' } }
+
+##
+# @CacheStats
+#
+# Detailed XBZRLE migration cache statistics
+#
+# @cache_size: XBZRLE cache size
+#
+# @xbzrle_bytes: amount of bytes already transferred to the target VM
+#
+# @xbzrle_pages: amount of pages transferred to the target VM
+#
+# @xbzrle_cache_miss: numer of cache miss
+#
+# @xbzrle_overflow: number of overflows
+#
+# Since: 1.1
+##
+{ 'type': 'CacheStats',
+ 'data': {'cache_size': 'int', 'xbzrle_bytes': 'int', 'xbzrle_pages': 'int',
+ 'xbzrle_cache_miss': 'int', 'xbzrle_overflow': 'int' } }
##
# @MigrationInfo
@@ -262,7 +283,7 @@
##
{ 'type': 'MigrationInfo',
'data': {'*status': 'str', '*ram': 'MigrationStats',
- '*disk': 'MigrationStats'} }
+ '*disk': 'MigrationStats', '*cache': 'CacheStats'} }
##
# @query-migrate
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 3f2c9e2..a47df1d 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2032,6 +2032,13 @@ The main json-object contains the following:
- "transferred": amount transferred (json-int)
- "remaining": amount remaining (json-int)
- "total": total (json-int)
+- "cache": only present if "status" and XBZRLE is active.
+ it is a json-object with the following XBZRLE information:
+ - "cache size": XBZRLE cache size
+ - "xbzrle_bytes": total XBZRLE bytes transferred
+ - "xbzrle_pages": number of XBZRLE compressed pages
+ - "cache_miss": number of cache misses
+ - "overflow": number of XBZRLE overflows
Examples:
@@ -2083,6 +2090,27 @@ Examples:
}
}
+5. Migration is being performed and XBZRLE is active:
+
+-> { "execute": "query-migrate" }
+<- {
+ "return":{
+ "status":"active",
+ "ram":{
+ "total":1057024,
+ "remaining":1053304,
+ "transferred":3720
+ },
+ "cache":{
+ "size": 1024
+ "xbzrle_transferred":20971520,
+ "xbzrle_pages":2444343,
+ "xbzrle_cache_miss:2244,
+ "xbzrle_overflow":34434
+ }
+ }
+ }
+
EQMP
{