qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 01/11] Add migration capabilities
  2012-07-24 18:19 [Qemu-devel] [PATCH 00/11] Migration next v5 Juan Quintela
@ 2012-07-24 18:19 ` Juan Quintela
  0 siblings, 0 replies; 47+ messages in thread
From: Juan Quintela @ 2012-07-24 18:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Orit Wasserman

From: Orit Wasserman <owasserm@redhat.com>

Add migration capabilities that can be queried by the management.
The management can query the source QEMU and the destination QEMU in order to
verify both support some migration capability (currently only XBZRLE).

Signed-off-by: Orit Wasserman <owasserm@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
 hmp-commands.hx  |    2 ++
 hmp.c            |   19 +++++++++++++++++++
 hmp.h            |    1 +
 migration.c      |   11 +++++++++++
 monitor.c        |    7 +++++++
 qapi-schema.json |   39 +++++++++++++++++++++++++++++++++++++++
 qmp-commands.hx  |   24 ++++++++++++++++++++++++
 7 files changed, 103 insertions(+)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index eea8b32..8786148 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1417,6 +1417,8 @@ show CPU statistics
 show user network stack connection states
 @item info migrate
 show migration status
+@item info migration_capabilities
+show migration capabilities
 @item info balloon
 show balloon information
 @item info qtree
diff --git a/hmp.c b/hmp.c
index 6b72a64..5c7d0be 100644
--- a/hmp.c
+++ b/hmp.c
@@ -161,6 +161,25 @@ void hmp_info_migrate(Monitor *mon)
     qapi_free_MigrationInfo(info);
 }

+void hmp_info_migration_capabilities(Monitor *mon)
+{
+    MigrationCapabilityStatusList *caps_list, *cap;
+
+    caps_list = qmp_query_migration_capabilities(NULL);
+    if (!caps_list) {
+        monitor_printf(mon, "No migration capabilities found\n");
+        return;
+    }
+
+    for (cap = caps_list; cap; cap = cap->next) {
+        monitor_printf(mon, "%s: %s ",
+                       MigrationCapability_lookup[cap->value->capability],
+                       cap->value->state ? "on" : "off");
+    }
+
+    qapi_free_MigrationCapabilityStatusList(caps_list);
+}
+
 void hmp_info_cpus(Monitor *mon)
 {
     CpuInfoList *cpu_list, *cpu;
diff --git a/hmp.h b/hmp.h
index 8d2b0d7..2fb44ca 100644
--- a/hmp.h
+++ b/hmp.h
@@ -25,6 +25,7 @@ void hmp_info_uuid(Monitor *mon);
 void hmp_info_chardev(Monitor *mon);
 void hmp_info_mice(Monitor *mon);
 void hmp_info_migrate(Monitor *mon);
+void hmp_info_migration_capabilities(Monitor *mon);
 void hmp_info_cpus(Monitor *mon);
 void hmp_info_block(Monitor *mon);
 void hmp_info_blockstats(Monitor *mon);
diff --git a/migration.c b/migration.c
index 8db1b43..8c27347 100644
--- a/migration.c
+++ b/migration.c
@@ -166,6 +166,17 @@ MigrationInfo *qmp_query_migrate(Error **errp)
     return info;
 }

+MigrationCapabilityStatusList *qmp_query_migration_capabilities(Error **errp)
+{
+    MigrationCapabilityStatusList *caps_list = g_malloc0(sizeof(*caps_list));
+
+    caps_list->value = g_malloc(sizeof(*caps_list->value));
+    caps_list->value->capability = MIGRATION_CAPABILITY_XBZRLE;
+    caps_list->next = NULL;
+
+    return caps_list;
+}
+
 /* shared migration helpers */

 static int migrate_fd_cleanup(MigrationState *s)
diff --git a/monitor.c b/monitor.c
index 49dccfe..1d3f721 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2655,6 +2655,13 @@ static mon_cmd_t info_cmds[] = {
         .mhandler.info = hmp_info_migrate,
     },
     {
+        .name       = "migration-capabilities",
+        .args_type  = "",
+        .params     = "",
+        .help       = "show migration capabilities",
+        .mhandler.info = hmp_info_migration_capabilities,
+    },
+    {
         .name       = "balloon",
         .args_type  = "",
         .params     = "",
diff --git a/qapi-schema.json b/qapi-schema.json
index bc55ed2..eddb32d 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -306,6 +306,45 @@
 { 'command': 'query-migrate', 'returns': 'MigrationInfo' }

 ##
+# @MigrationCapability
+#
+# Migration capabilities enumeration
+#
+# @xbzrle: Migration supports xbzrle (Xor Based Zero Length Encoding).
+#          This feature allows us to minimize migration traffic for certain work
+#          loads, by sending compressed difference of the pages
+#
+# Since: 1.2
+##
+{ 'enum': 'MigrationCapability',
+  'data': ['xbzrle'] }
+
+##
+# @MigrationCapabilityStatus
+#
+# Migration capability information
+#
+# @capability: capability enum
+#
+# @state: capability state bool
+#
+# Since: 1.2
+##
+{ 'type': 'MigrationCapabilityStatus',
+  'data': { 'capability' : 'MigrationCapability', 'state' : 'bool' } }
+
+##
+# @query-migration-capabilities
+#
+# Returns information about current migration process capabilties.
+#
+# Returns: @MigrationCapabilityStatus list
+#
+# Since: 1.2
+##
+{ 'command': 'query-migration-capabilities', 'returns': ['MigrationCapabilityStatus'] }
+
+##
 # @MouseInfo:
 #
 # Information about a mouse device.
diff --git a/qmp-commands.hx b/qmp-commands.hx
index e3cf3c5..c0ed14c 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2141,6 +2141,30 @@ EQMP
     },

 SQMP
+query-migration-capabilities
+-------
+
+Query migration capabilities
+
+- "xbzrle": xbzrle support
+
+Arguments:
+
+Example:
+
+-> { "execute": "query-migration-capabilities"}
+<- { "return": [ { "capability": "xbzrle", "state": true },
+                 { "capability": "foobar", "state": false } ] }
+
+EQMP
+
+    {
+        .name       = "query-migration-capabilities",
+        .args_type  = "",
+	.mhandler.cmd_new = qmp_marshal_input_query_migration_capabilities,
+    },
+
+SQMP
 query-balloon
 -------------

-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH 01/11] Add migration capabilities
  2012-07-25 14:50 [Qemu-devel] [PATCH 00/11] Migration next v6 Orit Wasserman
@ 2012-07-25 14:50 ` Orit Wasserman
  0 siblings, 0 replies; 47+ messages in thread
From: Orit Wasserman @ 2012-07-25 14:50 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, aliguori, quintela, stefanha, mdroth, lcapitulino,
	blauwirbel, Orit Wasserman, chegu_vinod, avi, pbonzini, eblake

Add migration capabilities that can be queried by the management.
The management can query the source QEMU and the destination QEMU in order to
verify both support some migration capability (currently only XBZRLE).

Signed-off-by: Orit Wasserman <owasserm@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
 hmp-commands.hx  |    2 ++
 hmp.c            |   19 +++++++++++++++++++
 hmp.h            |    1 +
 migration.c      |   11 +++++++++++
 monitor.c        |    7 +++++++
 qapi-schema.json |   39 +++++++++++++++++++++++++++++++++++++++
 qmp-commands.hx  |   24 ++++++++++++++++++++++++
 7 files changed, 103 insertions(+), 0 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index eea8b32..8786148 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1417,6 +1417,8 @@ show CPU statistics
 show user network stack connection states
 @item info migrate
 show migration status
+@item info migration_capabilities
+show migration capabilities
 @item info balloon
 show balloon information
 @item info qtree
diff --git a/hmp.c b/hmp.c
index 6b72a64..5c7d0be 100644
--- a/hmp.c
+++ b/hmp.c
@@ -161,6 +161,25 @@ void hmp_info_migrate(Monitor *mon)
     qapi_free_MigrationInfo(info);
 }
 
+void hmp_info_migration_capabilities(Monitor *mon)
+{
+    MigrationCapabilityStatusList *caps_list, *cap;
+
+    caps_list = qmp_query_migration_capabilities(NULL);
+    if (!caps_list) {
+        monitor_printf(mon, "No migration capabilities found\n");
+        return;
+    }
+
+    for (cap = caps_list; cap; cap = cap->next) {
+        monitor_printf(mon, "%s: %s ",
+                       MigrationCapability_lookup[cap->value->capability],
+                       cap->value->state ? "on" : "off");
+    }
+
+    qapi_free_MigrationCapabilityStatusList(caps_list);
+}
+
 void hmp_info_cpus(Monitor *mon)
 {
     CpuInfoList *cpu_list, *cpu;
diff --git a/hmp.h b/hmp.h
index 8d2b0d7..2fb44ca 100644
--- a/hmp.h
+++ b/hmp.h
@@ -25,6 +25,7 @@ void hmp_info_uuid(Monitor *mon);
 void hmp_info_chardev(Monitor *mon);
 void hmp_info_mice(Monitor *mon);
 void hmp_info_migrate(Monitor *mon);
+void hmp_info_migration_capabilities(Monitor *mon);
 void hmp_info_cpus(Monitor *mon);
 void hmp_info_block(Monitor *mon);
 void hmp_info_blockstats(Monitor *mon);
diff --git a/migration.c b/migration.c
index 8db1b43..8c27347 100644
--- a/migration.c
+++ b/migration.c
@@ -166,6 +166,17 @@ MigrationInfo *qmp_query_migrate(Error **errp)
     return info;
 }
 
+MigrationCapabilityStatusList *qmp_query_migration_capabilities(Error **errp)
+{
+    MigrationCapabilityStatusList *caps_list = g_malloc0(sizeof(*caps_list));
+
+    caps_list->value = g_malloc(sizeof(*caps_list->value));
+    caps_list->value->capability = MIGRATION_CAPABILITY_XBZRLE;
+    caps_list->next = NULL;
+
+    return caps_list;
+}
+
 /* shared migration helpers */
 
 static int migrate_fd_cleanup(MigrationState *s)
diff --git a/monitor.c b/monitor.c
index 09aa3cd..fd57c5e 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2662,6 +2662,13 @@ static mon_cmd_t info_cmds[] = {
         .mhandler.info = hmp_info_migrate,
     },
     {
+        .name       = "migration-capabilities",
+        .args_type  = "",
+        .params     = "",
+        .help       = "show migration capabilities",
+        .mhandler.info = hmp_info_migration_capabilities,
+    },
+    {
         .name       = "balloon",
         .args_type  = "",
         .params     = "",
diff --git a/qapi-schema.json b/qapi-schema.json
index a92adb1..b4d4dd6 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -306,6 +306,45 @@
 { 'command': 'query-migrate', 'returns': 'MigrationInfo' }
 
 ##
+# @MigrationCapability
+#
+# Migration capabilities enumeration
+#
+# @xbzrle: Migration supports xbzrle (Xor Based Zero Length Encoding).
+#          This feature allows us to minimize migration traffic for certain work
+#          loads, by sending compressed difference of the pages
+#
+# Since: 1.2
+##
+{ 'enum': 'MigrationCapability',
+  'data': ['xbzrle'] }
+
+##
+# @MigrationCapabilityStatus
+#
+# Migration capability information
+#
+# @capability: capability enum
+#
+# @state: capability state bool
+#
+# Since: 1.2
+##
+{ 'type': 'MigrationCapabilityStatus',
+  'data': { 'capability' : 'MigrationCapability', 'state' : 'bool' } }
+
+##
+# @query-migration-capabilities
+#
+# Returns information about current migration process capabilities.
+#
+# Returns: @MigrationCapabilityStatus list
+#
+# Since: 1.2
+##
+{ 'command': 'query-migration-capabilities', 'returns': ['MigrationCapabilityStatus'] }
+
+##
 # @MouseInfo:
 #
 # Information about a mouse device.
diff --git a/qmp-commands.hx b/qmp-commands.hx
index e3cf3c5..c0ed14c 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2141,6 +2141,30 @@ EQMP
     },
 
 SQMP
+query-migration-capabilities
+-------
+
+Query migration capabilities
+
+- "xbzrle": xbzrle support
+
+Arguments:
+
+Example:
+
+-> { "execute": "query-migration-capabilities"}
+<- { "return": [ { "capability": "xbzrle", "state": true },
+                 { "capability": "foobar", "state": false } ] }
+
+EQMP
+
+    {
+        .name       = "query-migration-capabilities",
+        .args_type  = "",
+	.mhandler.cmd_new = qmp_marshal_input_query_migration_capabilities,
+    },
+
+SQMP
 query-balloon
 -------------
 
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH 00/11]  Migration next v7
@ 2012-07-29  9:42 Orit Wasserman
  2012-07-29  9:42 ` [Qemu-devel] [PATCH 01/11] Add migration capabilities Orit Wasserman
                   ` (11 more replies)
  0 siblings, 12 replies; 47+ messages in thread
From: Orit Wasserman @ 2012-07-29  9:42 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, aliguori, quintela, stefanha, mdroth, lcapitulino,
	blauwirbel, Orit Wasserman, chegu_vinod, avi, pbonzini, eblake

Those are the latest XBZRLE patches (part of the migration next branch).

changes from v6:
fix memory leak in cache_init.
using size_t for cache_get_cache_pos.
fix qapi-schema.json comments.
fix other comments by Eric Blake.

changes from v5:
Add query-migrate-parameters that display the migration parameters
(currently only capabilities I will add the other parameters separately).
Remove capabilities from query-migrate.

Please review

Juan Quintela (1):
  Restart optimization on stage3 update version

Orit Wasserman (10):
  Add migration capabilities
  Add migrate_set_parameter and query-migrate-parameters
  Add XBZRLE documentation
  Add cache handling functions
  Add uleb encoding/decoding functions
  Add xbzrle_encode_buffer and xbzrle_decode_buffer functions
  Add XBZRLE to ram_save_block and ram_save_live
  Add migrate_set_cachesize command
  Add migration accounting for normal and duplicate pages
  Add XBZRLE statistics

 Makefile.objs             |    1 +
 arch_init.c               |  246 ++++++++++++++++++++++++++++++++++++++++++++-
 cutils.c                  |   42 ++++++++
 docs/xbzrle.txt           |  136 +++++++++++++++++++++++++
 hmp-commands.hx           |   38 +++++++
 hmp.c                     |  124 +++++++++++++++++++++++
 hmp.h                     |    4 +
 include/qemu/page_cache.h |   79 +++++++++++++++
 migration.c               |  123 ++++++++++++++++++++++-
 migration.h               |   21 ++++
 monitor.c                 |   14 +++
 page_cache.c              |  218 +++++++++++++++++++++++++++++++++++++++
 qapi-schema.json          |  127 +++++++++++++++++++++++-
 qemu-common.h             |   21 ++++
 qmp-commands.hx           |  154 +++++++++++++++++++++++++++-
 savevm.c                  |  159 +++++++++++++++++++++++++++++
 16 files changed, 1494 insertions(+), 13 deletions(-)
 create mode 100644 docs/xbzrle.txt
 create mode 100644 include/qemu/page_cache.h
 create mode 100644 page_cache.c

-- 
1.7.7.6

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH 01/11] Add migration capabilities
  2012-07-29  9:42 [Qemu-devel] [PATCH 00/11] Migration next v7 Orit Wasserman
@ 2012-07-29  9:42 ` Orit Wasserman
  2012-07-30 17:24   ` Luiz Capitulino
  2012-07-30 17:45   ` Eric Blake
  2012-07-29  9:42 ` [Qemu-devel] [PATCH 02/11] Add migrate_set_parameter and query-migrate-parameters Orit Wasserman
                   ` (10 subsequent siblings)
  11 siblings, 2 replies; 47+ messages in thread
From: Orit Wasserman @ 2012-07-29  9:42 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, aliguori, quintela, stefanha, mdroth, lcapitulino,
	blauwirbel, Orit Wasserman, chegu_vinod, avi, pbonzini, eblake

Add migration capabilities that can be queried by the management.
The management can query the source QEMU and the destination QEMU in order to
verify both support some migration capability (currently only XBZRLE).

Signed-off-by: Orit Wasserman <owasserm@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
 hmp-commands.hx  |    2 ++
 hmp.c            |   19 +++++++++++++++++++
 hmp.h            |    1 +
 migration.c      |   11 +++++++++++
 monitor.c        |    7 +++++++
 qapi-schema.json |   39 +++++++++++++++++++++++++++++++++++++++
 qmp-commands.hx  |   24 ++++++++++++++++++++++++
 7 files changed, 103 insertions(+), 0 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index eea8b32..8786148 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1417,6 +1417,8 @@ show CPU statistics
 show user network stack connection states
 @item info migrate
 show migration status
+@item info migration_capabilities
+show migration capabilities
 @item info balloon
 show balloon information
 @item info qtree
diff --git a/hmp.c b/hmp.c
index 6b72a64..5c7d0be 100644
--- a/hmp.c
+++ b/hmp.c
@@ -161,6 +161,25 @@ void hmp_info_migrate(Monitor *mon)
     qapi_free_MigrationInfo(info);
 }
 
+void hmp_info_migration_capabilities(Monitor *mon)
+{
+    MigrationCapabilityStatusList *caps_list, *cap;
+
+    caps_list = qmp_query_migration_capabilities(NULL);
+    if (!caps_list) {
+        monitor_printf(mon, "No migration capabilities found\n");
+        return;
+    }
+
+    for (cap = caps_list; cap; cap = cap->next) {
+        monitor_printf(mon, "%s: %s ",
+                       MigrationCapability_lookup[cap->value->capability],
+                       cap->value->state ? "on" : "off");
+    }
+
+    qapi_free_MigrationCapabilityStatusList(caps_list);
+}
+
 void hmp_info_cpus(Monitor *mon)
 {
     CpuInfoList *cpu_list, *cpu;
diff --git a/hmp.h b/hmp.h
index 8d2b0d7..2fb44ca 100644
--- a/hmp.h
+++ b/hmp.h
@@ -25,6 +25,7 @@ void hmp_info_uuid(Monitor *mon);
 void hmp_info_chardev(Monitor *mon);
 void hmp_info_mice(Monitor *mon);
 void hmp_info_migrate(Monitor *mon);
+void hmp_info_migration_capabilities(Monitor *mon);
 void hmp_info_cpus(Monitor *mon);
 void hmp_info_block(Monitor *mon);
 void hmp_info_blockstats(Monitor *mon);
diff --git a/migration.c b/migration.c
index 8db1b43..8c27347 100644
--- a/migration.c
+++ b/migration.c
@@ -166,6 +166,17 @@ MigrationInfo *qmp_query_migrate(Error **errp)
     return info;
 }
 
+MigrationCapabilityStatusList *qmp_query_migration_capabilities(Error **errp)
+{
+    MigrationCapabilityStatusList *caps_list = g_malloc0(sizeof(*caps_list));
+
+    caps_list->value = g_malloc(sizeof(*caps_list->value));
+    caps_list->value->capability = MIGRATION_CAPABILITY_XBZRLE;
+    caps_list->next = NULL;
+
+    return caps_list;
+}
+
 /* shared migration helpers */
 
 static int migrate_fd_cleanup(MigrationState *s)
diff --git a/monitor.c b/monitor.c
index 09aa3cd..fd57c5e 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2662,6 +2662,13 @@ static mon_cmd_t info_cmds[] = {
         .mhandler.info = hmp_info_migrate,
     },
     {
+        .name       = "migration-capabilities",
+        .args_type  = "",
+        .params     = "",
+        .help       = "show migration capabilities",
+        .mhandler.info = hmp_info_migration_capabilities,
+    },
+    {
         .name       = "balloon",
         .args_type  = "",
         .params     = "",
diff --git a/qapi-schema.json b/qapi-schema.json
index a92adb1..b4d4dd6 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -306,6 +306,45 @@
 { 'command': 'query-migrate', 'returns': 'MigrationInfo' }
 
 ##
+# @MigrationCapability
+#
+# Migration capabilities enumeration
+#
+# @xbzrle: Migration supports xbzrle (Xor Based Zero Length Encoding).
+#          This feature allows us to minimize migration traffic for certain work
+#          loads, by sending compressed difference of the pages
+#
+# Since: 1.2
+##
+{ 'enum': 'MigrationCapability',
+  'data': ['xbzrle'] }
+
+##
+# @MigrationCapabilityStatus
+#
+# Migration capability information
+#
+# @capability: capability enum
+#
+# @state: capability state bool
+#
+# Since: 1.2
+##
+{ 'type': 'MigrationCapabilityStatus',
+  'data': { 'capability' : 'MigrationCapability', 'state' : 'bool' } }
+
+##
+# @query-migration-capabilities
+#
+# Returns information about current migration process capabilities.
+#
+# Returns: @MigrationCapabilityStatus list
+#
+# Since: 1.2
+##
+{ 'command': 'query-migration-capabilities', 'returns': ['MigrationCapabilityStatus'] }
+
+##
 # @MouseInfo:
 #
 # Information about a mouse device.
diff --git a/qmp-commands.hx b/qmp-commands.hx
index e3cf3c5..c0ed14c 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2141,6 +2141,30 @@ EQMP
     },
 
 SQMP
+query-migration-capabilities
+-------
+
+Query migration capabilities
+
+- "xbzrle": xbzrle support
+
+Arguments:
+
+Example:
+
+-> { "execute": "query-migration-capabilities"}
+<- { "return": [ { "capability": "xbzrle", "state": true },
+                 { "capability": "foobar", "state": false } ] }
+
+EQMP
+
+    {
+        .name       = "query-migration-capabilities",
+        .args_type  = "",
+	.mhandler.cmd_new = qmp_marshal_input_query_migration_capabilities,
+    },
+
+SQMP
 query-balloon
 -------------
 
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH 02/11] Add migrate_set_parameter and query-migrate-parameters
  2012-07-29  9:42 [Qemu-devel] [PATCH 00/11] Migration next v7 Orit Wasserman
  2012-07-29  9:42 ` [Qemu-devel] [PATCH 01/11] Add migration capabilities Orit Wasserman
@ 2012-07-29  9:42 ` Orit Wasserman
  2012-07-30 17:41   ` Luiz Capitulino
                     ` (3 more replies)
  2012-07-29  9:42 ` [Qemu-devel] [PATCH 03/11] Add XBZRLE documentation Orit Wasserman
                   ` (9 subsequent siblings)
  11 siblings, 4 replies; 47+ messages in thread
From: Orit Wasserman @ 2012-07-29  9:42 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, aliguori, quintela, stefanha, mdroth, lcapitulino,
	blauwirbel, Orit Wasserman, chegu_vinod, avi, pbonzini, eblake

The management can enable/disable a capability for the next migration by using
migrate_set_parameter command.
The management can query the current migration capabilities using
query-migrate-parameters

Signed-off-by: Orit Wasserman <owasserm@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
 hmp-commands.hx  |   16 ++++++++++++
 hmp.c            |   71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hmp.h            |    2 +
 migration.c      |   42 +++++++++++++++++++++++++++++++-
 migration.h      |    2 +
 monitor.c        |    7 +++++
 qapi-schema.json |   32 ++++++++++++++++++++++++
 qmp-commands.hx  |   60 ++++++++++++++++++++++++++++++++++++++++++++-
 8 files changed, 229 insertions(+), 3 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 8786148..3e15338 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -861,6 +861,20 @@ Set maximum tolerated downtime (in seconds) for migration.
 ETEXI
 
     {
+        .name       = "migrate_set_parameter",
+        .args_type  = "capability:s,state:b",
+        .params     = "capability state",
+        .help       = "Enable/Disable the usage of a capability for migration",
+        .mhandler.cmd = hmp_migrate_set_parameter,
+    },
+
+STEXI
+@item migrate_set_parameter @var{capability} @var{state}
+@findex migrate_set_parameter
+Enable/Disable the usage of a capability @var{capability} for migration.
+ETEXI
+
+    {
         .name       = "client_migrate_info",
         .args_type  = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?",
         .params     = "protocol hostname port tls-port cert-subject",
@@ -1419,6 +1433,8 @@ show user network stack connection states
 show migration status
 @item info migration_capabilities
 show migration capabilities
+@item info migrate_parameters
+show current migration parameters
 @item info balloon
 show balloon information
 @item info qtree
diff --git a/hmp.c b/hmp.c
index 5c7d0be..f2f63fd 100644
--- a/hmp.c
+++ b/hmp.c
@@ -131,8 +131,22 @@ void hmp_info_mice(Monitor *mon)
 void hmp_info_migrate(Monitor *mon)
 {
     MigrationInfo *info;
+    MigrationCapabilityStatusList *cap;
+    MigrationParameters *params;
 
     info = qmp_query_migrate(NULL);
+    params = qmp_query_migrate_parameters(NULL);
+
+    /* do not display parameters during setup */
+    if (info->has_status && params->capabilities) {
+        monitor_printf(mon, "capabilities: ");
+        for (cap = params->capabilities; cap; cap = cap->next) {
+            monitor_printf(mon, "%s: %s ",
+                           MigrationCapability_lookup[cap->value->capability],
+                           cap->value->state ? "on" : "off");
+        }
+        monitor_printf(mon, "\n");
+    }
 
     if (info->has_status) {
         monitor_printf(mon, "Migration status: %s\n", info->status);
@@ -159,6 +173,7 @@ void hmp_info_migrate(Monitor *mon)
     }
 
     qapi_free_MigrationInfo(info);
+    qapi_free_MigrationParameters(params);
 }
 
 void hmp_info_migration_capabilities(Monitor *mon)
@@ -180,6 +195,27 @@ void hmp_info_migration_capabilities(Monitor *mon)
     qapi_free_MigrationCapabilityStatusList(caps_list);
 }
 
+void hmp_info_migrate_parameters(Monitor *mon)
+{
+
+    MigrationCapabilityStatusList *cap;
+    MigrationParameters *params;
+
+    params = qmp_query_migrate_parameters(NULL);
+
+    if (params->capabilities) {
+        monitor_printf(mon, "capabilities: ");
+        for (cap = params->capabilities; cap; cap = cap->next) {
+            monitor_printf(mon, "%s: %s ",
+                           MigrationCapability_lookup[cap->value->capability],
+                           cap->value->state ? "on" : "off");
+        }
+        monitor_printf(mon, "\n");
+    }
+
+    qapi_free_MigrationParameters(params);
+}
+
 void hmp_info_cpus(Monitor *mon)
 {
     CpuInfoList *cpu_list, *cpu;
@@ -754,6 +790,41 @@ void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict)
     qmp_migrate_set_speed(value, NULL);
 }
 
+void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
+{
+    const char *cap = qdict_get_str(qdict, "capability");
+    bool state = qdict_get_bool(qdict, "state");
+    Error *err = NULL;
+    MigrationCapabilityStatusList *params = NULL;
+    int i;
+
+    for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
+        if (strcmp(cap, MigrationCapability_lookup[i]) == 0) {
+            if (!params) {
+                params = g_malloc0(sizeof(*params));
+            }
+            params->value = g_malloc0(sizeof(*params->value));
+            params->value->capability = i;
+            params->value->state = state;
+            params->next = NULL;
+            qmp_migrate_set_parameters(params, &err);
+            break;
+        }
+    }
+
+    if (i == MIGRATION_CAPABILITY_MAX) {
+        error_set(&err, QERR_INVALID_PARAMETER, cap);
+    }
+
+    qapi_free_MigrationCapabilityStatusList(params);
+
+    if (err) {
+        monitor_printf(mon, "migrate_set_parameter: %s\n",
+                       error_get_pretty(err));
+        error_free(err);
+    }
+}
+
 void hmp_set_password(Monitor *mon, const QDict *qdict)
 {
     const char *protocol  = qdict_get_str(qdict, "protocol");
diff --git a/hmp.h b/hmp.h
index 2fb44ca..ceb2f06 100644
--- a/hmp.h
+++ b/hmp.h
@@ -26,6 +26,7 @@ void hmp_info_chardev(Monitor *mon);
 void hmp_info_mice(Monitor *mon);
 void hmp_info_migrate(Monitor *mon);
 void hmp_info_migration_capabilities(Monitor *mon);
+void hmp_info_migrate_parameters(Monitor *mon);
 void hmp_info_cpus(Monitor *mon);
 void hmp_info_block(Monitor *mon);
 void hmp_info_blockstats(Monitor *mon);
@@ -52,6 +53,7 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict);
 void hmp_migrate_cancel(Monitor *mon, const QDict *qdict);
 void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict);
 void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict);
+void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict);
 void hmp_set_password(Monitor *mon, const QDict *qdict);
 void hmp_expire_password(Monitor *mon, const QDict *qdict);
 void hmp_eject(Monitor *mon, const QDict *qdict);
diff --git a/migration.c b/migration.c
index 8c27347..e844290 100644
--- a/migration.c
+++ b/migration.c
@@ -113,6 +113,25 @@ uint64_t migrate_max_downtime(void)
     return max_downtime;
 }
 
+MigrationParameters *qmp_query_migrate_parameters(Error **errp)
+{
+    MigrationParameters *params = g_malloc0(sizeof(*params));
+    MigrationState *s = migrate_get_current();
+    int i;
+
+    params->capabilities = g_malloc0(sizeof(*params->capabilities));
+
+    for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
+        params->capabilities->value =
+            g_malloc(sizeof(*params->capabilities->value));
+        params->capabilities->value->capability = i;
+        params->capabilities->value->state = s->enabled_capabilities[i];
+        params->capabilities->next = NULL;
+    }
+
+    return params;
+}
+
 MigrationInfo *qmp_query_migrate(Error **errp)
 {
     MigrationInfo *info = g_malloc0(sizeof(*info));
@@ -177,6 +196,22 @@ MigrationCapabilityStatusList *qmp_query_migration_capabilities(Error **errp)
     return caps_list;
 }
 
+void qmp_migrate_set_parameters(MigrationCapabilityStatusList *params,
+                                Error **errp)
+{
+    MigrationState *s = migrate_get_current();
+    MigrationCapabilityStatusList *cap;
+
+    if (s->state == MIG_STATE_ACTIVE) {
+        error_set(errp, QERR_MIGRATION_ACTIVE);
+        return;
+    }
+
+    for (cap = params; cap; cap = cap->next) {
+        s->enabled_capabilities[cap->value->capability] = cap->value->state;
+    }
+}
+
 /* shared migration helpers */
 
 static int migrate_fd_cleanup(MigrationState *s)
@@ -386,12 +421,17 @@ static MigrationState *migrate_init(const MigrationParams *params)
 {
     MigrationState *s = migrate_get_current();
     int64_t bandwidth_limit = s->bandwidth_limit;
+    bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
+
+    memcpy(enabled_capabilities, s->enabled_capabilities,
+           sizeof(enabled_capabilities));
 
     memset(s, 0, sizeof(*s));
     s->bandwidth_limit = bandwidth_limit;
     s->params = *params;
+    memcpy(s->enabled_capabilities, enabled_capabilities,
+           sizeof(enabled_capabilities));
 
-    s->bandwidth_limit = bandwidth_limit;
     s->state = MIG_STATE_SETUP;
     s->total_time = qemu_get_clock_ms(rt_clock);
 
diff --git a/migration.h b/migration.h
index 57572a6..713aae0 100644
--- a/migration.h
+++ b/migration.h
@@ -19,6 +19,7 @@
 #include "notify.h"
 #include "error.h"
 #include "vmstate.h"
+#include "qapi-types.h"
 
 struct MigrationParams {
     bool blk;
@@ -39,6 +40,7 @@ struct MigrationState
     void *opaque;
     MigrationParams params;
     int64_t total_time;
+    bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
 };
 
 void process_incoming_migration(QEMUFile *f);
diff --git a/monitor.c b/monitor.c
index fd57c5e..e07af97 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2669,6 +2669,13 @@ static mon_cmd_t info_cmds[] = {
         .mhandler.info = hmp_info_migration_capabilities,
     },
     {
+        .name       = "migrate-parameters",
+        .args_type  = "",
+        .params     = "",
+        .help       = "show current migration parameters",
+        .mhandler.info = hmp_info_migrate_parameters,
+    },
+    {
         .name       = "balloon",
         .args_type  = "",
         .params     = "",
diff --git a/qapi-schema.json b/qapi-schema.json
index b4d4dd6..9d6759d 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -345,6 +345,38 @@
 { 'command': 'query-migration-capabilities', 'returns': ['MigrationCapabilityStatus'] }
 
 ##
+# @migrate-set-parameters
+#
+# Enable/Disable the following migration capabilities (like xbzrle)
+#
+# Since: 1.2
+##
+{ 'command': 'migrate-set-parameters',
+  'data': { 'capabilities': ['MigrationCapabilityStatus'] } }
+
+##
+# @MigrationParameters
+#
+# @capabilities: @MigrationCapabilityStatus list contain current migration
+#                capabilities status
+# Since: 1.2
+##
+{ 'type': 'MigrationParameters',
+  'data': {'capabilities': ['MigrationCapabilityStatus']} }
+
+
+##
+# @query-migrate-parameters
+#
+# Returns information about the current migration capabilities status
+#
+# Returns: @MigrationParameters
+#
+# Since: 1.2
+##
+{ 'command': 'query-migrate-parameters', 'returns': 'MigrationParameters' }
+
+##
 # @MouseInfo:
 #
 # Information about a mouse device.
diff --git a/qmp-commands.hx b/qmp-commands.hx
index c0ed14c..7f40e2a 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2081,7 +2081,6 @@ The main json-object contains the following:
          - "transferred": amount transferred (json-int)
          - "remaining": amount remaining (json-int)
          - "total": total (json-int)
-
 Examples:
 
 1. Before the first migration
@@ -2092,7 +2091,15 @@ Examples:
 2. Migration is done and has succeeded
 
 -> { "execute": "query-migrate" }
-<- { "return": { "status": "completed" } }
+<- { "return": {
+        "status": "completed",
+        "ram":{
+          "transferred":123,
+          "remaining":123,
+          "total":246
+        }
+     }
+   }
 
 3. Migration is done and has failed
 
@@ -2165,6 +2172,55 @@ EQMP
     },
 
 SQMP
+migrate-set-parameters
+-------
+
+Enable/Disable migration capabilities
+
+- "xbzrle": xbzrle support
+
+Arguments:
+
+Example:
+
+-> { "execute": "migrate-set-parameters" , "arguments":
+     { "parameters": [ { "capability": "xbzrle", "state": true } ] } }
+
+EQMP
+
+    {
+        .name       = "migrate_set_parameters",
+        .args_type  = "parameters:O",
+        .params     = "capability:s,state:b",
+	.mhandler.cmd_new = qmp_marshal_input_migrate_set_parameters,
+    },
+SQMP
+query-migrate-parameters
+-------
+
+Query current migration parameters
+
+- "capabilities": migration capabilities state
+         - "xbzrle" : XBZRLE state (json-bool)
+
+Arguments:
+
+Example:
+
+-> { "execute": "query-migrate-parameters" }
+<- { "return": {
+        "capabilities" :  [ { "capability" : "xbzrle", "state" : false } ]
+     }
+   }
+EQMP
+
+    {
+        .name       = "query-migrate-parameters",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_migrate_parameters,
+    },
+
+SQMP
 query-balloon
 -------------
 
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH 03/11] Add XBZRLE documentation
  2012-07-29  9:42 [Qemu-devel] [PATCH 00/11] Migration next v7 Orit Wasserman
  2012-07-29  9:42 ` [Qemu-devel] [PATCH 01/11] Add migration capabilities Orit Wasserman
  2012-07-29  9:42 ` [Qemu-devel] [PATCH 02/11] Add migrate_set_parameter and query-migrate-parameters Orit Wasserman
@ 2012-07-29  9:42 ` Orit Wasserman
  2012-07-29  9:42 ` [Qemu-devel] [PATCH 04/11] Add cache handling functions Orit Wasserman
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 47+ messages in thread
From: Orit Wasserman @ 2012-07-29  9:42 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, aliguori, quintela, stefanha, mdroth, lcapitulino,
	blauwirbel, Orit Wasserman, chegu_vinod, avi, pbonzini, eblake

Signed-off-by: Orit Wasserman <owasserm@redhat.com>
---
 docs/xbzrle.txt |  136 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 136 insertions(+), 0 deletions(-)
 create mode 100644 docs/xbzrle.txt

diff --git a/docs/xbzrle.txt b/docs/xbzrle.txt
new file mode 100644
index 0000000..f70e851
--- /dev/null
+++ b/docs/xbzrle.txt
@@ -0,0 +1,136 @@
+XBZRLE (Xor Based Zero Run Length Encoding)
+===========================================
+
+Using XBZRLE (Xor Based Zero Run Length Encoding) allows for the reduction
+of VM downtime and the total live-migration time of Virtual machines.
+It is particularly useful for virtual machines running memory write intensive
+workloads that are typical of large enterprise applications such as SAP ERP
+Systems, and generally speaking for any application that uses a sparse memory
+update pattern.
+
+Instead of sending the changed guest memory page this solution will send a
+compressed version of the updates, thus reducing the amount of data sent during
+live migration.
+In order to be able to calculate the update, the previous memory pages need to
+be stored on the source. Those pages are stored in a dedicated cache
+(hash table) and are
+accessed by their address.
+The larger the cache size the better the chances are that the page has already
+been stored in the cache.
+A small cache size will result in high cache miss rate.
+Cache size can be changed before and during migration.
+
+Format
+=======
+
+The compression format performs a XOR between the previous and current content
+of the page, where zero represents an unchanged value.
+The page data delta is represented by zero and non zero runs.
+A zero run is represented by its length (in bytes).
+A non zero run is represented by its length (in bytes) and the new data.
+The run length is encoded using ULEB128 (http://en.wikipedia.org/wiki/LEB128)
+
+There can be more than one valid encoding, the sender may send a longer encoding
+for the benefit of reducing computation cost.
+
+page = zrun nzrun
+       | zrun nzrun page
+
+zrun = length
+
+nzrun = length byte...
+
+length = uleb128 encoded integer
+
+On the sender side XBZRLE is used as a compact delta encoding of page updates,
+retrieving the old page content from the cache (default size of 512 MB). The
+receiving side uses the existing page's content and XBZRLE to decode the new
+page's content.
+
+This work was originally based on research results published
+VEE 2011: Evaluation of Delta Compression Techniques for Efficient Live
+Migration of Large Virtual Machines by Benoit, Svard, Tordsson and Elmroth.
+Additionally the delta encoder XBRLE was improved further using the XBZRLE
+instead.
+
+XBZRLE has a sustained bandwidth of 2-2.5 GB/s for typical workloads making it
+ideal for in-line, real-time encoding such as is needed for live-migration.
+
+Example
+old buffer:
+1001 zeros
+05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 68 00 00 6b 00 6d
+3074 zeros
+
+new buffer:
+1001 zeros
+01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 68 00 00 67 00 69
+3074 zeros
+
+encoded buffer:
+
+encoded length 24
+e9 07 0f 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 03 01 67 01 01 69
+
+Migration Capabilities
+======================
+In order to use XBZRLE the destination QEMU version should be able to
+decode the new format.
+Adding a new migration capabilities command that will allow external management
+to query for it support.
+A typical use for the destination
+    {qemu} info migrate_capabilities
+    {qemu} xbzrle, ...
+
+In order to enable capabilities for future live migration,
+a new command migrate_set_parameter is introduced:
+    {qemu} migrate_set_parameter xbzrle
+
+Usage
+======
+
+1. Activate xbzrle
+2. Set the XBZRLE cache size - the cache size is in MBytes and should be a
+power of 2. The cache default value is 64MBytes.
+3. start outgoing migration
+
+A typical usage scenario:
+On the incoming QEMU:
+    {qemu} migrate_set_parameter xbzrle on
+On the outgoing QEMU:
+    {qemu} migrate_set_parameter xbzrle on
+    {qemu} migrate_set_cachesize 256m
+    {qemu} migrate -d tcp:destination.host:4444
+    {qemu} info migrate
+    ...
+    cache size: 67108864 bytes
+    transferred ram-duplicate: A kbytes
+    transferred ram-normal: B kbytes
+    transferred ram-xbrle: C kbytes
+    overflow ram-xbrle: D pages
+    cache-miss ram-xbrle: E pages
+
+cache-miss: the number of cache misses to date - high cache-miss rate
+indicates that the cache size is set too low.
+overflow: the number of overflows in the decoding which where the delta could
+not be compressed. This can happen if the changes in the pages are too large
+or there are many short changes; for example, changing every second byte (half a
+page).
+
+Testing: Testing indicated that live migration with XBZRLE was completed in 110
+seconds, whereas without it would not be able to complete.
+
+A simple synthetic memory r/w load generator:
+..    include <stdlib.h>
+..    include <stdio.h>
+..    int main()
+..    {
+..        char *buf = (char *) calloc(4096, 4096);
+..        while (1) {
+..            int i;
+..            for (i = 0; i < 4096 * 4; i++) {
+..                buf[i * 4096 / 4]++;
+..            }
+..            printf(".");
+..        }
+..    }
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH 04/11] Add cache handling functions
  2012-07-29  9:42 [Qemu-devel] [PATCH 00/11] Migration next v7 Orit Wasserman
                   ` (2 preceding siblings ...)
  2012-07-29  9:42 ` [Qemu-devel] [PATCH 03/11] Add XBZRLE documentation Orit Wasserman
@ 2012-07-29  9:42 ` Orit Wasserman
  2012-07-29  9:42 ` [Qemu-devel] [PATCH 05/11] Add uleb encoding/decoding functions Orit Wasserman
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 47+ messages in thread
From: Orit Wasserman @ 2012-07-29  9:42 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, aliguori, quintela, Petter Svard, stefanha, mdroth,
	Benoit Hudzia, lcapitulino, blauwirbel, Orit Wasserman,
	chegu_vinod, avi, Aidan Shribman, pbonzini, eblake

Add MRU page cache mechanism.
The page are accessed by their address.

Signed-off-by: Benoit Hudzia <benoit.hudzia@sap.com>
Signed-off-by: Petter Svard <petters@cs.umu.se>
Signed-off-by: Aidan Shribman <aidan.shribman@sap.com>
Signed-off-by: Orit Wasserman <owasserm@redhat.com>
---
 Makefile.objs             |    1 +
 cutils.c                  |    9 ++
 include/qemu/page_cache.h |   79 ++++++++++++++++
 page_cache.c              |  218 +++++++++++++++++++++++++++++++++++++++++++++
 qemu-common.h             |   13 +++
 5 files changed, 320 insertions(+), 0 deletions(-)
 create mode 100644 include/qemu/page_cache.h
 create mode 100644 page_cache.c

diff --git a/Makefile.objs b/Makefile.objs
index 5ebbcfa..e0fb69b 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -77,6 +77,7 @@ common-obj-y += qemu-char.o #aio.o
 common-obj-y += block-migration.o iohandler.o
 common-obj-y += pflib.o
 common-obj-y += bitmap.o bitops.o
+common-obj-y += page_cache.o
 
 common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
 common-obj-$(CONFIG_WIN32) += version.o
diff --git a/cutils.c b/cutils.c
index e2bc1b8..b0bdd4b 100644
--- a/cutils.c
+++ b/cutils.c
@@ -375,3 +375,12 @@ int qemu_parse_fd(const char *param)
     }
     return fd;
 }
+
+/* round down to the nearest power of 2*/
+int64_t pow2floor(int64_t value)
+{
+    if (!is_power_of_2(value)) {
+        value = 0x8000000000000000ULL >> clz64(value);
+    }
+    return value;
+}
diff --git a/include/qemu/page_cache.h b/include/qemu/page_cache.h
new file mode 100644
index 0000000..3839ac7
--- /dev/null
+++ b/include/qemu/page_cache.h
@@ -0,0 +1,79 @@
+/*
+ * Page cache for QEMU
+ * The cache is base on a hash of the page address
+ *
+ * Copyright 2012 Red Hat, Inc. and/or its affiliates
+ *
+ * Authors:
+ *  Orit Wasserman  <owasserm@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef PAGE_CACHE_H
+#define PAGE_CACHE_H
+
+/* Page cache for storing guest pages */
+typedef struct PageCache PageCache;
+
+/**
+ * cache_init: Initialize the page cache
+ *
+ *
+ * Returns new allocated cache or NULL on error
+ *
+ * @cache pointer to the PageCache struct
+ * @num_pages: cache maximal number of cached pages
+ * @page_size: cache page size
+ */
+PageCache *cache_init(int64_t num_pages, unsigned int page_size);
+
+/**
+ * cache_fini: free all cache resources
+ * @cache pointer to the PageCache struct
+ */
+void cache_fini(PageCache *cache);
+
+/**
+ * cache_is_cached: Checks to see if the page is cached
+ *
+ * Returns %true if page is cached
+ *
+ * @cache pointer to the PageCache struct
+ * @addr: page addr
+ */
+bool cache_is_cached(const PageCache *cache, uint64_t addr);
+
+/**
+ * get_cached_data: Get the data cached for an addr
+ *
+ * Returns pointer to the data cached or NULL if not cached
+ *
+ * @cache pointer to the PageCache struct
+ * @addr: page addr
+ */
+uint8_t *get_cached_data(const PageCache *cache, uint64_t addr);
+
+/**
+ * cache_insert: insert the page into the cache. the previous value will be overwritten
+ *
+ * @cache pointer to the PageCache struct
+ * @addr: page address
+ * @pdata: pointer to the page
+ */
+void cache_insert(PageCache *cache, uint64_t addr, uint8_t *pdata);
+
+/**
+ * cache_resize: resize the page cache. In case of size reduction the extra
+ * pages will be freed
+ *
+ * Returns -1 on error new cache size on success
+ *
+ * @cache pointer to the PageCache struct
+ * @num_pages: new page cache size (in pages)
+ */
+int64_t cache_resize(PageCache *cache, int64_t num_pages);
+
+#endif
diff --git a/page_cache.c b/page_cache.c
new file mode 100644
index 0000000..0294f7e
--- /dev/null
+++ b/page_cache.c
@@ -0,0 +1,218 @@
+/*
+ * Page cache for QEMU
+ * The cache is base on a hash of the page address
+ *
+ * Copyright 2012 Red Hat, Inc. and/or its affiliates
+ *
+ * Authors:
+ *  Orit Wasserman  <owasserm@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <stdbool.h>
+#include <glib.h>
+#include <strings.h>
+
+#include "qemu-common.h"
+#include "qemu/page_cache.h"
+
+#ifdef DEBUG_CACHE
+#define DPRINTF(fmt, ...) \
+    do { fprintf(stdout, "cache: " fmt, ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) \
+    do { } while (0)
+#endif
+
+typedef struct CacheItem CacheItem;
+
+struct CacheItem {
+    uint64_t it_addr;
+    uint64_t it_age;
+    uint8_t *it_data;
+};
+
+struct PageCache {
+    CacheItem *page_cache;
+    unsigned int page_size;
+    int64_t max_num_items;
+    uint64_t max_item_age;
+    int64_t num_items;
+};
+
+PageCache *cache_init(int64_t num_pages, unsigned int page_size)
+{
+    int64_t i;
+
+    PageCache *cache;
+
+    if (num_pages <= 0) {
+        DPRINTF("invalid number of pages\n");
+        return NULL;
+    }
+
+    cache = g_malloc(sizeof(*cache));
+
+    /* round down to the nearest power of 2 */
+    if (!is_power_of_2(num_pages)) {
+        num_pages = pow2floor(num_pages);
+        DPRINTF("rounding down to %" PRId64 "\n", num_pages);
+    }
+    cache->page_size = page_size;
+    cache->num_items = 0;
+    cache->max_item_age = 0;
+    cache->max_num_items = num_pages;
+
+    DPRINTF("Setting cache buckets to %" PRId64 "\n", cache->max_num_items);
+
+    cache->page_cache = g_malloc((cache->max_num_items) *
+                                 sizeof(*cache->page_cache));
+
+    for (i = 0; i < cache->max_num_items; i++) {
+        cache->page_cache[i].it_data = NULL;
+        cache->page_cache[i].it_age = 0;
+        cache->page_cache[i].it_addr = -1;
+    }
+
+    return cache;
+}
+
+void cache_fini(PageCache *cache)
+{
+    int64_t i;
+
+    g_assert(cache);
+    g_assert(cache->page_cache);
+
+    for (i = 0; i < cache->max_num_items; i++) {
+        g_free(cache->page_cache[i].it_data);
+    }
+
+    g_free(cache->page_cache);
+    cache->page_cache = NULL;
+}
+
+static size_t cache_get_cache_pos(const PageCache *cache,
+                                  uint64_t address)
+{
+    size_t pos;
+
+    g_assert(cache->max_num_items);
+    pos = (address / cache->page_size) & (cache->max_num_items - 1);
+    return pos;
+}
+
+bool cache_is_cached(const PageCache *cache, uint64_t addr)
+{
+    size_t pos;
+
+    g_assert(cache);
+    g_assert(cache->page_cache);
+
+    pos = cache_get_cache_pos(cache, addr);
+
+    return (cache->page_cache[pos].it_addr == addr);
+}
+
+static CacheItem *cache_get_by_addr(const PageCache *cache, uint64_t addr)
+{
+    size_t pos;
+
+    g_assert(cache);
+    g_assert(cache->page_cache);
+
+    pos = cache_get_cache_pos(cache, addr);
+
+    return &cache->page_cache[pos];
+}
+
+uint8_t *get_cached_data(const PageCache *cache, uint64_t addr)
+{
+    return cache_get_by_addr(cache, addr)->it_data;
+}
+
+void cache_insert(PageCache *cache, uint64_t addr, uint8_t *pdata)
+{
+
+    CacheItem *it = NULL;
+
+    g_assert(cache);
+    g_assert(cache->page_cache);
+
+    /* actual update of entry */
+    it = cache_get_by_addr(cache, addr);
+
+    if (!it->it_data) {
+        cache->num_items++;
+    }
+
+    it->it_data = pdata;
+    it->it_age = ++cache->max_item_age;
+    it->it_addr = addr;
+}
+
+int64_t cache_resize(PageCache *cache, int64_t new_num_pages)
+{
+    PageCache *new_cache;
+    int64_t i;
+
+    CacheItem *old_it, *new_it;
+
+    g_assert(cache);
+
+    /* cache was not inited */
+    if (cache->page_cache == NULL) {
+        return -1;
+    }
+
+    /* same size */
+    if (pow2floor(new_num_pages) == cache->max_num_items) {
+        return cache->max_num_items;
+    }
+
+    new_cache = cache_init(new_num_pages, cache->page_size);
+    if (!(new_cache)) {
+        DPRINTF("Error creating new cache\n");
+        return -1;
+    }
+
+    /* move all data from old cache */
+    for (i = 0; i < cache->max_num_items; i++) {
+        old_it = &cache->page_cache[i];
+        if (old_it->it_addr != -1) {
+            /* check for collision, if there is, keep MRU page */
+            new_it = cache_get_by_addr(new_cache, old_it->it_addr);
+            if (new_it->it_data) {
+                /* keep the MRU page */
+                if (new_it->it_age >= old_it->it_age) {
+                    g_free(old_it->it_data);
+                } else {
+                    g_free(new_it->it_data);
+                    new_it->it_data = old_it->it_data;
+                    new_it->it_age = old_it->it_age;
+                    new_it->it_addr = old_it->it_addr;
+                }
+            } else {
+                cache_insert(new_cache, old_it->it_addr, old_it->it_data);
+            }
+        }
+    }
+
+    cache->page_cache = new_cache->page_cache;
+    cache->max_num_items = new_cache->max_num_items;
+    cache->num_items = new_cache->num_items;
+
+    g_free(new_cache);
+
+    return cache->max_num_items;
+}
diff --git a/qemu-common.h b/qemu-common.h
index 09676f5..855f242 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -1,3 +1,4 @@
+
 /* Common header file that is included by all of qemu.  */
 #ifndef QEMU_COMMON_H
 #define QEMU_COMMON_H
@@ -411,6 +412,18 @@ static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
 /* Round number up to multiple */
 #define QEMU_ALIGN_UP(n, m) QEMU_ALIGN_DOWN((n) + (m) - 1, (m))
 
+static inline bool is_power_of_2(uint64_t value)
+{
+    if (!value) {
+        return 0;
+    }
+
+    return !(value & (value - 1));
+}
+
+/* round down to the nearest power of 2*/
+int64_t pow2floor(int64_t value);
+
 #include "module.h"
 
 #endif
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH 05/11] Add uleb encoding/decoding functions
  2012-07-29  9:42 [Qemu-devel] [PATCH 00/11] Migration next v7 Orit Wasserman
                   ` (3 preceding siblings ...)
  2012-07-29  9:42 ` [Qemu-devel] [PATCH 04/11] Add cache handling functions Orit Wasserman
@ 2012-07-29  9:42 ` Orit Wasserman
  2012-07-29  9:42 ` [Qemu-devel] [PATCH 06/11] Add xbzrle_encode_buffer and xbzrle_decode_buffer functions Orit Wasserman
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 47+ messages in thread
From: Orit Wasserman @ 2012-07-29  9:42 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, aliguori, quintela, stefanha, mdroth, lcapitulino,
	blauwirbel, Orit Wasserman, chegu_vinod, avi, pbonzini, eblake

Implement Unsigned Little Endian Base 128.

Signed-off-by: Orit Wasserman <owasserm@redhat.com>
---
 cutils.c      |   33 +++++++++++++++++++++++++++++++++
 qemu-common.h |    8 ++++++++
 2 files changed, 41 insertions(+), 0 deletions(-)

diff --git a/cutils.c b/cutils.c
index b0bdd4b..700f943 100644
--- a/cutils.c
+++ b/cutils.c
@@ -384,3 +384,36 @@ int64_t pow2floor(int64_t value)
     }
     return value;
 }
+
+/*
+ * Implementation of  ULEB128 (http://en.wikipedia.org/wiki/LEB128)
+ * Input is limited to 14-bit numbers
+ */
+int uleb128_encode_small(uint8_t *out, uint32_t n)
+{
+    g_assert(n <= 0x3fff);
+    if (n < 0x80) {
+        *out++ = n;
+        return 1;
+    } else {
+        *out++ = (n & 0x7f) | 0x80;
+        *out++ = n >> 7;
+        return 2;
+    }
+}
+
+int uleb128_decode_small(const uint8_t *in, uint32_t *n)
+{
+    if (!(*in & 0x80)) {
+        *n = *in++;
+        return 1;
+    } else {
+        *n = *in++ & 0x7f;
+        /* we exceed 14 bit number */
+        if (*in & 0x80) {
+            return -1;
+        }
+        *n |= *in++ << 7;
+        return 2;
+    }
+}
diff --git a/qemu-common.h b/qemu-common.h
index 855f242..93d1c63 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -426,4 +426,12 @@ int64_t pow2floor(int64_t value);
 
 #include "module.h"
 
+/*
+ * Implementation of ULEB128 (http://en.wikipedia.org/wiki/LEB128)
+ * Input is limited to 14-bit numbers
+ */
+
+int uleb128_encode_small(uint8_t *out, uint32_t n);
+int uleb128_decode_small(const uint8_t *in, uint32_t *n);
+
 #endif
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH 06/11] Add xbzrle_encode_buffer and xbzrle_decode_buffer functions
  2012-07-29  9:42 [Qemu-devel] [PATCH 00/11] Migration next v7 Orit Wasserman
                   ` (4 preceding siblings ...)
  2012-07-29  9:42 ` [Qemu-devel] [PATCH 05/11] Add uleb encoding/decoding functions Orit Wasserman
@ 2012-07-29  9:42 ` Orit Wasserman
  2012-07-29  9:42 ` [Qemu-devel] [PATCH 07/11] Add XBZRLE to ram_save_block and ram_save_live Orit Wasserman
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 47+ messages in thread
From: Orit Wasserman @ 2012-07-29  9:42 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, aliguori, quintela, Petter Svard, stefanha, mdroth,
	Benoit Hudzia, lcapitulino, blauwirbel, Orit Wasserman,
	chegu_vinod, avi, Aidan Shribman, pbonzini, eblake

For performance we are encoding long word at a time.
For nzrun we use long-word-at-a-time NULL-detection tricks from strcmp():
using ((lword - 0x0101010101010101) & (~lword) & 0x8080808080808080) test
to find out if any byte in the long word is zero.

Signed-off-by: Benoit Hudzia <benoit.hudzia@sap.com>
Signed-off-by: Petter Svard <petters@cs.umu.se>
Signed-off-by: Aidan Shribman <aidan.shribman@sap.com>
Signed-off-by: Orit Wasserman <owasserm@redhat.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
---
 migration.h |    4 ++
 savevm.c    |  159 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 163 insertions(+), 0 deletions(-)

diff --git a/migration.h b/migration.h
index 713aae0..743c366 100644
--- a/migration.h
+++ b/migration.h
@@ -100,4 +100,8 @@ void migrate_add_blocker(Error *reason);
  */
 void migrate_del_blocker(Error *reason);
 
+int xbzrle_encode_buffer(uint8_t *old_buf, uint8_t *new_buf, int slen,
+                         uint8_t *dst, int dlen);
+int xbzrle_decode_buffer(uint8_t *src, int slen, uint8_t *dst, int dlen);
+
 #endif
diff --git a/savevm.c b/savevm.c
index 6e82b2d..0ea10c9 100644
--- a/savevm.c
+++ b/savevm.c
@@ -2392,3 +2392,162 @@ void vmstate_register_ram_global(MemoryRegion *mr)
 {
     vmstate_register_ram(mr, NULL);
 }
+
+/*
+  page = zrun nzrun
+       | zrun nzrun page
+
+  zrun = length
+
+  nzrun = length byte...
+
+  length = uleb128 encoded integer
+ */
+int xbzrle_encode_buffer(uint8_t *old_buf, uint8_t *new_buf, int slen,
+                         uint8_t *dst, int dlen)
+{
+    uint32_t zrun_len = 0, nzrun_len = 0;
+    int d = 0, i = 0;
+    long res, xor;
+    uint8_t *nzrun_start = NULL;
+
+    g_assert(!(((uintptr_t)old_buf | (uintptr_t)new_buf | slen) %
+               sizeof(long)));
+
+    while (i < slen) {
+        /* overflow */
+        if (d + 2 > dlen) {
+            return -1;
+        }
+
+        /* not aligned to sizeof(long) */
+        res = (slen - i) % sizeof(long);
+        while (res && old_buf[i] == new_buf[i]) {
+            zrun_len++;
+            i++;
+            res--;
+        }
+
+        /* word at a time for speed */
+        if (!res) {
+            while (i < slen &&
+                   (*(long *)(old_buf + i)) == (*(long *)(new_buf + i))) {
+                i += sizeof(long);
+                zrun_len += sizeof(long);
+            }
+
+            /* go over the rest */
+            while (i < slen && old_buf[i] == new_buf[i]) {
+                zrun_len++;
+                i++;
+            }
+        }
+
+        /* buffer unchanged */
+        if (zrun_len == slen) {
+            return 0;
+        }
+
+        /* skip last zero run */
+        if (i == slen) {
+            return d;
+        }
+
+        d += uleb128_encode_small(dst + d, zrun_len);
+
+        zrun_len = 0;
+        nzrun_start = new_buf + i;
+
+        /* overflow */
+        if (d + 2 > dlen) {
+            return -1;
+        }
+        /* not aligned to sizeof(long) */
+        res = (slen - i) % sizeof(long);
+        while (res && old_buf[i] != new_buf[i]) {
+            i++;
+            nzrun_len++;
+            res--;
+        }
+
+        /* word at a time for speed, use of 32-bit long okay */
+        if (!res) {
+            /* truncation to 32-bit long okay */
+            long mask = 0x0101010101010101ULL;
+            while (i < slen) {
+                xor = *(long *)(old_buf + i) ^ *(long *)(new_buf + i);
+                if ((xor - mask) & ~xor & (mask << 7)) {
+                    /* found the end of an nzrun within the current long */
+                    while (old_buf[i] != new_buf[i]) {
+                        nzrun_len++;
+                        i++;
+                    }
+                    break;
+                } else {
+                    i += sizeof(long);
+                    nzrun_len += sizeof(long);
+                }
+            }
+        }
+
+        d += uleb128_encode_small(dst + d, nzrun_len);
+        /* overflow */
+        if (d + nzrun_len > dlen) {
+            return -1;
+        }
+        memcpy(dst + d, nzrun_start, nzrun_len);
+        d += nzrun_len;
+        nzrun_len = 0;
+    }
+
+    return d;
+}
+
+int xbzrle_decode_buffer(uint8_t *src, int slen, uint8_t *dst, int dlen)
+{
+    int i = 0, d = 0;
+    int ret;
+    uint32_t count = 0;
+
+    while (i < slen) {
+
+        /* zrun */
+        if ((slen - i) < 2) {
+            return -1;
+        }
+
+        ret = uleb128_decode_small(src + i, &count);
+        if (ret < 0 || (i && !count)) {
+            return -1;
+        }
+        i += ret;
+        d += count;
+
+        /* overflow */
+        if (d > dlen) {
+            return -1;
+        }
+
+        /* nzrun */
+        if ((slen - i) < 2) {
+            return -1;
+        }
+
+        ret = uleb128_decode_small(src + i, &count);
+        if (ret < 0 || !count) {
+            return -1;
+        }
+        i += ret;
+
+        /* overflow */
+        if (d + count > dlen || i + count > slen) {
+            return -1;
+        }
+
+        memcpy(dst + d, src + i, count);
+        d += count;
+        i += count;
+    }
+
+    return d;
+}
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH 07/11] Add XBZRLE to ram_save_block and ram_save_live
  2012-07-29  9:42 [Qemu-devel] [PATCH 00/11] Migration next v7 Orit Wasserman
                   ` (5 preceding siblings ...)
  2012-07-29  9:42 ` [Qemu-devel] [PATCH 06/11] Add xbzrle_encode_buffer and xbzrle_decode_buffer functions Orit Wasserman
@ 2012-07-29  9:42 ` Orit Wasserman
  2012-07-29  9:43 ` [Qemu-devel] [PATCH 08/11] Add migrate_set_cachesize command Orit Wasserman
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 47+ messages in thread
From: Orit Wasserman @ 2012-07-29  9:42 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, aliguori, quintela, Petter Svard, stefanha, mdroth,
	Benoit Hudzia, lcapitulino, blauwirbel, Orit Wasserman,
	chegu_vinod, avi, Aidan Shribman, pbonzini, eblake

In the outgoing migration check to see if the page is cached and
changed, then send compressed page by using save_xbrle_page function.
In the incoming migration check to see if RAM_SAVE_FLAG_XBZRLE is set
and decompress the page (by using load_xbrle function).

Signed-off-by: Benoit Hudzia <benoit.hudzia@sap.com>
Signed-off-by: Petter Svard <petters@cs.umu.se>
Signed-off-by: Aidan Shribman <aidan.shribman@sap.com>
Signed-off-by: Orit Wasserman <owasserm@redhat.com>
---
 arch_init.c |  158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 migration.c |   24 +++++++++
 migration.h |    4 ++
 3 files changed, 184 insertions(+), 2 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index 78cdf50..410ba4d 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -43,6 +43,7 @@
 #include "hw/smbios.h"
 #include "exec-memory.h"
 #include "hw/pcspk.h"
+#include "qemu/page_cache.h"
 
 #ifdef DEBUG_ARCH_INIT
 #define DPRINTF(fmt, ...) \
@@ -102,6 +103,7 @@ const uint32_t arch_type = QEMU_ARCH;
 #define RAM_SAVE_FLAG_PAGE     0x08
 #define RAM_SAVE_FLAG_EOS      0x10
 #define RAM_SAVE_FLAG_CONTINUE 0x20
+#define RAM_SAVE_FLAG_XBZRLE   0x40
 
 #ifdef __ALTIVEC__
 #include <altivec.h>
@@ -169,6 +171,24 @@ static int is_dup_page(uint8_t *page)
     return 1;
 }
 
+/* struct contains XBZRLE cache and a static page
+   used by the compression */
+static struct {
+    /* buffer used for XBZRLE encoding */
+    uint8_t *encoded_buf;
+    /* buffer for storing page content */
+    uint8_t *current_buf;
+    /* buffer used for XBZRLE decoding */
+    uint8_t *decoded_buf;
+    /* Cache for XBZRLE */
+    PageCache *cache;
+} XBZRLE = {
+    .encoded_buf = NULL,
+    .current_buf = NULL,
+    .decoded_buf = NULL,
+    .cache = NULL,
+};
+
 static void save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset,
         int cont, int flag)
 {
@@ -181,6 +201,53 @@ static void save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset,
 
 }
 
+#define ENCODING_FLAG_XBZRLE 0x1
+
+static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
+                            ram_addr_t current_addr, RAMBlock *block,
+                            ram_addr_t offset, int cont)
+{
+    int encoded_len = 0, bytes_sent = -1;
+    uint8_t *prev_cached_page;
+
+    if (!cache_is_cached(XBZRLE.cache, current_addr)) {
+        cache_insert(XBZRLE.cache, current_addr,
+                     g_memdup(current_data, TARGET_PAGE_SIZE));
+        return -1;
+    }
+
+    prev_cached_page = get_cached_data(XBZRLE.cache, current_addr);
+
+    /* save current buffer into memory */
+    memcpy(XBZRLE.current_buf, current_data, TARGET_PAGE_SIZE);
+
+    /* XBZRLE encoding (if there is no overflow) */
+    encoded_len = xbzrle_encode_buffer(prev_cached_page, XBZRLE.current_buf,
+                                       TARGET_PAGE_SIZE, XBZRLE.encoded_buf,
+                                       TARGET_PAGE_SIZE);
+    if (encoded_len == 0) {
+        DPRINTF("Skipping unmodified page\n");
+        return 0;
+    } else if (encoded_len == -1) {
+        DPRINTF("Overflow\n");
+        /* update data in the cache */
+        memcpy(prev_cached_page, current_data, TARGET_PAGE_SIZE);
+        return -1;
+    }
+
+    /* we need to update the data in the cache, in order to get the same data */
+    memcpy(prev_cached_page, XBZRLE.current_buf, TARGET_PAGE_SIZE);
+
+    /* Send XBZRLE based compressed page */
+    save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_XBZRLE);
+    qemu_put_byte(f, ENCODING_FLAG_XBZRLE);
+    qemu_put_be16(f, encoded_len);
+    qemu_put_buffer(f, XBZRLE.encoded_buf, encoded_len);
+    bytes_sent = encoded_len + 1 + 2;
+
+    return bytes_sent;
+}
+
 static RAMBlock *last_block;
 static ram_addr_t last_offset;
 
@@ -198,6 +265,7 @@ static int ram_save_block(QEMUFile *f)
     ram_addr_t offset = last_offset;
     int bytes_sent = -1;
     MemoryRegion *mr;
+    ram_addr_t current_addr;
 
     if (!block)
         block = QLIST_FIRST(&ram_list.blocks);
@@ -218,13 +286,24 @@ static int ram_save_block(QEMUFile *f)
                 save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_COMPRESS);
                 qemu_put_byte(f, *p);
                 bytes_sent = 1;
-            } else {
+            } else if (migrate_use_xbzrle()) {
+                current_addr = block->offset + offset;
+                bytes_sent = save_xbzrle_page(f, p, current_addr, block,
+                                              offset, cont);
+                p = get_cached_data(XBZRLE.cache, current_addr);
+            }
+
+            /* either we didn't send yet (we may have had XBZRLE overflow) */
+            if (bytes_sent == -1) {
                 save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_PAGE);
                 qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
                 bytes_sent = TARGET_PAGE_SIZE;
             }
 
-            break;
+            /* if page is unmodified, continue to the next */
+            if (bytes_sent != 0) {
+                break;
+            }
         }
 
         offset += TARGET_PAGE_SIZE;
@@ -302,6 +381,15 @@ static void sort_ram_list(void)
 static void migration_end(void)
 {
     memory_global_dirty_log_stop();
+
+    if (migrate_use_xbzrle()) {
+        cache_fini(XBZRLE.cache);
+        g_free(XBZRLE.cache);
+        g_free(XBZRLE.encoded_buf);
+        g_free(XBZRLE.current_buf);
+        g_free(XBZRLE.decoded_buf);
+        XBZRLE.cache = NULL;
+    }
 }
 
 static void ram_migration_cancel(void *opaque)
@@ -321,6 +409,18 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
     last_offset = 0;
     sort_ram_list();
 
+    if (migrate_use_xbzrle()) {
+        XBZRLE.cache = cache_init(migrate_xbzrle_cache_size() /
+                                  TARGET_PAGE_SIZE,
+                                  TARGET_PAGE_SIZE);
+        if (!XBZRLE.cache) {
+            DPRINTF("Error creating cache\n");
+            return -1;
+        }
+        XBZRLE.encoded_buf = g_malloc0(TARGET_PAGE_SIZE);
+        XBZRLE.current_buf = g_malloc(TARGET_PAGE_SIZE);
+    }
+
     /* Make sure all dirty bits are set */
     QLIST_FOREACH(block, &ram_list.blocks, next) {
         for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) {
@@ -436,6 +536,47 @@ static int ram_save_complete(QEMUFile *f, void *opaque)
     return 0;
 }
 
+static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host)
+{
+    int ret, rc = 0;
+    unsigned int xh_len;
+    int xh_flags;
+
+    if (!XBZRLE.decoded_buf) {
+        XBZRLE.decoded_buf = g_malloc(TARGET_PAGE_SIZE);
+    }
+
+    /* extract RLE header */
+    xh_flags = qemu_get_byte(f);
+    xh_len = qemu_get_be16(f);
+
+    if (xh_flags != ENCODING_FLAG_XBZRLE) {
+        fprintf(stderr, "Failed to load XBZRLE page - wrong compression!\n");
+        return -1;
+    }
+
+    if (xh_len > TARGET_PAGE_SIZE) {
+        fprintf(stderr, "Failed to load XBZRLE page - len overflow!\n");
+        return -1;
+    }
+    /* load data and decode */
+    qemu_get_buffer(f, XBZRLE.decoded_buf, xh_len);
+
+    /* decode RLE */
+    ret = xbzrle_decode_buffer(XBZRLE.decoded_buf, xh_len, host,
+                               TARGET_PAGE_SIZE);
+    if (ret == -1) {
+        fprintf(stderr, "Failed to load XBZRLE page - decode error!\n");
+        rc = -1;
+    } else  if (ret > TARGET_PAGE_SIZE) {
+        fprintf(stderr, "Failed to load XBZRLE page - size %d exceeds %d!\n",
+                ret, TARGET_PAGE_SIZE);
+        abort();
+    }
+
+    return rc;
+}
+
 static inline void *host_from_stream_offset(QEMUFile *f,
                                             ram_addr_t offset,
                                             int flags)
@@ -549,6 +690,19 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
             }
 
             qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
+        } else if (flags & RAM_SAVE_FLAG_XBZRLE) {
+            if (!migrate_use_xbzrle()) {
+                return -EINVAL;
+            }
+            void *host = host_from_stream_offset(f, addr, flags);
+            if (!host) {
+                return -EINVAL;
+            }
+
+            if (load_xbzrle(f, addr, host) < 0) {
+                ret = -EINVAL;
+                goto done;
+            }
         }
         error = qemu_file_get_error(f);
         if (error) {
diff --git a/migration.c b/migration.c
index e844290..167398a 100644
--- a/migration.c
+++ b/migration.c
@@ -43,6 +43,9 @@ enum {
 
 #define MAX_THROTTLE  (32 << 20)      /* Migration speed throttling */
 
+/* Migration XBZRLE default cache size */
+#define DEFAULT_MIGRATE_CACHE_SIZE (64 * 1024 * 1024)
+
 static NotifierList migration_state_notifiers =
     NOTIFIER_LIST_INITIALIZER(migration_state_notifiers);
 
@@ -55,6 +58,7 @@ static MigrationState *migrate_get_current(void)
     static MigrationState current_migration = {
         .state = MIG_STATE_SETUP,
         .bandwidth_limit = MAX_THROTTLE,
+        .xbzrle_cache_size = DEFAULT_MIGRATE_CACHE_SIZE,
     };
 
     return &current_migration;
@@ -422,6 +426,7 @@ static MigrationState *migrate_init(const MigrationParams *params)
     MigrationState *s = migrate_get_current();
     int64_t bandwidth_limit = s->bandwidth_limit;
     bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
+    int64_t xbzrle_cache_size = s->xbzrle_cache_size;
 
     memcpy(enabled_capabilities, s->enabled_capabilities,
            sizeof(enabled_capabilities));
@@ -431,6 +436,7 @@ static MigrationState *migrate_init(const MigrationParams *params)
     s->params = *params;
     memcpy(s->enabled_capabilities, enabled_capabilities,
            sizeof(enabled_capabilities));
+    s->xbzrle_cache_size = xbzrle_cache_size;
 
     s->state = MIG_STATE_SETUP;
     s->total_time = qemu_get_clock_ms(rt_clock);
@@ -529,3 +535,21 @@ void qmp_migrate_set_downtime(double value, Error **errp)
     value = MAX(0, MIN(UINT64_MAX, value));
     max_downtime = (uint64_t)value;
 }
+
+int migrate_use_xbzrle(void)
+{
+    MigrationState *s;
+
+    s = migrate_get_current();
+
+    return s->enabled_capabilities[MIGRATION_CAPABILITY_XBZRLE];
+}
+
+int64_t migrate_xbzrle_cache_size(void)
+{
+    MigrationState *s;
+
+    s = migrate_get_current();
+
+    return s->xbzrle_cache_size;
+}
diff --git a/migration.h b/migration.h
index 743c366..cdf6787 100644
--- a/migration.h
+++ b/migration.h
@@ -41,6 +41,7 @@ struct MigrationState
     MigrationParams params;
     int64_t total_time;
     bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
+    int64_t xbzrle_cache_size;
 };
 
 void process_incoming_migration(QEMUFile *f);
@@ -104,4 +105,7 @@ int xbzrle_encode_buffer(uint8_t *old_buf, uint8_t *new_buf, int slen,
                          uint8_t *dst, int dlen);
 int xbzrle_decode_buffer(uint8_t *src, int slen, uint8_t *dst, int dlen);
 
+int migrate_use_xbzrle(void);
+int64_t migrate_xbzrle_cache_size(void);
+
 #endif
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH 08/11] Add migrate_set_cachesize command
  2012-07-29  9:42 [Qemu-devel] [PATCH 00/11] Migration next v7 Orit Wasserman
                   ` (6 preceding siblings ...)
  2012-07-29  9:42 ` [Qemu-devel] [PATCH 07/11] Add XBZRLE to ram_save_block and ram_save_live Orit Wasserman
@ 2012-07-29  9:43 ` Orit Wasserman
  2012-07-29  9:43 ` [Qemu-devel] [PATCH 09/11] Add migration accounting for normal and duplicate pages Orit Wasserman
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 47+ messages in thread
From: Orit Wasserman @ 2012-07-29  9:43 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, aliguori, quintela, Petter Svard, stefanha, mdroth,
	Benoit Hudzia, lcapitulino, blauwirbel, Orit Wasserman,
	chegu_vinod, avi, Aidan Shribman, pbonzini, eblake

Change XBZRLE cache size in bytes (the size should be a power of 2, it will be
rounded down to the nearest power of 2).
If XBZRLE cache size is too small there will be many cache miss.

Signed-off-by: Benoit Hudzia <benoit.hudzia@sap.com>
Signed-off-by: Petter Svard <petters@cs.umu.se>
Signed-off-by: Aidan Shribman <aidan.shribman@sap.com>
Signed-off-by: Orit Wasserman <owasserm@redhat.com>
---
 arch_init.c      |   10 ++++++++++
 hmp-commands.hx  |   20 ++++++++++++++++++++
 hmp.c            |   13 +++++++++++++
 hmp.h            |    1 +
 migration.c      |   14 ++++++++++++++
 migration.h      |    2 ++
 qapi-schema.json |   16 ++++++++++++++++
 qmp-commands.hx  |   23 +++++++++++++++++++++++
 8 files changed, 99 insertions(+), 0 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index 410ba4d..d709ccb 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -189,6 +189,16 @@ static struct {
     .cache = NULL,
 };
 
+
+int64_t xbzrle_cache_resize(int64_t new_size)
+{
+    if (XBZRLE.cache != NULL) {
+        return cache_resize(XBZRLE.cache, new_size / TARGET_PAGE_SIZE) *
+            TARGET_PAGE_SIZE;
+    }
+    return pow2floor(new_size);
+}
+
 static void save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset,
         int cont, int flag)
 {
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 3e15338..cda3937 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -829,6 +829,26 @@ STEXI
 @item migrate_cancel
 @findex migrate_cancel
 Cancel the current VM migration.
+
+ETEXI
+
+    {
+        .name       = "migrate_set_cachesize",
+        .args_type  = "value:o",
+        .params     = "value",
+        .help       = "set cache size (in bytes) for XBZRLE migrations,"
+                      "the cache size will be rounded down to the nearest "
+                      "power of 2.\n"
+                      "The cache size affects the number of cache misses."
+                      "In case of a high cache miss ratio you need to increase"
+                      " the cache size",
+        .mhandler.cmd = hmp_migrate_set_cachesize,
+    },
+
+STEXI
+@item migrate_set_cachesize @var{value}
+@findex migrate_set_cachesize
+Set cache size to @var{value} (in bytes) for xbzrle migrations.
 ETEXI
 
     {
diff --git a/hmp.c b/hmp.c
index f2f63fd..9770d7b 100644
--- a/hmp.c
+++ b/hmp.c
@@ -784,6 +784,19 @@ void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict)
     qmp_migrate_set_downtime(value, NULL);
 }
 
+void hmp_migrate_set_cachesize(Monitor *mon, const QDict *qdict)
+{
+    int64_t value = qdict_get_int(qdict, "value");
+    Error *err = NULL;
+
+    qmp_migrate_set_cache_size(value, &err);
+    if (err) {
+        monitor_printf(mon, "%s\n", error_get_pretty(err));
+        error_free(err);
+        return;
+    }
+}
+
 void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict)
 {
     int64_t value = qdict_get_int(qdict, "value");
diff --git a/hmp.h b/hmp.h
index ceb2f06..a5c2e01 100644
--- a/hmp.h
+++ b/hmp.h
@@ -54,6 +54,7 @@ void hmp_migrate_cancel(Monitor *mon, const QDict *qdict);
 void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict);
 void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict);
 void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict);
+void hmp_migrate_set_cachesize(Monitor *mon, const QDict *qdict);
 void hmp_set_password(Monitor *mon, const QDict *qdict);
 void hmp_expire_password(Monitor *mon, const QDict *qdict);
 void hmp_eject(Monitor *mon, const QDict *qdict);
diff --git a/migration.c b/migration.c
index 167398a..bc2231d 100644
--- a/migration.c
+++ b/migration.c
@@ -516,6 +516,20 @@ void qmp_migrate_cancel(Error **errp)
     migrate_fd_cancel(migrate_get_current());
 }
 
+void qmp_migrate_set_cache_size(int64_t value, Error **errp)
+{
+    MigrationState *s = migrate_get_current();
+
+    /* Check for truncation */
+    if (value != (size_t)value) {
+        error_set(errp, QERR_INVALID_PARAMETER_VALUE, "cache size",
+                  "exceeding address space");
+        return;
+    }
+
+    s->xbzrle_cache_size = xbzrle_cache_resize(value);
+}
+
 void qmp_migrate_set_speed(int64_t value, Error **errp)
 {
     MigrationState *s;
diff --git a/migration.h b/migration.h
index cdf6787..337e225 100644
--- a/migration.h
+++ b/migration.h
@@ -108,4 +108,6 @@ int xbzrle_decode_buffer(uint8_t *src, int slen, uint8_t *dst, int dlen);
 int migrate_use_xbzrle(void);
 int64_t migrate_xbzrle_cache_size(void);
 
+int64_t xbzrle_cache_resize(int64_t new_size);
+
 #endif
diff --git a/qapi-schema.json b/qapi-schema.json
index 9d6759d..04adcee 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1412,6 +1412,22 @@
 { 'command': 'migrate_set_speed', 'data': {'value': 'int'} }
 
 ##
+# @migrate-set-cache-size
+#
+# Set XBZRLE cache size
+#
+# @value: cache size in bytes
+#
+# The size will be rounded down to the nearest power of 2.
+# The cache size can be modified before and during ongoing migration
+#
+# Returns: nothing on success
+#
+# Since: 1.2
+##
+{ 'command': 'migrate-set-cache-size', 'data': {'value': 'int'} }
+
+##
 # @ObjectPropertyInfo:
 #
 # @name: the name of the property
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 7f40e2a..cfc950e 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -520,6 +520,29 @@ Example:
 <- { "return": {} }
 
 EQMP
+{
+        .name       = "migrate-set-cache-size",
+        .args_type  = "value:o",
+        .mhandler.cmd_new = qmp_marshal_input_migrate_set_cache_size,
+    },
+
+SQMP
+migrate-set-cache-size
+---------------------
+
+Set cache size to be used by XBZRLE migration, the cache size will be rounded
+down to the nearest power of 2
+
+Arguments:
+
+- "value": cache size in bytes (json-int)
+
+Example:
+
+-> { "execute": "migrate-set-cache-size", "arguments": { "value": 536870912 } }
+<- { "return": {} }
+
+EQMP
 
     {
         .name       = "migrate_set_speed",
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH 09/11] Add migration accounting for normal and duplicate pages
  2012-07-29  9:42 [Qemu-devel] [PATCH 00/11] Migration next v7 Orit Wasserman
                   ` (7 preceding siblings ...)
  2012-07-29  9:43 ` [Qemu-devel] [PATCH 08/11] Add migrate_set_cachesize command Orit Wasserman
@ 2012-07-29  9:43 ` Orit Wasserman
  2012-07-30 19:30   ` Luiz Capitulino
  2012-07-29  9:43 ` [Qemu-devel] [PATCH 10/11] Add XBZRLE statistics Orit Wasserman
                   ` (2 subsequent siblings)
  11 siblings, 1 reply; 47+ messages in thread
From: Orit Wasserman @ 2012-07-29  9:43 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, aliguori, quintela, Petter Svard, stefanha, mdroth,
	Benoit Hudzia, lcapitulino, blauwirbel, Orit Wasserman,
	chegu_vinod, avi, Aidan Shribman, pbonzini, eblake

Signed-off-by: Benoit Hudzia <benoit.hudzia@sap.com>
Signed-off-by: Petter Svard <petters@cs.umu.se>
Signed-off-by: Aidan Shribman <aidan.shribman@sap.com>
Signed-off-by: Orit Wasserman <owasserm@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
 arch_init.c      |   38 ++++++++++++++++++++++++++++++++++++++
 migration.c      |    4 ++++
 migration.h      |    5 +++++
 qapi-schema.json |    8 ++++++--
 qmp-commands.hx  |   14 +++++++++++---
 5 files changed, 64 insertions(+), 5 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index d709ccb..7f12317 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -199,6 +199,40 @@ int64_t xbzrle_cache_resize(int64_t new_size)
     return pow2floor(new_size);
 }
 
+/* accounting for migration statistics */
+typedef struct AccountingInfo {
+    uint64_t dup_pages;
+    uint64_t norm_pages;
+    uint64_t iterations;
+} 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;
+}
+
 static void save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset,
         int cont, int flag)
 {
@@ -293,6 +327,7 @@ static int ram_save_block(QEMUFile *f)
             p = memory_region_get_ram_ptr(mr) + offset;
 
             if (is_dup_page(p)) {
+                acct_info.dup_pages++;
                 save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_COMPRESS);
                 qemu_put_byte(f, *p);
                 bytes_sent = 1;
@@ -308,6 +343,7 @@ static int ram_save_block(QEMUFile *f)
                 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++;
             }
 
             /* if page is unmodified, continue to the next */
@@ -429,6 +465,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
         }
         XBZRLE.encoded_buf = g_malloc0(TARGET_PAGE_SIZE);
         XBZRLE.current_buf = g_malloc(TARGET_PAGE_SIZE);
+        acct_clear();
     }
 
     /* Make sure all dirty bits are set */
@@ -477,6 +514,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque)
             break;
         }
         bytes_transferred += bytes_sent;
+        acct_info.iterations++;
         /* we want to check in the 1st loop, just in case it was the 1st time
            and we had to sync the dirty bitmap.
            qemu_get_clock_ns() is a bit expensive, so we only check each some
diff --git a/migration.c b/migration.c
index bc2231d..4dc99ba 100644
--- a/migration.c
+++ b/migration.c
@@ -156,6 +156,8 @@ MigrationInfo *qmp_query_migrate(Error **errp)
         info->ram->total = ram_bytes_total();
         info->ram->total_time = qemu_get_clock_ms(rt_clock)
             - s->total_time;
+        info->ram->duplicate = dup_mig_pages_transferred();
+        info->ram->normal = norm_mig_pages_transferred();
 
         if (blk_mig_active()) {
             info->has_disk = true;
@@ -175,6 +177,8 @@ MigrationInfo *qmp_query_migrate(Error **errp)
         info->ram->remaining = 0;
         info->ram->total = ram_bytes_total();
         info->ram->total_time = s->total_time;
+        info->ram->duplicate = dup_mig_pages_transferred();
+        info->ram->normal = norm_mig_pages_transferred();
         break;
     case MIG_STATE_ERROR:
         info->has_status = true;
diff --git a/migration.h b/migration.h
index 337e225..e4a7cd7 100644
--- a/migration.h
+++ b/migration.h
@@ -87,6 +87,11 @@ uint64_t ram_bytes_total(void);
 
 extern SaveVMHandlers savevm_ram_handlers;
 
+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);
+
 /**
  * @migrate_add_blocker - prevent migration from proceeding
  *
diff --git a/qapi-schema.json b/qapi-schema.json
index 04adcee..a936714 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -264,11 +264,15 @@
 #        migration has ended, it returns the total migration
 #        time. (since 1.2)
 #
-# Since: 0.14.0.
+# @duplicate: number of duplicate pages (since 1.2)
+#
+# @normal : number of normal pages (since 1.2)
+#
+# Since: 0.14.0
 ##
 { 'type': 'MigrationStats',
   'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int' ,
-           'total_time': 'int' } }
+           'total_time': 'int', 'duplicate': 'int', 'normal': 'int' } }
 
 ##
 # @MigrationInfo
diff --git a/qmp-commands.hx b/qmp-commands.hx
index cfc950e..a5a67eb 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2099,6 +2099,8 @@ The main json-object contains the following:
          - "transferred": amount transferred (json-int)
          - "remaining": amount remaining (json-int)
          - "total": total (json-int)
+	 - "duplicate": number of duplicated pages (json-int)
+	 - "normal" : number of normal pages transferred (json-int)
 - "disk": only present if "status" is "active" and it is a block migration,
   it is a json-object with the following disk information (in bytes):
          - "transferred": amount transferred (json-int)
@@ -2119,7 +2121,9 @@ Examples:
         "ram":{
           "transferred":123,
           "remaining":123,
-          "total":246
+          "total":246,
+          "duplicate":123,
+          "normal":123
         }
      }
    }
@@ -2138,7 +2142,9 @@ Examples:
          "ram":{
             "transferred":123,
             "remaining":123,
-            "total":246
+            "total":246,
+            "duplicate":123,
+            "normal":123
          }
       }
    }
@@ -2152,7 +2158,9 @@ Examples:
          "ram":{
             "total":1057024,
             "remaining":1053304,
-            "transferred":3720
+            "transferred":3720,
+            "duplicate":123,
+            "normal":123
          },
          "disk":{
             "total":20971520,
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH 10/11] Add XBZRLE statistics
  2012-07-29  9:42 [Qemu-devel] [PATCH 00/11] Migration next v7 Orit Wasserman
                   ` (8 preceding siblings ...)
  2012-07-29  9:43 ` [Qemu-devel] [PATCH 09/11] Add migration accounting for normal and duplicate pages Orit Wasserman
@ 2012-07-29  9:43 ` Orit Wasserman
  2012-07-30 19:37   ` Luiz Capitulino
  2012-07-29  9:43 ` [Qemu-devel] [PATCH 11/11] Restart optimization on stage3 update version Orit Wasserman
  2012-07-30 19:38 ` [Qemu-devel] [PATCH 00/11] Migration next v7 Luiz Capitulino
  11 siblings, 1 reply; 47+ messages in thread
From: Orit Wasserman @ 2012-07-29  9:43 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, aliguori, quintela, Petter Svard, stefanha, mdroth,
	Benoit Hudzia, lcapitulino, blauwirbel, Orit Wasserman,
	chegu_vinod, avi, Aidan Shribman, pbonzini, eblake

Signed-off-by: Benoit Hudzia <benoit.hudzia@sap.com>
Signed-off-by: Petter Svard <petters@cs.umu.se>
Signed-off-by: Aidan Shribman <aidan.shribman@sap.com>
Signed-off-by: Orit Wasserman <owasserm@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
 arch_init.c      |   28 ++++++++++++++++++++++++++++
 hmp.c            |   21 +++++++++++++++++++++
 migration.c      |   28 ++++++++++++++++++++++++++++
 migration.h      |    4 ++++
 qapi-schema.json |   32 +++++++++++++++++++++++++++++++-
 qmp-commands.hx  |   35 +++++++++++++++++++++++++++++++++++
 6 files changed, 147 insertions(+), 1 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index 7f12317..9833d54 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -203,7 +203,11 @@ int64_t xbzrle_cache_resize(int64_t new_size)
 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;
@@ -233,6 +237,26 @@ 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;
+}
+
 static void save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset,
         int cont, int flag)
 {
@@ -257,6 +281,7 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
     if (!cache_is_cached(XBZRLE.cache, current_addr)) {
         cache_insert(XBZRLE.cache, current_addr,
                      g_memdup(current_data, TARGET_PAGE_SIZE));
+        acct_info.xbzrle_cache_miss++;
         return -1;
     }
 
@@ -274,6 +299,7 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
         return 0;
     } else if (encoded_len == -1) {
         DPRINTF("Overflow\n");
+        acct_info.xbzrle_overflows++;
         /* update data in the cache */
         memcpy(prev_cached_page, current_data, TARGET_PAGE_SIZE);
         return -1;
@@ -288,6 +314,8 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
     qemu_put_be16(f, encoded_len);
     qemu_put_buffer(f, XBZRLE.encoded_buf, encoded_len);
     bytes_sent = encoded_len + 1 + 2;
+    acct_info.xbzrle_pages++;
+    acct_info.xbzrle_bytes += bytes_sent;
 
     return bytes_sent;
 }
diff --git a/hmp.c b/hmp.c
index 9770d7b..383d5b1 100644
--- a/hmp.c
+++ b/hmp.c
@@ -172,6 +172,27 @@ void hmp_info_migrate(Monitor *mon)
                        info->disk->total >> 10);
     }
 
+    if (info->has_xbzrle_cache) {
+        monitor_printf(mon, "cache size: %" PRIu64 " bytes\n",
+                       info->xbzrle_cache->cache_size);
+        if (info->xbzrle_cache->has_xbzrle_bytes) {
+            monitor_printf(mon, "xbzrle transferred: %" PRIu64 " kbytes\n",
+                           info->xbzrle_cache->xbzrle_bytes >> 10);
+        }
+        if (info->xbzrle_cache->has_xbzrle_pages) {
+            monitor_printf(mon, "xbzrle pages: %" PRIu64 " pages\n",
+                           info->xbzrle_cache->xbzrle_pages);
+        }
+        if (info->xbzrle_cache->has_xbzrle_cache_miss) {
+            monitor_printf(mon, "xbzrle cache miss: %" PRIu64 "\n",
+                           info->xbzrle_cache->xbzrle_cache_miss);
+        }
+        if (info->xbzrle_cache->has_xbzrle_overflow) {
+            monitor_printf(mon, "xbzrle overflow : %" PRIu64 "\n",
+                           info->xbzrle_cache->xbzrle_overflow);
+        }
+    }
+
     qapi_free_MigrationInfo(info);
     qapi_free_MigrationParameters(params);
 }
diff --git a/migration.c b/migration.c
index 4dc99ba..fb802bc 100644
--- a/migration.c
+++ b/migration.c
@@ -136,6 +136,23 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp)
     return params;
 }
 
+static void get_xbzrle_cache_stats(MigrationInfo *info)
+{
+    if (migrate_use_xbzrle()) {
+        info->has_xbzrle_cache = true;
+        info->xbzrle_cache = g_malloc0(sizeof(*info->xbzrle_cache));
+        info->xbzrle_cache->cache_size = migrate_xbzrle_cache_size();
+        info->xbzrle_cache->has_xbzrle_bytes = true;
+        info->xbzrle_cache->xbzrle_bytes = xbzrle_mig_bytes_transferred();
+        info->xbzrle_cache->has_xbzrle_pages = true;
+        info->xbzrle_cache->xbzrle_pages = xbzrle_mig_pages_transferred();
+        info->xbzrle_cache->has_xbzrle_cache_miss = true;
+        info->xbzrle_cache->xbzrle_cache_miss = xbzrle_mig_pages_cache_miss();
+        info->xbzrle_cache->has_xbzrle_overflow = true;
+        info->xbzrle_cache->xbzrle_overflow = xbzrle_mig_pages_overflow();
+    }
+}
+
 MigrationInfo *qmp_query_migrate(Error **errp)
 {
     MigrationInfo *info = g_malloc0(sizeof(*info));
@@ -144,6 +161,13 @@ MigrationInfo *qmp_query_migrate(Error **errp)
     switch (s->state) {
     case MIG_STATE_SETUP:
         /* no migration has happened ever */
+
+        /* display xbzrle cache size */
+        if (migrate_use_xbzrle()) {
+            info->has_xbzrle_cache = true;
+            info->xbzrle_cache = g_malloc0(sizeof(*info->xbzrle_cache));
+            info->xbzrle_cache->cache_size = migrate_xbzrle_cache_size();
+        }
         break;
     case MIG_STATE_ACTIVE:
         info->has_status = true;
@@ -166,8 +190,12 @@ MigrationInfo *qmp_query_migrate(Error **errp)
             info->disk->remaining = blk_mig_bytes_remaining();
             info->disk->total = blk_mig_bytes_total();
         }
+
+        get_xbzrle_cache_stats(info);
         break;
     case MIG_STATE_COMPLETED:
+        get_xbzrle_cache_stats(info);
+
         info->has_status = true;
         info->status = g_strdup("completed");
 
diff --git a/migration.h b/migration.h
index e4a7cd7..a9852fc 100644
--- a/migration.h
+++ b/migration.h
@@ -91,6 +91,10 @@ 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);
 
 /**
  * @migrate_add_blocker - prevent migration from proceeding
diff --git a/qapi-schema.json b/qapi-schema.json
index a936714..91dee72 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -275,6 +275,31 @@
            'total_time': 'int', 'duplicate': 'int', 'normal': 'int' } }
 
 ##
+# @XBZRLECacheStats
+#
+# Detailed XBZRLE migration cache statistics
+#
+# @cache-size: XBZRLE cache size
+#
+# @xbzrle-bytes: @optional, amount of bytes already transferred to the target VM
+#                only returned when migration is active or completed
+#
+# @xbzrle-pages: @optional, amount of pages transferred to the target VM
+#                only returned when migration is active or completed
+#
+# @xbzrle-cache-miss: @optional, number of cache miss
+#                     only returned when migration is active or completed
+#
+# @xbzrle-overflow: @optional, number of overflows
+#                   only returned when migration is active or completed
+#
+# Since: 1.2
+##
+{ 'type': 'XBZRLECacheStats',
+  'data': {'cache-size': 'int', '*xbzrle-bytes': 'int', '*xbzrle-pages': 'int',
+           '*xbzrle-cache-miss': 'int', '*xbzrle-overflow': 'int' } }
+
+##
 # @MigrationInfo
 #
 # Information about current migration process.
@@ -292,11 +317,16 @@
 #        status, only returned if status is 'active' and it is a block
 #        migration
 #
+# @xbzrle-cache: #optional @XBZRLECacheStats containing detailed XBZRLE
+#                migration statistics, only returned if XBZRLE feature is on
+#                (since 1.2)
+#
 # Since: 0.14.0
 ##
 { 'type': 'MigrationInfo',
   'data': {'*status': 'str', '*ram': 'MigrationStats',
-           '*disk': 'MigrationStats'} }
+           '*disk': 'MigrationStats',
+           '*xbzrle-cache': 'XBZRLECacheStats'} }
 
 ##
 # @query-migrate
diff --git a/qmp-commands.hx b/qmp-commands.hx
index a5a67eb..0546f42 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2106,6 +2106,17 @@ The main json-object contains the following:
          - "transferred": amount transferred (json-int)
          - "remaining": amount remaining (json-int)
          - "total": total (json-int)
+- "xbzrle-cache": only present if XBZRLE is active.
+  It is a json-object with the following XBZRLE information:
+         - "cache-size": XBZRLE cache size
+         - "xbzrle-bytes": total XBZRLE bytes transferred, only present if
+                           status is "active" or "completed"
+         - "xbzrle-pages": number of XBZRLE compressed pages, only present if
+                           status is "active" or "completed"
+         - "cache-miss": number of cache misses, only present if
+                           status is "active" or "completed"
+         - "overflow": number of XBZRLE overflows, only present if
+                           status is "active" or "completed"
 Examples:
 
 1. Before the first migration
@@ -2170,6 +2181,30 @@ Examples:
       }
    }
 
+6. Migration is being performed and XBZRLE is active:
+
+-> { "execute": "query-migrate" }
+<- {
+      "return":{
+         "status":"active",
+         "capabilities" : [ { "capability": "xbzrle", "state" : true } ],
+         "ram":{
+            "total":1057024,
+            "remaining":1053304,
+            "transferred":3720,
+            "duplicate": 10,
+            "normal" : 3333
+         },
+         "cache":{
+            "cache-size": 1024
+            "xbzrle-transferred":20971520,
+            "xbzrle-pages":2444343,
+            "xbzrle-cache-miss":2244,
+            "xbzrle-overflow":34434
+         }
+      }
+   }
+
 EQMP
 
     {
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH 11/11] Restart optimization on stage3 update version
  2012-07-29  9:42 [Qemu-devel] [PATCH 00/11] Migration next v7 Orit Wasserman
                   ` (9 preceding siblings ...)
  2012-07-29  9:43 ` [Qemu-devel] [PATCH 10/11] Add XBZRLE statistics Orit Wasserman
@ 2012-07-29  9:43 ` Orit Wasserman
  2012-07-30 19:38 ` [Qemu-devel] [PATCH 00/11] Migration next v7 Luiz Capitulino
  11 siblings, 0 replies; 47+ messages in thread
From: Orit Wasserman @ 2012-07-29  9:43 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, aliguori, quintela, stefanha, mdroth, lcapitulino,
	blauwirbel, chegu_vinod, avi, pbonzini, eblake

From: Juan Quintela <quintela@redhat.com>

Signed-off-by: Juan Quintela <quintela@redhat.com>
---
 arch_init.c |   24 +++++++++++++++---------
 1 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index 9833d54..21031d1 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -273,14 +273,16 @@ static void save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset,
 
 static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
                             ram_addr_t current_addr, RAMBlock *block,
-                            ram_addr_t offset, int cont)
+                            ram_addr_t offset, int cont, bool last_stage)
 {
     int encoded_len = 0, bytes_sent = -1;
     uint8_t *prev_cached_page;
 
     if (!cache_is_cached(XBZRLE.cache, current_addr)) {
-        cache_insert(XBZRLE.cache, current_addr,
-                     g_memdup(current_data, TARGET_PAGE_SIZE));
+        if (!last_stage) {
+            cache_insert(XBZRLE.cache, current_addr,
+                         g_memdup(current_data, TARGET_PAGE_SIZE));
+        }
         acct_info.xbzrle_cache_miss++;
         return -1;
     }
@@ -306,7 +308,9 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
     }
 
     /* we need to update the data in the cache, in order to get the same data */
-    memcpy(prev_cached_page, XBZRLE.current_buf, TARGET_PAGE_SIZE);
+    if (!last_stage) {
+        memcpy(prev_cached_page, XBZRLE.current_buf, TARGET_PAGE_SIZE);
+    }
 
     /* Send XBZRLE based compressed page */
     save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_XBZRLE);
@@ -331,7 +335,7 @@ static ram_addr_t last_offset;
  *           n: the amount of bytes written in other case
  */
 
-static int ram_save_block(QEMUFile *f)
+static int ram_save_block(QEMUFile *f, bool last_stage)
 {
     RAMBlock *block = last_block;
     ram_addr_t offset = last_offset;
@@ -362,8 +366,10 @@ static int ram_save_block(QEMUFile *f)
             } else if (migrate_use_xbzrle()) {
                 current_addr = block->offset + offset;
                 bytes_sent = save_xbzrle_page(f, p, current_addr, block,
-                                              offset, cont);
-                p = get_cached_data(XBZRLE.cache, current_addr);
+                                              offset, cont, last_stage);
+                if (!last_stage) {
+                    p = get_cached_data(XBZRLE.cache, current_addr);
+                }
             }
 
             /* either we didn't send yet (we may have had XBZRLE overflow) */
@@ -536,7 +542,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque)
     while ((ret = qemu_file_rate_limit(f)) == 0) {
         int bytes_sent;
 
-        bytes_sent = ram_save_block(f);
+        bytes_sent = ram_save_block(f, false);
         /* no more blocks to sent */
         if (bytes_sent < 0) {
             break;
@@ -598,7 +604,7 @@ static int ram_save_complete(QEMUFile *f, void *opaque)
     while (true) {
         int bytes_sent;
 
-        bytes_sent = ram_save_block(f);
+        bytes_sent = ram_save_block(f, true);
         /* no more blocks to sent */
         if (bytes_sent < 0) {
             break;
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 01/11] Add migration capabilities
  2012-07-29  9:42 ` [Qemu-devel] [PATCH 01/11] Add migration capabilities Orit Wasserman
@ 2012-07-30 17:24   ` Luiz Capitulino
  2012-07-30 17:29     ` Luiz Capitulino
  2012-07-30 17:45   ` Eric Blake
  1 sibling, 1 reply; 47+ messages in thread
From: Luiz Capitulino @ 2012-07-30 17:24 UTC (permalink / raw)
  To: Orit Wasserman
  Cc: peter.maydell, aliguori, quintela, stefanha, qemu-devel, mdroth,
	blauwirbel, chegu_vinod, avi, pbonzini, eblake

On Sun, 29 Jul 2012 12:42:53 +0300
Orit Wasserman <owasserm@redhat.com> wrote:

> Add migration capabilities that can be queried by the management.
> The management can query the source QEMU and the destination QEMU in order to
> verify both support some migration capability (currently only XBZRLE).
> 
> Signed-off-by: Orit Wasserman <owasserm@redhat.com>
> Signed-off-by: Juan Quintela <quintela@redhat.com>
> ---
>  hmp-commands.hx  |    2 ++
>  hmp.c            |   19 +++++++++++++++++++
>  hmp.h            |    1 +
>  migration.c      |   11 +++++++++++
>  monitor.c        |    7 +++++++
>  qapi-schema.json |   39 +++++++++++++++++++++++++++++++++++++++
>  qmp-commands.hx  |   24 ++++++++++++++++++++++++
>  7 files changed, 103 insertions(+), 0 deletions(-)
> 
> diff --git a/hmp-commands.hx b/hmp-commands.hx
> index eea8b32..8786148 100644
> --- a/hmp-commands.hx
> +++ b/hmp-commands.hx
> @@ -1417,6 +1417,8 @@ show CPU statistics
>  show user network stack connection states
>  @item info migrate
>  show migration status
> +@item info migration_capabilities
> +show migration capabilities
>  @item info balloon
>  show balloon information
>  @item info qtree
> diff --git a/hmp.c b/hmp.c
> index 6b72a64..5c7d0be 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -161,6 +161,25 @@ void hmp_info_migrate(Monitor *mon)
>      qapi_free_MigrationInfo(info);
>  }
>  
> +void hmp_info_migration_capabilities(Monitor *mon)
> +{
> +    MigrationCapabilityStatusList *caps_list, *cap;
> +
> +    caps_list = qmp_query_migration_capabilities(NULL);
> +    if (!caps_list) {
> +        monitor_printf(mon, "No migration capabilities found\n");
> +        return;
> +    }
> +
> +    for (cap = caps_list; cap; cap = cap->next) {
> +        monitor_printf(mon, "%s: %s ",
> +                       MigrationCapability_lookup[cap->value->capability],
> +                       cap->value->state ? "on" : "off");
> +    }
> +
> +    qapi_free_MigrationCapabilityStatusList(caps_list);
> +}
> +
>  void hmp_info_cpus(Monitor *mon)
>  {
>      CpuInfoList *cpu_list, *cpu;
> diff --git a/hmp.h b/hmp.h
> index 8d2b0d7..2fb44ca 100644
> --- a/hmp.h
> +++ b/hmp.h
> @@ -25,6 +25,7 @@ void hmp_info_uuid(Monitor *mon);
>  void hmp_info_chardev(Monitor *mon);
>  void hmp_info_mice(Monitor *mon);
>  void hmp_info_migrate(Monitor *mon);
> +void hmp_info_migration_capabilities(Monitor *mon);
>  void hmp_info_cpus(Monitor *mon);
>  void hmp_info_block(Monitor *mon);
>  void hmp_info_blockstats(Monitor *mon);
> diff --git a/migration.c b/migration.c
> index 8db1b43..8c27347 100644
> --- a/migration.c
> +++ b/migration.c
> @@ -166,6 +166,17 @@ MigrationInfo *qmp_query_migrate(Error **errp)
>      return info;
>  }
>  
> +MigrationCapabilityStatusList *qmp_query_migration_capabilities(Error **errp)
> +{
> +    MigrationCapabilityStatusList *caps_list = g_malloc0(sizeof(*caps_list));
> +
> +    caps_list->value = g_malloc(sizeof(*caps_list->value));
> +    caps_list->value->capability = MIGRATION_CAPABILITY_XBZRLE;
> +    caps_list->next = NULL;
> +
> +    return caps_list;
> +}

This is missing an entry in qmp-commands.hx, otherwise looks good.

> +
>  /* shared migration helpers */
>  
>  static int migrate_fd_cleanup(MigrationState *s)
> diff --git a/monitor.c b/monitor.c
> index 09aa3cd..fd57c5e 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -2662,6 +2662,13 @@ static mon_cmd_t info_cmds[] = {
>          .mhandler.info = hmp_info_migrate,
>      },
>      {
> +        .name       = "migration-capabilities",
> +        .args_type  = "",
> +        .params     = "",
> +        .help       = "show migration capabilities",
> +        .mhandler.info = hmp_info_migration_capabilities,
> +    },
> +    {
>          .name       = "balloon",
>          .args_type  = "",
>          .params     = "",
> diff --git a/qapi-schema.json b/qapi-schema.json
> index a92adb1..b4d4dd6 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -306,6 +306,45 @@
>  { 'command': 'query-migrate', 'returns': 'MigrationInfo' }
>  
>  ##
> +# @MigrationCapability
> +#
> +# Migration capabilities enumeration
> +#
> +# @xbzrle: Migration supports xbzrle (Xor Based Zero Length Encoding).
> +#          This feature allows us to minimize migration traffic for certain work
> +#          loads, by sending compressed difference of the pages
> +#
> +# Since: 1.2
> +##
> +{ 'enum': 'MigrationCapability',
> +  'data': ['xbzrle'] }
> +
> +##
> +# @MigrationCapabilityStatus
> +#
> +# Migration capability information
> +#
> +# @capability: capability enum
> +#
> +# @state: capability state bool
> +#
> +# Since: 1.2
> +##
> +{ 'type': 'MigrationCapabilityStatus',
> +  'data': { 'capability' : 'MigrationCapability', 'state' : 'bool' } }
> +
> +##
> +# @query-migration-capabilities
> +#
> +# Returns information about current migration process capabilities.
> +#
> +# Returns: @MigrationCapabilityStatus list
> +#
> +# Since: 1.2
> +##
> +{ 'command': 'query-migration-capabilities', 'returns': ['MigrationCapabilityStatus'] }
> +
> +##
>  # @MouseInfo:
>  #
>  # Information about a mouse device.
> diff --git a/qmp-commands.hx b/qmp-commands.hx
> index e3cf3c5..c0ed14c 100644
> --- a/qmp-commands.hx
> +++ b/qmp-commands.hx
> @@ -2141,6 +2141,30 @@ EQMP
>      },
>  
>  SQMP
> +query-migration-capabilities
> +-------
> +
> +Query migration capabilities
> +
> +- "xbzrle": xbzrle support
> +
> +Arguments:
> +
> +Example:
> +
> +-> { "execute": "query-migration-capabilities"}
> +<- { "return": [ { "capability": "xbzrle", "state": true },
> +                 { "capability": "foobar", "state": false } ] }
> +
> +EQMP
> +
> +    {
> +        .name       = "query-migration-capabilities",
> +        .args_type  = "",
> +	.mhandler.cmd_new = qmp_marshal_input_query_migration_capabilities,
> +    },
> +
> +SQMP
>  query-balloon
>  -------------
>  

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 01/11] Add migration capabilities
  2012-07-30 17:24   ` Luiz Capitulino
@ 2012-07-30 17:29     ` Luiz Capitulino
  0 siblings, 0 replies; 47+ messages in thread
From: Luiz Capitulino @ 2012-07-30 17:29 UTC (permalink / raw)
  To: Luiz Capitulino
  Cc: peter.maydell, aliguori, quintela, stefanha, qemu-devel, mdroth,
	blauwirbel, Orit Wasserman, chegu_vinod, avi, pbonzini, eblake

On Mon, 30 Jul 2012 14:24:18 -0300
Luiz Capitulino <lcapitulino@redhat.com> wrote:

> On Sun, 29 Jul 2012 12:42:53 +0300
> Orit Wasserman <owasserm@redhat.com> wrote:
> 
> > Add migration capabilities that can be queried by the management.
> > The management can query the source QEMU and the destination QEMU in order to
> > verify both support some migration capability (currently only XBZRLE).
> > 
> > Signed-off-by: Orit Wasserman <owasserm@redhat.com>
> > Signed-off-by: Juan Quintela <quintela@redhat.com>
> > ---
> >  hmp-commands.hx  |    2 ++
> >  hmp.c            |   19 +++++++++++++++++++
> >  hmp.h            |    1 +
> >  migration.c      |   11 +++++++++++
> >  monitor.c        |    7 +++++++
> >  qapi-schema.json |   39 +++++++++++++++++++++++++++++++++++++++
> >  qmp-commands.hx  |   24 ++++++++++++++++++++++++
> >  7 files changed, 103 insertions(+), 0 deletions(-)
> > 
> > diff --git a/hmp-commands.hx b/hmp-commands.hx
> > index eea8b32..8786148 100644
> > --- a/hmp-commands.hx
> > +++ b/hmp-commands.hx
> > @@ -1417,6 +1417,8 @@ show CPU statistics
> >  show user network stack connection states
> >  @item info migrate
> >  show migration status
> > +@item info migration_capabilities
> > +show migration capabilities
> >  @item info balloon
> >  show balloon information
> >  @item info qtree
> > diff --git a/hmp.c b/hmp.c
> > index 6b72a64..5c7d0be 100644
> > --- a/hmp.c
> > +++ b/hmp.c
> > @@ -161,6 +161,25 @@ void hmp_info_migrate(Monitor *mon)
> >      qapi_free_MigrationInfo(info);
> >  }
> >  
> > +void hmp_info_migration_capabilities(Monitor *mon)
> > +{
> > +    MigrationCapabilityStatusList *caps_list, *cap;
> > +
> > +    caps_list = qmp_query_migration_capabilities(NULL);
> > +    if (!caps_list) {
> > +        monitor_printf(mon, "No migration capabilities found\n");
> > +        return;
> > +    }
> > +
> > +    for (cap = caps_list; cap; cap = cap->next) {
> > +        monitor_printf(mon, "%s: %s ",
> > +                       MigrationCapability_lookup[cap->value->capability],
> > +                       cap->value->state ? "on" : "off");
> > +    }
> > +
> > +    qapi_free_MigrationCapabilityStatusList(caps_list);
> > +}
> > +
> >  void hmp_info_cpus(Monitor *mon)
> >  {
> >      CpuInfoList *cpu_list, *cpu;
> > diff --git a/hmp.h b/hmp.h
> > index 8d2b0d7..2fb44ca 100644
> > --- a/hmp.h
> > +++ b/hmp.h
> > @@ -25,6 +25,7 @@ void hmp_info_uuid(Monitor *mon);
> >  void hmp_info_chardev(Monitor *mon);
> >  void hmp_info_mice(Monitor *mon);
> >  void hmp_info_migrate(Monitor *mon);
> > +void hmp_info_migration_capabilities(Monitor *mon);
> >  void hmp_info_cpus(Monitor *mon);
> >  void hmp_info_block(Monitor *mon);
> >  void hmp_info_blockstats(Monitor *mon);
> > diff --git a/migration.c b/migration.c
> > index 8db1b43..8c27347 100644
> > --- a/migration.c
> > +++ b/migration.c
> > @@ -166,6 +166,17 @@ MigrationInfo *qmp_query_migrate(Error **errp)
> >      return info;
> >  }
> >  
> > +MigrationCapabilityStatusList *qmp_query_migration_capabilities(Error **errp)
> > +{
> > +    MigrationCapabilityStatusList *caps_list = g_malloc0(sizeof(*caps_list));
> > +
> > +    caps_list->value = g_malloc(sizeof(*caps_list->value));
> > +    caps_list->value->capability = MIGRATION_CAPABILITY_XBZRLE;
> > +    caps_list->next = NULL;
> > +
> > +    return caps_list;
> > +}
> 
> This is missing an entry in qmp-commands.hx, otherwise looks good.

It's actually there, so:

 Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>

> 
> > +
> >  /* shared migration helpers */
> >  
> >  static int migrate_fd_cleanup(MigrationState *s)
> > diff --git a/monitor.c b/monitor.c
> > index 09aa3cd..fd57c5e 100644
> > --- a/monitor.c
> > +++ b/monitor.c
> > @@ -2662,6 +2662,13 @@ static mon_cmd_t info_cmds[] = {
> >          .mhandler.info = hmp_info_migrate,
> >      },
> >      {
> > +        .name       = "migration-capabilities",
> > +        .args_type  = "",
> > +        .params     = "",
> > +        .help       = "show migration capabilities",
> > +        .mhandler.info = hmp_info_migration_capabilities,
> > +    },
> > +    {
> >          .name       = "balloon",
> >          .args_type  = "",
> >          .params     = "",
> > diff --git a/qapi-schema.json b/qapi-schema.json
> > index a92adb1..b4d4dd6 100644
> > --- a/qapi-schema.json
> > +++ b/qapi-schema.json
> > @@ -306,6 +306,45 @@
> >  { 'command': 'query-migrate', 'returns': 'MigrationInfo' }
> >  
> >  ##
> > +# @MigrationCapability
> > +#
> > +# Migration capabilities enumeration
> > +#
> > +# @xbzrle: Migration supports xbzrle (Xor Based Zero Length Encoding).
> > +#          This feature allows us to minimize migration traffic for certain work
> > +#          loads, by sending compressed difference of the pages
> > +#
> > +# Since: 1.2
> > +##
> > +{ 'enum': 'MigrationCapability',
> > +  'data': ['xbzrle'] }
> > +
> > +##
> > +# @MigrationCapabilityStatus
> > +#
> > +# Migration capability information
> > +#
> > +# @capability: capability enum
> > +#
> > +# @state: capability state bool
> > +#
> > +# Since: 1.2
> > +##
> > +{ 'type': 'MigrationCapabilityStatus',
> > +  'data': { 'capability' : 'MigrationCapability', 'state' : 'bool' } }
> > +
> > +##
> > +# @query-migration-capabilities
> > +#
> > +# Returns information about current migration process capabilities.
> > +#
> > +# Returns: @MigrationCapabilityStatus list
> > +#
> > +# Since: 1.2
> > +##
> > +{ 'command': 'query-migration-capabilities', 'returns': ['MigrationCapabilityStatus'] }
> > +
> > +##
> >  # @MouseInfo:
> >  #
> >  # Information about a mouse device.
> > diff --git a/qmp-commands.hx b/qmp-commands.hx
> > index e3cf3c5..c0ed14c 100644
> > --- a/qmp-commands.hx
> > +++ b/qmp-commands.hx
> > @@ -2141,6 +2141,30 @@ EQMP
> >      },
> >  
> >  SQMP
> > +query-migration-capabilities
> > +-------
> > +
> > +Query migration capabilities
> > +
> > +- "xbzrle": xbzrle support
> > +
> > +Arguments:
> > +
> > +Example:
> > +
> > +-> { "execute": "query-migration-capabilities"}
> > +<- { "return": [ { "capability": "xbzrle", "state": true },
> > +                 { "capability": "foobar", "state": false } ] }
> > +
> > +EQMP
> > +
> > +    {
> > +        .name       = "query-migration-capabilities",
> > +        .args_type  = "",
> > +	.mhandler.cmd_new = qmp_marshal_input_query_migration_capabilities,
> > +    },
> > +
> > +SQMP
> >  query-balloon
> >  -------------
> >  
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 02/11] Add migrate_set_parameter and query-migrate-parameters
  2012-07-29  9:42 ` [Qemu-devel] [PATCH 02/11] Add migrate_set_parameter and query-migrate-parameters Orit Wasserman
@ 2012-07-30 17:41   ` Luiz Capitulino
  2012-07-31  7:46     ` Orit Wasserman
  2012-07-31  8:03     ` Orit Wasserman
  2012-07-30 18:11   ` Eric Blake
                     ` (2 subsequent siblings)
  3 siblings, 2 replies; 47+ messages in thread
From: Luiz Capitulino @ 2012-07-30 17:41 UTC (permalink / raw)
  To: Orit Wasserman
  Cc: peter.maydell, aliguori, quintela, stefanha, qemu-devel, mdroth,
	blauwirbel, chegu_vinod, avi, pbonzini, eblake

On Sun, 29 Jul 2012 12:42:54 +0300
Orit Wasserman <owasserm@redhat.com> wrote:

> The management can enable/disable a capability for the next migration by using
> migrate_set_parameter command.
> The management can query the current migration capabilities using
> query-migrate-parameters

In general looks good to me, I have a question and a few nitpick comments
below.

> 
> Signed-off-by: Orit Wasserman <owasserm@redhat.com>
> Signed-off-by: Juan Quintela <quintela@redhat.com>
> ---
>  hmp-commands.hx  |   16 ++++++++++++
>  hmp.c            |   71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  hmp.h            |    2 +
>  migration.c      |   42 +++++++++++++++++++++++++++++++-
>  migration.h      |    2 +
>  monitor.c        |    7 +++++
>  qapi-schema.json |   32 ++++++++++++++++++++++++
>  qmp-commands.hx  |   60 ++++++++++++++++++++++++++++++++++++++++++++-
>  8 files changed, 229 insertions(+), 3 deletions(-)
> 
> diff --git a/hmp-commands.hx b/hmp-commands.hx
> index 8786148..3e15338 100644
> --- a/hmp-commands.hx
> +++ b/hmp-commands.hx
> @@ -861,6 +861,20 @@ Set maximum tolerated downtime (in seconds) for migration.
>  ETEXI
>  
>      {
> +        .name       = "migrate_set_parameter",
> +        .args_type  = "capability:s,state:b",
> +        .params     = "capability state",
> +        .help       = "Enable/Disable the usage of a capability for migration",
> +        .mhandler.cmd = hmp_migrate_set_parameter,
> +    },
> +
> +STEXI
> +@item migrate_set_parameter @var{capability} @var{state}
> +@findex migrate_set_parameter
> +Enable/Disable the usage of a capability @var{capability} for migration.
> +ETEXI
> +
> +    {
>          .name       = "client_migrate_info",
>          .args_type  = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?",
>          .params     = "protocol hostname port tls-port cert-subject",
> @@ -1419,6 +1433,8 @@ show user network stack connection states
>  show migration status
>  @item info migration_capabilities
>  show migration capabilities
> +@item info migrate_parameters
> +show current migration parameters
>  @item info balloon
>  show balloon information
>  @item info qtree
> diff --git a/hmp.c b/hmp.c
> index 5c7d0be..f2f63fd 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -131,8 +131,22 @@ void hmp_info_mice(Monitor *mon)
>  void hmp_info_migrate(Monitor *mon)
>  {
>      MigrationInfo *info;
> +    MigrationCapabilityStatusList *cap;
> +    MigrationParameters *params;
>  
>      info = qmp_query_migrate(NULL);
> +    params = qmp_query_migrate_parameters(NULL);
> +
> +    /* do not display parameters during setup */
> +    if (info->has_status && params->capabilities) {
> +        monitor_printf(mon, "capabilities: ");
> +        for (cap = params->capabilities; cap; cap = cap->next) {
> +            monitor_printf(mon, "%s: %s ",
> +                           MigrationCapability_lookup[cap->value->capability],
> +                           cap->value->state ? "on" : "off");
> +        }
> +        monitor_printf(mon, "\n");
> +    }
>  
>      if (info->has_status) {
>          monitor_printf(mon, "Migration status: %s\n", info->status);
> @@ -159,6 +173,7 @@ void hmp_info_migrate(Monitor *mon)
>      }
>  
>      qapi_free_MigrationInfo(info);
> +    qapi_free_MigrationParameters(params);
>  }
>  
>  void hmp_info_migration_capabilities(Monitor *mon)
> @@ -180,6 +195,27 @@ void hmp_info_migration_capabilities(Monitor *mon)
>      qapi_free_MigrationCapabilityStatusList(caps_list);
>  }
>  
> +void hmp_info_migrate_parameters(Monitor *mon)
> +{
> +
> +    MigrationCapabilityStatusList *cap;
> +    MigrationParameters *params;
> +
> +    params = qmp_query_migrate_parameters(NULL);
> +
> +    if (params->capabilities) {
> +        monitor_printf(mon, "capabilities: ");
> +        for (cap = params->capabilities; cap; cap = cap->next) {
> +            monitor_printf(mon, "%s: %s ",
> +                           MigrationCapability_lookup[cap->value->capability],
> +                           cap->value->state ? "on" : "off");
> +        }
> +        monitor_printf(mon, "\n");
> +    }
> +
> +    qapi_free_MigrationParameters(params);
> +}
> +
>  void hmp_info_cpus(Monitor *mon)
>  {
>      CpuInfoList *cpu_list, *cpu;
> @@ -754,6 +790,41 @@ void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict)
>      qmp_migrate_set_speed(value, NULL);
>  }
>  
> +void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
> +{
> +    const char *cap = qdict_get_str(qdict, "capability");
> +    bool state = qdict_get_bool(qdict, "state");
> +    Error *err = NULL;
> +    MigrationCapabilityStatusList *params = NULL;
> +    int i;
> +
> +    for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
> +        if (strcmp(cap, MigrationCapability_lookup[i]) == 0) {
> +            if (!params) {
> +                params = g_malloc0(sizeof(*params));
> +            }

This if shouldn't be necessary, right?

> +            params->value = g_malloc0(sizeof(*params->value));
> +            params->value->capability = i;
> +            params->value->state = state;
> +            params->next = NULL;

nitpick: I'd make the code ready for future capabilities.

> +            qmp_migrate_set_parameters(params, &err);
> +            break;
> +        }
> +    }
> +
> +    if (i == MIGRATION_CAPABILITY_MAX) {
> +        error_set(&err, QERR_INVALID_PARAMETER, cap);
> +    }
> +
> +    qapi_free_MigrationCapabilityStatusList(params);
> +
> +    if (err) {
> +        monitor_printf(mon, "migrate_set_parameter: %s\n",
> +                       error_get_pretty(err));
> +        error_free(err);
> +    }
> +}
> +
>  void hmp_set_password(Monitor *mon, const QDict *qdict)
>  {
>      const char *protocol  = qdict_get_str(qdict, "protocol");
> diff --git a/hmp.h b/hmp.h
> index 2fb44ca..ceb2f06 100644
> --- a/hmp.h
> +++ b/hmp.h
> @@ -26,6 +26,7 @@ void hmp_info_chardev(Monitor *mon);
>  void hmp_info_mice(Monitor *mon);
>  void hmp_info_migrate(Monitor *mon);
>  void hmp_info_migration_capabilities(Monitor *mon);
> +void hmp_info_migrate_parameters(Monitor *mon);
>  void hmp_info_cpus(Monitor *mon);
>  void hmp_info_block(Monitor *mon);
>  void hmp_info_blockstats(Monitor *mon);
> @@ -52,6 +53,7 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict);
>  void hmp_migrate_cancel(Monitor *mon, const QDict *qdict);
>  void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict);
>  void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict);
> +void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict);
>  void hmp_set_password(Monitor *mon, const QDict *qdict);
>  void hmp_expire_password(Monitor *mon, const QDict *qdict);
>  void hmp_eject(Monitor *mon, const QDict *qdict);
> diff --git a/migration.c b/migration.c
> index 8c27347..e844290 100644
> --- a/migration.c
> +++ b/migration.c
> @@ -113,6 +113,25 @@ uint64_t migrate_max_downtime(void)
>      return max_downtime;
>  }
>  
> +MigrationParameters *qmp_query_migrate_parameters(Error **errp)
> +{
> +    MigrationParameters *params = g_malloc0(sizeof(*params));
> +    MigrationState *s = migrate_get_current();
> +    int i;
> +
> +    params->capabilities = g_malloc0(sizeof(*params->capabilities));
> +
> +    for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
> +        params->capabilities->value =
> +            g_malloc(sizeof(*params->capabilities->value));
> +        params->capabilities->value->capability = i;
> +        params->capabilities->value->state = s->enabled_capabilities[i];
> +        params->capabilities->next = NULL;
> +    }
> +
> +    return params;
> +}
> +
>  MigrationInfo *qmp_query_migrate(Error **errp)
>  {
>      MigrationInfo *info = g_malloc0(sizeof(*info));
> @@ -177,6 +196,22 @@ MigrationCapabilityStatusList *qmp_query_migration_capabilities(Error **errp)
>      return caps_list;
>  }
>  
> +void qmp_migrate_set_parameters(MigrationCapabilityStatusList *params,
> +                                Error **errp)
> +{
> +    MigrationState *s = migrate_get_current();
> +    MigrationCapabilityStatusList *cap;
> +
> +    if (s->state == MIG_STATE_ACTIVE) {
> +        error_set(errp, QERR_MIGRATION_ACTIVE);
> +        return;
> +    }
> +
> +    for (cap = params; cap; cap = cap->next) {
> +        s->enabled_capabilities[cap->value->capability] = cap->value->state;
> +    }
> +}
> +
>  /* shared migration helpers */
>  
>  static int migrate_fd_cleanup(MigrationState *s)
> @@ -386,12 +421,17 @@ static MigrationState *migrate_init(const MigrationParams *params)
>  {
>      MigrationState *s = migrate_get_current();
>      int64_t bandwidth_limit = s->bandwidth_limit;
> +    bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
> +
> +    memcpy(enabled_capabilities, s->enabled_capabilities,
> +           sizeof(enabled_capabilities));

Is s->enabled_capabilities initialized somewhere or are we making xbzrle
disabled by default?

>  
>      memset(s, 0, sizeof(*s));
>      s->bandwidth_limit = bandwidth_limit;
>      s->params = *params;
> +    memcpy(s->enabled_capabilities, enabled_capabilities,
> +           sizeof(enabled_capabilities));
>  
> -    s->bandwidth_limit = bandwidth_limit;

Unrelated change.

>      s->state = MIG_STATE_SETUP;
>      s->total_time = qemu_get_clock_ms(rt_clock);
>  
> diff --git a/migration.h b/migration.h
> index 57572a6..713aae0 100644
> --- a/migration.h
> +++ b/migration.h
> @@ -19,6 +19,7 @@
>  #include "notify.h"
>  #include "error.h"
>  #include "vmstate.h"
> +#include "qapi-types.h"
>  
>  struct MigrationParams {
>      bool blk;
> @@ -39,6 +40,7 @@ struct MigrationState
>      void *opaque;
>      MigrationParams params;
>      int64_t total_time;
> +    bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
>  };
>  
>  void process_incoming_migration(QEMUFile *f);
> diff --git a/monitor.c b/monitor.c
> index fd57c5e..e07af97 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -2669,6 +2669,13 @@ static mon_cmd_t info_cmds[] = {
>          .mhandler.info = hmp_info_migration_capabilities,
>      },
>      {
> +        .name       = "migrate-parameters",
> +        .args_type  = "",
> +        .params     = "",
> +        .help       = "show current migration parameters",
> +        .mhandler.info = hmp_info_migrate_parameters,
> +    },
> +    {
>          .name       = "balloon",
>          .args_type  = "",
>          .params     = "",
> diff --git a/qapi-schema.json b/qapi-schema.json
> index b4d4dd6..9d6759d 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -345,6 +345,38 @@
>  { 'command': 'query-migration-capabilities', 'returns': ['MigrationCapabilityStatus'] }
>  
>  ##
> +# @migrate-set-parameters
> +#
> +# Enable/Disable the following migration capabilities (like xbzrle)
> +#
> +# Since: 1.2
> +##
> +{ 'command': 'migrate-set-parameters',
> +  'data': { 'capabilities': ['MigrationCapabilityStatus'] } }
> +
> +##
> +# @MigrationParameters
> +#
> +# @capabilities: @MigrationCapabilityStatus list contain current migration
> +#                capabilities status
> +# Since: 1.2
> +##
> +{ 'type': 'MigrationParameters',
> +  'data': {'capabilities': ['MigrationCapabilityStatus']} }
> +
> +
> +##
> +# @query-migrate-parameters
> +#
> +# Returns information about the current migration capabilities status
> +#
> +# Returns: @MigrationParameters
> +#
> +# Since: 1.2
> +##
> +{ 'command': 'query-migrate-parameters', 'returns': 'MigrationParameters' }
> +
> +##
>  # @MouseInfo:
>  #
>  # Information about a mouse device.
> diff --git a/qmp-commands.hx b/qmp-commands.hx
> index c0ed14c..7f40e2a 100644
> --- a/qmp-commands.hx
> +++ b/qmp-commands.hx
> @@ -2081,7 +2081,6 @@ The main json-object contains the following:
>           - "transferred": amount transferred (json-int)
>           - "remaining": amount remaining (json-int)
>           - "total": total (json-int)
> -
>  Examples:
>  
>  1. Before the first migration
> @@ -2092,7 +2091,15 @@ Examples:
>  2. Migration is done and has succeeded
>  
>  -> { "execute": "query-migrate" }
> -<- { "return": { "status": "completed" } }
> +<- { "return": {
> +        "status": "completed",
> +        "ram":{
> +          "transferred":123,
> +          "remaining":123,
> +          "total":246
> +        }
> +     }
> +   }
>  
>  3. Migration is done and has failed
>  
> @@ -2165,6 +2172,55 @@ EQMP
>      },
>  
>  SQMP
> +migrate-set-parameters
> +-------
> +
> +Enable/Disable migration capabilities
> +
> +- "xbzrle": xbzrle support
> +
> +Arguments:
> +
> +Example:
> +
> +-> { "execute": "migrate-set-parameters" , "arguments":
> +     { "parameters": [ { "capability": "xbzrle", "state": true } ] } }
> +
> +EQMP
> +
> +    {
> +        .name       = "migrate_set_parameters",
> +        .args_type  = "parameters:O",
> +        .params     = "capability:s,state:b",
> +	.mhandler.cmd_new = qmp_marshal_input_migrate_set_parameters,
> +    },
> +SQMP
> +query-migrate-parameters
> +-------
> +
> +Query current migration parameters
> +
> +- "capabilities": migration capabilities state
> +         - "xbzrle" : XBZRLE state (json-bool)
> +
> +Arguments:
> +
> +Example:
> +
> +-> { "execute": "query-migrate-parameters" }
> +<- { "return": {
> +        "capabilities" :  [ { "capability" : "xbzrle", "state" : false } ]
> +     }
> +   }
> +EQMP
> +
> +    {
> +        .name       = "query-migrate-parameters",
> +        .args_type  = "",
> +        .mhandler.cmd_new = qmp_marshal_input_query_migrate_parameters,
> +    },
> +
> +SQMP
>  query-balloon
>  -------------
>  

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 01/11] Add migration capabilities
  2012-07-29  9:42 ` [Qemu-devel] [PATCH 01/11] Add migration capabilities Orit Wasserman
  2012-07-30 17:24   ` Luiz Capitulino
@ 2012-07-30 17:45   ` Eric Blake
  1 sibling, 0 replies; 47+ messages in thread
From: Eric Blake @ 2012-07-30 17:45 UTC (permalink / raw)
  To: Orit Wasserman
  Cc: peter.maydell, aliguori, quintela, stefanha, qemu-devel, mdroth,
	blauwirbel, avi, pbonzini, lcapitulino, chegu_vinod

[-- Attachment #1: Type: text/plain, Size: 1313 bytes --]

On 07/29/2012 03:42 AM, Orit Wasserman wrote:
> Add migration capabilities that can be queried by the management.
> The management can query the source QEMU and the destination QEMU in order to
> verify both support some migration capability (currently only XBZRLE).
> 
> Signed-off-by: Orit Wasserman <owasserm@redhat.com>
> Signed-off-by: Juan Quintela <quintela@redhat.com>

> +++ b/qapi-schema.json
> @@ -306,6 +306,45 @@
>  { 'command': 'query-migrate', 'returns': 'MigrationInfo' }
>  
>  ##
> +# @MigrationCapability
> +#
> +# Migration capabilities enumeration
> +#
> +# @xbzrle: Migration supports xbzrle (Xor Based Zero Length Encoding).

In patch 3/10, you named it:
XBZRLE (Xor Based Zero Run Length Encoding)

You are missing 'Run' here.

> +#          This feature allows us to minimize migration traffic for certain work
> +#          loads, by sending compressed difference of the pages
> +#
> +# Since: 1.2

We are inconsistent on whether this should be 'Since: 1.2.0' or 'Since:
1.2', but cleaning that up would be an independent patch since there are
pre-existing uses of both forms.

Other than that,

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake@redhat.com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 620 bytes --]

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 02/11] Add migrate_set_parameter and query-migrate-parameters
  2012-07-29  9:42 ` [Qemu-devel] [PATCH 02/11] Add migrate_set_parameter and query-migrate-parameters Orit Wasserman
  2012-07-30 17:41   ` Luiz Capitulino
@ 2012-07-30 18:11   ` Eric Blake
  2012-07-30 18:15     ` Luiz Capitulino
  2012-07-30 19:12   ` Juan Quintela
  2012-07-30 19:45   ` Anthony Liguori
  3 siblings, 1 reply; 47+ messages in thread
From: Eric Blake @ 2012-07-30 18:11 UTC (permalink / raw)
  To: Orit Wasserman
  Cc: peter.maydell, aliguori, quintela, stefanha, qemu-devel, mdroth,
	blauwirbel, avi, pbonzini, lcapitulino, chegu_vinod

[-- Attachment #1: Type: text/plain, Size: 1663 bytes --]

On 07/29/2012 03:42 AM, Orit Wasserman wrote:
> The management can enable/disable a capability for the next migration by using
> migrate_set_parameter command.
> The management can query the current migration capabilities using
> query-migrate-parameters

In addition to Luiz' nitpicks:

Here in the commit message, you are mixing HMP (migrate_set_parameter)
with QMP (query-migrate-parameters).  It might be better to stick to HMP
only (migrate_set_parameter, info migrate_parameters) or QMP only
(migrate-set-parameter, query-migrate-parameters), or even list the
spellings for both protocols.

> +++ b/hmp-commands.hx

> @@ -1419,6 +1433,8 @@ show user network stack connection states
>  show migration status
>  @item info migration_capabilities
>  show migration capabilities
> +@item info migrate_parameters
> +show current migration parameters

> +++ b/monitor.c
> @@ -2669,6 +2669,13 @@ static mon_cmd_t info_cmds[] = {
>          .mhandler.info = hmp_info_migration_capabilities,
>      },
>      {
> +        .name       = "migrate-parameters",

Is this the correct spelling?  Or is this feeding the HMP interface,
where you documented it above as 'info migrate_parameters'?

> +++ b/qapi-schema.json
> @@ -345,6 +345,38 @@
>  { 'command': 'query-migration-capabilities', 'returns': ['MigrationCapabilityStatus'] }
>  
>  ##
> +# @migrate-set-parameters
> +#
> +# Enable/Disable the following migration capabilities (like xbzrle)
> +#
> +# Since: 1.2

Same comment as in 1/11 about 1.2 vs. 1.2.0.

-- 
Eric Blake   eblake@redhat.com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 620 bytes --]

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 02/11] Add migrate_set_parameter and query-migrate-parameters
  2012-07-30 18:11   ` Eric Blake
@ 2012-07-30 18:15     ` Luiz Capitulino
  0 siblings, 0 replies; 47+ messages in thread
From: Luiz Capitulino @ 2012-07-30 18:15 UTC (permalink / raw)
  To: Eric Blake
  Cc: peter.maydell, aliguori, quintela, stefanha, qemu-devel, mdroth,
	blauwirbel, Orit Wasserman, avi, pbonzini, chegu_vinod

On Mon, 30 Jul 2012 12:11:52 -0600
Eric Blake <eblake@redhat.com> wrote:

> On 07/29/2012 03:42 AM, Orit Wasserman wrote:
> > The management can enable/disable a capability for the next migration by using
> > migrate_set_parameter command.
> > The management can query the current migration capabilities using
> > query-migrate-parameters
> 
> In addition to Luiz' nitpicks:
> 
> Here in the commit message, you are mixing HMP (migrate_set_parameter)
> with QMP (query-migrate-parameters).  It might be better to stick to HMP
> only (migrate_set_parameter, info migrate_parameters) or QMP only
> (migrate-set-parameter, query-migrate-parameters), or even list the
> spellings for both protocols.
> 
> > +++ b/hmp-commands.hx
> 
> > @@ -1419,6 +1433,8 @@ show user network stack connection states
> >  show migration status
> >  @item info migration_capabilities
> >  show migration capabilities
> > +@item info migrate_parameters
> > +show current migration parameters
> 
> > +++ b/monitor.c
> > @@ -2669,6 +2669,13 @@ static mon_cmd_t info_cmds[] = {
> >          .mhandler.info = hmp_info_migration_capabilities,
> >      },
> >      {
> > +        .name       = "migrate-parameters",
> 
> Is this the correct spelling?  Or is this feeding the HMP interface,
> where you documented it above as 'info migrate_parameters'?

It's the HMP interface, yes.

> 
> > +++ b/qapi-schema.json
> > @@ -345,6 +345,38 @@
> >  { 'command': 'query-migration-capabilities', 'returns': ['MigrationCapabilityStatus'] }
> >  
> >  ##
> > +# @migrate-set-parameters
> > +#
> > +# Enable/Disable the following migration capabilities (like xbzrle)
> > +#
> > +# Since: 1.2
> 
> Same comment as in 1/11 about 1.2 vs. 1.2.0.
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 02/11] Add migrate_set_parameter and query-migrate-parameters
  2012-07-29  9:42 ` [Qemu-devel] [PATCH 02/11] Add migrate_set_parameter and query-migrate-parameters Orit Wasserman
  2012-07-30 17:41   ` Luiz Capitulino
  2012-07-30 18:11   ` Eric Blake
@ 2012-07-30 19:12   ` Juan Quintela
  2012-07-30 19:24     ` Eric Blake
                       ` (2 more replies)
  2012-07-30 19:45   ` Anthony Liguori
  3 siblings, 3 replies; 47+ messages in thread
From: Juan Quintela @ 2012-07-30 19:12 UTC (permalink / raw)
  To: Orit Wasserman
  Cc: peter.maydell, aliguori, stefanha, qemu-devel, mdroth, blauwirbel,
	chegu_vinod, avi, pbonzini, lcapitulino, eblake

Orit Wasserman <owasserm@redhat.com> wrote:
> The management can enable/disable a capability for the next migration by using
> migrate_set_parameter command.
> The management can query the current migration capabilities using
> query-migrate-parameters
>
> Signed-off-by: Orit Wasserman <owasserm@redhat.com>
> Signed-off-by: Juan Quintela <quintela@redhat.com>

I just noticed .... shouldn't we use

migrate_set_parameter cache_size 256M
???

I think that even the old migration parameters could be added to this
one?

migrate_set_parameter downtime 30ms
migrate_set_parameter bandwidth 1G

This way everything would be more regular, and easier on libvirt, as new
parameters would be trivial to ask for?

Notice that I can understand that we have to maintain the old commands
for compability, but we can do "regularly" for new ones?

Later, Juan.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 02/11] Add migrate_set_parameter and query-migrate-parameters
  2012-07-30 19:12   ` Juan Quintela
@ 2012-07-30 19:24     ` Eric Blake
  2012-07-30 19:37     ` Anthony Liguori
  2012-07-30 20:21     ` Juan Quintela
  2 siblings, 0 replies; 47+ messages in thread
From: Eric Blake @ 2012-07-30 19:24 UTC (permalink / raw)
  To: quintela
  Cc: peter.maydell, aliguori, stefanha, qemu-devel, mdroth, blauwirbel,
	Orit Wasserman, avi, pbonzini, lcapitulino, chegu_vinod

[-- Attachment #1: Type: text/plain, Size: 1410 bytes --]

On 07/30/2012 01:12 PM, Juan Quintela wrote:
> Orit Wasserman <owasserm@redhat.com> wrote:
>> The management can enable/disable a capability for the next migration by using
>> migrate_set_parameter command.
>> The management can query the current migration capabilities using
>> query-migrate-parameters
>>
>> Signed-off-by: Orit Wasserman <owasserm@redhat.com>
>> Signed-off-by: Juan Quintela <quintela@redhat.com>
> 
> I just noticed .... shouldn't we use
> 
> migrate_set_parameter cache_size 256M
> ???
> 
> I think that even the old migration parameters could be added to this
> one?
> 
> migrate_set_parameter downtime 30ms
> migrate_set_parameter bandwidth 1G

The existing patch was written under the assumption that parameters were
only ever bool; but you are proposing allowing non-bool parameters.

> 
> This way everything would be more regular, and easier on libvirt, as new
> parameters would be trivial to ask for?

That depends on the QMP interface you come up with for expressing
non-bool parameters.  This patch series has already been churning for
several months now, which makes it feel a bit late to be changing the
interface to support non-bool parameters, unless we really like the idea
and can afford another delay in getting this series in.

-- 
Eric Blake   eblake@redhat.com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 620 bytes --]

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 09/11] Add migration accounting for normal and duplicate pages
  2012-07-29  9:43 ` [Qemu-devel] [PATCH 09/11] Add migration accounting for normal and duplicate pages Orit Wasserman
@ 2012-07-30 19:30   ` Luiz Capitulino
  2012-07-31  8:36     ` Orit Wasserman
  0 siblings, 1 reply; 47+ messages in thread
From: Luiz Capitulino @ 2012-07-30 19:30 UTC (permalink / raw)
  To: Orit Wasserman
  Cc: peter.maydell, aliguori, quintela, stefanha, qemu-devel,
	Benoit Hudzia, mdroth, blauwirbel, Petter Svard, chegu_vinod, avi,
	Aidan Shribman, pbonzini, eblake

On Sun, 29 Jul 2012 12:43:01 +0300
Orit Wasserman <owasserm@redhat.com> wrote:

> Signed-off-by: Benoit Hudzia <benoit.hudzia@sap.com>
> Signed-off-by: Petter Svard <petters@cs.umu.se>
> Signed-off-by: Aidan Shribman <aidan.shribman@sap.com>
> Signed-off-by: Orit Wasserman <owasserm@redhat.com>
> Signed-off-by: Juan Quintela <quintela@redhat.com>
> ---
>  arch_init.c      |   38 ++++++++++++++++++++++++++++++++++++++
>  migration.c      |    4 ++++
>  migration.h      |    5 +++++
>  qapi-schema.json |    8 ++++++--
>  qmp-commands.hx  |   14 +++++++++++---
>  5 files changed, 64 insertions(+), 5 deletions(-)
> 
> diff --git a/arch_init.c b/arch_init.c
> index d709ccb..7f12317 100644
> --- a/arch_init.c
> +++ b/arch_init.c
> @@ -199,6 +199,40 @@ int64_t xbzrle_cache_resize(int64_t new_size)
>      return pow2floor(new_size);
>  }
>  
> +/* accounting for migration statistics */
> +typedef struct AccountingInfo {
> +    uint64_t dup_pages;
> +    uint64_t norm_pages;
> +    uint64_t iterations;
> +} 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;
> +}
> +
>  static void save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset,
>          int cont, int flag)
>  {
> @@ -293,6 +327,7 @@ static int ram_save_block(QEMUFile *f)
>              p = memory_region_get_ram_ptr(mr) + offset;
>  
>              if (is_dup_page(p)) {
> +                acct_info.dup_pages++;
>                  save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_COMPRESS);
>                  qemu_put_byte(f, *p);
>                  bytes_sent = 1;
> @@ -308,6 +343,7 @@ static int ram_save_block(QEMUFile *f)
>                  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++;
>              }
>  
>              /* if page is unmodified, continue to the next */
> @@ -429,6 +465,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
>          }
>          XBZRLE.encoded_buf = g_malloc0(TARGET_PAGE_SIZE);
>          XBZRLE.current_buf = g_malloc(TARGET_PAGE_SIZE);
> +        acct_clear();
>      }
>  
>      /* Make sure all dirty bits are set */
> @@ -477,6 +514,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque)
>              break;
>          }
>          bytes_transferred += bytes_sent;
> +        acct_info.iterations++;
>          /* we want to check in the 1st loop, just in case it was the 1st time
>             and we had to sync the dirty bitmap.
>             qemu_get_clock_ns() is a bit expensive, so we only check each some
> diff --git a/migration.c b/migration.c
> index bc2231d..4dc99ba 100644
> --- a/migration.c
> +++ b/migration.c
> @@ -156,6 +156,8 @@ MigrationInfo *qmp_query_migrate(Error **errp)
>          info->ram->total = ram_bytes_total();
>          info->ram->total_time = qemu_get_clock_ms(rt_clock)
>              - s->total_time;
> +        info->ram->duplicate = dup_mig_pages_transferred();
> +        info->ram->normal = norm_mig_pages_transferred();
>  
>          if (blk_mig_active()) {
>              info->has_disk = true;
> @@ -175,6 +177,8 @@ MigrationInfo *qmp_query_migrate(Error **errp)
>          info->ram->remaining = 0;
>          info->ram->total = ram_bytes_total();
>          info->ram->total_time = s->total_time;
> +        info->ram->duplicate = dup_mig_pages_transferred();
> +        info->ram->normal = norm_mig_pages_transferred();
>          break;
>      case MIG_STATE_ERROR:
>          info->has_status = true;
> diff --git a/migration.h b/migration.h
> index 337e225..e4a7cd7 100644
> --- a/migration.h
> +++ b/migration.h
> @@ -87,6 +87,11 @@ uint64_t ram_bytes_total(void);
>  
>  extern SaveVMHandlers savevm_ram_handlers;
>  
> +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);
> +
>  /**
>   * @migrate_add_blocker - prevent migration from proceeding
>   *
> diff --git a/qapi-schema.json b/qapi-schema.json
> index 04adcee..a936714 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -264,11 +264,15 @@
>  #        migration has ended, it returns the total migration
>  #        time. (since 1.2)
>  #
> -# Since: 0.14.0.
> +# @duplicate: number of duplicate pages (since 1.2)
> +#
> +# @normal : number of normal pages (since 1.2)

Is the number of pages actually useful? I think this should be in bytes,
just like the other stats.

> +#
> +# Since: 0.14.0
>  ##
>  { 'type': 'MigrationStats',
>    'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int' ,
> -           'total_time': 'int' } }
> +           'total_time': 'int', 'duplicate': 'int', 'normal': 'int' } }
>  
>  ##
>  # @MigrationInfo
> diff --git a/qmp-commands.hx b/qmp-commands.hx
> index cfc950e..a5a67eb 100644
> --- a/qmp-commands.hx
> +++ b/qmp-commands.hx
> @@ -2099,6 +2099,8 @@ The main json-object contains the following:
>           - "transferred": amount transferred (json-int)
>           - "remaining": amount remaining (json-int)
>           - "total": total (json-int)
> +	 - "duplicate": number of duplicated pages (json-int)
> +	 - "normal" : number of normal pages transferred (json-int)
>  - "disk": only present if "status" is "active" and it is a block migration,
>    it is a json-object with the following disk information (in bytes):
>           - "transferred": amount transferred (json-int)
> @@ -2119,7 +2121,9 @@ Examples:
>          "ram":{
>            "transferred":123,
>            "remaining":123,
> -          "total":246
> +          "total":246,
> +          "duplicate":123,
> +          "normal":123
>          }
>       }
>     }
> @@ -2138,7 +2142,9 @@ Examples:
>           "ram":{
>              "transferred":123,
>              "remaining":123,
> -            "total":246
> +            "total":246,
> +            "duplicate":123,
> +            "normal":123
>           }
>        }
>     }
> @@ -2152,7 +2158,9 @@ Examples:
>           "ram":{
>              "total":1057024,
>              "remaining":1053304,
> -            "transferred":3720
> +            "transferred":3720,
> +            "duplicate":123,
> +            "normal":123
>           },
>           "disk":{
>              "total":20971520,

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 02/11] Add migrate_set_parameter and query-migrate-parameters
  2012-07-30 19:12   ` Juan Quintela
  2012-07-30 19:24     ` Eric Blake
@ 2012-07-30 19:37     ` Anthony Liguori
  2012-07-30 20:21     ` Juan Quintela
  2 siblings, 0 replies; 47+ messages in thread
From: Anthony Liguori @ 2012-07-30 19:37 UTC (permalink / raw)
  To: quintela, Orit Wasserman
  Cc: peter.maydell, stefanha, mdroth, qemu-devel, blauwirbel,
	chegu_vinod, avi, pbonzini, lcapitulino, eblake

Juan Quintela <quintela@redhat.com> writes:

> Orit Wasserman <owasserm@redhat.com> wrote:
>> The management can enable/disable a capability for the next migration by using
>> migrate_set_parameter command.
>> The management can query the current migration capabilities using
>> query-migrate-parameters
>>
>> Signed-off-by: Orit Wasserman <owasserm@redhat.com>
>> Signed-off-by: Juan Quintela <quintela@redhat.com>
>
> I just noticed .... shouldn't we use
>
> migrate_set_parameter cache_size 256M
> ???
>
> I think that even the old migration parameters could be added to this
> one?
>
> migrate_set_parameter downtime 30ms
> migrate_set_parameter bandwidth 1G
>
> This way everything would be more regular, and easier on libvirt, as new
> parameters would be trivial to ask for?
>
> Notice that I can understand that we have to maintain the old commands
> for compability, but we can do "regularly" for new ones?

I think this is worse.  How does libvirt determine which parameters are
valid?

Let's do migrate_set_cache_size.  Please don't introduce commands that
multiplex multiple behavior.  They do more harm than good.

Regards,

Anthony Liguori

>
> Later, Juan.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 10/11] Add XBZRLE statistics
  2012-07-29  9:43 ` [Qemu-devel] [PATCH 10/11] Add XBZRLE statistics Orit Wasserman
@ 2012-07-30 19:37   ` Luiz Capitulino
  2012-07-31  8:31     ` Orit Wasserman
  0 siblings, 1 reply; 47+ messages in thread
From: Luiz Capitulino @ 2012-07-30 19:37 UTC (permalink / raw)
  To: Orit Wasserman
  Cc: peter.maydell, aliguori, quintela, stefanha, qemu-devel,
	Benoit Hudzia, mdroth, blauwirbel, Petter Svard, chegu_vinod, avi,
	Aidan Shribman, pbonzini, eblake

On Sun, 29 Jul 2012 12:43:02 +0300
Orit Wasserman <owasserm@redhat.com> wrote:

> Signed-off-by: Benoit Hudzia <benoit.hudzia@sap.com>
> Signed-off-by: Petter Svard <petters@cs.umu.se>
> Signed-off-by: Aidan Shribman <aidan.shribman@sap.com>
> Signed-off-by: Orit Wasserman <owasserm@redhat.com>
> Signed-off-by: Juan Quintela <quintela@redhat.com>
> ---
>  arch_init.c      |   28 ++++++++++++++++++++++++++++
>  hmp.c            |   21 +++++++++++++++++++++
>  migration.c      |   28 ++++++++++++++++++++++++++++
>  migration.h      |    4 ++++
>  qapi-schema.json |   32 +++++++++++++++++++++++++++++++-
>  qmp-commands.hx  |   35 +++++++++++++++++++++++++++++++++++
>  6 files changed, 147 insertions(+), 1 deletions(-)
> 
> diff --git a/arch_init.c b/arch_init.c
> index 7f12317..9833d54 100644
> --- a/arch_init.c
> +++ b/arch_init.c
> @@ -203,7 +203,11 @@ int64_t xbzrle_cache_resize(int64_t new_size)
>  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;
> @@ -233,6 +237,26 @@ 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;
> +}
> +
>  static void save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset,
>          int cont, int flag)
>  {
> @@ -257,6 +281,7 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
>      if (!cache_is_cached(XBZRLE.cache, current_addr)) {
>          cache_insert(XBZRLE.cache, current_addr,
>                       g_memdup(current_data, TARGET_PAGE_SIZE));
> +        acct_info.xbzrle_cache_miss++;
>          return -1;
>      }
>  
> @@ -274,6 +299,7 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
>          return 0;
>      } else if (encoded_len == -1) {
>          DPRINTF("Overflow\n");
> +        acct_info.xbzrle_overflows++;
>          /* update data in the cache */
>          memcpy(prev_cached_page, current_data, TARGET_PAGE_SIZE);
>          return -1;
> @@ -288,6 +314,8 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
>      qemu_put_be16(f, encoded_len);
>      qemu_put_buffer(f, XBZRLE.encoded_buf, encoded_len);
>      bytes_sent = encoded_len + 1 + 2;
> +    acct_info.xbzrle_pages++;
> +    acct_info.xbzrle_bytes += bytes_sent;
>  
>      return bytes_sent;
>  }
> diff --git a/hmp.c b/hmp.c
> index 9770d7b..383d5b1 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -172,6 +172,27 @@ void hmp_info_migrate(Monitor *mon)
>                         info->disk->total >> 10);
>      }
>  
> +    if (info->has_xbzrle_cache) {
> +        monitor_printf(mon, "cache size: %" PRIu64 " bytes\n",
> +                       info->xbzrle_cache->cache_size);
> +        if (info->xbzrle_cache->has_xbzrle_bytes) {
> +            monitor_printf(mon, "xbzrle transferred: %" PRIu64 " kbytes\n",
> +                           info->xbzrle_cache->xbzrle_bytes >> 10);
> +        }
> +        if (info->xbzrle_cache->has_xbzrle_pages) {
> +            monitor_printf(mon, "xbzrle pages: %" PRIu64 " pages\n",
> +                           info->xbzrle_cache->xbzrle_pages);
> +        }
> +        if (info->xbzrle_cache->has_xbzrle_cache_miss) {
> +            monitor_printf(mon, "xbzrle cache miss: %" PRIu64 "\n",
> +                           info->xbzrle_cache->xbzrle_cache_miss);
> +        }
> +        if (info->xbzrle_cache->has_xbzrle_overflow) {
> +            monitor_printf(mon, "xbzrle overflow : %" PRIu64 "\n",
> +                           info->xbzrle_cache->xbzrle_overflow);
> +        }
> +    }
> +
>      qapi_free_MigrationInfo(info);
>      qapi_free_MigrationParameters(params);
>  }
> diff --git a/migration.c b/migration.c
> index 4dc99ba..fb802bc 100644
> --- a/migration.c
> +++ b/migration.c
> @@ -136,6 +136,23 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp)
>      return params;
>  }
>  
> +static void get_xbzrle_cache_stats(MigrationInfo *info)
> +{
> +    if (migrate_use_xbzrle()) {
> +        info->has_xbzrle_cache = true;
> +        info->xbzrle_cache = g_malloc0(sizeof(*info->xbzrle_cache));
> +        info->xbzrle_cache->cache_size = migrate_xbzrle_cache_size();
> +        info->xbzrle_cache->has_xbzrle_bytes = true;
> +        info->xbzrle_cache->xbzrle_bytes = xbzrle_mig_bytes_transferred();
> +        info->xbzrle_cache->has_xbzrle_pages = true;
> +        info->xbzrle_cache->xbzrle_pages = xbzrle_mig_pages_transferred();
> +        info->xbzrle_cache->has_xbzrle_cache_miss = true;
> +        info->xbzrle_cache->xbzrle_cache_miss = xbzrle_mig_pages_cache_miss();
> +        info->xbzrle_cache->has_xbzrle_overflow = true;
> +        info->xbzrle_cache->xbzrle_overflow = xbzrle_mig_pages_overflow();
> +    }
> +}
> +
>  MigrationInfo *qmp_query_migrate(Error **errp)
>  {
>      MigrationInfo *info = g_malloc0(sizeof(*info));
> @@ -144,6 +161,13 @@ MigrationInfo *qmp_query_migrate(Error **errp)
>      switch (s->state) {
>      case MIG_STATE_SETUP:
>          /* no migration has happened ever */
> +
> +        /* display xbzrle cache size */
> +        if (migrate_use_xbzrle()) {
> +            info->has_xbzrle_cache = true;
> +            info->xbzrle_cache = g_malloc0(sizeof(*info->xbzrle_cache));
> +            info->xbzrle_cache->cache_size = migrate_xbzrle_cache_size();
> +        }

Is it really useful to return this in MIG_SETUP? Can't the cache size
be queried by some query- command?

>          break;
>      case MIG_STATE_ACTIVE:
>          info->has_status = true;
> @@ -166,8 +190,12 @@ MigrationInfo *qmp_query_migrate(Error **errp)
>              info->disk->remaining = blk_mig_bytes_remaining();
>              info->disk->total = blk_mig_bytes_total();
>          }
> +
> +        get_xbzrle_cache_stats(info);
>          break;
>      case MIG_STATE_COMPLETED:
> +        get_xbzrle_cache_stats(info);
> +
>          info->has_status = true;
>          info->status = g_strdup("completed");
>  
> diff --git a/migration.h b/migration.h
> index e4a7cd7..a9852fc 100644
> --- a/migration.h
> +++ b/migration.h
> @@ -91,6 +91,10 @@ 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);
>  
>  /**
>   * @migrate_add_blocker - prevent migration from proceeding
> diff --git a/qapi-schema.json b/qapi-schema.json
> index a936714..91dee72 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -275,6 +275,31 @@
>             'total_time': 'int', 'duplicate': 'int', 'normal': 'int' } }
>  
>  ##
> +# @XBZRLECacheStats
> +#
> +# Detailed XBZRLE migration cache statistics
> +#
> +# @cache-size: XBZRLE cache size
> +#
> +# @xbzrle-bytes: @optional, amount of bytes already transferred to the target VM
> +#                only returned when migration is active or completed

s/xbzrle-bytes/transferred-bytes

> +#
> +# @xbzrle-pages: @optional, amount of pages transferred to the target VM
> +#                only returned when migration is active or completed

s/xbzrle-pages/transferred-pages

> +#
> +# @xbzrle-cache-miss: @optional, number of cache miss
> +#                     only returned when migration is active or completed

s/xbzrle/xbzrle//

> +#
> +# @xbzrle-overflow: @optional, number of overflows
> +#                   only returned when migration is active or completed

s/xbzrle///

Besides, all these parameters shouldn't be optional as they are unconditionally
included (BZRLECacheStats itself is optional as returned by query-migrate).

> +#
> +# Since: 1.2
> +##
> +{ 'type': 'XBZRLECacheStats',
> +  'data': {'cache-size': 'int', '*xbzrle-bytes': 'int', '*xbzrle-pages': 'int',
> +           '*xbzrle-cache-miss': 'int', '*xbzrle-overflow': 'int' } }
> +
> +##
>  # @MigrationInfo
>  #
>  # Information about current migration process.
> @@ -292,11 +317,16 @@
>  #        status, only returned if status is 'active' and it is a block
>  #        migration
>  #
> +# @xbzrle-cache: #optional @XBZRLECacheStats containing detailed XBZRLE
> +#                migration statistics, only returned if XBZRLE feature is on
> +#                (since 1.2)
> +#
>  # Since: 0.14.0
>  ##
>  { 'type': 'MigrationInfo',
>    'data': {'*status': 'str', '*ram': 'MigrationStats',
> -           '*disk': 'MigrationStats'} }
> +           '*disk': 'MigrationStats',
> +           '*xbzrle-cache': 'XBZRLECacheStats'} }
>  
>  ##
>  # @query-migrate
> diff --git a/qmp-commands.hx b/qmp-commands.hx
> index a5a67eb..0546f42 100644
> --- a/qmp-commands.hx
> +++ b/qmp-commands.hx
> @@ -2106,6 +2106,17 @@ The main json-object contains the following:
>           - "transferred": amount transferred (json-int)
>           - "remaining": amount remaining (json-int)
>           - "total": total (json-int)
> +- "xbzrle-cache": only present if XBZRLE is active.
> +  It is a json-object with the following XBZRLE information:
> +         - "cache-size": XBZRLE cache size
> +         - "xbzrle-bytes": total XBZRLE bytes transferred, only present if
> +                           status is "active" or "completed"
> +         - "xbzrle-pages": number of XBZRLE compressed pages, only present if
> +                           status is "active" or "completed"
> +         - "cache-miss": number of cache misses, only present if
> +                           status is "active" or "completed"
> +         - "overflow": number of XBZRLE overflows, only present if
> +                           status is "active" or "completed"
>  Examples:
>  
>  1. Before the first migration
> @@ -2170,6 +2181,30 @@ Examples:
>        }
>     }
>  
> +6. Migration is being performed and XBZRLE is active:
> +
> +-> { "execute": "query-migrate" }
> +<- {
> +      "return":{
> +         "status":"active",
> +         "capabilities" : [ { "capability": "xbzrle", "state" : true } ],
> +         "ram":{
> +            "total":1057024,
> +            "remaining":1053304,
> +            "transferred":3720,
> +            "duplicate": 10,
> +            "normal" : 3333
> +         },
> +         "cache":{
> +            "cache-size": 1024
> +            "xbzrle-transferred":20971520,
> +            "xbzrle-pages":2444343,
> +            "xbzrle-cache-miss":2244,
> +            "xbzrle-overflow":34434
> +         }
> +      }
> +   }
> +
>  EQMP
>  
>      {

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 00/11]  Migration next v7
  2012-07-29  9:42 [Qemu-devel] [PATCH 00/11] Migration next v7 Orit Wasserman
                   ` (10 preceding siblings ...)
  2012-07-29  9:43 ` [Qemu-devel] [PATCH 11/11] Restart optimization on stage3 update version Orit Wasserman
@ 2012-07-30 19:38 ` Luiz Capitulino
  2012-07-30 20:36   ` Orit Wasserman
  2012-07-30 22:13   ` Juan Quintela
  11 siblings, 2 replies; 47+ messages in thread
From: Luiz Capitulino @ 2012-07-30 19:38 UTC (permalink / raw)
  To: Orit Wasserman
  Cc: peter.maydell, aliguori, quintela, stefanha, qemu-devel, mdroth,
	blauwirbel, chegu_vinod, avi, pbonzini, eblake

On Sun, 29 Jul 2012 12:42:52 +0300
Orit Wasserman <owasserm@redhat.com> wrote:

> Those are the latest XBZRLE patches (part of the migration next branch).

I've concentrated my review on the QMP part, which looks good in general, but
has some details to be fixed.

I'd like to give this a try btw, but it doesn't apply on top of master. Which
branch is this against?

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 02/11] Add migrate_set_parameter and query-migrate-parameters
  2012-07-29  9:42 ` [Qemu-devel] [PATCH 02/11] Add migrate_set_parameter and query-migrate-parameters Orit Wasserman
                     ` (2 preceding siblings ...)
  2012-07-30 19:12   ` Juan Quintela
@ 2012-07-30 19:45   ` Anthony Liguori
  2012-07-30 19:58     ` Luiz Capitulino
  3 siblings, 1 reply; 47+ messages in thread
From: Anthony Liguori @ 2012-07-30 19:45 UTC (permalink / raw)
  To: Orit Wasserman, qemu-devel
  Cc: peter.maydell, quintela, stefanha, mdroth, lcapitulino,
	blauwirbel, chegu_vinod, avi, pbonzini, eblake

Orit Wasserman <owasserm@redhat.com> writes:

> The management can enable/disable a capability for the next migration by using
> migrate_set_parameter command.
> The management can query the current migration capabilities using
> query-migrate-parameters
>
> Signed-off-by: Orit Wasserman <owasserm@redhat.com>
> Signed-off-by: Juan Quintela <quintela@redhat.com>

We have a way to add new commands.  Let's not invent a new one.
Otherwise every subsystem would have it's own approach to querying
what's available.

Regards,

Anthony Liguori

> ---
>  hmp-commands.hx  |   16 ++++++++++++
>  hmp.c            |   71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  hmp.h            |    2 +
>  migration.c      |   42 +++++++++++++++++++++++++++++++-
>  migration.h      |    2 +
>  monitor.c        |    7 +++++
>  qapi-schema.json |   32 ++++++++++++++++++++++++
>  qmp-commands.hx  |   60 ++++++++++++++++++++++++++++++++++++++++++++-
>  8 files changed, 229 insertions(+), 3 deletions(-)
>
> diff --git a/hmp-commands.hx b/hmp-commands.hx
> index 8786148..3e15338 100644
> --- a/hmp-commands.hx
> +++ b/hmp-commands.hx
> @@ -861,6 +861,20 @@ Set maximum tolerated downtime (in seconds) for migration.
>  ETEXI
>  
>      {
> +        .name       = "migrate_set_parameter",
> +        .args_type  = "capability:s,state:b",
> +        .params     = "capability state",
> +        .help       = "Enable/Disable the usage of a capability for migration",
> +        .mhandler.cmd = hmp_migrate_set_parameter,
> +    },
> +
> +STEXI
> +@item migrate_set_parameter @var{capability} @var{state}
> +@findex migrate_set_parameter
> +Enable/Disable the usage of a capability @var{capability} for migration.
> +ETEXI
> +
> +    {
>          .name       = "client_migrate_info",
>          .args_type  = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?",
>          .params     = "protocol hostname port tls-port cert-subject",
> @@ -1419,6 +1433,8 @@ show user network stack connection states
>  show migration status
>  @item info migration_capabilities
>  show migration capabilities
> +@item info migrate_parameters
> +show current migration parameters
>  @item info balloon
>  show balloon information
>  @item info qtree
> diff --git a/hmp.c b/hmp.c
> index 5c7d0be..f2f63fd 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -131,8 +131,22 @@ void hmp_info_mice(Monitor *mon)
>  void hmp_info_migrate(Monitor *mon)
>  {
>      MigrationInfo *info;
> +    MigrationCapabilityStatusList *cap;
> +    MigrationParameters *params;
>  
>      info = qmp_query_migrate(NULL);
> +    params = qmp_query_migrate_parameters(NULL);
> +
> +    /* do not display parameters during setup */
> +    if (info->has_status && params->capabilities) {
> +        monitor_printf(mon, "capabilities: ");
> +        for (cap = params->capabilities; cap; cap = cap->next) {
> +            monitor_printf(mon, "%s: %s ",
> +                           MigrationCapability_lookup[cap->value->capability],
> +                           cap->value->state ? "on" : "off");
> +        }
> +        monitor_printf(mon, "\n");
> +    }
>  
>      if (info->has_status) {
>          monitor_printf(mon, "Migration status: %s\n", info->status);
> @@ -159,6 +173,7 @@ void hmp_info_migrate(Monitor *mon)
>      }
>  
>      qapi_free_MigrationInfo(info);
> +    qapi_free_MigrationParameters(params);
>  }
>  
>  void hmp_info_migration_capabilities(Monitor *mon)
> @@ -180,6 +195,27 @@ void hmp_info_migration_capabilities(Monitor *mon)
>      qapi_free_MigrationCapabilityStatusList(caps_list);
>  }
>  
> +void hmp_info_migrate_parameters(Monitor *mon)
> +{
> +
> +    MigrationCapabilityStatusList *cap;
> +    MigrationParameters *params;
> +
> +    params = qmp_query_migrate_parameters(NULL);
> +
> +    if (params->capabilities) {
> +        monitor_printf(mon, "capabilities: ");
> +        for (cap = params->capabilities; cap; cap = cap->next) {
> +            monitor_printf(mon, "%s: %s ",
> +                           MigrationCapability_lookup[cap->value->capability],
> +                           cap->value->state ? "on" : "off");
> +        }
> +        monitor_printf(mon, "\n");
> +    }
> +
> +    qapi_free_MigrationParameters(params);
> +}
> +
>  void hmp_info_cpus(Monitor *mon)
>  {
>      CpuInfoList *cpu_list, *cpu;
> @@ -754,6 +790,41 @@ void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict)
>      qmp_migrate_set_speed(value, NULL);
>  }
>  
> +void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
> +{
> +    const char *cap = qdict_get_str(qdict, "capability");
> +    bool state = qdict_get_bool(qdict, "state");
> +    Error *err = NULL;
> +    MigrationCapabilityStatusList *params = NULL;
> +    int i;
> +
> +    for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
> +        if (strcmp(cap, MigrationCapability_lookup[i]) == 0) {
> +            if (!params) {
> +                params = g_malloc0(sizeof(*params));
> +            }
> +            params->value = g_malloc0(sizeof(*params->value));
> +            params->value->capability = i;
> +            params->value->state = state;
> +            params->next = NULL;
> +            qmp_migrate_set_parameters(params, &err);
> +            break;
> +        }
> +    }
> +
> +    if (i == MIGRATION_CAPABILITY_MAX) {
> +        error_set(&err, QERR_INVALID_PARAMETER, cap);
> +    }
> +
> +    qapi_free_MigrationCapabilityStatusList(params);
> +
> +    if (err) {
> +        monitor_printf(mon, "migrate_set_parameter: %s\n",
> +                       error_get_pretty(err));
> +        error_free(err);
> +    }
> +}
> +
>  void hmp_set_password(Monitor *mon, const QDict *qdict)
>  {
>      const char *protocol  = qdict_get_str(qdict, "protocol");
> diff --git a/hmp.h b/hmp.h
> index 2fb44ca..ceb2f06 100644
> --- a/hmp.h
> +++ b/hmp.h
> @@ -26,6 +26,7 @@ void hmp_info_chardev(Monitor *mon);
>  void hmp_info_mice(Monitor *mon);
>  void hmp_info_migrate(Monitor *mon);
>  void hmp_info_migration_capabilities(Monitor *mon);
> +void hmp_info_migrate_parameters(Monitor *mon);
>  void hmp_info_cpus(Monitor *mon);
>  void hmp_info_block(Monitor *mon);
>  void hmp_info_blockstats(Monitor *mon);
> @@ -52,6 +53,7 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict);
>  void hmp_migrate_cancel(Monitor *mon, const QDict *qdict);
>  void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict);
>  void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict);
> +void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict);
>  void hmp_set_password(Monitor *mon, const QDict *qdict);
>  void hmp_expire_password(Monitor *mon, const QDict *qdict);
>  void hmp_eject(Monitor *mon, const QDict *qdict);
> diff --git a/migration.c b/migration.c
> index 8c27347..e844290 100644
> --- a/migration.c
> +++ b/migration.c
> @@ -113,6 +113,25 @@ uint64_t migrate_max_downtime(void)
>      return max_downtime;
>  }
>  
> +MigrationParameters *qmp_query_migrate_parameters(Error **errp)
> +{
> +    MigrationParameters *params = g_malloc0(sizeof(*params));
> +    MigrationState *s = migrate_get_current();
> +    int i;
> +
> +    params->capabilities = g_malloc0(sizeof(*params->capabilities));
> +
> +    for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
> +        params->capabilities->value =
> +            g_malloc(sizeof(*params->capabilities->value));
> +        params->capabilities->value->capability = i;
> +        params->capabilities->value->state = s->enabled_capabilities[i];
> +        params->capabilities->next = NULL;
> +    }
> +
> +    return params;
> +}
> +
>  MigrationInfo *qmp_query_migrate(Error **errp)
>  {
>      MigrationInfo *info = g_malloc0(sizeof(*info));
> @@ -177,6 +196,22 @@ MigrationCapabilityStatusList *qmp_query_migration_capabilities(Error **errp)
>      return caps_list;
>  }
>  
> +void qmp_migrate_set_parameters(MigrationCapabilityStatusList *params,
> +                                Error **errp)
> +{
> +    MigrationState *s = migrate_get_current();
> +    MigrationCapabilityStatusList *cap;
> +
> +    if (s->state == MIG_STATE_ACTIVE) {
> +        error_set(errp, QERR_MIGRATION_ACTIVE);
> +        return;
> +    }
> +
> +    for (cap = params; cap; cap = cap->next) {
> +        s->enabled_capabilities[cap->value->capability] = cap->value->state;
> +    }
> +}
> +
>  /* shared migration helpers */
>  
>  static int migrate_fd_cleanup(MigrationState *s)
> @@ -386,12 +421,17 @@ static MigrationState *migrate_init(const MigrationParams *params)
>  {
>      MigrationState *s = migrate_get_current();
>      int64_t bandwidth_limit = s->bandwidth_limit;
> +    bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
> +
> +    memcpy(enabled_capabilities, s->enabled_capabilities,
> +           sizeof(enabled_capabilities));
>  
>      memset(s, 0, sizeof(*s));
>      s->bandwidth_limit = bandwidth_limit;
>      s->params = *params;
> +    memcpy(s->enabled_capabilities, enabled_capabilities,
> +           sizeof(enabled_capabilities));
>  
> -    s->bandwidth_limit = bandwidth_limit;
>      s->state = MIG_STATE_SETUP;
>      s->total_time = qemu_get_clock_ms(rt_clock);
>  
> diff --git a/migration.h b/migration.h
> index 57572a6..713aae0 100644
> --- a/migration.h
> +++ b/migration.h
> @@ -19,6 +19,7 @@
>  #include "notify.h"
>  #include "error.h"
>  #include "vmstate.h"
> +#include "qapi-types.h"
>  
>  struct MigrationParams {
>      bool blk;
> @@ -39,6 +40,7 @@ struct MigrationState
>      void *opaque;
>      MigrationParams params;
>      int64_t total_time;
> +    bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
>  };
>  
>  void process_incoming_migration(QEMUFile *f);
> diff --git a/monitor.c b/monitor.c
> index fd57c5e..e07af97 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -2669,6 +2669,13 @@ static mon_cmd_t info_cmds[] = {
>          .mhandler.info = hmp_info_migration_capabilities,
>      },
>      {
> +        .name       = "migrate-parameters",
> +        .args_type  = "",
> +        .params     = "",
> +        .help       = "show current migration parameters",
> +        .mhandler.info = hmp_info_migrate_parameters,
> +    },
> +    {
>          .name       = "balloon",
>          .args_type  = "",
>          .params     = "",
> diff --git a/qapi-schema.json b/qapi-schema.json
> index b4d4dd6..9d6759d 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -345,6 +345,38 @@
>  { 'command': 'query-migration-capabilities', 'returns': ['MigrationCapabilityStatus'] }
>  
>  ##
> +# @migrate-set-parameters
> +#
> +# Enable/Disable the following migration capabilities (like xbzrle)
> +#
> +# Since: 1.2
> +##
> +{ 'command': 'migrate-set-parameters',
> +  'data': { 'capabilities': ['MigrationCapabilityStatus'] } }
> +
> +##
> +# @MigrationParameters
> +#
> +# @capabilities: @MigrationCapabilityStatus list contain current migration
> +#                capabilities status
> +# Since: 1.2
> +##
> +{ 'type': 'MigrationParameters',
> +  'data': {'capabilities': ['MigrationCapabilityStatus']} }
> +
> +
> +##
> +# @query-migrate-parameters
> +#
> +# Returns information about the current migration capabilities status
> +#
> +# Returns: @MigrationParameters
> +#
> +# Since: 1.2
> +##
> +{ 'command': 'query-migrate-parameters', 'returns': 'MigrationParameters' }
> +
> +##
>  # @MouseInfo:
>  #
>  # Information about a mouse device.
> diff --git a/qmp-commands.hx b/qmp-commands.hx
> index c0ed14c..7f40e2a 100644
> --- a/qmp-commands.hx
> +++ b/qmp-commands.hx
> @@ -2081,7 +2081,6 @@ The main json-object contains the following:
>           - "transferred": amount transferred (json-int)
>           - "remaining": amount remaining (json-int)
>           - "total": total (json-int)
> -
>  Examples:
>  
>  1. Before the first migration
> @@ -2092,7 +2091,15 @@ Examples:
>  2. Migration is done and has succeeded
>  
>  -> { "execute": "query-migrate" }
> -<- { "return": { "status": "completed" } }
> +<- { "return": {
> +        "status": "completed",
> +        "ram":{
> +          "transferred":123,
> +          "remaining":123,
> +          "total":246
> +        }
> +     }
> +   }
>  
>  3. Migration is done and has failed
>  
> @@ -2165,6 +2172,55 @@ EQMP
>      },
>  
>  SQMP
> +migrate-set-parameters
> +-------
> +
> +Enable/Disable migration capabilities
> +
> +- "xbzrle": xbzrle support
> +
> +Arguments:
> +
> +Example:
> +
> +-> { "execute": "migrate-set-parameters" , "arguments":
> +     { "parameters": [ { "capability": "xbzrle", "state": true } ] } }
> +
> +EQMP
> +
> +    {
> +        .name       = "migrate_set_parameters",
> +        .args_type  = "parameters:O",
> +        .params     = "capability:s,state:b",
> +	.mhandler.cmd_new = qmp_marshal_input_migrate_set_parameters,
> +    },
> +SQMP
> +query-migrate-parameters
> +-------
> +
> +Query current migration parameters
> +
> +- "capabilities": migration capabilities state
> +         - "xbzrle" : XBZRLE state (json-bool)
> +
> +Arguments:
> +
> +Example:
> +
> +-> { "execute": "query-migrate-parameters" }
> +<- { "return": {
> +        "capabilities" :  [ { "capability" : "xbzrle", "state" : false } ]
> +     }
> +   }
> +EQMP
> +
> +    {
> +        .name       = "query-migrate-parameters",
> +        .args_type  = "",
> +        .mhandler.cmd_new = qmp_marshal_input_query_migrate_parameters,
> +    },
> +
> +SQMP
>  query-balloon
>  -------------
>  
> -- 
> 1.7.7.6

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 02/11] Add migrate_set_parameter and query-migrate-parameters
  2012-07-30 19:45   ` Anthony Liguori
@ 2012-07-30 19:58     ` Luiz Capitulino
  2012-07-30 20:04       ` Anthony Liguori
  0 siblings, 1 reply; 47+ messages in thread
From: Luiz Capitulino @ 2012-07-30 19:58 UTC (permalink / raw)
  To: Anthony Liguori
  Cc: peter.maydell, quintela, stefanha, qemu-devel, mdroth, blauwirbel,
	Orit Wasserman, chegu_vinod, avi, pbonzini, eblake

On Mon, 30 Jul 2012 14:45:04 -0500
Anthony Liguori <aliguori@us.ibm.com> wrote:

> Orit Wasserman <owasserm@redhat.com> writes:
> 
> > The management can enable/disable a capability for the next migration by using
> > migrate_set_parameter command.
> > The management can query the current migration capabilities using
> > query-migrate-parameters
> >
> > Signed-off-by: Orit Wasserman <owasserm@redhat.com>
> > Signed-off-by: Juan Quintela <quintela@redhat.com>
> 
> We have a way to add new commands.  Let's not invent a new one.
> Otherwise every subsystem would have it's own approach to querying
> what's available.

I think it does make sense for setting/getting migration's capabilities, which
are just booleans. And that's what the commands currently do, btw.

I'd only recommend to rename them to migrate_set_capability
query-migrate-capabilities.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 02/11] Add migrate_set_parameter and query-migrate-parameters
  2012-07-30 19:58     ` Luiz Capitulino
@ 2012-07-30 20:04       ` Anthony Liguori
  2012-07-30 20:20         ` Luiz Capitulino
  0 siblings, 1 reply; 47+ messages in thread
From: Anthony Liguori @ 2012-07-30 20:04 UTC (permalink / raw)
  To: Luiz Capitulino
  Cc: peter.maydell, quintela, stefanha, qemu-devel, mdroth, blauwirbel,
	Orit Wasserman, chegu_vinod, avi, pbonzini, eblake

Luiz Capitulino <lcapitulino@redhat.com> writes:

> On Mon, 30 Jul 2012 14:45:04 -0500
> Anthony Liguori <aliguori@us.ibm.com> wrote:
>
>> Orit Wasserman <owasserm@redhat.com> writes:
>> 
>> > The management can enable/disable a capability for the next migration by using
>> > migrate_set_parameter command.
>> > The management can query the current migration capabilities using
>> > query-migrate-parameters
>> >
>> > Signed-off-by: Orit Wasserman <owasserm@redhat.com>
>> > Signed-off-by: Juan Quintela <quintela@redhat.com>
>> 
>> We have a way to add new commands.  Let's not invent a new one.
>> Otherwise every subsystem would have it's own approach to querying
>> what's available.
>
> I think it does make sense for setting/getting migration's capabilities, which
> are just booleans. And that's what the commands currently do, btw.
>
> I'd only recommend to rename them to migrate_set_capability
> query-migrate-capabilities.

If that's the intent, it should take/return a list of capabilities
(expressed as an enum).

Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 02/11] Add migrate_set_parameter and query-migrate-parameters
  2012-07-30 20:04       ` Anthony Liguori
@ 2012-07-30 20:20         ` Luiz Capitulino
  0 siblings, 0 replies; 47+ messages in thread
From: Luiz Capitulino @ 2012-07-30 20:20 UTC (permalink / raw)
  To: Anthony Liguori
  Cc: peter.maydell, quintela, stefanha, qemu-devel, mdroth, blauwirbel,
	Orit Wasserman, chegu_vinod, avi, pbonzini, eblake

On Mon, 30 Jul 2012 15:04:57 -0500
Anthony Liguori <aliguori@us.ibm.com> wrote:

> Luiz Capitulino <lcapitulino@redhat.com> writes:
> 
> > On Mon, 30 Jul 2012 14:45:04 -0500
> > Anthony Liguori <aliguori@us.ibm.com> wrote:
> >
> >> Orit Wasserman <owasserm@redhat.com> writes:
> >> 
> >> > The management can enable/disable a capability for the next migration by using
> >> > migrate_set_parameter command.
> >> > The management can query the current migration capabilities using
> >> > query-migrate-parameters
> >> >
> >> > Signed-off-by: Orit Wasserman <owasserm@redhat.com>
> >> > Signed-off-by: Juan Quintela <quintela@redhat.com>
> >> 
> >> We have a way to add new commands.  Let's not invent a new one.
> >> Otherwise every subsystem would have it's own approach to querying
> >> what's available.
> >
> > I think it does make sense for setting/getting migration's capabilities, which
> > are just booleans. And that's what the commands currently do, btw.
> >
> > I'd only recommend to rename them to migrate_set_capability
> > query-migrate-capabilities.
> 
> If that's the intent, it should take/return a list of capabilities
> (expressed as an enum).

Yes, it already does it iirc.

Now, there's something I'm not sure about. This series adds three commands:

 - migrate-set-parameter (should be renamed to migrate-set-capabilities)
 - query-migrate-parameters (should be renamed to query-migrate-capabilities)
 - query-migration-capabilities (should be dropped?)

That last command returns the supported capabilities. We should either,
rename it to query-migration-supported-capabilities or just drop it, because
if a capability appears in (this series') query-migrate-parameters it
means that the capability is supported.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 02/11] Add migrate_set_parameter and query-migrate-parameters
  2012-07-30 19:12   ` Juan Quintela
  2012-07-30 19:24     ` Eric Blake
  2012-07-30 19:37     ` Anthony Liguori
@ 2012-07-30 20:21     ` Juan Quintela
  2 siblings, 0 replies; 47+ messages in thread
From: Juan Quintela @ 2012-07-30 20:21 UTC (permalink / raw)
  To: Orit Wasserman
  Cc: peter.maydell, aliguori, stefanha, qemu-devel, mdroth, blauwirbel,
	chegu_vinod, avi, pbonzini, lcapitulino, eblake

Juan Quintela <quintela@redhat.com> wrote:
> Orit Wasserman <owasserm@redhat.com> wrote:
>> The management can enable/disable a capability for the next migration by using
>> migrate_set_parameter command.
>> The management can query the current migration capabilities using
>> query-migrate-parameters
>>
>> Signed-off-by: Orit Wasserman <owasserm@redhat.com>
>> Signed-off-by: Juan Quintela <quintela@redhat.com>
>
> I just noticed .... shouldn't we use
>
> migrate_set_parameter cache_size 256M
> ???
>
> I think that even the old migration parameters could be added to this
> one?
>
> migrate_set_parameter downtime 30ms
> migrate_set_parameter bandwidth 1G

/me nacks myself.  It appears that I am the only one that thinks that
command explosion is bad O;-)

(and yes, it is a different compromise.)

>
> This way everything would be more regular, and easier on libvirt, as new
> parameters would be trivial to ask for?
>
> Notice that I can understand that we have to maintain the old commands
> for compability, but we can do "regularly" for new ones?
>
> Later, Juan.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 00/11]  Migration next v7
  2012-07-30 19:38 ` [Qemu-devel] [PATCH 00/11] Migration next v7 Luiz Capitulino
@ 2012-07-30 20:36   ` Orit Wasserman
  2012-07-30 22:13   ` Juan Quintela
  1 sibling, 0 replies; 47+ messages in thread
From: Orit Wasserman @ 2012-07-30 20:36 UTC (permalink / raw)
  To: Luiz Capitulino
  Cc: peter.maydell, aliguori, quintela, stefanha, qemu-devel, mdroth,
	blauwirbel, chegu_vinod, avi, pbonzini, eblake

On 07/30/2012 10:38 PM, Luiz Capitulino wrote:
> On Sun, 29 Jul 2012 12:42:52 +0300
> Orit Wasserman <owasserm@redhat.com> wrote:
> 
>> Those are the latest XBZRLE patches (part of the migration next branch).
> 
> I've concentrated my review on the QMP part, which looks good in general, but
> has some details to be fixed.
> 
> I'd like to give this a try btw, but it doesn't apply on top of master. Which
> branch is this against?
> 
Well, those are only the XBZRLE patches, they are based on top another 10 patches.
You can try apply them on git://repo.or.cz/qemu/quintela.git migration-next-v5 branch.

Regards,
Orit

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 00/11]  Migration next v7
  2012-07-30 19:38 ` [Qemu-devel] [PATCH 00/11] Migration next v7 Luiz Capitulino
  2012-07-30 20:36   ` Orit Wasserman
@ 2012-07-30 22:13   ` Juan Quintela
  1 sibling, 0 replies; 47+ messages in thread
From: Juan Quintela @ 2012-07-30 22:13 UTC (permalink / raw)
  To: Luiz Capitulino
  Cc: peter.maydell, aliguori, stefanha, qemu-devel, mdroth, blauwirbel,
	Orit Wasserman, chegu_vinod, avi, pbonzini, eblake

Luiz Capitulino <lcapitulino@redhat.com> wrote:
> On Sun, 29 Jul 2012 12:42:52 +0300
> Orit Wasserman <owasserm@redhat.com> wrote:
>
>> Those are the latest XBZRLE patches (part of the migration next branch).
>
> I've concentrated my review on the QMP part, which looks good in general, but
> has some details to be fixed.
>
> I'd like to give this a try btw, but it doesn't apply on top of master. Which
> branch is this against?

On top of migraration-next-v5 on the list.

Later, Juan.)

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 02/11] Add migrate_set_parameter and query-migrate-parameters
  2012-07-30 17:41   ` Luiz Capitulino
@ 2012-07-31  7:46     ` Orit Wasserman
  2012-07-31 13:09       ` Luiz Capitulino
  2012-07-31  8:03     ` Orit Wasserman
  1 sibling, 1 reply; 47+ messages in thread
From: Orit Wasserman @ 2012-07-31  7:46 UTC (permalink / raw)
  To: Luiz Capitulino
  Cc: peter.maydell, aliguori, quintela, stefanha, qemu-devel, mdroth,
	blauwirbel, chegu_vinod, avi, pbonzini, eblake

On 07/30/2012 08:41 PM, Luiz Capitulino wrote:
> On Sun, 29 Jul 2012 12:42:54 +0300
> Orit Wasserman <owasserm@redhat.com> wrote:
> 
>> The management can enable/disable a capability for the next migration by using
>> migrate_set_parameter command.
>> The management can query the current migration capabilities using
>> query-migrate-parameters
> 
> In general looks good to me, I have a question and a few nitpick comments
> below.
> 
>>
>> Signed-off-by: Orit Wasserman <owasserm@redhat.com>
>> Signed-off-by: Juan Quintela <quintela@redhat.com>
>> ---
>>  hmp-commands.hx  |   16 ++++++++++++
>>  hmp.c            |   71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  hmp.h            |    2 +
>>  migration.c      |   42 +++++++++++++++++++++++++++++++-
>>  migration.h      |    2 +
>>  monitor.c        |    7 +++++
>>  qapi-schema.json |   32 ++++++++++++++++++++++++
>>  qmp-commands.hx  |   60 ++++++++++++++++++++++++++++++++++++++++++++-
>>  8 files changed, 229 insertions(+), 3 deletions(-)
>>
>> diff --git a/hmp-commands.hx b/hmp-commands.hx
>> index 8786148..3e15338 100644
>> --- a/hmp-commands.hx
>> +++ b/hmp-commands.hx
>> @@ -861,6 +861,20 @@ Set maximum tolerated downtime (in seconds) for migration.
>>  ETEXI
>>  
>>      {
>> +        .name       = "migrate_set_parameter",
>> +        .args_type  = "capability:s,state:b",
>> +        .params     = "capability state",
>> +        .help       = "Enable/Disable the usage of a capability for migration",
>> +        .mhandler.cmd = hmp_migrate_set_parameter,
>> +    },
>> +
>> +STEXI
>> +@item migrate_set_parameter @var{capability} @var{state}
>> +@findex migrate_set_parameter
>> +Enable/Disable the usage of a capability @var{capability} for migration.
>> +ETEXI
>> +
>> +    {
>>          .name       = "client_migrate_info",
>>          .args_type  = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?",
>>          .params     = "protocol hostname port tls-port cert-subject",
>> @@ -1419,6 +1433,8 @@ show user network stack connection states
>>  show migration status
>>  @item info migration_capabilities
>>  show migration capabilities
>> +@item info migrate_parameters
>> +show current migration parameters
>>  @item info balloon
>>  show balloon information
>>  @item info qtree
>> diff --git a/hmp.c b/hmp.c
>> index 5c7d0be..f2f63fd 100644
>> --- a/hmp.c
>> +++ b/hmp.c
>> @@ -131,8 +131,22 @@ void hmp_info_mice(Monitor *mon)
>>  void hmp_info_migrate(Monitor *mon)
>>  {
>>      MigrationInfo *info;
>> +    MigrationCapabilityStatusList *cap;
>> +    MigrationParameters *params;
>>  
>>      info = qmp_query_migrate(NULL);
>> +    params = qmp_query_migrate_parameters(NULL);
>> +
>> +    /* do not display parameters during setup */
>> +    if (info->has_status && params->capabilities) {
>> +        monitor_printf(mon, "capabilities: ");
>> +        for (cap = params->capabilities; cap; cap = cap->next) {
>> +            monitor_printf(mon, "%s: %s ",
>> +                           MigrationCapability_lookup[cap->value->capability],
>> +                           cap->value->state ? "on" : "off");
>> +        }
>> +        monitor_printf(mon, "\n");
>> +    }
>>  
>>      if (info->has_status) {
>>          monitor_printf(mon, "Migration status: %s\n", info->status);
>> @@ -159,6 +173,7 @@ void hmp_info_migrate(Monitor *mon)
>>      }
>>  
>>      qapi_free_MigrationInfo(info);
>> +    qapi_free_MigrationParameters(params);
>>  }
>>  
>>  void hmp_info_migration_capabilities(Monitor *mon)
>> @@ -180,6 +195,27 @@ void hmp_info_migration_capabilities(Monitor *mon)
>>      qapi_free_MigrationCapabilityStatusList(caps_list);
>>  }
>>  
>> +void hmp_info_migrate_parameters(Monitor *mon)
>> +{
>> +
>> +    MigrationCapabilityStatusList *cap;
>> +    MigrationParameters *params;
>> +
>> +    params = qmp_query_migrate_parameters(NULL);
>> +
>> +    if (params->capabilities) {
>> +        monitor_printf(mon, "capabilities: ");
>> +        for (cap = params->capabilities; cap; cap = cap->next) {
>> +            monitor_printf(mon, "%s: %s ",
>> +                           MigrationCapability_lookup[cap->value->capability],
>> +                           cap->value->state ? "on" : "off");
>> +        }
>> +        monitor_printf(mon, "\n");
>> +    }
>> +
>> +    qapi_free_MigrationParameters(params);
>> +}
>> +
>>  void hmp_info_cpus(Monitor *mon)
>>  {
>>      CpuInfoList *cpu_list, *cpu;
>> @@ -754,6 +790,41 @@ void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict)
>>      qmp_migrate_set_speed(value, NULL);
>>  }
>>  
>> +void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
>> +{
>> +    const char *cap = qdict_get_str(qdict, "capability");
>> +    bool state = qdict_get_bool(qdict, "state");
>> +    Error *err = NULL;
>> +    MigrationCapabilityStatusList *params = NULL;
>> +    int i;
>> +
>> +    for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
>> +        if (strcmp(cap, MigrationCapability_lookup[i]) == 0) {
>> +            if (!params) {
>> +                params = g_malloc0(sizeof(*params));
>> +            }
> 
> This if shouldn't be necessary, right?
You are right I can always allocate it.
> 
>> +            params->value = g_malloc0(sizeof(*params->value));
>> +            params->value->capability = i;
>> +            params->value->state = state;
>> +            params->next = NULL;
> 
> nitpick: I'd make the code ready for future capabilities.
Could you give me a bit more details ?

Orit
> 
>> +            qmp_migrate_set_parameters(params, &err);
>> +            break;
>> +        }
>> +    }
>> +
>> +    if (i == MIGRATION_CAPABILITY_MAX) {
>> +        error_set(&err, QERR_INVALID_PARAMETER, cap);
>> +    }
>> +
>> +    qapi_free_MigrationCapabilityStatusList(params);
>> +
>> +    if (err) {
>> +        monitor_printf(mon, "migrate_set_parameter: %s\n",
>> +                       error_get_pretty(err));
>> +        error_free(err);
>> +    }
>> +}
>> +
>>  void hmp_set_password(Monitor *mon, const QDict *qdict)
>>  {
>>      const char *protocol  = qdict_get_str(qdict, "protocol");
>> diff --git a/hmp.h b/hmp.h
>> index 2fb44ca..ceb2f06 100644
>> --- a/hmp.h
>> +++ b/hmp.h
>> @@ -26,6 +26,7 @@ void hmp_info_chardev(Monitor *mon);
>>  void hmp_info_mice(Monitor *mon);
>>  void hmp_info_migrate(Monitor *mon);
>>  void hmp_info_migration_capabilities(Monitor *mon);
>> +void hmp_info_migrate_parameters(Monitor *mon);
>>  void hmp_info_cpus(Monitor *mon);
>>  void hmp_info_block(Monitor *mon);
>>  void hmp_info_blockstats(Monitor *mon);
>> @@ -52,6 +53,7 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict);
>>  void hmp_migrate_cancel(Monitor *mon, const QDict *qdict);
>>  void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict);
>>  void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict);
>> +void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict);
>>  void hmp_set_password(Monitor *mon, const QDict *qdict);
>>  void hmp_expire_password(Monitor *mon, const QDict *qdict);
>>  void hmp_eject(Monitor *mon, const QDict *qdict);
>> diff --git a/migration.c b/migration.c
>> index 8c27347..e844290 100644
>> --- a/migration.c
>> +++ b/migration.c
>> @@ -113,6 +113,25 @@ uint64_t migrate_max_downtime(void)
>>      return max_downtime;
>>  }
>>  
>> +MigrationParameters *qmp_query_migrate_parameters(Error **errp)
>> +{
>> +    MigrationParameters *params = g_malloc0(sizeof(*params));
>> +    MigrationState *s = migrate_get_current();
>> +    int i;
>> +
>> +    params->capabilities = g_malloc0(sizeof(*params->capabilities));
>> +
>> +    for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
>> +        params->capabilities->value =
>> +            g_malloc(sizeof(*params->capabilities->value));
>> +        params->capabilities->value->capability = i;
>> +        params->capabilities->value->state = s->enabled_capabilities[i];
>> +        params->capabilities->next = NULL;
>> +    }
>> +
>> +    return params;
>> +}
>> +
>>  MigrationInfo *qmp_query_migrate(Error **errp)
>>  {
>>      MigrationInfo *info = g_malloc0(sizeof(*info));
>> @@ -177,6 +196,22 @@ MigrationCapabilityStatusList *qmp_query_migration_capabilities(Error **errp)
>>      return caps_list;
>>  }
>>  
>> +void qmp_migrate_set_parameters(MigrationCapabilityStatusList *params,
>> +                                Error **errp)
>> +{
>> +    MigrationState *s = migrate_get_current();
>> +    MigrationCapabilityStatusList *cap;
>> +
>> +    if (s->state == MIG_STATE_ACTIVE) {
>> +        error_set(errp, QERR_MIGRATION_ACTIVE);
>> +        return;
>> +    }
>> +
>> +    for (cap = params; cap; cap = cap->next) {
>> +        s->enabled_capabilities[cap->value->capability] = cap->value->state;
>> +    }
>> +}
>> +
>>  /* shared migration helpers */
>>  
>>  static int migrate_fd_cleanup(MigrationState *s)
>> @@ -386,12 +421,17 @@ static MigrationState *migrate_init(const MigrationParams *params)
>>  {
>>      MigrationState *s = migrate_get_current();
>>      int64_t bandwidth_limit = s->bandwidth_limit;
>> +    bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
>> +
>> +    memcpy(enabled_capabilities, s->enabled_capabilities,
>> +           sizeof(enabled_capabilities));
> 
> Is s->enabled_capabilities initialized somewhere or are we making xbzrle
> disabled by default?
> 
>>  
>>      memset(s, 0, sizeof(*s));
>>      s->bandwidth_limit = bandwidth_limit;
>>      s->params = *params;
>> +    memcpy(s->enabled_capabilities, enabled_capabilities,
>> +           sizeof(enabled_capabilities));
>>  
>> -    s->bandwidth_limit = bandwidth_limit;
> 
> Unrelated change.
> 
>>      s->state = MIG_STATE_SETUP;
>>      s->total_time = qemu_get_clock_ms(rt_clock);
>>  
>> diff --git a/migration.h b/migration.h
>> index 57572a6..713aae0 100644
>> --- a/migration.h
>> +++ b/migration.h
>> @@ -19,6 +19,7 @@
>>  #include "notify.h"
>>  #include "error.h"
>>  #include "vmstate.h"
>> +#include "qapi-types.h"
>>  
>>  struct MigrationParams {
>>      bool blk;
>> @@ -39,6 +40,7 @@ struct MigrationState
>>      void *opaque;
>>      MigrationParams params;
>>      int64_t total_time;
>> +    bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
>>  };
>>  
>>  void process_incoming_migration(QEMUFile *f);
>> diff --git a/monitor.c b/monitor.c
>> index fd57c5e..e07af97 100644
>> --- a/monitor.c
>> +++ b/monitor.c
>> @@ -2669,6 +2669,13 @@ static mon_cmd_t info_cmds[] = {
>>          .mhandler.info = hmp_info_migration_capabilities,
>>      },
>>      {
>> +        .name       = "migrate-parameters",
>> +        .args_type  = "",
>> +        .params     = "",
>> +        .help       = "show current migration parameters",
>> +        .mhandler.info = hmp_info_migrate_parameters,
>> +    },
>> +    {
>>          .name       = "balloon",
>>          .args_type  = "",
>>          .params     = "",
>> diff --git a/qapi-schema.json b/qapi-schema.json
>> index b4d4dd6..9d6759d 100644
>> --- a/qapi-schema.json
>> +++ b/qapi-schema.json
>> @@ -345,6 +345,38 @@
>>  { 'command': 'query-migration-capabilities', 'returns': ['MigrationCapabilityStatus'] }
>>  
>>  ##
>> +# @migrate-set-parameters
>> +#
>> +# Enable/Disable the following migration capabilities (like xbzrle)
>> +#
>> +# Since: 1.2
>> +##
>> +{ 'command': 'migrate-set-parameters',
>> +  'data': { 'capabilities': ['MigrationCapabilityStatus'] } }
>> +
>> +##
>> +# @MigrationParameters
>> +#
>> +# @capabilities: @MigrationCapabilityStatus list contain current migration
>> +#                capabilities status
>> +# Since: 1.2
>> +##
>> +{ 'type': 'MigrationParameters',
>> +  'data': {'capabilities': ['MigrationCapabilityStatus']} }
>> +
>> +
>> +##
>> +# @query-migrate-parameters
>> +#
>> +# Returns information about the current migration capabilities status
>> +#
>> +# Returns: @MigrationParameters
>> +#
>> +# Since: 1.2
>> +##
>> +{ 'command': 'query-migrate-parameters', 'returns': 'MigrationParameters' }
>> +
>> +##
>>  # @MouseInfo:
>>  #
>>  # Information about a mouse device.
>> diff --git a/qmp-commands.hx b/qmp-commands.hx
>> index c0ed14c..7f40e2a 100644
>> --- a/qmp-commands.hx
>> +++ b/qmp-commands.hx
>> @@ -2081,7 +2081,6 @@ The main json-object contains the following:
>>           - "transferred": amount transferred (json-int)
>>           - "remaining": amount remaining (json-int)
>>           - "total": total (json-int)
>> -
>>  Examples:
>>  
>>  1. Before the first migration
>> @@ -2092,7 +2091,15 @@ Examples:
>>  2. Migration is done and has succeeded
>>  
>>  -> { "execute": "query-migrate" }
>> -<- { "return": { "status": "completed" } }
>> +<- { "return": {
>> +        "status": "completed",
>> +        "ram":{
>> +          "transferred":123,
>> +          "remaining":123,
>> +          "total":246
>> +        }
>> +     }
>> +   }
>>  
>>  3. Migration is done and has failed
>>  
>> @@ -2165,6 +2172,55 @@ EQMP
>>      },
>>  
>>  SQMP
>> +migrate-set-parameters
>> +-------
>> +
>> +Enable/Disable migration capabilities
>> +
>> +- "xbzrle": xbzrle support
>> +
>> +Arguments:
>> +
>> +Example:
>> +
>> +-> { "execute": "migrate-set-parameters" , "arguments":
>> +     { "parameters": [ { "capability": "xbzrle", "state": true } ] } }
>> +
>> +EQMP
>> +
>> +    {
>> +        .name       = "migrate_set_parameters",
>> +        .args_type  = "parameters:O",
>> +        .params     = "capability:s,state:b",
>> +	.mhandler.cmd_new = qmp_marshal_input_migrate_set_parameters,
>> +    },
>> +SQMP
>> +query-migrate-parameters
>> +-------
>> +
>> +Query current migration parameters
>> +
>> +- "capabilities": migration capabilities state
>> +         - "xbzrle" : XBZRLE state (json-bool)
>> +
>> +Arguments:
>> +
>> +Example:
>> +
>> +-> { "execute": "query-migrate-parameters" }
>> +<- { "return": {
>> +        "capabilities" :  [ { "capability" : "xbzrle", "state" : false } ]
>> +     }
>> +   }
>> +EQMP
>> +
>> +    {
>> +        .name       = "query-migrate-parameters",
>> +        .args_type  = "",
>> +        .mhandler.cmd_new = qmp_marshal_input_query_migrate_parameters,
>> +    },
>> +
>> +SQMP
>>  query-balloon
>>  -------------
>>  
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 02/11] Add migrate_set_parameter and query-migrate-parameters
  2012-07-30 17:41   ` Luiz Capitulino
  2012-07-31  7:46     ` Orit Wasserman
@ 2012-07-31  8:03     ` Orit Wasserman
  1 sibling, 0 replies; 47+ messages in thread
From: Orit Wasserman @ 2012-07-31  8:03 UTC (permalink / raw)
  To: Luiz Capitulino
  Cc: peter.maydell, aliguori, quintela, stefanha, qemu-devel, mdroth,
	blauwirbel, chegu_vinod, avi, pbonzini, eblake

On 07/30/2012 08:41 PM, Luiz Capitulino wrote:
> On Sun, 29 Jul 2012 12:42:54 +0300
> Orit Wasserman <owasserm@redhat.com> wrote:
> 
>> The management can enable/disable a capability for the next migration by using
>> migrate_set_parameter command.
>> The management can query the current migration capabilities using
>> query-migrate-parameters
> 
> In general looks good to me, I have a question and a few nitpick comments
> below.
> 
>>
>> Signed-off-by: Orit Wasserman <owasserm@redhat.com>
>> Signed-off-by: Juan Quintela <quintela@redhat.com>
>> ---
>>  hmp-commands.hx  |   16 ++++++++++++
>>  hmp.c            |   71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  hmp.h            |    2 +
>>  migration.c      |   42 +++++++++++++++++++++++++++++++-
>>  migration.h      |    2 +
>>  monitor.c        |    7 +++++
>>  qapi-schema.json |   32 ++++++++++++++++++++++++
>>  qmp-commands.hx  |   60 ++++++++++++++++++++++++++++++++++++++++++++-
>>  8 files changed, 229 insertions(+), 3 deletions(-)
>>
>> diff --git a/hmp-commands.hx b/hmp-commands.hx
>> index 8786148..3e15338 100644
>> --- a/hmp-commands.hx
>> +++ b/hmp-commands.hx
>> @@ -861,6 +861,20 @@ Set maximum tolerated downtime (in seconds) for migration.
>>  ETEXI
>>  
>>      {
>> +        .name       = "migrate_set_parameter",
>> +        .args_type  = "capability:s,state:b",
>> +        .params     = "capability state",
>> +        .help       = "Enable/Disable the usage of a capability for migration",
>> +        .mhandler.cmd = hmp_migrate_set_parameter,
>> +    },
>> +
>> +STEXI
>> +@item migrate_set_parameter @var{capability} @var{state}
>> +@findex migrate_set_parameter
>> +Enable/Disable the usage of a capability @var{capability} for migration.
>> +ETEXI
>> +
>> +    {
>>          .name       = "client_migrate_info",
>>          .args_type  = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?",
>>          .params     = "protocol hostname port tls-port cert-subject",
>> @@ -1419,6 +1433,8 @@ show user network stack connection states
>>  show migration status
>>  @item info migration_capabilities
>>  show migration capabilities
>> +@item info migrate_parameters
>> +show current migration parameters
>>  @item info balloon
>>  show balloon information
>>  @item info qtree
>> diff --git a/hmp.c b/hmp.c
>> index 5c7d0be..f2f63fd 100644
>> --- a/hmp.c
>> +++ b/hmp.c
>> @@ -131,8 +131,22 @@ void hmp_info_mice(Monitor *mon)
>>  void hmp_info_migrate(Monitor *mon)
>>  {
>>      MigrationInfo *info;
>> +    MigrationCapabilityStatusList *cap;
>> +    MigrationParameters *params;
>>  
>>      info = qmp_query_migrate(NULL);
>> +    params = qmp_query_migrate_parameters(NULL);
>> +
>> +    /* do not display parameters during setup */
>> +    if (info->has_status && params->capabilities) {
>> +        monitor_printf(mon, "capabilities: ");
>> +        for (cap = params->capabilities; cap; cap = cap->next) {
>> +            monitor_printf(mon, "%s: %s ",
>> +                           MigrationCapability_lookup[cap->value->capability],
>> +                           cap->value->state ? "on" : "off");
>> +        }
>> +        monitor_printf(mon, "\n");
>> +    }
>>  
>>      if (info->has_status) {
>>          monitor_printf(mon, "Migration status: %s\n", info->status);
>> @@ -159,6 +173,7 @@ void hmp_info_migrate(Monitor *mon)
>>      }
>>  
>>      qapi_free_MigrationInfo(info);
>> +    qapi_free_MigrationParameters(params);
>>  }
>>  
>>  void hmp_info_migration_capabilities(Monitor *mon)
>> @@ -180,6 +195,27 @@ void hmp_info_migration_capabilities(Monitor *mon)
>>      qapi_free_MigrationCapabilityStatusList(caps_list);
>>  }
>>  
>> +void hmp_info_migrate_parameters(Monitor *mon)
>> +{
>> +
>> +    MigrationCapabilityStatusList *cap;
>> +    MigrationParameters *params;
>> +
>> +    params = qmp_query_migrate_parameters(NULL);
>> +
>> +    if (params->capabilities) {
>> +        monitor_printf(mon, "capabilities: ");
>> +        for (cap = params->capabilities; cap; cap = cap->next) {
>> +            monitor_printf(mon, "%s: %s ",
>> +                           MigrationCapability_lookup[cap->value->capability],
>> +                           cap->value->state ? "on" : "off");
>> +        }
>> +        monitor_printf(mon, "\n");
>> +    }
>> +
>> +    qapi_free_MigrationParameters(params);
>> +}
>> +
>>  void hmp_info_cpus(Monitor *mon)
>>  {
>>      CpuInfoList *cpu_list, *cpu;
>> @@ -754,6 +790,41 @@ void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict)
>>      qmp_migrate_set_speed(value, NULL);
>>  }
>>  
>> +void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
>> +{
>> +    const char *cap = qdict_get_str(qdict, "capability");
>> +    bool state = qdict_get_bool(qdict, "state");
>> +    Error *err = NULL;
>> +    MigrationCapabilityStatusList *params = NULL;
>> +    int i;
>> +
>> +    for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
>> +        if (strcmp(cap, MigrationCapability_lookup[i]) == 0) {
>> +            if (!params) {
>> +                params = g_malloc0(sizeof(*params));
>> +            }
> 
> This if shouldn't be necessary, right?
> 
>> +            params->value = g_malloc0(sizeof(*params->value));
>> +            params->value->capability = i;
>> +            params->value->state = state;
>> +            params->next = NULL;
> 
> nitpick: I'd make the code ready for future capabilities.
> 
>> +            qmp_migrate_set_parameters(params, &err);
>> +            break;
>> +        }
>> +    }
>> +
>> +    if (i == MIGRATION_CAPABILITY_MAX) {
>> +        error_set(&err, QERR_INVALID_PARAMETER, cap);
>> +    }
>> +
>> +    qapi_free_MigrationCapabilityStatusList(params);
>> +
>> +    if (err) {
>> +        monitor_printf(mon, "migrate_set_parameter: %s\n",
>> +                       error_get_pretty(err));
>> +        error_free(err);
>> +    }
>> +}
>> +
>>  void hmp_set_password(Monitor *mon, const QDict *qdict)
>>  {
>>      const char *protocol  = qdict_get_str(qdict, "protocol");
>> diff --git a/hmp.h b/hmp.h
>> index 2fb44ca..ceb2f06 100644
>> --- a/hmp.h
>> +++ b/hmp.h
>> @@ -26,6 +26,7 @@ void hmp_info_chardev(Monitor *mon);
>>  void hmp_info_mice(Monitor *mon);
>>  void hmp_info_migrate(Monitor *mon);
>>  void hmp_info_migration_capabilities(Monitor *mon);
>> +void hmp_info_migrate_parameters(Monitor *mon);
>>  void hmp_info_cpus(Monitor *mon);
>>  void hmp_info_block(Monitor *mon);
>>  void hmp_info_blockstats(Monitor *mon);
>> @@ -52,6 +53,7 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict);
>>  void hmp_migrate_cancel(Monitor *mon, const QDict *qdict);
>>  void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict);
>>  void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict);
>> +void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict);
>>  void hmp_set_password(Monitor *mon, const QDict *qdict);
>>  void hmp_expire_password(Monitor *mon, const QDict *qdict);
>>  void hmp_eject(Monitor *mon, const QDict *qdict);
>> diff --git a/migration.c b/migration.c
>> index 8c27347..e844290 100644
>> --- a/migration.c
>> +++ b/migration.c
>> @@ -113,6 +113,25 @@ uint64_t migrate_max_downtime(void)
>>      return max_downtime;
>>  }
>>  
>> +MigrationParameters *qmp_query_migrate_parameters(Error **errp)
>> +{
>> +    MigrationParameters *params = g_malloc0(sizeof(*params));
>> +    MigrationState *s = migrate_get_current();
>> +    int i;
>> +
>> +    params->capabilities = g_malloc0(sizeof(*params->capabilities));
>> +
>> +    for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
>> +        params->capabilities->value =
>> +            g_malloc(sizeof(*params->capabilities->value));
>> +        params->capabilities->value->capability = i;
>> +        params->capabilities->value->state = s->enabled_capabilities[i];
>> +        params->capabilities->next = NULL;
>> +    }
>> +
>> +    return params;
>> +}
>> +
>>  MigrationInfo *qmp_query_migrate(Error **errp)
>>  {
>>      MigrationInfo *info = g_malloc0(sizeof(*info));
>> @@ -177,6 +196,22 @@ MigrationCapabilityStatusList *qmp_query_migration_capabilities(Error **errp)
>>      return caps_list;
>>  }
>>  
>> +void qmp_migrate_set_parameters(MigrationCapabilityStatusList *params,
>> +                                Error **errp)
>> +{
>> +    MigrationState *s = migrate_get_current();
>> +    MigrationCapabilityStatusList *cap;
>> +
>> +    if (s->state == MIG_STATE_ACTIVE) {
>> +        error_set(errp, QERR_MIGRATION_ACTIVE);
>> +        return;
>> +    }
>> +
>> +    for (cap = params; cap; cap = cap->next) {
>> +        s->enabled_capabilities[cap->value->capability] = cap->value->state;
>> +    }
>> +}
>> +
>>  /* shared migration helpers */
>>  
>>  static int migrate_fd_cleanup(MigrationState *s)
>> @@ -386,12 +421,17 @@ static MigrationState *migrate_init(const MigrationParams *params)
>>  {
>>      MigrationState *s = migrate_get_current();
>>      int64_t bandwidth_limit = s->bandwidth_limit;
>> +    bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
>> +
>> +    memcpy(enabled_capabilities, s->enabled_capabilities,
>> +           sizeof(enabled_capabilities));
> 
> Is s->enabled_capabilities initialized somewhere or are we making xbzrle
> disabled by default?
It is automatically zeroed because it is static, which means all capabilities are
disabled by default

Orit
> 
>>  
>>      memset(s, 0, sizeof(*s));
>>      s->bandwidth_limit = bandwidth_limit;
>>      s->params = *params;
>> +    memcpy(s->enabled_capabilities, enabled_capabilities,
>> +           sizeof(enabled_capabilities));
>>  
>> -    s->bandwidth_limit = bandwidth_limit;
> 
> Unrelated change.
> 
>>      s->state = MIG_STATE_SETUP;
>>      s->total_time = qemu_get_clock_ms(rt_clock);
>>  
>> diff --git a/migration.h b/migration.h
>> index 57572a6..713aae0 100644
>> --- a/migration.h
>> +++ b/migration.h
>> @@ -19,6 +19,7 @@
>>  #include "notify.h"
>>  #include "error.h"
>>  #include "vmstate.h"
>> +#include "qapi-types.h"
>>  
>>  struct MigrationParams {
>>      bool blk;
>> @@ -39,6 +40,7 @@ struct MigrationState
>>      void *opaque;
>>      MigrationParams params;
>>      int64_t total_time;
>> +    bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
>>  };
>>  
>>  void process_incoming_migration(QEMUFile *f);
>> diff --git a/monitor.c b/monitor.c
>> index fd57c5e..e07af97 100644
>> --- a/monitor.c
>> +++ b/monitor.c
>> @@ -2669,6 +2669,13 @@ static mon_cmd_t info_cmds[] = {
>>          .mhandler.info = hmp_info_migration_capabilities,
>>      },
>>      {
>> +        .name       = "migrate-parameters",
>> +        .args_type  = "",
>> +        .params     = "",
>> +        .help       = "show current migration parameters",
>> +        .mhandler.info = hmp_info_migrate_parameters,
>> +    },
>> +    {
>>          .name       = "balloon",
>>          .args_type  = "",
>>          .params     = "",
>> diff --git a/qapi-schema.json b/qapi-schema.json
>> index b4d4dd6..9d6759d 100644
>> --- a/qapi-schema.json
>> +++ b/qapi-schema.json
>> @@ -345,6 +345,38 @@
>>  { 'command': 'query-migration-capabilities', 'returns': ['MigrationCapabilityStatus'] }
>>  
>>  ##
>> +# @migrate-set-parameters
>> +#
>> +# Enable/Disable the following migration capabilities (like xbzrle)
>> +#
>> +# Since: 1.2
>> +##
>> +{ 'command': 'migrate-set-parameters',
>> +  'data': { 'capabilities': ['MigrationCapabilityStatus'] } }
>> +
>> +##
>> +# @MigrationParameters
>> +#
>> +# @capabilities: @MigrationCapabilityStatus list contain current migration
>> +#                capabilities status
>> +# Since: 1.2
>> +##
>> +{ 'type': 'MigrationParameters',
>> +  'data': {'capabilities': ['MigrationCapabilityStatus']} }
>> +
>> +
>> +##
>> +# @query-migrate-parameters
>> +#
>> +# Returns information about the current migration capabilities status
>> +#
>> +# Returns: @MigrationParameters
>> +#
>> +# Since: 1.2
>> +##
>> +{ 'command': 'query-migrate-parameters', 'returns': 'MigrationParameters' }
>> +
>> +##
>>  # @MouseInfo:
>>  #
>>  # Information about a mouse device.
>> diff --git a/qmp-commands.hx b/qmp-commands.hx
>> index c0ed14c..7f40e2a 100644
>> --- a/qmp-commands.hx
>> +++ b/qmp-commands.hx
>> @@ -2081,7 +2081,6 @@ The main json-object contains the following:
>>           - "transferred": amount transferred (json-int)
>>           - "remaining": amount remaining (json-int)
>>           - "total": total (json-int)
>> -
>>  Examples:
>>  
>>  1. Before the first migration
>> @@ -2092,7 +2091,15 @@ Examples:
>>  2. Migration is done and has succeeded
>>  
>>  -> { "execute": "query-migrate" }
>> -<- { "return": { "status": "completed" } }
>> +<- { "return": {
>> +        "status": "completed",
>> +        "ram":{
>> +          "transferred":123,
>> +          "remaining":123,
>> +          "total":246
>> +        }
>> +     }
>> +   }
>>  
>>  3. Migration is done and has failed
>>  
>> @@ -2165,6 +2172,55 @@ EQMP
>>      },
>>  
>>  SQMP
>> +migrate-set-parameters
>> +-------
>> +
>> +Enable/Disable migration capabilities
>> +
>> +- "xbzrle": xbzrle support
>> +
>> +Arguments:
>> +
>> +Example:
>> +
>> +-> { "execute": "migrate-set-parameters" , "arguments":
>> +     { "parameters": [ { "capability": "xbzrle", "state": true } ] } }
>> +
>> +EQMP
>> +
>> +    {
>> +        .name       = "migrate_set_parameters",
>> +        .args_type  = "parameters:O",
>> +        .params     = "capability:s,state:b",
>> +	.mhandler.cmd_new = qmp_marshal_input_migrate_set_parameters,
>> +    },
>> +SQMP
>> +query-migrate-parameters
>> +-------
>> +
>> +Query current migration parameters
>> +
>> +- "capabilities": migration capabilities state
>> +         - "xbzrle" : XBZRLE state (json-bool)
>> +
>> +Arguments:
>> +
>> +Example:
>> +
>> +-> { "execute": "query-migrate-parameters" }
>> +<- { "return": {
>> +        "capabilities" :  [ { "capability" : "xbzrle", "state" : false } ]
>> +     }
>> +   }
>> +EQMP
>> +
>> +    {
>> +        .name       = "query-migrate-parameters",
>> +        .args_type  = "",
>> +        .mhandler.cmd_new = qmp_marshal_input_query_migrate_parameters,
>> +    },
>> +
>> +SQMP
>>  query-balloon
>>  -------------
>>  
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 10/11] Add XBZRLE statistics
  2012-07-30 19:37   ` Luiz Capitulino
@ 2012-07-31  8:31     ` Orit Wasserman
  2012-07-31 13:16       ` Luiz Capitulino
  0 siblings, 1 reply; 47+ messages in thread
From: Orit Wasserman @ 2012-07-31  8:31 UTC (permalink / raw)
  To: Luiz Capitulino
  Cc: peter.maydell, aliguori, quintela, stefanha, qemu-devel,
	Benoit Hudzia, mdroth, blauwirbel, Petter Svard, chegu_vinod, avi,
	Aidan Shribman, pbonzini, eblake

On 07/30/2012 10:37 PM, Luiz Capitulino wrote:
> On Sun, 29 Jul 2012 12:43:02 +0300
> Orit Wasserman <owasserm@redhat.com> wrote:
> 
>> Signed-off-by: Benoit Hudzia <benoit.hudzia@sap.com>
>> Signed-off-by: Petter Svard <petters@cs.umu.se>
>> Signed-off-by: Aidan Shribman <aidan.shribman@sap.com>
>> Signed-off-by: Orit Wasserman <owasserm@redhat.com>
>> Signed-off-by: Juan Quintela <quintela@redhat.com>
>> ---
>>  arch_init.c      |   28 ++++++++++++++++++++++++++++
>>  hmp.c            |   21 +++++++++++++++++++++
>>  migration.c      |   28 ++++++++++++++++++++++++++++
>>  migration.h      |    4 ++++
>>  qapi-schema.json |   32 +++++++++++++++++++++++++++++++-
>>  qmp-commands.hx  |   35 +++++++++++++++++++++++++++++++++++
>>  6 files changed, 147 insertions(+), 1 deletions(-)
>>
>> diff --git a/arch_init.c b/arch_init.c
>> index 7f12317..9833d54 100644
>> --- a/arch_init.c
>> +++ b/arch_init.c
>> @@ -203,7 +203,11 @@ int64_t xbzrle_cache_resize(int64_t new_size)
>>  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;
>> @@ -233,6 +237,26 @@ 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;
>> +}
>> +
>>  static void save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset,
>>          int cont, int flag)
>>  {
>> @@ -257,6 +281,7 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
>>      if (!cache_is_cached(XBZRLE.cache, current_addr)) {
>>          cache_insert(XBZRLE.cache, current_addr,
>>                       g_memdup(current_data, TARGET_PAGE_SIZE));
>> +        acct_info.xbzrle_cache_miss++;
>>          return -1;
>>      }
>>  
>> @@ -274,6 +299,7 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
>>          return 0;
>>      } else if (encoded_len == -1) {
>>          DPRINTF("Overflow\n");
>> +        acct_info.xbzrle_overflows++;
>>          /* update data in the cache */
>>          memcpy(prev_cached_page, current_data, TARGET_PAGE_SIZE);
>>          return -1;
>> @@ -288,6 +314,8 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
>>      qemu_put_be16(f, encoded_len);
>>      qemu_put_buffer(f, XBZRLE.encoded_buf, encoded_len);
>>      bytes_sent = encoded_len + 1 + 2;
>> +    acct_info.xbzrle_pages++;
>> +    acct_info.xbzrle_bytes += bytes_sent;
>>  
>>      return bytes_sent;
>>  }
>> diff --git a/hmp.c b/hmp.c
>> index 9770d7b..383d5b1 100644
>> --- a/hmp.c
>> +++ b/hmp.c
>> @@ -172,6 +172,27 @@ void hmp_info_migrate(Monitor *mon)
>>                         info->disk->total >> 10);
>>      }
>>  
>> +    if (info->has_xbzrle_cache) {
>> +        monitor_printf(mon, "cache size: %" PRIu64 " bytes\n",
>> +                       info->xbzrle_cache->cache_size);
>> +        if (info->xbzrle_cache->has_xbzrle_bytes) {
>> +            monitor_printf(mon, "xbzrle transferred: %" PRIu64 " kbytes\n",
>> +                           info->xbzrle_cache->xbzrle_bytes >> 10);
>> +        }
>> +        if (info->xbzrle_cache->has_xbzrle_pages) {
>> +            monitor_printf(mon, "xbzrle pages: %" PRIu64 " pages\n",
>> +                           info->xbzrle_cache->xbzrle_pages);
>> +        }
>> +        if (info->xbzrle_cache->has_xbzrle_cache_miss) {
>> +            monitor_printf(mon, "xbzrle cache miss: %" PRIu64 "\n",
>> +                           info->xbzrle_cache->xbzrle_cache_miss);
>> +        }
>> +        if (info->xbzrle_cache->has_xbzrle_overflow) {
>> +            monitor_printf(mon, "xbzrle overflow : %" PRIu64 "\n",
>> +                           info->xbzrle_cache->xbzrle_overflow);
>> +        }
>> +    }
>> +
>>      qapi_free_MigrationInfo(info);
>>      qapi_free_MigrationParameters(params);
>>  }
>> diff --git a/migration.c b/migration.c
>> index 4dc99ba..fb802bc 100644
>> --- a/migration.c
>> +++ b/migration.c
>> @@ -136,6 +136,23 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp)
>>      return params;
>>  }
>>  
>> +static void get_xbzrle_cache_stats(MigrationInfo *info)
>> +{
>> +    if (migrate_use_xbzrle()) {
>> +        info->has_xbzrle_cache = true;
>> +        info->xbzrle_cache = g_malloc0(sizeof(*info->xbzrle_cache));
>> +        info->xbzrle_cache->cache_size = migrate_xbzrle_cache_size();
>> +        info->xbzrle_cache->has_xbzrle_bytes = true;
>> +        info->xbzrle_cache->xbzrle_bytes = xbzrle_mig_bytes_transferred();
>> +        info->xbzrle_cache->has_xbzrle_pages = true;
>> +        info->xbzrle_cache->xbzrle_pages = xbzrle_mig_pages_transferred();
>> +        info->xbzrle_cache->has_xbzrle_cache_miss = true;
>> +        info->xbzrle_cache->xbzrle_cache_miss = xbzrle_mig_pages_cache_miss();
>> +        info->xbzrle_cache->has_xbzrle_overflow = true;
>> +        info->xbzrle_cache->xbzrle_overflow = xbzrle_mig_pages_overflow();
>> +    }
>> +}
>> +
>>  MigrationInfo *qmp_query_migrate(Error **errp)
>>  {
>>      MigrationInfo *info = g_malloc0(sizeof(*info));
>> @@ -144,6 +161,13 @@ MigrationInfo *qmp_query_migrate(Error **errp)
>>      switch (s->state) {
>>      case MIG_STATE_SETUP:
>>          /* no migration has happened ever */
>> +
>> +        /* display xbzrle cache size */
>> +        if (migrate_use_xbzrle()) {
>> +            info->has_xbzrle_cache = true;
>> +            info->xbzrle_cache = g_malloc0(sizeof(*info->xbzrle_cache));
>> +            info->xbzrle_cache->cache_size = migrate_xbzrle_cache_size();
>> +        }
> 
> Is it really useful to return this in MIG_SETUP? Can't the cache size
> be queried by some query- command?
I like it this way and it is very simple to use, you need to use query-migrate command if you do migration 
anyway.
Otherwise we will need to add a query command for each configurable parameters,
so one for speed and another for downtime and probably more in the future.
This way we use one command to query the migration setup.

Orit
> 
>>          break;
>>      case MIG_STATE_ACTIVE:
>>          info->has_status = true;
>> @@ -166,8 +190,12 @@ MigrationInfo *qmp_query_migrate(Error **errp)
>>              info->disk->remaining = blk_mig_bytes_remaining();
>>              info->disk->total = blk_mig_bytes_total();
>>          }
>> +
>> +        get_xbzrle_cache_stats(info);
>>          break;
>>      case MIG_STATE_COMPLETED:
>> +        get_xbzrle_cache_stats(info);
>> +
>>          info->has_status = true;
>>          info->status = g_strdup("completed");
>>  
>> diff --git a/migration.h b/migration.h
>> index e4a7cd7..a9852fc 100644
>> --- a/migration.h
>> +++ b/migration.h
>> @@ -91,6 +91,10 @@ 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);
>>  
>>  /**
>>   * @migrate_add_blocker - prevent migration from proceeding
>> diff --git a/qapi-schema.json b/qapi-schema.json
>> index a936714..91dee72 100644
>> --- a/qapi-schema.json
>> +++ b/qapi-schema.json
>> @@ -275,6 +275,31 @@
>>             'total_time': 'int', 'duplicate': 'int', 'normal': 'int' } }
>>  
>>  ##
>> +# @XBZRLECacheStats
>> +#
>> +# Detailed XBZRLE migration cache statistics
>> +#
>> +# @cache-size: XBZRLE cache size
>> +#
>> +# @xbzrle-bytes: @optional, amount of bytes already transferred to the target VM
>> +#                only returned when migration is active or completed
> 
> s/xbzrle-bytes/transferred-bytes
> 
>> +#
>> +# @xbzrle-pages: @optional, amount of pages transferred to the target VM
>> +#                only returned when migration is active or completed
> 
> s/xbzrle-pages/transferred-pages
> 
>> +#
>> +# @xbzrle-cache-miss: @optional, number of cache miss
>> +#                     only returned when migration is active or completed
> 
> s/xbzrle/xbzrle//
> 
>> +#
>> +# @xbzrle-overflow: @optional, number of overflows
>> +#                   only returned when migration is active or completed
> 
> s/xbzrle///
> 
> Besides, all these parameters shouldn't be optional as they are unconditionally
> included (BZRLECacheStats itself is optional as returned by query-migrate).
> 
>> +#
>> +# Since: 1.2
>> +##
>> +{ 'type': 'XBZRLECacheStats',
>> +  'data': {'cache-size': 'int', '*xbzrle-bytes': 'int', '*xbzrle-pages': 'int',
>> +           '*xbzrle-cache-miss': 'int', '*xbzrle-overflow': 'int' } }
>> +
>> +##
>>  # @MigrationInfo
>>  #
>>  # Information about current migration process.
>> @@ -292,11 +317,16 @@
>>  #        status, only returned if status is 'active' and it is a block
>>  #        migration
>>  #
>> +# @xbzrle-cache: #optional @XBZRLECacheStats containing detailed XBZRLE
>> +#                migration statistics, only returned if XBZRLE feature is on
>> +#                (since 1.2)
>> +#
>>  # Since: 0.14.0
>>  ##
>>  { 'type': 'MigrationInfo',
>>    'data': {'*status': 'str', '*ram': 'MigrationStats',
>> -           '*disk': 'MigrationStats'} }
>> +           '*disk': 'MigrationStats',
>> +           '*xbzrle-cache': 'XBZRLECacheStats'} }
>>  
>>  ##
>>  # @query-migrate
>> diff --git a/qmp-commands.hx b/qmp-commands.hx
>> index a5a67eb..0546f42 100644
>> --- a/qmp-commands.hx
>> +++ b/qmp-commands.hx
>> @@ -2106,6 +2106,17 @@ The main json-object contains the following:
>>           - "transferred": amount transferred (json-int)
>>           - "remaining": amount remaining (json-int)
>>           - "total": total (json-int)
>> +- "xbzrle-cache": only present if XBZRLE is active.
>> +  It is a json-object with the following XBZRLE information:
>> +         - "cache-size": XBZRLE cache size
>> +         - "xbzrle-bytes": total XBZRLE bytes transferred, only present if
>> +                           status is "active" or "completed"
>> +         - "xbzrle-pages": number of XBZRLE compressed pages, only present if
>> +                           status is "active" or "completed"
>> +         - "cache-miss": number of cache misses, only present if
>> +                           status is "active" or "completed"
>> +         - "overflow": number of XBZRLE overflows, only present if
>> +                           status is "active" or "completed"
>>  Examples:
>>  
>>  1. Before the first migration
>> @@ -2170,6 +2181,30 @@ Examples:
>>        }
>>     }
>>  
>> +6. Migration is being performed and XBZRLE is active:
>> +
>> +-> { "execute": "query-migrate" }
>> +<- {
>> +      "return":{
>> +         "status":"active",
>> +         "capabilities" : [ { "capability": "xbzrle", "state" : true } ],
>> +         "ram":{
>> +            "total":1057024,
>> +            "remaining":1053304,
>> +            "transferred":3720,
>> +            "duplicate": 10,
>> +            "normal" : 3333
>> +         },
>> +         "cache":{
>> +            "cache-size": 1024
>> +            "xbzrle-transferred":20971520,
>> +            "xbzrle-pages":2444343,
>> +            "xbzrle-cache-miss":2244,
>> +            "xbzrle-overflow":34434
>> +         }
>> +      }
>> +   }
>> +
>>  EQMP
>>  
>>      {
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 09/11] Add migration accounting for normal and duplicate pages
  2012-07-30 19:30   ` Luiz Capitulino
@ 2012-07-31  8:36     ` Orit Wasserman
  2012-07-31 13:19       ` Luiz Capitulino
  0 siblings, 1 reply; 47+ messages in thread
From: Orit Wasserman @ 2012-07-31  8:36 UTC (permalink / raw)
  To: Luiz Capitulino
  Cc: peter.maydell, aliguori, quintela, stefanha, qemu-devel,
	Benoit Hudzia, mdroth, blauwirbel, Petter Svard, chegu_vinod, avi,
	Aidan Shribman, pbonzini, eblake

On 07/30/2012 10:30 PM, Luiz Capitulino wrote:
> On Sun, 29 Jul 2012 12:43:01 +0300
> Orit Wasserman <owasserm@redhat.com> wrote:
> 
>> Signed-off-by: Benoit Hudzia <benoit.hudzia@sap.com>
>> Signed-off-by: Petter Svard <petters@cs.umu.se>
>> Signed-off-by: Aidan Shribman <aidan.shribman@sap.com>
>> Signed-off-by: Orit Wasserman <owasserm@redhat.com>
>> Signed-off-by: Juan Quintela <quintela@redhat.com>
>> ---
>>  arch_init.c      |   38 ++++++++++++++++++++++++++++++++++++++
>>  migration.c      |    4 ++++
>>  migration.h      |    5 +++++
>>  qapi-schema.json |    8 ++++++--
>>  qmp-commands.hx  |   14 +++++++++++---
>>  5 files changed, 64 insertions(+), 5 deletions(-)
>>
>> diff --git a/arch_init.c b/arch_init.c
>> index d709ccb..7f12317 100644
>> --- a/arch_init.c
>> +++ b/arch_init.c
>> @@ -199,6 +199,40 @@ int64_t xbzrle_cache_resize(int64_t new_size)
>>      return pow2floor(new_size);
>>  }
>>  
>> +/* accounting for migration statistics */
>> +typedef struct AccountingInfo {
>> +    uint64_t dup_pages;
>> +    uint64_t norm_pages;
>> +    uint64_t iterations;
>> +} 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;
>> +}
>> +
>>  static void save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset,
>>          int cont, int flag)
>>  {
>> @@ -293,6 +327,7 @@ static int ram_save_block(QEMUFile *f)
>>              p = memory_region_get_ram_ptr(mr) + offset;
>>  
>>              if (is_dup_page(p)) {
>> +                acct_info.dup_pages++;
>>                  save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_COMPRESS);
>>                  qemu_put_byte(f, *p);
>>                  bytes_sent = 1;
>> @@ -308,6 +343,7 @@ static int ram_save_block(QEMUFile *f)
>>                  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++;
>>              }
>>  
>>              /* if page is unmodified, continue to the next */
>> @@ -429,6 +465,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
>>          }
>>          XBZRLE.encoded_buf = g_malloc0(TARGET_PAGE_SIZE);
>>          XBZRLE.current_buf = g_malloc(TARGET_PAGE_SIZE);
>> +        acct_clear();
>>      }
>>  
>>      /* Make sure all dirty bits are set */
>> @@ -477,6 +514,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque)
>>              break;
>>          }
>>          bytes_transferred += bytes_sent;
>> +        acct_info.iterations++;
>>          /* we want to check in the 1st loop, just in case it was the 1st time
>>             and we had to sync the dirty bitmap.
>>             qemu_get_clock_ns() is a bit expensive, so we only check each some
>> diff --git a/migration.c b/migration.c
>> index bc2231d..4dc99ba 100644
>> --- a/migration.c
>> +++ b/migration.c
>> @@ -156,6 +156,8 @@ MigrationInfo *qmp_query_migrate(Error **errp)
>>          info->ram->total = ram_bytes_total();
>>          info->ram->total_time = qemu_get_clock_ms(rt_clock)
>>              - s->total_time;
>> +        info->ram->duplicate = dup_mig_pages_transferred();
>> +        info->ram->normal = norm_mig_pages_transferred();
>>  
>>          if (blk_mig_active()) {
>>              info->has_disk = true;
>> @@ -175,6 +177,8 @@ MigrationInfo *qmp_query_migrate(Error **errp)
>>          info->ram->remaining = 0;
>>          info->ram->total = ram_bytes_total();
>>          info->ram->total_time = s->total_time;
>> +        info->ram->duplicate = dup_mig_pages_transferred();
>> +        info->ram->normal = norm_mig_pages_transferred();
>>          break;
>>      case MIG_STATE_ERROR:
>>          info->has_status = true;
>> diff --git a/migration.h b/migration.h
>> index 337e225..e4a7cd7 100644
>> --- a/migration.h
>> +++ b/migration.h
>> @@ -87,6 +87,11 @@ uint64_t ram_bytes_total(void);
>>  
>>  extern SaveVMHandlers savevm_ram_handlers;
>>  
>> +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);
>> +
>>  /**
>>   * @migrate_add_blocker - prevent migration from proceeding
>>   *
>> diff --git a/qapi-schema.json b/qapi-schema.json
>> index 04adcee..a936714 100644
>> --- a/qapi-schema.json
>> +++ b/qapi-schema.json
>> @@ -264,11 +264,15 @@
>>  #        migration has ended, it returns the total migration
>>  #        time. (since 1.2)
>>  #
>> -# Since: 0.14.0.
>> +# @duplicate: number of duplicate pages (since 1.2)
>> +#
>> +# @normal : number of normal pages (since 1.2)
> 
> Is the number of pages actually useful? I think this should be in bytes,
> just like the other stats.
> 
Why? the pages are always the same size (4k), and what is interesting here is the number of the normal
pages compared to the duplicate pages not the total bytes.
In XBZRLE there is meaning both for the bytes and the number of pages because the page size is not fixed.

Orit
>> +#
>> +# Since: 0.14.0
>>  ##
>>  { 'type': 'MigrationStats',
>>    'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int' ,
>> -           'total_time': 'int' } }
>> +           'total_time': 'int', 'duplicate': 'int', 'normal': 'int' } }
>>  
>>  ##
>>  # @MigrationInfo
>> diff --git a/qmp-commands.hx b/qmp-commands.hx
>> index cfc950e..a5a67eb 100644
>> --- a/qmp-commands.hx
>> +++ b/qmp-commands.hx
>> @@ -2099,6 +2099,8 @@ The main json-object contains the following:
>>           - "transferred": amount transferred (json-int)
>>           - "remaining": amount remaining (json-int)
>>           - "total": total (json-int)
>> +	 - "duplicate": number of duplicated pages (json-int)
>> +	 - "normal" : number of normal pages transferred (json-int)
>>  - "disk": only present if "status" is "active" and it is a block migration,
>>    it is a json-object with the following disk information (in bytes):
>>           - "transferred": amount transferred (json-int)
>> @@ -2119,7 +2121,9 @@ Examples:
>>          "ram":{
>>            "transferred":123,
>>            "remaining":123,
>> -          "total":246
>> +          "total":246,
>> +          "duplicate":123,
>> +          "normal":123
>>          }
>>       }
>>     }
>> @@ -2138,7 +2142,9 @@ Examples:
>>           "ram":{
>>              "transferred":123,
>>              "remaining":123,
>> -            "total":246
>> +            "total":246,
>> +            "duplicate":123,
>> +            "normal":123
>>           }
>>        }
>>     }
>> @@ -2152,7 +2158,9 @@ Examples:
>>           "ram":{
>>              "total":1057024,
>>              "remaining":1053304,
>> -            "transferred":3720
>> +            "transferred":3720,
>> +            "duplicate":123,
>> +            "normal":123
>>           },
>>           "disk":{
>>              "total":20971520,
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 02/11] Add migrate_set_parameter and query-migrate-parameters
  2012-07-31  7:46     ` Orit Wasserman
@ 2012-07-31 13:09       ` Luiz Capitulino
  0 siblings, 0 replies; 47+ messages in thread
From: Luiz Capitulino @ 2012-07-31 13:09 UTC (permalink / raw)
  To: Orit Wasserman
  Cc: peter.maydell, aliguori, quintela, stefanha, qemu-devel, mdroth,
	blauwirbel, chegu_vinod, avi, pbonzini, eblake

On Tue, 31 Jul 2012 10:46:02 +0300
Orit Wasserman <owasserm@redhat.com> wrote:

> On 07/30/2012 08:41 PM, Luiz Capitulino wrote:
> > On Sun, 29 Jul 2012 12:42:54 +0300
> > Orit Wasserman <owasserm@redhat.com> wrote:
> > 
> >> The management can enable/disable a capability for the next migration by using
> >> migrate_set_parameter command.
> >> The management can query the current migration capabilities using
> >> query-migrate-parameters
> > 
> > In general looks good to me, I have a question and a few nitpick comments
> > below.
> > 
> >>
> >> Signed-off-by: Orit Wasserman <owasserm@redhat.com>
> >> Signed-off-by: Juan Quintela <quintela@redhat.com>
> >> ---
> >>  hmp-commands.hx  |   16 ++++++++++++
> >>  hmp.c            |   71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >>  hmp.h            |    2 +
> >>  migration.c      |   42 +++++++++++++++++++++++++++++++-
> >>  migration.h      |    2 +
> >>  monitor.c        |    7 +++++
> >>  qapi-schema.json |   32 ++++++++++++++++++++++++
> >>  qmp-commands.hx  |   60 ++++++++++++++++++++++++++++++++++++++++++++-
> >>  8 files changed, 229 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/hmp-commands.hx b/hmp-commands.hx
> >> index 8786148..3e15338 100644
> >> --- a/hmp-commands.hx
> >> +++ b/hmp-commands.hx
> >> @@ -861,6 +861,20 @@ Set maximum tolerated downtime (in seconds) for migration.
> >>  ETEXI
> >>  
> >>      {
> >> +        .name       = "migrate_set_parameter",
> >> +        .args_type  = "capability:s,state:b",
> >> +        .params     = "capability state",
> >> +        .help       = "Enable/Disable the usage of a capability for migration",
> >> +        .mhandler.cmd = hmp_migrate_set_parameter,
> >> +    },
> >> +
> >> +STEXI
> >> +@item migrate_set_parameter @var{capability} @var{state}
> >> +@findex migrate_set_parameter
> >> +Enable/Disable the usage of a capability @var{capability} for migration.
> >> +ETEXI
> >> +
> >> +    {
> >>          .name       = "client_migrate_info",
> >>          .args_type  = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?",
> >>          .params     = "protocol hostname port tls-port cert-subject",
> >> @@ -1419,6 +1433,8 @@ show user network stack connection states
> >>  show migration status
> >>  @item info migration_capabilities
> >>  show migration capabilities
> >> +@item info migrate_parameters
> >> +show current migration parameters
> >>  @item info balloon
> >>  show balloon information
> >>  @item info qtree
> >> diff --git a/hmp.c b/hmp.c
> >> index 5c7d0be..f2f63fd 100644
> >> --- a/hmp.c
> >> +++ b/hmp.c
> >> @@ -131,8 +131,22 @@ void hmp_info_mice(Monitor *mon)
> >>  void hmp_info_migrate(Monitor *mon)
> >>  {
> >>      MigrationInfo *info;
> >> +    MigrationCapabilityStatusList *cap;
> >> +    MigrationParameters *params;
> >>  
> >>      info = qmp_query_migrate(NULL);
> >> +    params = qmp_query_migrate_parameters(NULL);
> >> +
> >> +    /* do not display parameters during setup */
> >> +    if (info->has_status && params->capabilities) {
> >> +        monitor_printf(mon, "capabilities: ");
> >> +        for (cap = params->capabilities; cap; cap = cap->next) {
> >> +            monitor_printf(mon, "%s: %s ",
> >> +                           MigrationCapability_lookup[cap->value->capability],
> >> +                           cap->value->state ? "on" : "off");
> >> +        }
> >> +        monitor_printf(mon, "\n");
> >> +    }
> >>  
> >>      if (info->has_status) {
> >>          monitor_printf(mon, "Migration status: %s\n", info->status);
> >> @@ -159,6 +173,7 @@ void hmp_info_migrate(Monitor *mon)
> >>      }
> >>  
> >>      qapi_free_MigrationInfo(info);
> >> +    qapi_free_MigrationParameters(params);
> >>  }
> >>  
> >>  void hmp_info_migration_capabilities(Monitor *mon)
> >> @@ -180,6 +195,27 @@ void hmp_info_migration_capabilities(Monitor *mon)
> >>      qapi_free_MigrationCapabilityStatusList(caps_list);
> >>  }
> >>  
> >> +void hmp_info_migrate_parameters(Monitor *mon)
> >> +{
> >> +
> >> +    MigrationCapabilityStatusList *cap;
> >> +    MigrationParameters *params;
> >> +
> >> +    params = qmp_query_migrate_parameters(NULL);
> >> +
> >> +    if (params->capabilities) {
> >> +        monitor_printf(mon, "capabilities: ");
> >> +        for (cap = params->capabilities; cap; cap = cap->next) {
> >> +            monitor_printf(mon, "%s: %s ",
> >> +                           MigrationCapability_lookup[cap->value->capability],
> >> +                           cap->value->state ? "on" : "off");
> >> +        }
> >> +        monitor_printf(mon, "\n");
> >> +    }
> >> +
> >> +    qapi_free_MigrationParameters(params);
> >> +}
> >> +
> >>  void hmp_info_cpus(Monitor *mon)
> >>  {
> >>      CpuInfoList *cpu_list, *cpu;
> >> @@ -754,6 +790,41 @@ void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict)
> >>      qmp_migrate_set_speed(value, NULL);
> >>  }
> >>  
> >> +void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
> >> +{
> >> +    const char *cap = qdict_get_str(qdict, "capability");
> >> +    bool state = qdict_get_bool(qdict, "state");
> >> +    Error *err = NULL;
> >> +    MigrationCapabilityStatusList *params = NULL;
> >> +    int i;
> >> +
> >> +    for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
> >> +        if (strcmp(cap, MigrationCapability_lookup[i]) == 0) {
> >> +            if (!params) {
> >> +                params = g_malloc0(sizeof(*params));
> >> +            }
> > 
> > This if shouldn't be necessary, right?
> You are right I can always allocate it.
> > 
> >> +            params->value = g_malloc0(sizeof(*params->value));
> >> +            params->value->capability = i;
> >> +            params->value->state = state;
> >> +            params->next = NULL;
> > 
> > nitpick: I'd make the code ready for future capabilities.
> Could you give me a bit more details ?

This is not a proper list, it will break when we add a new capability.

But that comment doesn't apply here, I meant to add that command to
qmp_query_migrate_parameters()'s hunk.

> 
> Orit
> > 
> >> +            qmp_migrate_set_parameters(params, &err);
> >> +            break;
> >> +        }
> >> +    }
> >> +
> >> +    if (i == MIGRATION_CAPABILITY_MAX) {
> >> +        error_set(&err, QERR_INVALID_PARAMETER, cap);
> >> +    }
> >> +
> >> +    qapi_free_MigrationCapabilityStatusList(params);
> >> +
> >> +    if (err) {
> >> +        monitor_printf(mon, "migrate_set_parameter: %s\n",
> >> +                       error_get_pretty(err));
> >> +        error_free(err);
> >> +    }
> >> +}
> >> +
> >>  void hmp_set_password(Monitor *mon, const QDict *qdict)
> >>  {
> >>      const char *protocol  = qdict_get_str(qdict, "protocol");
> >> diff --git a/hmp.h b/hmp.h
> >> index 2fb44ca..ceb2f06 100644
> >> --- a/hmp.h
> >> +++ b/hmp.h
> >> @@ -26,6 +26,7 @@ void hmp_info_chardev(Monitor *mon);
> >>  void hmp_info_mice(Monitor *mon);
> >>  void hmp_info_migrate(Monitor *mon);
> >>  void hmp_info_migration_capabilities(Monitor *mon);
> >> +void hmp_info_migrate_parameters(Monitor *mon);
> >>  void hmp_info_cpus(Monitor *mon);
> >>  void hmp_info_block(Monitor *mon);
> >>  void hmp_info_blockstats(Monitor *mon);
> >> @@ -52,6 +53,7 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict);
> >>  void hmp_migrate_cancel(Monitor *mon, const QDict *qdict);
> >>  void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict);
> >>  void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict);
> >> +void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict);
> >>  void hmp_set_password(Monitor *mon, const QDict *qdict);
> >>  void hmp_expire_password(Monitor *mon, const QDict *qdict);
> >>  void hmp_eject(Monitor *mon, const QDict *qdict);
> >> diff --git a/migration.c b/migration.c
> >> index 8c27347..e844290 100644
> >> --- a/migration.c
> >> +++ b/migration.c
> >> @@ -113,6 +113,25 @@ uint64_t migrate_max_downtime(void)
> >>      return max_downtime;
> >>  }
> >>  
> >> +MigrationParameters *qmp_query_migrate_parameters(Error **errp)
> >> +{
> >> +    MigrationParameters *params = g_malloc0(sizeof(*params));
> >> +    MigrationState *s = migrate_get_current();
> >> +    int i;
> >> +
> >> +    params->capabilities = g_malloc0(sizeof(*params->capabilities));
> >> +
> >> +    for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
> >> +        params->capabilities->value =
> >> +            g_malloc(sizeof(*params->capabilities->value));
> >> +        params->capabilities->value->capability = i;
> >> +        params->capabilities->value->state = s->enabled_capabilities[i];
> >> +        params->capabilities->next = NULL;
> >> +    }
> >> +
> >> +    return params;
> >> +}
> >> +
> >>  MigrationInfo *qmp_query_migrate(Error **errp)
> >>  {
> >>      MigrationInfo *info = g_malloc0(sizeof(*info));
> >> @@ -177,6 +196,22 @@ MigrationCapabilityStatusList *qmp_query_migration_capabilities(Error **errp)
> >>      return caps_list;
> >>  }
> >>  
> >> +void qmp_migrate_set_parameters(MigrationCapabilityStatusList *params,
> >> +                                Error **errp)
> >> +{
> >> +    MigrationState *s = migrate_get_current();
> >> +    MigrationCapabilityStatusList *cap;
> >> +
> >> +    if (s->state == MIG_STATE_ACTIVE) {
> >> +        error_set(errp, QERR_MIGRATION_ACTIVE);
> >> +        return;
> >> +    }
> >> +
> >> +    for (cap = params; cap; cap = cap->next) {
> >> +        s->enabled_capabilities[cap->value->capability] = cap->value->state;
> >> +    }
> >> +}
> >> +
> >>  /* shared migration helpers */
> >>  
> >>  static int migrate_fd_cleanup(MigrationState *s)
> >> @@ -386,12 +421,17 @@ static MigrationState *migrate_init(const MigrationParams *params)
> >>  {
> >>      MigrationState *s = migrate_get_current();
> >>      int64_t bandwidth_limit = s->bandwidth_limit;
> >> +    bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
> >> +
> >> +    memcpy(enabled_capabilities, s->enabled_capabilities,
> >> +           sizeof(enabled_capabilities));
> > 
> > Is s->enabled_capabilities initialized somewhere or are we making xbzrle
> > disabled by default?
> > 
> >>  
> >>      memset(s, 0, sizeof(*s));
> >>      s->bandwidth_limit = bandwidth_limit;
> >>      s->params = *params;
> >> +    memcpy(s->enabled_capabilities, enabled_capabilities,
> >> +           sizeof(enabled_capabilities));
> >>  
> >> -    s->bandwidth_limit = bandwidth_limit;
> > 
> > Unrelated change.
> > 
> >>      s->state = MIG_STATE_SETUP;
> >>      s->total_time = qemu_get_clock_ms(rt_clock);
> >>  
> >> diff --git a/migration.h b/migration.h
> >> index 57572a6..713aae0 100644
> >> --- a/migration.h
> >> +++ b/migration.h
> >> @@ -19,6 +19,7 @@
> >>  #include "notify.h"
> >>  #include "error.h"
> >>  #include "vmstate.h"
> >> +#include "qapi-types.h"
> >>  
> >>  struct MigrationParams {
> >>      bool blk;
> >> @@ -39,6 +40,7 @@ struct MigrationState
> >>      void *opaque;
> >>      MigrationParams params;
> >>      int64_t total_time;
> >> +    bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
> >>  };
> >>  
> >>  void process_incoming_migration(QEMUFile *f);
> >> diff --git a/monitor.c b/monitor.c
> >> index fd57c5e..e07af97 100644
> >> --- a/monitor.c
> >> +++ b/monitor.c
> >> @@ -2669,6 +2669,13 @@ static mon_cmd_t info_cmds[] = {
> >>          .mhandler.info = hmp_info_migration_capabilities,
> >>      },
> >>      {
> >> +        .name       = "migrate-parameters",
> >> +        .args_type  = "",
> >> +        .params     = "",
> >> +        .help       = "show current migration parameters",
> >> +        .mhandler.info = hmp_info_migrate_parameters,
> >> +    },
> >> +    {
> >>          .name       = "balloon",
> >>          .args_type  = "",
> >>          .params     = "",
> >> diff --git a/qapi-schema.json b/qapi-schema.json
> >> index b4d4dd6..9d6759d 100644
> >> --- a/qapi-schema.json
> >> +++ b/qapi-schema.json
> >> @@ -345,6 +345,38 @@
> >>  { 'command': 'query-migration-capabilities', 'returns': ['MigrationCapabilityStatus'] }
> >>  
> >>  ##
> >> +# @migrate-set-parameters
> >> +#
> >> +# Enable/Disable the following migration capabilities (like xbzrle)
> >> +#
> >> +# Since: 1.2
> >> +##
> >> +{ 'command': 'migrate-set-parameters',
> >> +  'data': { 'capabilities': ['MigrationCapabilityStatus'] } }
> >> +
> >> +##
> >> +# @MigrationParameters
> >> +#
> >> +# @capabilities: @MigrationCapabilityStatus list contain current migration
> >> +#                capabilities status
> >> +# Since: 1.2
> >> +##
> >> +{ 'type': 'MigrationParameters',
> >> +  'data': {'capabilities': ['MigrationCapabilityStatus']} }
> >> +
> >> +
> >> +##
> >> +# @query-migrate-parameters
> >> +#
> >> +# Returns information about the current migration capabilities status
> >> +#
> >> +# Returns: @MigrationParameters
> >> +#
> >> +# Since: 1.2
> >> +##
> >> +{ 'command': 'query-migrate-parameters', 'returns': 'MigrationParameters' }
> >> +
> >> +##
> >>  # @MouseInfo:
> >>  #
> >>  # Information about a mouse device.
> >> diff --git a/qmp-commands.hx b/qmp-commands.hx
> >> index c0ed14c..7f40e2a 100644
> >> --- a/qmp-commands.hx
> >> +++ b/qmp-commands.hx
> >> @@ -2081,7 +2081,6 @@ The main json-object contains the following:
> >>           - "transferred": amount transferred (json-int)
> >>           - "remaining": amount remaining (json-int)
> >>           - "total": total (json-int)
> >> -
> >>  Examples:
> >>  
> >>  1. Before the first migration
> >> @@ -2092,7 +2091,15 @@ Examples:
> >>  2. Migration is done and has succeeded
> >>  
> >>  -> { "execute": "query-migrate" }
> >> -<- { "return": { "status": "completed" } }
> >> +<- { "return": {
> >> +        "status": "completed",
> >> +        "ram":{
> >> +          "transferred":123,
> >> +          "remaining":123,
> >> +          "total":246
> >> +        }
> >> +     }
> >> +   }
> >>  
> >>  3. Migration is done and has failed
> >>  
> >> @@ -2165,6 +2172,55 @@ EQMP
> >>      },
> >>  
> >>  SQMP
> >> +migrate-set-parameters
> >> +-------
> >> +
> >> +Enable/Disable migration capabilities
> >> +
> >> +- "xbzrle": xbzrle support
> >> +
> >> +Arguments:
> >> +
> >> +Example:
> >> +
> >> +-> { "execute": "migrate-set-parameters" , "arguments":
> >> +     { "parameters": [ { "capability": "xbzrle", "state": true } ] } }
> >> +
> >> +EQMP
> >> +
> >> +    {
> >> +        .name       = "migrate_set_parameters",
> >> +        .args_type  = "parameters:O",
> >> +        .params     = "capability:s,state:b",
> >> +	.mhandler.cmd_new = qmp_marshal_input_migrate_set_parameters,
> >> +    },
> >> +SQMP
> >> +query-migrate-parameters
> >> +-------
> >> +
> >> +Query current migration parameters
> >> +
> >> +- "capabilities": migration capabilities state
> >> +         - "xbzrle" : XBZRLE state (json-bool)
> >> +
> >> +Arguments:
> >> +
> >> +Example:
> >> +
> >> +-> { "execute": "query-migrate-parameters" }
> >> +<- { "return": {
> >> +        "capabilities" :  [ { "capability" : "xbzrle", "state" : false } ]
> >> +     }
> >> +   }
> >> +EQMP
> >> +
> >> +    {
> >> +        .name       = "query-migrate-parameters",
> >> +        .args_type  = "",
> >> +        .mhandler.cmd_new = qmp_marshal_input_query_migrate_parameters,
> >> +    },
> >> +
> >> +SQMP
> >>  query-balloon
> >>  -------------
> >>  
> > 
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 10/11] Add XBZRLE statistics
  2012-07-31  8:31     ` Orit Wasserman
@ 2012-07-31 13:16       ` Luiz Capitulino
  2012-07-31 14:13         ` Orit Wasserman
  0 siblings, 1 reply; 47+ messages in thread
From: Luiz Capitulino @ 2012-07-31 13:16 UTC (permalink / raw)
  To: Orit Wasserman
  Cc: peter.maydell, aliguori, quintela, stefanha, qemu-devel,
	Benoit Hudzia, mdroth, blauwirbel, Petter Svard, chegu_vinod, avi,
	Aidan Shribman, pbonzini, eblake

On Tue, 31 Jul 2012 11:31:09 +0300
Orit Wasserman <owasserm@redhat.com> wrote:

> On 07/30/2012 10:37 PM, Luiz Capitulino wrote:
> > On Sun, 29 Jul 2012 12:43:02 +0300
> > Orit Wasserman <owasserm@redhat.com> wrote:
> > 
> >> Signed-off-by: Benoit Hudzia <benoit.hudzia@sap.com>
> >> Signed-off-by: Petter Svard <petters@cs.umu.se>
> >> Signed-off-by: Aidan Shribman <aidan.shribman@sap.com>
> >> Signed-off-by: Orit Wasserman <owasserm@redhat.com>
> >> Signed-off-by: Juan Quintela <quintela@redhat.com>
> >> ---
> >>  arch_init.c      |   28 ++++++++++++++++++++++++++++
> >>  hmp.c            |   21 +++++++++++++++++++++
> >>  migration.c      |   28 ++++++++++++++++++++++++++++
> >>  migration.h      |    4 ++++
> >>  qapi-schema.json |   32 +++++++++++++++++++++++++++++++-
> >>  qmp-commands.hx  |   35 +++++++++++++++++++++++++++++++++++
> >>  6 files changed, 147 insertions(+), 1 deletions(-)
> >>
> >> diff --git a/arch_init.c b/arch_init.c
> >> index 7f12317..9833d54 100644
> >> --- a/arch_init.c
> >> +++ b/arch_init.c
> >> @@ -203,7 +203,11 @@ int64_t xbzrle_cache_resize(int64_t new_size)
> >>  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;
> >> @@ -233,6 +237,26 @@ 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;
> >> +}
> >> +
> >>  static void save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset,
> >>          int cont, int flag)
> >>  {
> >> @@ -257,6 +281,7 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
> >>      if (!cache_is_cached(XBZRLE.cache, current_addr)) {
> >>          cache_insert(XBZRLE.cache, current_addr,
> >>                       g_memdup(current_data, TARGET_PAGE_SIZE));
> >> +        acct_info.xbzrle_cache_miss++;
> >>          return -1;
> >>      }
> >>  
> >> @@ -274,6 +299,7 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
> >>          return 0;
> >>      } else if (encoded_len == -1) {
> >>          DPRINTF("Overflow\n");
> >> +        acct_info.xbzrle_overflows++;
> >>          /* update data in the cache */
> >>          memcpy(prev_cached_page, current_data, TARGET_PAGE_SIZE);
> >>          return -1;
> >> @@ -288,6 +314,8 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
> >>      qemu_put_be16(f, encoded_len);
> >>      qemu_put_buffer(f, XBZRLE.encoded_buf, encoded_len);
> >>      bytes_sent = encoded_len + 1 + 2;
> >> +    acct_info.xbzrle_pages++;
> >> +    acct_info.xbzrle_bytes += bytes_sent;
> >>  
> >>      return bytes_sent;
> >>  }
> >> diff --git a/hmp.c b/hmp.c
> >> index 9770d7b..383d5b1 100644
> >> --- a/hmp.c
> >> +++ b/hmp.c
> >> @@ -172,6 +172,27 @@ void hmp_info_migrate(Monitor *mon)
> >>                         info->disk->total >> 10);
> >>      }
> >>  
> >> +    if (info->has_xbzrle_cache) {
> >> +        monitor_printf(mon, "cache size: %" PRIu64 " bytes\n",
> >> +                       info->xbzrle_cache->cache_size);
> >> +        if (info->xbzrle_cache->has_xbzrle_bytes) {
> >> +            monitor_printf(mon, "xbzrle transferred: %" PRIu64 " kbytes\n",
> >> +                           info->xbzrle_cache->xbzrle_bytes >> 10);
> >> +        }
> >> +        if (info->xbzrle_cache->has_xbzrle_pages) {
> >> +            monitor_printf(mon, "xbzrle pages: %" PRIu64 " pages\n",
> >> +                           info->xbzrle_cache->xbzrle_pages);
> >> +        }
> >> +        if (info->xbzrle_cache->has_xbzrle_cache_miss) {
> >> +            monitor_printf(mon, "xbzrle cache miss: %" PRIu64 "\n",
> >> +                           info->xbzrle_cache->xbzrle_cache_miss);
> >> +        }
> >> +        if (info->xbzrle_cache->has_xbzrle_overflow) {
> >> +            monitor_printf(mon, "xbzrle overflow : %" PRIu64 "\n",
> >> +                           info->xbzrle_cache->xbzrle_overflow);
> >> +        }
> >> +    }
> >> +
> >>      qapi_free_MigrationInfo(info);
> >>      qapi_free_MigrationParameters(params);
> >>  }
> >> diff --git a/migration.c b/migration.c
> >> index 4dc99ba..fb802bc 100644
> >> --- a/migration.c
> >> +++ b/migration.c
> >> @@ -136,6 +136,23 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp)
> >>      return params;
> >>  }
> >>  
> >> +static void get_xbzrle_cache_stats(MigrationInfo *info)
> >> +{
> >> +    if (migrate_use_xbzrle()) {
> >> +        info->has_xbzrle_cache = true;
> >> +        info->xbzrle_cache = g_malloc0(sizeof(*info->xbzrle_cache));
> >> +        info->xbzrle_cache->cache_size = migrate_xbzrle_cache_size();
> >> +        info->xbzrle_cache->has_xbzrle_bytes = true;
> >> +        info->xbzrle_cache->xbzrle_bytes = xbzrle_mig_bytes_transferred();
> >> +        info->xbzrle_cache->has_xbzrle_pages = true;
> >> +        info->xbzrle_cache->xbzrle_pages = xbzrle_mig_pages_transferred();
> >> +        info->xbzrle_cache->has_xbzrle_cache_miss = true;
> >> +        info->xbzrle_cache->xbzrle_cache_miss = xbzrle_mig_pages_cache_miss();
> >> +        info->xbzrle_cache->has_xbzrle_overflow = true;
> >> +        info->xbzrle_cache->xbzrle_overflow = xbzrle_mig_pages_overflow();
> >> +    }
> >> +}
> >> +
> >>  MigrationInfo *qmp_query_migrate(Error **errp)
> >>  {
> >>      MigrationInfo *info = g_malloc0(sizeof(*info));
> >> @@ -144,6 +161,13 @@ MigrationInfo *qmp_query_migrate(Error **errp)
> >>      switch (s->state) {
> >>      case MIG_STATE_SETUP:
> >>          /* no migration has happened ever */
> >> +
> >> +        /* display xbzrle cache size */
> >> +        if (migrate_use_xbzrle()) {
> >> +            info->has_xbzrle_cache = true;
> >> +            info->xbzrle_cache = g_malloc0(sizeof(*info->xbzrle_cache));
> >> +            info->xbzrle_cache->cache_size = migrate_xbzrle_cache_size();
> >> +        }
> > 
> > Is it really useful to return this in MIG_SETUP? Can't the cache size
> > be queried by some query- command?
> I like it this way and it is very simple to use, you need to use query-migrate command if you do migration 
> anyway.

But this will only be returned before a migration takes place. Then it will
never be returned again. Doesn't seem to be the right place for it.

> Otherwise we will need to add a query command for each configurable parameters,
> so one for speed and another for downtime and probably more in the future.

I don't think this is a problem. We're trying to design QMP commands as we
would design a C API, and I'd have different functions to query different things.

Besides, let's not mix what's best to a human user and what's best for a
machine protocol. If we add different query commands for different parameters,
then it's possible to call them from 'info migrate' if you wish.

> This way we use one command to query the migration setup.

Again, that information would only be returned before a first migration
occurs.

> 
> Orit
> > 
> >>          break;
> >>      case MIG_STATE_ACTIVE:
> >>          info->has_status = true;
> >> @@ -166,8 +190,12 @@ MigrationInfo *qmp_query_migrate(Error **errp)
> >>              info->disk->remaining = blk_mig_bytes_remaining();
> >>              info->disk->total = blk_mig_bytes_total();
> >>          }
> >> +
> >> +        get_xbzrle_cache_stats(info);
> >>          break;
> >>      case MIG_STATE_COMPLETED:
> >> +        get_xbzrle_cache_stats(info);
> >> +
> >>          info->has_status = true;
> >>          info->status = g_strdup("completed");
> >>  
> >> diff --git a/migration.h b/migration.h
> >> index e4a7cd7..a9852fc 100644
> >> --- a/migration.h
> >> +++ b/migration.h
> >> @@ -91,6 +91,10 @@ 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);
> >>  
> >>  /**
> >>   * @migrate_add_blocker - prevent migration from proceeding
> >> diff --git a/qapi-schema.json b/qapi-schema.json
> >> index a936714..91dee72 100644
> >> --- a/qapi-schema.json
> >> +++ b/qapi-schema.json
> >> @@ -275,6 +275,31 @@
> >>             'total_time': 'int', 'duplicate': 'int', 'normal': 'int' } }
> >>  
> >>  ##
> >> +# @XBZRLECacheStats
> >> +#
> >> +# Detailed XBZRLE migration cache statistics
> >> +#
> >> +# @cache-size: XBZRLE cache size
> >> +#
> >> +# @xbzrle-bytes: @optional, amount of bytes already transferred to the target VM
> >> +#                only returned when migration is active or completed
> > 
> > s/xbzrle-bytes/transferred-bytes
> > 
> >> +#
> >> +# @xbzrle-pages: @optional, amount of pages transferred to the target VM
> >> +#                only returned when migration is active or completed
> > 
> > s/xbzrle-pages/transferred-pages
> > 
> >> +#
> >> +# @xbzrle-cache-miss: @optional, number of cache miss
> >> +#                     only returned when migration is active or completed
> > 
> > s/xbzrle/xbzrle//
> > 
> >> +#
> >> +# @xbzrle-overflow: @optional, number of overflows
> >> +#                   only returned when migration is active or completed
> > 
> > s/xbzrle///
> > 
> > Besides, all these parameters shouldn't be optional as they are unconditionally
> > included (BZRLECacheStats itself is optional as returned by query-migrate).
> > 
> >> +#
> >> +# Since: 1.2
> >> +##
> >> +{ 'type': 'XBZRLECacheStats',
> >> +  'data': {'cache-size': 'int', '*xbzrle-bytes': 'int', '*xbzrle-pages': 'int',
> >> +           '*xbzrle-cache-miss': 'int', '*xbzrle-overflow': 'int' } }
> >> +
> >> +##
> >>  # @MigrationInfo
> >>  #
> >>  # Information about current migration process.
> >> @@ -292,11 +317,16 @@
> >>  #        status, only returned if status is 'active' and it is a block
> >>  #        migration
> >>  #
> >> +# @xbzrle-cache: #optional @XBZRLECacheStats containing detailed XBZRLE
> >> +#                migration statistics, only returned if XBZRLE feature is on
> >> +#                (since 1.2)
> >> +#
> >>  # Since: 0.14.0
> >>  ##
> >>  { 'type': 'MigrationInfo',
> >>    'data': {'*status': 'str', '*ram': 'MigrationStats',
> >> -           '*disk': 'MigrationStats'} }
> >> +           '*disk': 'MigrationStats',
> >> +           '*xbzrle-cache': 'XBZRLECacheStats'} }
> >>  
> >>  ##
> >>  # @query-migrate
> >> diff --git a/qmp-commands.hx b/qmp-commands.hx
> >> index a5a67eb..0546f42 100644
> >> --- a/qmp-commands.hx
> >> +++ b/qmp-commands.hx
> >> @@ -2106,6 +2106,17 @@ The main json-object contains the following:
> >>           - "transferred": amount transferred (json-int)
> >>           - "remaining": amount remaining (json-int)
> >>           - "total": total (json-int)
> >> +- "xbzrle-cache": only present if XBZRLE is active.
> >> +  It is a json-object with the following XBZRLE information:
> >> +         - "cache-size": XBZRLE cache size
> >> +         - "xbzrle-bytes": total XBZRLE bytes transferred, only present if
> >> +                           status is "active" or "completed"
> >> +         - "xbzrle-pages": number of XBZRLE compressed pages, only present if
> >> +                           status is "active" or "completed"
> >> +         - "cache-miss": number of cache misses, only present if
> >> +                           status is "active" or "completed"
> >> +         - "overflow": number of XBZRLE overflows, only present if
> >> +                           status is "active" or "completed"
> >>  Examples:
> >>  
> >>  1. Before the first migration
> >> @@ -2170,6 +2181,30 @@ Examples:
> >>        }
> >>     }
> >>  
> >> +6. Migration is being performed and XBZRLE is active:
> >> +
> >> +-> { "execute": "query-migrate" }
> >> +<- {
> >> +      "return":{
> >> +         "status":"active",
> >> +         "capabilities" : [ { "capability": "xbzrle", "state" : true } ],
> >> +         "ram":{
> >> +            "total":1057024,
> >> +            "remaining":1053304,
> >> +            "transferred":3720,
> >> +            "duplicate": 10,
> >> +            "normal" : 3333
> >> +         },
> >> +         "cache":{
> >> +            "cache-size": 1024
> >> +            "xbzrle-transferred":20971520,
> >> +            "xbzrle-pages":2444343,
> >> +            "xbzrle-cache-miss":2244,
> >> +            "xbzrle-overflow":34434
> >> +         }
> >> +      }
> >> +   }
> >> +
> >>  EQMP
> >>  
> >>      {
> > 
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 09/11] Add migration accounting for normal and duplicate pages
  2012-07-31  8:36     ` Orit Wasserman
@ 2012-07-31 13:19       ` Luiz Capitulino
  0 siblings, 0 replies; 47+ messages in thread
From: Luiz Capitulino @ 2012-07-31 13:19 UTC (permalink / raw)
  To: Orit Wasserman
  Cc: peter.maydell, aliguori, quintela, stefanha, qemu-devel,
	Benoit Hudzia, mdroth, blauwirbel, Petter Svard, chegu_vinod, avi,
	Aidan Shribman, pbonzini, eblake

On Tue, 31 Jul 2012 11:36:03 +0300
Orit Wasserman <owasserm@redhat.com> wrote:

> On 07/30/2012 10:30 PM, Luiz Capitulino wrote:
> > On Sun, 29 Jul 2012 12:43:01 +0300
> > Orit Wasserman <owasserm@redhat.com> wrote:
> > 
> >> Signed-off-by: Benoit Hudzia <benoit.hudzia@sap.com>
> >> Signed-off-by: Petter Svard <petters@cs.umu.se>
> >> Signed-off-by: Aidan Shribman <aidan.shribman@sap.com>
> >> Signed-off-by: Orit Wasserman <owasserm@redhat.com>
> >> Signed-off-by: Juan Quintela <quintela@redhat.com>
> >> ---
> >>  arch_init.c      |   38 ++++++++++++++++++++++++++++++++++++++
> >>  migration.c      |    4 ++++
> >>  migration.h      |    5 +++++
> >>  qapi-schema.json |    8 ++++++--
> >>  qmp-commands.hx  |   14 +++++++++++---
> >>  5 files changed, 64 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/arch_init.c b/arch_init.c
> >> index d709ccb..7f12317 100644
> >> --- a/arch_init.c
> >> +++ b/arch_init.c
> >> @@ -199,6 +199,40 @@ int64_t xbzrle_cache_resize(int64_t new_size)
> >>      return pow2floor(new_size);
> >>  }
> >>  
> >> +/* accounting for migration statistics */
> >> +typedef struct AccountingInfo {
> >> +    uint64_t dup_pages;
> >> +    uint64_t norm_pages;
> >> +    uint64_t iterations;
> >> +} 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;
> >> +}
> >> +
> >>  static void save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset,
> >>          int cont, int flag)
> >>  {
> >> @@ -293,6 +327,7 @@ static int ram_save_block(QEMUFile *f)
> >>              p = memory_region_get_ram_ptr(mr) + offset;
> >>  
> >>              if (is_dup_page(p)) {
> >> +                acct_info.dup_pages++;
> >>                  save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_COMPRESS);
> >>                  qemu_put_byte(f, *p);
> >>                  bytes_sent = 1;
> >> @@ -308,6 +343,7 @@ static int ram_save_block(QEMUFile *f)
> >>                  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++;
> >>              }
> >>  
> >>              /* if page is unmodified, continue to the next */
> >> @@ -429,6 +465,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
> >>          }
> >>          XBZRLE.encoded_buf = g_malloc0(TARGET_PAGE_SIZE);
> >>          XBZRLE.current_buf = g_malloc(TARGET_PAGE_SIZE);
> >> +        acct_clear();
> >>      }
> >>  
> >>      /* Make sure all dirty bits are set */
> >> @@ -477,6 +514,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque)
> >>              break;
> >>          }
> >>          bytes_transferred += bytes_sent;
> >> +        acct_info.iterations++;
> >>          /* we want to check in the 1st loop, just in case it was the 1st time
> >>             and we had to sync the dirty bitmap.
> >>             qemu_get_clock_ns() is a bit expensive, so we only check each some
> >> diff --git a/migration.c b/migration.c
> >> index bc2231d..4dc99ba 100644
> >> --- a/migration.c
> >> +++ b/migration.c
> >> @@ -156,6 +156,8 @@ MigrationInfo *qmp_query_migrate(Error **errp)
> >>          info->ram->total = ram_bytes_total();
> >>          info->ram->total_time = qemu_get_clock_ms(rt_clock)
> >>              - s->total_time;
> >> +        info->ram->duplicate = dup_mig_pages_transferred();
> >> +        info->ram->normal = norm_mig_pages_transferred();
> >>  
> >>          if (blk_mig_active()) {
> >>              info->has_disk = true;
> >> @@ -175,6 +177,8 @@ MigrationInfo *qmp_query_migrate(Error **errp)
> >>          info->ram->remaining = 0;
> >>          info->ram->total = ram_bytes_total();
> >>          info->ram->total_time = s->total_time;
> >> +        info->ram->duplicate = dup_mig_pages_transferred();
> >> +        info->ram->normal = norm_mig_pages_transferred();
> >>          break;
> >>      case MIG_STATE_ERROR:
> >>          info->has_status = true;
> >> diff --git a/migration.h b/migration.h
> >> index 337e225..e4a7cd7 100644
> >> --- a/migration.h
> >> +++ b/migration.h
> >> @@ -87,6 +87,11 @@ uint64_t ram_bytes_total(void);
> >>  
> >>  extern SaveVMHandlers savevm_ram_handlers;
> >>  
> >> +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);
> >> +
> >>  /**
> >>   * @migrate_add_blocker - prevent migration from proceeding
> >>   *
> >> diff --git a/qapi-schema.json b/qapi-schema.json
> >> index 04adcee..a936714 100644
> >> --- a/qapi-schema.json
> >> +++ b/qapi-schema.json
> >> @@ -264,11 +264,15 @@
> >>  #        migration has ended, it returns the total migration
> >>  #        time. (since 1.2)
> >>  #
> >> -# Since: 0.14.0.
> >> +# @duplicate: number of duplicate pages (since 1.2)
> >> +#
> >> +# @normal : number of normal pages (since 1.2)
> > 
> > Is the number of pages actually useful? I think this should be in bytes,
> > just like the other stats.
> > 
> Why? the pages are always the same size (4k), and what is interesting here is the number of the normal
> pages compared to the duplicate pages not the total bytes.
> In XBZRLE there is meaning both for the bytes and the number of pages because the page size is not fixed.

Can we have both them?

> 
> Orit
> >> +#
> >> +# Since: 0.14.0
> >>  ##
> >>  { 'type': 'MigrationStats',
> >>    'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int' ,
> >> -           'total_time': 'int' } }
> >> +           'total_time': 'int', 'duplicate': 'int', 'normal': 'int' } }
> >>  
> >>  ##
> >>  # @MigrationInfo
> >> diff --git a/qmp-commands.hx b/qmp-commands.hx
> >> index cfc950e..a5a67eb 100644
> >> --- a/qmp-commands.hx
> >> +++ b/qmp-commands.hx
> >> @@ -2099,6 +2099,8 @@ The main json-object contains the following:
> >>           - "transferred": amount transferred (json-int)
> >>           - "remaining": amount remaining (json-int)
> >>           - "total": total (json-int)
> >> +	 - "duplicate": number of duplicated pages (json-int)
> >> +	 - "normal" : number of normal pages transferred (json-int)
> >>  - "disk": only present if "status" is "active" and it is a block migration,
> >>    it is a json-object with the following disk information (in bytes):
> >>           - "transferred": amount transferred (json-int)
> >> @@ -2119,7 +2121,9 @@ Examples:
> >>          "ram":{
> >>            "transferred":123,
> >>            "remaining":123,
> >> -          "total":246
> >> +          "total":246,
> >> +          "duplicate":123,
> >> +          "normal":123
> >>          }
> >>       }
> >>     }
> >> @@ -2138,7 +2142,9 @@ Examples:
> >>           "ram":{
> >>              "transferred":123,
> >>              "remaining":123,
> >> -            "total":246
> >> +            "total":246,
> >> +            "duplicate":123,
> >> +            "normal":123
> >>           }
> >>        }
> >>     }
> >> @@ -2152,7 +2158,9 @@ Examples:
> >>           "ram":{
> >>              "total":1057024,
> >>              "remaining":1053304,
> >> -            "transferred":3720
> >> +            "transferred":3720,
> >> +            "duplicate":123,
> >> +            "normal":123
> >>           },
> >>           "disk":{
> >>              "total":20971520,
> > 
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 10/11] Add XBZRLE statistics
  2012-07-31 13:16       ` Luiz Capitulino
@ 2012-07-31 14:13         ` Orit Wasserman
  2012-07-31 15:54           ` Luiz Capitulino
  0 siblings, 1 reply; 47+ messages in thread
From: Orit Wasserman @ 2012-07-31 14:13 UTC (permalink / raw)
  To: Luiz Capitulino
  Cc: peter.maydell, aliguori, quintela, stefanha, qemu-devel,
	Benoit Hudzia, mdroth, blauwirbel, Petter Svard, chegu_vinod, avi,
	Aidan Shribman, pbonzini, eblake

On 07/31/2012 04:16 PM, Luiz Capitulino wrote:
> On Tue, 31 Jul 2012 11:31:09 +0300
> Orit Wasserman <owasserm@redhat.com> wrote:
> 
>> On 07/30/2012 10:37 PM, Luiz Capitulino wrote:
>>> On Sun, 29 Jul 2012 12:43:02 +0300
>>> Orit Wasserman <owasserm@redhat.com> wrote:
>>>
>>>> Signed-off-by: Benoit Hudzia <benoit.hudzia@sap.com>
>>>> Signed-off-by: Petter Svard <petters@cs.umu.se>
>>>> Signed-off-by: Aidan Shribman <aidan.shribman@sap.com>
>>>> Signed-off-by: Orit Wasserman <owasserm@redhat.com>
>>>> Signed-off-by: Juan Quintela <quintela@redhat.com>
>>>> ---
>>>>  arch_init.c      |   28 ++++++++++++++++++++++++++++
>>>>  hmp.c            |   21 +++++++++++++++++++++
>>>>  migration.c      |   28 ++++++++++++++++++++++++++++
>>>>  migration.h      |    4 ++++
>>>>  qapi-schema.json |   32 +++++++++++++++++++++++++++++++-
>>>>  qmp-commands.hx  |   35 +++++++++++++++++++++++++++++++++++
>>>>  6 files changed, 147 insertions(+), 1 deletions(-)
>>>>
>>>> diff --git a/arch_init.c b/arch_init.c
>>>> index 7f12317..9833d54 100644
>>>> --- a/arch_init.c
>>>> +++ b/arch_init.c
>>>> @@ -203,7 +203,11 @@ int64_t xbzrle_cache_resize(int64_t new_size)
>>>>  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;
>>>> @@ -233,6 +237,26 @@ 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;
>>>> +}
>>>> +
>>>>  static void save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset,
>>>>          int cont, int flag)
>>>>  {
>>>> @@ -257,6 +281,7 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
>>>>      if (!cache_is_cached(XBZRLE.cache, current_addr)) {
>>>>          cache_insert(XBZRLE.cache, current_addr,
>>>>                       g_memdup(current_data, TARGET_PAGE_SIZE));
>>>> +        acct_info.xbzrle_cache_miss++;
>>>>          return -1;
>>>>      }
>>>>  
>>>> @@ -274,6 +299,7 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
>>>>          return 0;
>>>>      } else if (encoded_len == -1) {
>>>>          DPRINTF("Overflow\n");
>>>> +        acct_info.xbzrle_overflows++;
>>>>          /* update data in the cache */
>>>>          memcpy(prev_cached_page, current_data, TARGET_PAGE_SIZE);
>>>>          return -1;
>>>> @@ -288,6 +314,8 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
>>>>      qemu_put_be16(f, encoded_len);
>>>>      qemu_put_buffer(f, XBZRLE.encoded_buf, encoded_len);
>>>>      bytes_sent = encoded_len + 1 + 2;
>>>> +    acct_info.xbzrle_pages++;
>>>> +    acct_info.xbzrle_bytes += bytes_sent;
>>>>  
>>>>      return bytes_sent;
>>>>  }
>>>> diff --git a/hmp.c b/hmp.c
>>>> index 9770d7b..383d5b1 100644
>>>> --- a/hmp.c
>>>> +++ b/hmp.c
>>>> @@ -172,6 +172,27 @@ void hmp_info_migrate(Monitor *mon)
>>>>                         info->disk->total >> 10);
>>>>      }
>>>>  
>>>> +    if (info->has_xbzrle_cache) {
>>>> +        monitor_printf(mon, "cache size: %" PRIu64 " bytes\n",
>>>> +                       info->xbzrle_cache->cache_size);
>>>> +        if (info->xbzrle_cache->has_xbzrle_bytes) {
>>>> +            monitor_printf(mon, "xbzrle transferred: %" PRIu64 " kbytes\n",
>>>> +                           info->xbzrle_cache->xbzrle_bytes >> 10);
>>>> +        }
>>>> +        if (info->xbzrle_cache->has_xbzrle_pages) {
>>>> +            monitor_printf(mon, "xbzrle pages: %" PRIu64 " pages\n",
>>>> +                           info->xbzrle_cache->xbzrle_pages);
>>>> +        }
>>>> +        if (info->xbzrle_cache->has_xbzrle_cache_miss) {
>>>> +            monitor_printf(mon, "xbzrle cache miss: %" PRIu64 "\n",
>>>> +                           info->xbzrle_cache->xbzrle_cache_miss);
>>>> +        }
>>>> +        if (info->xbzrle_cache->has_xbzrle_overflow) {
>>>> +            monitor_printf(mon, "xbzrle overflow : %" PRIu64 "\n",
>>>> +                           info->xbzrle_cache->xbzrle_overflow);
>>>> +        }
>>>> +    }
>>>> +
>>>>      qapi_free_MigrationInfo(info);
>>>>      qapi_free_MigrationParameters(params);
>>>>  }
>>>> diff --git a/migration.c b/migration.c
>>>> index 4dc99ba..fb802bc 100644
>>>> --- a/migration.c
>>>> +++ b/migration.c
>>>> @@ -136,6 +136,23 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp)
>>>>      return params;
>>>>  }
>>>>  
>>>> +static void get_xbzrle_cache_stats(MigrationInfo *info)
>>>> +{
>>>> +    if (migrate_use_xbzrle()) {
>>>> +        info->has_xbzrle_cache = true;
>>>> +        info->xbzrle_cache = g_malloc0(sizeof(*info->xbzrle_cache));
>>>> +        info->xbzrle_cache->cache_size = migrate_xbzrle_cache_size();
>>>> +        info->xbzrle_cache->has_xbzrle_bytes = true;
>>>> +        info->xbzrle_cache->xbzrle_bytes = xbzrle_mig_bytes_transferred();
>>>> +        info->xbzrle_cache->has_xbzrle_pages = true;
>>>> +        info->xbzrle_cache->xbzrle_pages = xbzrle_mig_pages_transferred();
>>>> +        info->xbzrle_cache->has_xbzrle_cache_miss = true;
>>>> +        info->xbzrle_cache->xbzrle_cache_miss = xbzrle_mig_pages_cache_miss();
>>>> +        info->xbzrle_cache->has_xbzrle_overflow = true;
>>>> +        info->xbzrle_cache->xbzrle_overflow = xbzrle_mig_pages_overflow();
>>>> +    }
>>>> +}
>>>> +
>>>>  MigrationInfo *qmp_query_migrate(Error **errp)
>>>>  {
>>>>      MigrationInfo *info = g_malloc0(sizeof(*info));
>>>> @@ -144,6 +161,13 @@ MigrationInfo *qmp_query_migrate(Error **errp)
>>>>      switch (s->state) {
>>>>      case MIG_STATE_SETUP:
>>>>          /* no migration has happened ever */
>>>> +
>>>> +        /* display xbzrle cache size */
>>>> +        if (migrate_use_xbzrle()) {
>>>> +            info->has_xbzrle_cache = true;
>>>> +            info->xbzrle_cache = g_malloc0(sizeof(*info->xbzrle_cache));
>>>> +            info->xbzrle_cache->cache_size = migrate_xbzrle_cache_size();
>>>> +        }
>>>
>>> Is it really useful to return this in MIG_SETUP? Can't the cache size
>>> be queried by some query- command?
>> I like it this way and it is very simple to use, you need to use query-migrate command if you do migration 
>> anyway.
> 
> But this will only be returned before a migration takes place. Then it will
> never be returned again. Doesn't seem to be the right place for it.
It is returned also in MIG_ACTIVE and MIG_COMPLETE (when XBZRLE are active).
> 
>> Otherwise we will need to add a query command for each configurable parameters,
>> so one for speed and another for downtime and probably more in the future.
> 
> I don't think this is a problem. We're trying to design QMP commands as we
> would design a C API, and I'd have different functions to query different things.
> 
> Besides, let's not mix what's best to a human user and what's best for a
> machine protocol. If we add different query commands for different parameters,
> then it's possible to call them from 'info migrate' if you wish.
sounds reasonable, I will change it.

Orit 
> 
>> This way we use one command to query the migration setup.
> 
> Again, that information would only be returned before a first migration
> occurs.
> 
>>
>> Orit
>>>
>>>>          break;
>>>>      case MIG_STATE_ACTIVE:
>>>>          info->has_status = true;
>>>> @@ -166,8 +190,12 @@ MigrationInfo *qmp_query_migrate(Error **errp)
>>>>              info->disk->remaining = blk_mig_bytes_remaining();
>>>>              info->disk->total = blk_mig_bytes_total();
>>>>          }
>>>> +
>>>> +        get_xbzrle_cache_stats(info);
>>>>          break;
>>>>      case MIG_STATE_COMPLETED:
>>>> +        get_xbzrle_cache_stats(info);
>>>> +
>>>>          info->has_status = true;
>>>>          info->status = g_strdup("completed");
>>>>  
>>>> diff --git a/migration.h b/migration.h
>>>> index e4a7cd7..a9852fc 100644
>>>> --- a/migration.h
>>>> +++ b/migration.h
>>>> @@ -91,6 +91,10 @@ 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);
>>>>  
>>>>  /**
>>>>   * @migrate_add_blocker - prevent migration from proceeding
>>>> diff --git a/qapi-schema.json b/qapi-schema.json
>>>> index a936714..91dee72 100644
>>>> --- a/qapi-schema.json
>>>> +++ b/qapi-schema.json
>>>> @@ -275,6 +275,31 @@
>>>>             'total_time': 'int', 'duplicate': 'int', 'normal': 'int' } }
>>>>  
>>>>  ##
>>>> +# @XBZRLECacheStats
>>>> +#
>>>> +# Detailed XBZRLE migration cache statistics
>>>> +#
>>>> +# @cache-size: XBZRLE cache size
>>>> +#
>>>> +# @xbzrle-bytes: @optional, amount of bytes already transferred to the target VM
>>>> +#                only returned when migration is active or completed
>>>
>>> s/xbzrle-bytes/transferred-bytes
>>>
>>>> +#
>>>> +# @xbzrle-pages: @optional, amount of pages transferred to the target VM
>>>> +#                only returned when migration is active or completed
>>>
>>> s/xbzrle-pages/transferred-pages
>>>
>>>> +#
>>>> +# @xbzrle-cache-miss: @optional, number of cache miss
>>>> +#                     only returned when migration is active or completed
>>>
>>> s/xbzrle/xbzrle//
>>>
>>>> +#
>>>> +# @xbzrle-overflow: @optional, number of overflows
>>>> +#                   only returned when migration is active or completed
>>>
>>> s/xbzrle///
>>>
>>> Besides, all these parameters shouldn't be optional as they are unconditionally
>>> included (BZRLECacheStats itself is optional as returned by query-migrate).
>>>
>>>> +#
>>>> +# Since: 1.2
>>>> +##
>>>> +{ 'type': 'XBZRLECacheStats',
>>>> +  'data': {'cache-size': 'int', '*xbzrle-bytes': 'int', '*xbzrle-pages': 'int',
>>>> +           '*xbzrle-cache-miss': 'int', '*xbzrle-overflow': 'int' } }
>>>> +
>>>> +##
>>>>  # @MigrationInfo
>>>>  #
>>>>  # Information about current migration process.
>>>> @@ -292,11 +317,16 @@
>>>>  #        status, only returned if status is 'active' and it is a block
>>>>  #        migration
>>>>  #
>>>> +# @xbzrle-cache: #optional @XBZRLECacheStats containing detailed XBZRLE
>>>> +#                migration statistics, only returned if XBZRLE feature is on
>>>> +#                (since 1.2)
>>>> +#
>>>>  # Since: 0.14.0
>>>>  ##
>>>>  { 'type': 'MigrationInfo',
>>>>    'data': {'*status': 'str', '*ram': 'MigrationStats',
>>>> -           '*disk': 'MigrationStats'} }
>>>> +           '*disk': 'MigrationStats',
>>>> +           '*xbzrle-cache': 'XBZRLECacheStats'} }
>>>>  
>>>>  ##
>>>>  # @query-migrate
>>>> diff --git a/qmp-commands.hx b/qmp-commands.hx
>>>> index a5a67eb..0546f42 100644
>>>> --- a/qmp-commands.hx
>>>> +++ b/qmp-commands.hx
>>>> @@ -2106,6 +2106,17 @@ The main json-object contains the following:
>>>>           - "transferred": amount transferred (json-int)
>>>>           - "remaining": amount remaining (json-int)
>>>>           - "total": total (json-int)
>>>> +- "xbzrle-cache": only present if XBZRLE is active.
>>>> +  It is a json-object with the following XBZRLE information:
>>>> +         - "cache-size": XBZRLE cache size
>>>> +         - "xbzrle-bytes": total XBZRLE bytes transferred, only present if
>>>> +                           status is "active" or "completed"
>>>> +         - "xbzrle-pages": number of XBZRLE compressed pages, only present if
>>>> +                           status is "active" or "completed"
>>>> +         - "cache-miss": number of cache misses, only present if
>>>> +                           status is "active" or "completed"
>>>> +         - "overflow": number of XBZRLE overflows, only present if
>>>> +                           status is "active" or "completed"
>>>>  Examples:
>>>>  
>>>>  1. Before the first migration
>>>> @@ -2170,6 +2181,30 @@ Examples:
>>>>        }
>>>>     }
>>>>  
>>>> +6. Migration is being performed and XBZRLE is active:
>>>> +
>>>> +-> { "execute": "query-migrate" }
>>>> +<- {
>>>> +      "return":{
>>>> +         "status":"active",
>>>> +         "capabilities" : [ { "capability": "xbzrle", "state" : true } ],
>>>> +         "ram":{
>>>> +            "total":1057024,
>>>> +            "remaining":1053304,
>>>> +            "transferred":3720,
>>>> +            "duplicate": 10,
>>>> +            "normal" : 3333
>>>> +         },
>>>> +         "cache":{
>>>> +            "cache-size": 1024
>>>> +            "xbzrle-transferred":20971520,
>>>> +            "xbzrle-pages":2444343,
>>>> +            "xbzrle-cache-miss":2244,
>>>> +            "xbzrle-overflow":34434
>>>> +         }
>>>> +      }
>>>> +   }
>>>> +
>>>>  EQMP
>>>>  
>>>>      {
>>>
>>
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 10/11] Add XBZRLE statistics
  2012-07-31 14:13         ` Orit Wasserman
@ 2012-07-31 15:54           ` Luiz Capitulino
  0 siblings, 0 replies; 47+ messages in thread
From: Luiz Capitulino @ 2012-07-31 15:54 UTC (permalink / raw)
  To: Orit Wasserman
  Cc: peter.maydell, aliguori, quintela, stefanha, qemu-devel,
	Benoit Hudzia, mdroth, blauwirbel, Petter Svard, chegu_vinod, avi,
	Aidan Shribman, pbonzini, eblake

On Tue, 31 Jul 2012 17:13:46 +0300
Orit Wasserman <owasserm@redhat.com> wrote:

> On 07/31/2012 04:16 PM, Luiz Capitulino wrote:
> > On Tue, 31 Jul 2012 11:31:09 +0300
> > Orit Wasserman <owasserm@redhat.com> wrote:
> > 
> >> On 07/30/2012 10:37 PM, Luiz Capitulino wrote:
> >>> On Sun, 29 Jul 2012 12:43:02 +0300
> >>> Orit Wasserman <owasserm@redhat.com> wrote:
> >>>
> >>>> Signed-off-by: Benoit Hudzia <benoit.hudzia@sap.com>
> >>>> Signed-off-by: Petter Svard <petters@cs.umu.se>
> >>>> Signed-off-by: Aidan Shribman <aidan.shribman@sap.com>
> >>>> Signed-off-by: Orit Wasserman <owasserm@redhat.com>
> >>>> Signed-off-by: Juan Quintela <quintela@redhat.com>
> >>>> ---
> >>>>  arch_init.c      |   28 ++++++++++++++++++++++++++++
> >>>>  hmp.c            |   21 +++++++++++++++++++++
> >>>>  migration.c      |   28 ++++++++++++++++++++++++++++
> >>>>  migration.h      |    4 ++++
> >>>>  qapi-schema.json |   32 +++++++++++++++++++++++++++++++-
> >>>>  qmp-commands.hx  |   35 +++++++++++++++++++++++++++++++++++
> >>>>  6 files changed, 147 insertions(+), 1 deletions(-)
> >>>>
> >>>> diff --git a/arch_init.c b/arch_init.c
> >>>> index 7f12317..9833d54 100644
> >>>> --- a/arch_init.c
> >>>> +++ b/arch_init.c
> >>>> @@ -203,7 +203,11 @@ int64_t xbzrle_cache_resize(int64_t new_size)
> >>>>  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;
> >>>> @@ -233,6 +237,26 @@ 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;
> >>>> +}
> >>>> +
> >>>>  static void save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset,
> >>>>          int cont, int flag)
> >>>>  {
> >>>> @@ -257,6 +281,7 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
> >>>>      if (!cache_is_cached(XBZRLE.cache, current_addr)) {
> >>>>          cache_insert(XBZRLE.cache, current_addr,
> >>>>                       g_memdup(current_data, TARGET_PAGE_SIZE));
> >>>> +        acct_info.xbzrle_cache_miss++;
> >>>>          return -1;
> >>>>      }
> >>>>  
> >>>> @@ -274,6 +299,7 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
> >>>>          return 0;
> >>>>      } else if (encoded_len == -1) {
> >>>>          DPRINTF("Overflow\n");
> >>>> +        acct_info.xbzrle_overflows++;
> >>>>          /* update data in the cache */
> >>>>          memcpy(prev_cached_page, current_data, TARGET_PAGE_SIZE);
> >>>>          return -1;
> >>>> @@ -288,6 +314,8 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
> >>>>      qemu_put_be16(f, encoded_len);
> >>>>      qemu_put_buffer(f, XBZRLE.encoded_buf, encoded_len);
> >>>>      bytes_sent = encoded_len + 1 + 2;
> >>>> +    acct_info.xbzrle_pages++;
> >>>> +    acct_info.xbzrle_bytes += bytes_sent;
> >>>>  
> >>>>      return bytes_sent;
> >>>>  }
> >>>> diff --git a/hmp.c b/hmp.c
> >>>> index 9770d7b..383d5b1 100644
> >>>> --- a/hmp.c
> >>>> +++ b/hmp.c
> >>>> @@ -172,6 +172,27 @@ void hmp_info_migrate(Monitor *mon)
> >>>>                         info->disk->total >> 10);
> >>>>      }
> >>>>  
> >>>> +    if (info->has_xbzrle_cache) {
> >>>> +        monitor_printf(mon, "cache size: %" PRIu64 " bytes\n",
> >>>> +                       info->xbzrle_cache->cache_size);
> >>>> +        if (info->xbzrle_cache->has_xbzrle_bytes) {
> >>>> +            monitor_printf(mon, "xbzrle transferred: %" PRIu64 " kbytes\n",
> >>>> +                           info->xbzrle_cache->xbzrle_bytes >> 10);
> >>>> +        }
> >>>> +        if (info->xbzrle_cache->has_xbzrle_pages) {
> >>>> +            monitor_printf(mon, "xbzrle pages: %" PRIu64 " pages\n",
> >>>> +                           info->xbzrle_cache->xbzrle_pages);
> >>>> +        }
> >>>> +        if (info->xbzrle_cache->has_xbzrle_cache_miss) {
> >>>> +            monitor_printf(mon, "xbzrle cache miss: %" PRIu64 "\n",
> >>>> +                           info->xbzrle_cache->xbzrle_cache_miss);
> >>>> +        }
> >>>> +        if (info->xbzrle_cache->has_xbzrle_overflow) {
> >>>> +            monitor_printf(mon, "xbzrle overflow : %" PRIu64 "\n",
> >>>> +                           info->xbzrle_cache->xbzrle_overflow);
> >>>> +        }
> >>>> +    }
> >>>> +
> >>>>      qapi_free_MigrationInfo(info);
> >>>>      qapi_free_MigrationParameters(params);
> >>>>  }
> >>>> diff --git a/migration.c b/migration.c
> >>>> index 4dc99ba..fb802bc 100644
> >>>> --- a/migration.c
> >>>> +++ b/migration.c
> >>>> @@ -136,6 +136,23 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp)
> >>>>      return params;
> >>>>  }
> >>>>  
> >>>> +static void get_xbzrle_cache_stats(MigrationInfo *info)
> >>>> +{
> >>>> +    if (migrate_use_xbzrle()) {
> >>>> +        info->has_xbzrle_cache = true;
> >>>> +        info->xbzrle_cache = g_malloc0(sizeof(*info->xbzrle_cache));
> >>>> +        info->xbzrle_cache->cache_size = migrate_xbzrle_cache_size();
> >>>> +        info->xbzrle_cache->has_xbzrle_bytes = true;
> >>>> +        info->xbzrle_cache->xbzrle_bytes = xbzrle_mig_bytes_transferred();
> >>>> +        info->xbzrle_cache->has_xbzrle_pages = true;
> >>>> +        info->xbzrle_cache->xbzrle_pages = xbzrle_mig_pages_transferred();
> >>>> +        info->xbzrle_cache->has_xbzrle_cache_miss = true;
> >>>> +        info->xbzrle_cache->xbzrle_cache_miss = xbzrle_mig_pages_cache_miss();
> >>>> +        info->xbzrle_cache->has_xbzrle_overflow = true;
> >>>> +        info->xbzrle_cache->xbzrle_overflow = xbzrle_mig_pages_overflow();
> >>>> +    }
> >>>> +}
> >>>> +
> >>>>  MigrationInfo *qmp_query_migrate(Error **errp)
> >>>>  {
> >>>>      MigrationInfo *info = g_malloc0(sizeof(*info));
> >>>> @@ -144,6 +161,13 @@ MigrationInfo *qmp_query_migrate(Error **errp)
> >>>>      switch (s->state) {
> >>>>      case MIG_STATE_SETUP:
> >>>>          /* no migration has happened ever */
> >>>> +
> >>>> +        /* display xbzrle cache size */
> >>>> +        if (migrate_use_xbzrle()) {
> >>>> +            info->has_xbzrle_cache = true;
> >>>> +            info->xbzrle_cache = g_malloc0(sizeof(*info->xbzrle_cache));
> >>>> +            info->xbzrle_cache->cache_size = migrate_xbzrle_cache_size();
> >>>> +        }
> >>>
> >>> Is it really useful to return this in MIG_SETUP? Can't the cache size
> >>> be queried by some query- command?
> >> I like it this way and it is very simple to use, you need to use query-migrate command if you do migration 
> >> anyway.
> > 
> > But this will only be returned before a migration takes place. Then it will
> > never be returned again. Doesn't seem to be the right place for it.
> It is returned also in MIG_ACTIVE and MIG_COMPLETE (when XBZRLE are active).

That's fine.

> > 
> >> Otherwise we will need to add a query command for each configurable parameters,
> >> so one for speed and another for downtime and probably more in the future.
> > 
> > I don't think this is a problem. We're trying to design QMP commands as we
> > would design a C API, and I'd have different functions to query different things.
> > 
> > Besides, let's not mix what's best to a human user and what's best for a
> > machine protocol. If we add different query commands for different parameters,
> > then it's possible to call them from 'info migrate' if you wish.
> sounds reasonable, I will change it.
> 
> Orit 
> > 
> >> This way we use one command to query the migration setup.
> > 
> > Again, that information would only be returned before a first migration
> > occurs.
> > 
> >>
> >> Orit
> >>>
> >>>>          break;
> >>>>      case MIG_STATE_ACTIVE:
> >>>>          info->has_status = true;
> >>>> @@ -166,8 +190,12 @@ MigrationInfo *qmp_query_migrate(Error **errp)
> >>>>              info->disk->remaining = blk_mig_bytes_remaining();
> >>>>              info->disk->total = blk_mig_bytes_total();
> >>>>          }
> >>>> +
> >>>> +        get_xbzrle_cache_stats(info);
> >>>>          break;
> >>>>      case MIG_STATE_COMPLETED:
> >>>> +        get_xbzrle_cache_stats(info);
> >>>> +
> >>>>          info->has_status = true;
> >>>>          info->status = g_strdup("completed");
> >>>>  
> >>>> diff --git a/migration.h b/migration.h
> >>>> index e4a7cd7..a9852fc 100644
> >>>> --- a/migration.h
> >>>> +++ b/migration.h
> >>>> @@ -91,6 +91,10 @@ 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);
> >>>>  
> >>>>  /**
> >>>>   * @migrate_add_blocker - prevent migration from proceeding
> >>>> diff --git a/qapi-schema.json b/qapi-schema.json
> >>>> index a936714..91dee72 100644
> >>>> --- a/qapi-schema.json
> >>>> +++ b/qapi-schema.json
> >>>> @@ -275,6 +275,31 @@
> >>>>             'total_time': 'int', 'duplicate': 'int', 'normal': 'int' } }
> >>>>  
> >>>>  ##
> >>>> +# @XBZRLECacheStats
> >>>> +#
> >>>> +# Detailed XBZRLE migration cache statistics
> >>>> +#
> >>>> +# @cache-size: XBZRLE cache size
> >>>> +#
> >>>> +# @xbzrle-bytes: @optional, amount of bytes already transferred to the target VM
> >>>> +#                only returned when migration is active or completed
> >>>
> >>> s/xbzrle-bytes/transferred-bytes
> >>>
> >>>> +#
> >>>> +# @xbzrle-pages: @optional, amount of pages transferred to the target VM
> >>>> +#                only returned when migration is active or completed
> >>>
> >>> s/xbzrle-pages/transferred-pages
> >>>
> >>>> +#
> >>>> +# @xbzrle-cache-miss: @optional, number of cache miss
> >>>> +#                     only returned when migration is active or completed
> >>>
> >>> s/xbzrle/xbzrle//
> >>>
> >>>> +#
> >>>> +# @xbzrle-overflow: @optional, number of overflows
> >>>> +#                   only returned when migration is active or completed
> >>>
> >>> s/xbzrle///
> >>>
> >>> Besides, all these parameters shouldn't be optional as they are unconditionally
> >>> included (BZRLECacheStats itself is optional as returned by query-migrate).
> >>>
> >>>> +#
> >>>> +# Since: 1.2
> >>>> +##
> >>>> +{ 'type': 'XBZRLECacheStats',
> >>>> +  'data': {'cache-size': 'int', '*xbzrle-bytes': 'int', '*xbzrle-pages': 'int',
> >>>> +           '*xbzrle-cache-miss': 'int', '*xbzrle-overflow': 'int' } }
> >>>> +
> >>>> +##
> >>>>  # @MigrationInfo
> >>>>  #
> >>>>  # Information about current migration process.
> >>>> @@ -292,11 +317,16 @@
> >>>>  #        status, only returned if status is 'active' and it is a block
> >>>>  #        migration
> >>>>  #
> >>>> +# @xbzrle-cache: #optional @XBZRLECacheStats containing detailed XBZRLE
> >>>> +#                migration statistics, only returned if XBZRLE feature is on
> >>>> +#                (since 1.2)
> >>>> +#
> >>>>  # Since: 0.14.0
> >>>>  ##
> >>>>  { 'type': 'MigrationInfo',
> >>>>    'data': {'*status': 'str', '*ram': 'MigrationStats',
> >>>> -           '*disk': 'MigrationStats'} }
> >>>> +           '*disk': 'MigrationStats',
> >>>> +           '*xbzrle-cache': 'XBZRLECacheStats'} }
> >>>>  
> >>>>  ##
> >>>>  # @query-migrate
> >>>> diff --git a/qmp-commands.hx b/qmp-commands.hx
> >>>> index a5a67eb..0546f42 100644
> >>>> --- a/qmp-commands.hx
> >>>> +++ b/qmp-commands.hx
> >>>> @@ -2106,6 +2106,17 @@ The main json-object contains the following:
> >>>>           - "transferred": amount transferred (json-int)
> >>>>           - "remaining": amount remaining (json-int)
> >>>>           - "total": total (json-int)
> >>>> +- "xbzrle-cache": only present if XBZRLE is active.
> >>>> +  It is a json-object with the following XBZRLE information:
> >>>> +         - "cache-size": XBZRLE cache size
> >>>> +         - "xbzrle-bytes": total XBZRLE bytes transferred, only present if
> >>>> +                           status is "active" or "completed"
> >>>> +         - "xbzrle-pages": number of XBZRLE compressed pages, only present if
> >>>> +                           status is "active" or "completed"
> >>>> +         - "cache-miss": number of cache misses, only present if
> >>>> +                           status is "active" or "completed"
> >>>> +         - "overflow": number of XBZRLE overflows, only present if
> >>>> +                           status is "active" or "completed"
> >>>>  Examples:
> >>>>  
> >>>>  1. Before the first migration
> >>>> @@ -2170,6 +2181,30 @@ Examples:
> >>>>        }
> >>>>     }
> >>>>  
> >>>> +6. Migration is being performed and XBZRLE is active:
> >>>> +
> >>>> +-> { "execute": "query-migrate" }
> >>>> +<- {
> >>>> +      "return":{
> >>>> +         "status":"active",
> >>>> +         "capabilities" : [ { "capability": "xbzrle", "state" : true } ],
> >>>> +         "ram":{
> >>>> +            "total":1057024,
> >>>> +            "remaining":1053304,
> >>>> +            "transferred":3720,
> >>>> +            "duplicate": 10,
> >>>> +            "normal" : 3333
> >>>> +         },
> >>>> +         "cache":{
> >>>> +            "cache-size": 1024
> >>>> +            "xbzrle-transferred":20971520,
> >>>> +            "xbzrle-pages":2444343,
> >>>> +            "xbzrle-cache-miss":2244,
> >>>> +            "xbzrle-overflow":34434
> >>>> +         }
> >>>> +      }
> >>>> +   }
> >>>> +
> >>>>  EQMP
> >>>>  
> >>>>      {
> >>>
> >>
> > 
> 

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH 01/11] Add migration capabilities
  2012-07-31 18:54 [Qemu-devel] [PATCH 00/11] Migration next v8 Orit Wasserman
@ 2012-07-31 18:54 ` Orit Wasserman
  0 siblings, 0 replies; 47+ messages in thread
From: Orit Wasserman @ 2012-07-31 18:54 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, aliguori, quintela, stefanha, mdroth, lcapitulino,
	blauwirbel, Orit Wasserman, chegu_vinod, avi, pbonzini, eblake

Add migration capabilities that can be queried by the management using
query-migration-supported-capabilities command.
The management can query the source QEMU and the destination QEMU in order to
verify both support some migration capability (currently only XBZRLE).

Signed-off-by: Orit Wasserman <owasserm@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
 hmp-commands.hx  |    2 ++
 hmp.c            |   21 +++++++++++++++++++++
 hmp.h            |    1 +
 migration.c      |   12 ++++++++++++
 monitor.c        |    7 +++++++
 qapi-schema.json |   39 +++++++++++++++++++++++++++++++++++++++
 qmp-commands.hx  |   25 +++++++++++++++++++++++++
 7 files changed, 107 insertions(+), 0 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index eea8b32..8267237 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1417,6 +1417,8 @@ show CPU statistics
 show user network stack connection states
 @item info migrate
 show migration status
+@item info migration_supported_capabilities
+show migration supported capabilities
 @item info balloon
 show balloon information
 @item info qtree
diff --git a/hmp.c b/hmp.c
index 6b72a64..2ff71a3 100644
--- a/hmp.c
+++ b/hmp.c
@@ -161,6 +161,27 @@ void hmp_info_migrate(Monitor *mon)
     qapi_free_MigrationInfo(info);
 }
 
+void hmp_info_migration_supported_capabilities(Monitor *mon)
+{
+    MigrationCapabilityStatusList *caps_list, *cap;
+
+    caps_list = qmp_query_migration_supported_capabilities(NULL);
+    if (!caps_list) {
+        monitor_printf(mon, "No supported migration capabilities found\n");
+        return;
+    }
+
+    for (cap = caps_list; cap; cap = cap->next) {
+        monitor_printf(mon, "%s: %s ",
+                       MigrationCapability_lookup[cap->value->capability],
+                       cap->value->state ? "on" : "off");
+    }
+
+    monitor_printf(mon, "\n");
+
+    qapi_free_MigrationCapabilityStatusList(caps_list);
+}
+
 void hmp_info_cpus(Monitor *mon)
 {
     CpuInfoList *cpu_list, *cpu;
diff --git a/hmp.h b/hmp.h
index 8d2b0d7..8442c22 100644
--- a/hmp.h
+++ b/hmp.h
@@ -25,6 +25,7 @@ void hmp_info_uuid(Monitor *mon);
 void hmp_info_chardev(Monitor *mon);
 void hmp_info_mice(Monitor *mon);
 void hmp_info_migrate(Monitor *mon);
+void hmp_info_migration_supported_capabilities(Monitor *mon);
 void hmp_info_cpus(Monitor *mon);
 void hmp_info_block(Monitor *mon);
 void hmp_info_blockstats(Monitor *mon);
diff --git a/migration.c b/migration.c
index 8db1b43..35444f7 100644
--- a/migration.c
+++ b/migration.c
@@ -166,6 +166,18 @@ MigrationInfo *qmp_query_migrate(Error **errp)
     return info;
 }
 
+MigrationCapabilityStatusList *
+qmp_query_migration_supported_capabilities(Error **errp)
+{
+    MigrationCapabilityStatusList *caps_list = g_malloc0(sizeof(*caps_list));
+
+    caps_list->value = g_malloc(sizeof(*caps_list->value));
+    caps_list->value->capability = MIGRATION_CAPABILITY_XBZRLE;
+    caps_list->next = NULL;
+
+    return caps_list;
+}
+
 /* shared migration helpers */
 
 static int migrate_fd_cleanup(MigrationState *s)
diff --git a/monitor.c b/monitor.c
index 09aa3cd..43f7df5 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2662,6 +2662,13 @@ static mon_cmd_t info_cmds[] = {
         .mhandler.info = hmp_info_migrate,
     },
     {
+        .name       = "migration_supported_capabilities",
+        .args_type  = "",
+        .params     = "",
+        .help       = "show migration supported capabilities",
+        .mhandler.info = hmp_info_migration_supported_capabilities,
+    },
+    {
         .name       = "balloon",
         .args_type  = "",
         .params     = "",
diff --git a/qapi-schema.json b/qapi-schema.json
index a92adb1..68d0fbb 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -306,6 +306,45 @@
 { 'command': 'query-migrate', 'returns': 'MigrationInfo' }
 
 ##
+# @MigrationCapability
+#
+# Migration capabilities enumeration
+#
+# @xbzrle: Migration supports xbzrle (Xor Based Zero Run Length Encoding).
+#          This feature allows us to minimize migration traffic for certain work
+#          loads, by sending compressed difference of the pages
+#
+# Since: 1.2
+##
+{ 'enum': 'MigrationCapability',
+  'data': ['xbzrle'] }
+
+##
+# @MigrationCapabilityStatus
+#
+# Migration capability information
+#
+# @capability: capability enum
+#
+# @state: capability state bool
+#
+# Since: 1.2
+##
+{ 'type': 'MigrationCapabilityStatus',
+  'data': { 'capability' : 'MigrationCapability', 'state' : 'bool' } }
+
+##
+# @query-migration-supported-capabilities
+#
+# Returns information about current migration process capabilities.
+#
+# Returns: @MigrationCapabilityStatus list
+#
+# Since: 1.2
+##
+{ 'command': 'query-migration-supported-capabilities', 'returns': ['MigrationCapabilityStatus'] }
+
+##
 # @MouseInfo:
 #
 # Information about a mouse device.
diff --git a/qmp-commands.hx b/qmp-commands.hx
index e3cf3c5..16fbcef 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2141,6 +2141,31 @@ EQMP
     },
 
 SQMP
+query-migration-supported-capabilities
+-------
+
+Query migration supported capabilities
+
+- "xbzrle": xbzrle support
+
+Arguments:
+
+Example:
+
+-> { "execute": "query-migration-supported-capabilities"}
+<- { "return": [ { "capability": "xbzrle", "state": true },
+                 { "capability": "foobar", "state": false } ] }
+
+EQMP
+
+    {
+        .name       = "query-migration-supported-capabilities",
+        .args_type  = "",
+	.mhandler.cmd_new =
+            qmp_marshal_input_query_migration_supported_capabilities,
+    },
+
+SQMP
 query-balloon
 -------------
 
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH 01/11] Add migration capabilities
  2012-08-01 18:01 [Qemu-devel] [PULL 00/11] Migration next Juan Quintela
@ 2012-08-01 18:01 ` Juan Quintela
  0 siblings, 0 replies; 47+ messages in thread
From: Juan Quintela @ 2012-08-01 18:01 UTC (permalink / raw)
  To: qemu-devel; +Cc: Orit Wasserman

From: Orit Wasserman <owasserm@redhat.com>

Add migration capabilities that can be queried by the management using
query-migration-supported-capabilities command.
The management can query the source QEMU and the destination QEMU in order to
verify both support some migration capability (currently only XBZRLE).

Signed-off-by: Orit Wasserman <owasserm@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
 hmp-commands.hx  |  2 ++
 hmp.c            | 21 +++++++++++++++++++++
 hmp.h            |  1 +
 migration.c      | 12 ++++++++++++
 monitor.c        |  7 +++++++
 qapi-schema.json | 39 +++++++++++++++++++++++++++++++++++++++
 qmp-commands.hx  | 25 +++++++++++++++++++++++++
 7 files changed, 107 insertions(+)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index eea8b32..8267237 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1417,6 +1417,8 @@ show CPU statistics
 show user network stack connection states
 @item info migrate
 show migration status
+@item info migration_supported_capabilities
+show migration supported capabilities
 @item info balloon
 show balloon information
 @item info qtree
diff --git a/hmp.c b/hmp.c
index 6b72a64..2ff71a3 100644
--- a/hmp.c
+++ b/hmp.c
@@ -161,6 +161,27 @@ void hmp_info_migrate(Monitor *mon)
     qapi_free_MigrationInfo(info);
 }

+void hmp_info_migration_supported_capabilities(Monitor *mon)
+{
+    MigrationCapabilityStatusList *caps_list, *cap;
+
+    caps_list = qmp_query_migration_supported_capabilities(NULL);
+    if (!caps_list) {
+        monitor_printf(mon, "No supported migration capabilities found\n");
+        return;
+    }
+
+    for (cap = caps_list; cap; cap = cap->next) {
+        monitor_printf(mon, "%s: %s ",
+                       MigrationCapability_lookup[cap->value->capability],
+                       cap->value->state ? "on" : "off");
+    }
+
+    monitor_printf(mon, "\n");
+
+    qapi_free_MigrationCapabilityStatusList(caps_list);
+}
+
 void hmp_info_cpus(Monitor *mon)
 {
     CpuInfoList *cpu_list, *cpu;
diff --git a/hmp.h b/hmp.h
index 8d2b0d7..8442c22 100644
--- a/hmp.h
+++ b/hmp.h
@@ -25,6 +25,7 @@ void hmp_info_uuid(Monitor *mon);
 void hmp_info_chardev(Monitor *mon);
 void hmp_info_mice(Monitor *mon);
 void hmp_info_migrate(Monitor *mon);
+void hmp_info_migration_supported_capabilities(Monitor *mon);
 void hmp_info_cpus(Monitor *mon);
 void hmp_info_block(Monitor *mon);
 void hmp_info_blockstats(Monitor *mon);
diff --git a/migration.c b/migration.c
index 8db1b43..35444f7 100644
--- a/migration.c
+++ b/migration.c
@@ -166,6 +166,18 @@ MigrationInfo *qmp_query_migrate(Error **errp)
     return info;
 }

+MigrationCapabilityStatusList *
+qmp_query_migration_supported_capabilities(Error **errp)
+{
+    MigrationCapabilityStatusList *caps_list = g_malloc0(sizeof(*caps_list));
+
+    caps_list->value = g_malloc(sizeof(*caps_list->value));
+    caps_list->value->capability = MIGRATION_CAPABILITY_XBZRLE;
+    caps_list->next = NULL;
+
+    return caps_list;
+}
+
 /* shared migration helpers */

 static int migrate_fd_cleanup(MigrationState *s)
diff --git a/monitor.c b/monitor.c
index 49dccfe..bb55168 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2655,6 +2655,13 @@ static mon_cmd_t info_cmds[] = {
         .mhandler.info = hmp_info_migrate,
     },
     {
+        .name       = "migration_supported_capabilities",
+        .args_type  = "",
+        .params     = "",
+        .help       = "show migration supported capabilities",
+        .mhandler.info = hmp_info_migration_supported_capabilities,
+    },
+    {
         .name       = "balloon",
         .args_type  = "",
         .params     = "",
diff --git a/qapi-schema.json b/qapi-schema.json
index bc55ed2..9d4107b 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -306,6 +306,45 @@
 { 'command': 'query-migrate', 'returns': 'MigrationInfo' }

 ##
+# @MigrationCapability
+#
+# Migration capabilities enumeration
+#
+# @xbzrle: Migration supports xbzrle (Xor Based Zero Run Length Encoding).
+#          This feature allows us to minimize migration traffic for certain work
+#          loads, by sending compressed difference of the pages
+#
+# Since: 1.2
+##
+{ 'enum': 'MigrationCapability',
+  'data': ['xbzrle'] }
+
+##
+# @MigrationCapabilityStatus
+#
+# Migration capability information
+#
+# @capability: capability enum
+#
+# @state: capability state bool
+#
+# Since: 1.2
+##
+{ 'type': 'MigrationCapabilityStatus',
+  'data': { 'capability' : 'MigrationCapability', 'state' : 'bool' } }
+
+##
+# @query-migration-supported-capabilities
+#
+# Returns information about current migration process capabilities.
+#
+# Returns: @MigrationCapabilityStatus list
+#
+# Since: 1.2
+##
+{ 'command': 'query-migration-supported-capabilities', 'returns': ['MigrationCapabilityStatus'] }
+
+##
 # @MouseInfo:
 #
 # Information about a mouse device.
diff --git a/qmp-commands.hx b/qmp-commands.hx
index e3cf3c5..16fbcef 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2141,6 +2141,31 @@ EQMP
     },

 SQMP
+query-migration-supported-capabilities
+-------
+
+Query migration supported capabilities
+
+- "xbzrle": xbzrle support
+
+Arguments:
+
+Example:
+
+-> { "execute": "query-migration-supported-capabilities"}
+<- { "return": [ { "capability": "xbzrle", "state": true },
+                 { "capability": "foobar", "state": false } ] }
+
+EQMP
+
+    {
+        .name       = "query-migration-supported-capabilities",
+        .args_type  = "",
+	.mhandler.cmd_new =
+            qmp_marshal_input_query_migration_supported_capabilities,
+    },
+
+SQMP
 query-balloon
 -------------

-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH 01/11] Add migration capabilities
  2012-08-02 12:44 [Qemu-devel] [PATCH 00/11] Migration next v9 Orit Wasserman
@ 2012-08-02 12:44 ` Orit Wasserman
  2012-08-03 17:11   ` Luiz Capitulino
  0 siblings, 1 reply; 47+ messages in thread
From: Orit Wasserman @ 2012-08-02 12:44 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, aliguori, quintela, stefanha, mdroth, lcapitulino,
	blauwirbel, Orit Wasserman, chegu_vinod, avi, pbonzini, eblake

Add migration capabilities that can be queried by the management using
query-migration-supported-capabilities command.
The management can query the source QEMU and the destination QEMU in order to
verify both support some migration capability (currently only XBZRLE).

Signed-off-by: Orit Wasserman <owasserm@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
 hmp-commands.hx  |    2 ++
 hmp.c            |   21 +++++++++++++++++++++
 hmp.h            |    1 +
 migration.c      |   12 ++++++++++++
 monitor.c        |    7 +++++++
 qapi-schema.json |   39 +++++++++++++++++++++++++++++++++++++++
 qmp-commands.hx  |   25 +++++++++++++++++++++++++
 7 files changed, 107 insertions(+), 0 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index eea8b32..8267237 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1417,6 +1417,8 @@ show CPU statistics
 show user network stack connection states
 @item info migrate
 show migration status
+@item info migration_supported_capabilities
+show migration supported capabilities
 @item info balloon
 show balloon information
 @item info qtree
diff --git a/hmp.c b/hmp.c
index 6b72a64..2ff71a3 100644
--- a/hmp.c
+++ b/hmp.c
@@ -161,6 +161,27 @@ void hmp_info_migrate(Monitor *mon)
     qapi_free_MigrationInfo(info);
 }
 
+void hmp_info_migration_supported_capabilities(Monitor *mon)
+{
+    MigrationCapabilityStatusList *caps_list, *cap;
+
+    caps_list = qmp_query_migration_supported_capabilities(NULL);
+    if (!caps_list) {
+        monitor_printf(mon, "No supported migration capabilities found\n");
+        return;
+    }
+
+    for (cap = caps_list; cap; cap = cap->next) {
+        monitor_printf(mon, "%s: %s ",
+                       MigrationCapability_lookup[cap->value->capability],
+                       cap->value->state ? "on" : "off");
+    }
+
+    monitor_printf(mon, "\n");
+
+    qapi_free_MigrationCapabilityStatusList(caps_list);
+}
+
 void hmp_info_cpus(Monitor *mon)
 {
     CpuInfoList *cpu_list, *cpu;
diff --git a/hmp.h b/hmp.h
index 8d2b0d7..8442c22 100644
--- a/hmp.h
+++ b/hmp.h
@@ -25,6 +25,7 @@ void hmp_info_uuid(Monitor *mon);
 void hmp_info_chardev(Monitor *mon);
 void hmp_info_mice(Monitor *mon);
 void hmp_info_migrate(Monitor *mon);
+void hmp_info_migration_supported_capabilities(Monitor *mon);
 void hmp_info_cpus(Monitor *mon);
 void hmp_info_block(Monitor *mon);
 void hmp_info_blockstats(Monitor *mon);
diff --git a/migration.c b/migration.c
index 8db1b43..35444f7 100644
--- a/migration.c
+++ b/migration.c
@@ -166,6 +166,18 @@ MigrationInfo *qmp_query_migrate(Error **errp)
     return info;
 }
 
+MigrationCapabilityStatusList *
+qmp_query_migration_supported_capabilities(Error **errp)
+{
+    MigrationCapabilityStatusList *caps_list = g_malloc0(sizeof(*caps_list));
+
+    caps_list->value = g_malloc(sizeof(*caps_list->value));
+    caps_list->value->capability = MIGRATION_CAPABILITY_XBZRLE;
+    caps_list->next = NULL;
+
+    return caps_list;
+}
+
 /* shared migration helpers */
 
 static int migrate_fd_cleanup(MigrationState *s)
diff --git a/monitor.c b/monitor.c
index 09aa3cd..43f7df5 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2662,6 +2662,13 @@ static mon_cmd_t info_cmds[] = {
         .mhandler.info = hmp_info_migrate,
     },
     {
+        .name       = "migration_supported_capabilities",
+        .args_type  = "",
+        .params     = "",
+        .help       = "show migration supported capabilities",
+        .mhandler.info = hmp_info_migration_supported_capabilities,
+    },
+    {
         .name       = "balloon",
         .args_type  = "",
         .params     = "",
diff --git a/qapi-schema.json b/qapi-schema.json
index a92adb1..68d0fbb 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -306,6 +306,45 @@
 { 'command': 'query-migrate', 'returns': 'MigrationInfo' }
 
 ##
+# @MigrationCapability
+#
+# Migration capabilities enumeration
+#
+# @xbzrle: Migration supports xbzrle (Xor Based Zero Run Length Encoding).
+#          This feature allows us to minimize migration traffic for certain work
+#          loads, by sending compressed difference of the pages
+#
+# Since: 1.2
+##
+{ 'enum': 'MigrationCapability',
+  'data': ['xbzrle'] }
+
+##
+# @MigrationCapabilityStatus
+#
+# Migration capability information
+#
+# @capability: capability enum
+#
+# @state: capability state bool
+#
+# Since: 1.2
+##
+{ 'type': 'MigrationCapabilityStatus',
+  'data': { 'capability' : 'MigrationCapability', 'state' : 'bool' } }
+
+##
+# @query-migration-supported-capabilities
+#
+# Returns information about current migration process capabilities.
+#
+# Returns: @MigrationCapabilityStatus list
+#
+# Since: 1.2
+##
+{ 'command': 'query-migration-supported-capabilities', 'returns': ['MigrationCapabilityStatus'] }
+
+##
 # @MouseInfo:
 #
 # Information about a mouse device.
diff --git a/qmp-commands.hx b/qmp-commands.hx
index e3cf3c5..16fbcef 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2141,6 +2141,31 @@ EQMP
     },
 
 SQMP
+query-migration-supported-capabilities
+-------
+
+Query migration supported capabilities
+
+- "xbzrle": xbzrle support
+
+Arguments:
+
+Example:
+
+-> { "execute": "query-migration-supported-capabilities"}
+<- { "return": [ { "capability": "xbzrle", "state": true },
+                 { "capability": "foobar", "state": false } ] }
+
+EQMP
+
+    {
+        .name       = "query-migration-supported-capabilities",
+        .args_type  = "",
+	.mhandler.cmd_new =
+            qmp_marshal_input_query_migration_supported_capabilities,
+    },
+
+SQMP
 query-balloon
 -------------
 
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: [Qemu-devel] [PATCH 01/11] Add migration capabilities
  2012-08-02 12:44 ` [Qemu-devel] [PATCH 01/11] Add migration capabilities Orit Wasserman
@ 2012-08-03 17:11   ` Luiz Capitulino
  0 siblings, 0 replies; 47+ messages in thread
From: Luiz Capitulino @ 2012-08-03 17:11 UTC (permalink / raw)
  To: Orit Wasserman
  Cc: peter.maydell, aliguori, quintela, stefanha, qemu-devel, mdroth,
	blauwirbel, chegu_vinod, avi, pbonzini, eblake

On Thu,  2 Aug 2012 15:44:44 +0300
Orit Wasserman <owasserm@redhat.com> wrote:

> Add migration capabilities that can be queried by the management using
> query-migration-supported-capabilities command.
> The management can query the source QEMU and the destination QEMU in order to
> verify both support some migration capability (currently only XBZRLE).
> 
> Signed-off-by: Orit Wasserman <owasserm@redhat.com>
> Signed-off-by: Juan Quintela <quintela@redhat.com>
> ---
>  hmp-commands.hx  |    2 ++
>  hmp.c            |   21 +++++++++++++++++++++
>  hmp.h            |    1 +
>  migration.c      |   12 ++++++++++++
>  monitor.c        |    7 +++++++
>  qapi-schema.json |   39 +++++++++++++++++++++++++++++++++++++++
>  qmp-commands.hx  |   25 +++++++++++++++++++++++++
>  7 files changed, 107 insertions(+), 0 deletions(-)
> 
> diff --git a/hmp-commands.hx b/hmp-commands.hx
> index eea8b32..8267237 100644
> --- a/hmp-commands.hx
> +++ b/hmp-commands.hx
> @@ -1417,6 +1417,8 @@ show CPU statistics
>  show user network stack connection states
>  @item info migrate
>  show migration status
> +@item info migration_supported_capabilities
> +show migration supported capabilities
>  @item info balloon
>  show balloon information
>  @item info qtree
> diff --git a/hmp.c b/hmp.c
> index 6b72a64..2ff71a3 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -161,6 +161,27 @@ void hmp_info_migrate(Monitor *mon)
>      qapi_free_MigrationInfo(info);
>  }
>  
> +void hmp_info_migration_supported_capabilities(Monitor *mon)
> +{
> +    MigrationCapabilityStatusList *caps_list, *cap;
> +
> +    caps_list = qmp_query_migration_supported_capabilities(NULL);
> +    if (!caps_list) {
> +        monitor_printf(mon, "No supported migration capabilities found\n");
> +        return;
> +    }
> +
> +    for (cap = caps_list; cap; cap = cap->next) {
> +        monitor_printf(mon, "%s: %s ",
> +                       MigrationCapability_lookup[cap->value->capability],
> +                       cap->value->state ? "on" : "off");
> +    }
> +
> +    monitor_printf(mon, "\n");
> +
> +    qapi_free_MigrationCapabilityStatusList(caps_list);
> +}
> +
>  void hmp_info_cpus(Monitor *mon)
>  {
>      CpuInfoList *cpu_list, *cpu;
> diff --git a/hmp.h b/hmp.h
> index 8d2b0d7..8442c22 100644
> --- a/hmp.h
> +++ b/hmp.h
> @@ -25,6 +25,7 @@ void hmp_info_uuid(Monitor *mon);
>  void hmp_info_chardev(Monitor *mon);
>  void hmp_info_mice(Monitor *mon);
>  void hmp_info_migrate(Monitor *mon);
> +void hmp_info_migration_supported_capabilities(Monitor *mon);
>  void hmp_info_cpus(Monitor *mon);
>  void hmp_info_block(Monitor *mon);
>  void hmp_info_blockstats(Monitor *mon);
> diff --git a/migration.c b/migration.c
> index 8db1b43..35444f7 100644
> --- a/migration.c
> +++ b/migration.c
> @@ -166,6 +166,18 @@ MigrationInfo *qmp_query_migrate(Error **errp)
>      return info;
>  }
>  
> +MigrationCapabilityStatusList *
> +qmp_query_migration_supported_capabilities(Error **errp)
> +{
> +    MigrationCapabilityStatusList *caps_list = g_malloc0(sizeof(*caps_list));
> +
> +    caps_list->value = g_malloc(sizeof(*caps_list->value));
> +    caps_list->value->capability = MIGRATION_CAPABILITY_XBZRLE;

This is missing:

caps_list->value->state = true;

> +    caps_list->next = NULL;
> +
> +    return caps_list;
> +}
> +
>  /* shared migration helpers */
>  
>  static int migrate_fd_cleanup(MigrationState *s)
> diff --git a/monitor.c b/monitor.c
> index 09aa3cd..43f7df5 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -2662,6 +2662,13 @@ static mon_cmd_t info_cmds[] = {
>          .mhandler.info = hmp_info_migrate,
>      },
>      {
> +        .name       = "migration_supported_capabilities",

I'd do s/migration/migrate for all commands you're introducing.

> +        .args_type  = "",
> +        .params     = "",
> +        .help       = "show migration supported capabilities",
> +        .mhandler.info = hmp_info_migration_supported_capabilities,
> +    },
> +    {
>          .name       = "balloon",
>          .args_type  = "",
>          .params     = "",
> diff --git a/qapi-schema.json b/qapi-schema.json
> index a92adb1..68d0fbb 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -306,6 +306,45 @@
>  { 'command': 'query-migrate', 'returns': 'MigrationInfo' }
>  
>  ##
> +# @MigrationCapability
> +#
> +# Migration capabilities enumeration
> +#
> +# @xbzrle: Migration supports xbzrle (Xor Based Zero Run Length Encoding).
> +#          This feature allows us to minimize migration traffic for certain work
> +#          loads, by sending compressed difference of the pages
> +#
> +# Since: 1.2
> +##
> +{ 'enum': 'MigrationCapability',
> +  'data': ['xbzrle'] }
> +
> +##
> +# @MigrationCapabilityStatus
> +#
> +# Migration capability information
> +#
> +# @capability: capability enum
> +#
> +# @state: capability state bool
> +#
> +# Since: 1.2
> +##
> +{ 'type': 'MigrationCapabilityStatus',
> +  'data': { 'capability' : 'MigrationCapability', 'state' : 'bool' } }
> +
> +##
> +# @query-migration-supported-capabilities
> +#
> +# Returns information about current migration process capabilities.
> +#
> +# Returns: @MigrationCapabilityStatus list
> +#
> +# Since: 1.2
> +##
> +{ 'command': 'query-migration-supported-capabilities', 'returns': ['MigrationCapabilityStatus'] }
> +
> +##
>  # @MouseInfo:
>  #
>  # Information about a mouse device.
> diff --git a/qmp-commands.hx b/qmp-commands.hx
> index e3cf3c5..16fbcef 100644
> --- a/qmp-commands.hx
> +++ b/qmp-commands.hx
> @@ -2141,6 +2141,31 @@ EQMP
>      },
>  
>  SQMP
> +query-migration-supported-capabilities
> +-------
> +
> +Query migration supported capabilities
> +
> +- "xbzrle": xbzrle support
> +
> +Arguments:
> +
> +Example:
> +
> +-> { "execute": "query-migration-supported-capabilities"}
> +<- { "return": [ { "capability": "xbzrle", "state": true },
> +                 { "capability": "foobar", "state": false } ] }
> +
> +EQMP
> +
> +    {
> +        .name       = "query-migration-supported-capabilities",
> +        .args_type  = "",
> +	.mhandler.cmd_new =
> +            qmp_marshal_input_query_migration_supported_capabilities,
> +    },
> +
> +SQMP
>  query-balloon
>  -------------
>  

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [Qemu-devel] [PATCH 01/11] Add migration capabilities
  2012-08-05  9:13 [Qemu-devel] [PATCH 00/11] Migration next v10 Orit Wasserman
@ 2012-08-05  9:13 ` Orit Wasserman
  0 siblings, 0 replies; 47+ messages in thread
From: Orit Wasserman @ 2012-08-05  9:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, aliguori, quintela, stefanha, mdroth, lcapitulino,
	blauwirbel, Orit Wasserman, chegu_vinod, avi, pbonzini, eblake

Add migration capabilities that can be queried by the management using
query-migrate-supported-capabilities command.
The management can query the source QEMU and the destination QEMU in order to
verify both support some migration capability (currently only XBZRLE).

Signed-off-by: Orit Wasserman <owasserm@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
 hmp-commands.hx  |    2 ++
 hmp.c            |   21 +++++++++++++++++++++
 hmp.h            |    1 +
 migration.c      |   13 +++++++++++++
 monitor.c        |    7 +++++++
 qapi-schema.json |   39 +++++++++++++++++++++++++++++++++++++++
 qmp-commands.hx  |   25 +++++++++++++++++++++++++
 7 files changed, 108 insertions(+), 0 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index eea8b32..1aa314f 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1417,6 +1417,8 @@ show CPU statistics
 show user network stack connection states
 @item info migrate
 show migration status
+@item info migrate_supported_capabilities
+show migrate supported capabilities
 @item info balloon
 show balloon information
 @item info qtree
diff --git a/hmp.c b/hmp.c
index 6b72a64..b5c7afe 100644
--- a/hmp.c
+++ b/hmp.c
@@ -161,6 +161,27 @@ void hmp_info_migrate(Monitor *mon)
     qapi_free_MigrationInfo(info);
 }
 
+void hmp_info_migrate_supported_capabilities(Monitor *mon)
+{
+    MigrationCapabilityStatusList *caps_list, *cap;
+
+    caps_list = qmp_query_migrate_supported_capabilities(NULL);
+    if (!caps_list) {
+        monitor_printf(mon, "No supported migration capabilities found\n");
+        return;
+    }
+
+    for (cap = caps_list; cap; cap = cap->next) {
+        monitor_printf(mon, "%s: %s ",
+                       MigrationCapability_lookup[cap->value->capability],
+                       cap->value->state ? "on" : "off");
+    }
+
+    monitor_printf(mon, "\n");
+
+    qapi_free_MigrationCapabilityStatusList(caps_list);
+}
+
 void hmp_info_cpus(Monitor *mon)
 {
     CpuInfoList *cpu_list, *cpu;
diff --git a/hmp.h b/hmp.h
index 8d2b0d7..a6194c1 100644
--- a/hmp.h
+++ b/hmp.h
@@ -25,6 +25,7 @@ void hmp_info_uuid(Monitor *mon);
 void hmp_info_chardev(Monitor *mon);
 void hmp_info_mice(Monitor *mon);
 void hmp_info_migrate(Monitor *mon);
+void hmp_info_migrate_supported_capabilities(Monitor *mon);
 void hmp_info_cpus(Monitor *mon);
 void hmp_info_block(Monitor *mon);
 void hmp_info_blockstats(Monitor *mon);
diff --git a/migration.c b/migration.c
index 8db1b43..fc40f1f 100644
--- a/migration.c
+++ b/migration.c
@@ -166,6 +166,19 @@ MigrationInfo *qmp_query_migrate(Error **errp)
     return info;
 }
 
+MigrationCapabilityStatusList *
+qmp_query_migrate_supported_capabilities(Error **errp)
+{
+    MigrationCapabilityStatusList *caps_list = g_malloc0(sizeof(*caps_list));
+
+    caps_list->value = g_malloc(sizeof(*caps_list->value));
+    caps_list->value->capability = MIGRATION_CAPABILITY_XBZRLE;
+    caps_list->value->state = true;
+    caps_list->next = NULL;
+
+    return caps_list;
+}
+
 /* shared migration helpers */
 
 static int migrate_fd_cleanup(MigrationState *s)
diff --git a/monitor.c b/monitor.c
index 09aa3cd..d09cf4e 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2662,6 +2662,13 @@ static mon_cmd_t info_cmds[] = {
         .mhandler.info = hmp_info_migrate,
     },
     {
+        .name       = "migrate_supported_capabilities",
+        .args_type  = "",
+        .params     = "",
+        .help       = "show migration supported capabilities",
+        .mhandler.info = hmp_info_migrate_supported_capabilities,
+    },
+    {
         .name       = "balloon",
         .args_type  = "",
         .params     = "",
diff --git a/qapi-schema.json b/qapi-schema.json
index a92adb1..8050069 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -306,6 +306,45 @@
 { 'command': 'query-migrate', 'returns': 'MigrationInfo' }
 
 ##
+# @MigrationCapability
+#
+# Migration capabilities enumeration
+#
+# @xbzrle: Migration supports xbzrle (Xor Based Zero Run Length Encoding).
+#          This feature allows us to minimize migration traffic for certain work
+#          loads, by sending compressed difference of the pages
+#
+# Since: 1.2
+##
+{ 'enum': 'MigrationCapability',
+  'data': ['xbzrle'] }
+
+##
+# @MigrationCapabilityStatus
+#
+# Migration capability information
+#
+# @capability: capability enum
+#
+# @state: capability state bool
+#
+# Since: 1.2
+##
+{ 'type': 'MigrationCapabilityStatus',
+  'data': { 'capability' : 'MigrationCapability', 'state' : 'bool' } }
+
+##
+# @query-migrate-supported-capabilities
+#
+# Returns information about current migration process capabilities.
+#
+# Returns: @MigrationCapabilityStatus list
+#
+# Since: 1.2
+##
+{ 'command': 'query-migrate-supported-capabilities', 'returns': ['MigrationCapabilityStatus'] }
+
+##
 # @MouseInfo:
 #
 # Information about a mouse device.
diff --git a/qmp-commands.hx b/qmp-commands.hx
index e3cf3c5..d2f68ab 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2141,6 +2141,31 @@ EQMP
     },
 
 SQMP
+query-migrate-supported-capabilities
+-------
+
+Query migration supported capabilities
+
+- "xbzrle": xbzrle support
+
+Arguments:
+
+Example:
+
+-> { "execute": "query-migrate-supported-capabilities"}
+<- { "return": [ { "capability": "xbzrle", "state": true },
+                 { "capability": "foobar", "state": false } ] }
+
+EQMP
+
+    {
+        .name       = "query-migrate-supported-capabilities",
+        .args_type  = "",
+	.mhandler.cmd_new =
+            qmp_marshal_input_query_migrate_supported_capabilities,
+    },
+
+SQMP
 query-balloon
 -------------
 
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 47+ messages in thread

end of thread, other threads:[~2012-08-05  9:13 UTC | newest]

Thread overview: 47+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-07-29  9:42 [Qemu-devel] [PATCH 00/11] Migration next v7 Orit Wasserman
2012-07-29  9:42 ` [Qemu-devel] [PATCH 01/11] Add migration capabilities Orit Wasserman
2012-07-30 17:24   ` Luiz Capitulino
2012-07-30 17:29     ` Luiz Capitulino
2012-07-30 17:45   ` Eric Blake
2012-07-29  9:42 ` [Qemu-devel] [PATCH 02/11] Add migrate_set_parameter and query-migrate-parameters Orit Wasserman
2012-07-30 17:41   ` Luiz Capitulino
2012-07-31  7:46     ` Orit Wasserman
2012-07-31 13:09       ` Luiz Capitulino
2012-07-31  8:03     ` Orit Wasserman
2012-07-30 18:11   ` Eric Blake
2012-07-30 18:15     ` Luiz Capitulino
2012-07-30 19:12   ` Juan Quintela
2012-07-30 19:24     ` Eric Blake
2012-07-30 19:37     ` Anthony Liguori
2012-07-30 20:21     ` Juan Quintela
2012-07-30 19:45   ` Anthony Liguori
2012-07-30 19:58     ` Luiz Capitulino
2012-07-30 20:04       ` Anthony Liguori
2012-07-30 20:20         ` Luiz Capitulino
2012-07-29  9:42 ` [Qemu-devel] [PATCH 03/11] Add XBZRLE documentation Orit Wasserman
2012-07-29  9:42 ` [Qemu-devel] [PATCH 04/11] Add cache handling functions Orit Wasserman
2012-07-29  9:42 ` [Qemu-devel] [PATCH 05/11] Add uleb encoding/decoding functions Orit Wasserman
2012-07-29  9:42 ` [Qemu-devel] [PATCH 06/11] Add xbzrle_encode_buffer and xbzrle_decode_buffer functions Orit Wasserman
2012-07-29  9:42 ` [Qemu-devel] [PATCH 07/11] Add XBZRLE to ram_save_block and ram_save_live Orit Wasserman
2012-07-29  9:43 ` [Qemu-devel] [PATCH 08/11] Add migrate_set_cachesize command Orit Wasserman
2012-07-29  9:43 ` [Qemu-devel] [PATCH 09/11] Add migration accounting for normal and duplicate pages Orit Wasserman
2012-07-30 19:30   ` Luiz Capitulino
2012-07-31  8:36     ` Orit Wasserman
2012-07-31 13:19       ` Luiz Capitulino
2012-07-29  9:43 ` [Qemu-devel] [PATCH 10/11] Add XBZRLE statistics Orit Wasserman
2012-07-30 19:37   ` Luiz Capitulino
2012-07-31  8:31     ` Orit Wasserman
2012-07-31 13:16       ` Luiz Capitulino
2012-07-31 14:13         ` Orit Wasserman
2012-07-31 15:54           ` Luiz Capitulino
2012-07-29  9:43 ` [Qemu-devel] [PATCH 11/11] Restart optimization on stage3 update version Orit Wasserman
2012-07-30 19:38 ` [Qemu-devel] [PATCH 00/11] Migration next v7 Luiz Capitulino
2012-07-30 20:36   ` Orit Wasserman
2012-07-30 22:13   ` Juan Quintela
  -- strict thread matches above, loose matches on Subject: below --
2012-08-05  9:13 [Qemu-devel] [PATCH 00/11] Migration next v10 Orit Wasserman
2012-08-05  9:13 ` [Qemu-devel] [PATCH 01/11] Add migration capabilities Orit Wasserman
2012-08-02 12:44 [Qemu-devel] [PATCH 00/11] Migration next v9 Orit Wasserman
2012-08-02 12:44 ` [Qemu-devel] [PATCH 01/11] Add migration capabilities Orit Wasserman
2012-08-03 17:11   ` Luiz Capitulino
2012-08-01 18:01 [Qemu-devel] [PULL 00/11] Migration next Juan Quintela
2012-08-01 18:01 ` [Qemu-devel] [PATCH 01/11] Add migration capabilities Juan Quintela
2012-07-31 18:54 [Qemu-devel] [PATCH 00/11] Migration next v8 Orit Wasserman
2012-07-31 18:54 ` [Qemu-devel] [PATCH 01/11] Add migration capabilities Orit Wasserman
2012-07-25 14:50 [Qemu-devel] [PATCH 00/11] Migration next v6 Orit Wasserman
2012-07-25 14:50 ` [Qemu-devel] [PATCH 01/11] Add migration capabilities Orit Wasserman
2012-07-24 18:19 [Qemu-devel] [PATCH 00/11] Migration next v5 Juan Quintela
2012-07-24 18:19 ` [Qemu-devel] [PATCH 01/11] Add migration capabilities Juan Quintela

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).