From e64c75a9752c5d0fd64eb2e684c656a5ea7d03c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Fri, 23 Sep 2016 00:39:25 +0400 Subject: [PATCH 01/11] qmp: fix object-add assert() without props MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit ad739706bbadee49, user_creatable_add_type() expects to be given a qdict. However, if object-add is called without props, you reach the assert: "qemu/qom/object_interfaces.c:115: user_creatable_add_type: Assertion `qdict' failed.", because the qdict isn't created in this case (it's optional). Furthermore, qmp_input_visitor_new() is not meant to be called without a dict, and a further commit will assert in this situation. If none given, create an empty qdict in qmp to avoid the user_creatable_add_type() assert(qdict). Signed-off-by: Marc-André Lureau Reviewed-by: Eric Blake Message-Id: <20160922203927.28241-2-marcandre.lureau@redhat.com> Tested-by: Xiao Long Jiang Reviewed-by: Markus Armbruster Signed-off-by: Markus Armbruster --- qmp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/qmp.c b/qmp.c index 621f6ae6d9..b3ba9ef9c4 100644 --- a/qmp.c +++ b/qmp.c @@ -660,7 +660,7 @@ void qmp_add_client(const char *protocol, const char *fdname, void qmp_object_add(const char *type, const char *id, bool has_props, QObject *props, Error **errp) { - const QDict *pdict = NULL; + QDict *pdict; Visitor *v; Object *obj; @@ -670,14 +670,18 @@ void qmp_object_add(const char *type, const char *id, error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict"); return; } + QINCREF(pdict); + } else { + pdict = qdict_new(); } - v = qmp_input_visitor_new(props, true); + v = qmp_input_visitor_new(QOBJECT(pdict), true); obj = user_creatable_add_type(type, id, pdict, v, errp); visit_free(v); if (obj) { object_unref(obj); } + QDECREF(pdict); } void qmp_object_del(const char *id, Error **errp) From c489780203f9b22aca5539ec7589b7140bdc951f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Fri, 23 Sep 2016 00:39:26 +0400 Subject: [PATCH 02/11] qapi: Fix crash when 'any' or 'null' parameter is missing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unlike the other visit methods, visit_type_any() and visit_type_null() neglect to check whether qmp_input_get_object() succeeded. They crash when it fails. Reproducer: { "execute": "qom-set", "arguments": { "path": "/machine", "property": "rtc-time" } } Will crash with: qapi/qapi-visit-core.c:277: visit_type_any: Assertion `!err != !*obj' failed Broken in commit 5c678ee. Fix by adding the missing error checks. Signed-off-by: Marc-André Lureau Reviewed-by: Eric Blake Message-Id: <20160922203927.28241-3-marcandre.lureau@redhat.com> Reviewed-by: Markus Armbruster [Commit message rephrased] Signed-off-by: Markus Armbruster --- qapi/qmp-input-visitor.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c index 64dd392e6f..fc91e74894 100644 --- a/qapi/qmp-input-visitor.c +++ b/qapi/qmp-input-visitor.c @@ -338,6 +338,12 @@ static void qmp_input_type_any(Visitor *v, const char *name, QObject **obj, QmpInputVisitor *qiv = to_qiv(v); QObject *qobj = qmp_input_get_object(qiv, name, true); + if (!qobj) { + error_setg(errp, QERR_MISSING_PARAMETER, name ? name : "null"); + *obj = NULL; + return; + } + qobject_incref(qobj); *obj = qobj; } @@ -347,6 +353,11 @@ static void qmp_input_type_null(Visitor *v, const char *name, Error **errp) QmpInputVisitor *qiv = to_qiv(v); QObject *qobj = qmp_input_get_object(qiv, name, true); + if (!qobj) { + error_setg(errp, QERR_MISSING_PARAMETER, name ? name : "null"); + return; + } + if (qobject_type(qobj) != QTYPE_QNULL) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", "null"); From bce3035a44c40bd3ec29d3162025fd350f2d8dbf Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 4 Oct 2016 17:23:50 +0200 Subject: [PATCH 03/11] tests/test-qmp-input-strict: Cover missing struct members These tests would have caught the bug fixed by the previous commit. Signed-off-by: Markus Armbruster Message-Id: <1475594630-24758-1-git-send-email-armbru@redhat.com> --- tests/test-qmp-input-strict.c | 46 +++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/tests/test-qmp-input-strict.c b/tests/test-qmp-input-strict.c index 814550ac71..d87f8b89a7 100644 --- a/tests/test-qmp-input-strict.c +++ b/tests/test-qmp-input-strict.c @@ -193,6 +193,50 @@ static void test_validate_fail_struct_nested(TestInputVisitorData *data, g_assert(!udp); } +static void test_validate_fail_struct_missing(TestInputVisitorData *data, + const void *unused) +{ + Error *err = NULL; + Visitor *v; + QObject *any; + GenericAlternate *alt; + bool present; + int en; + int64_t i64; + uint32_t u32; + int8_t i8; + char *str; + double dbl; + + v = validate_test_init(data, "{}"); + visit_start_struct(v, NULL, NULL, 0, &error_abort); + visit_start_struct(v, "struct", NULL, 0, &err); + error_free_or_abort(&err); + visit_start_list(v, "list", NULL, 0, &err); + error_free_or_abort(&err); + visit_start_alternate(v, "alternate", &alt, sizeof(*alt), false, &err); + error_free_or_abort(&err); + visit_optional(v, "optional", &present); + g_assert(!present); + visit_type_enum(v, "enum", &en, EnumOne_lookup, &err); + error_free_or_abort(&err); + visit_type_int(v, "i64", &i64, &err); + error_free_or_abort(&err); + visit_type_uint32(v, "u32", &u32, &err); + error_free_or_abort(&err); + visit_type_int8(v, "i8", &i8, &err); + error_free_or_abort(&err); + visit_type_str(v, "i8", &str, &err); + error_free_or_abort(&err); + visit_type_number(v, "dbl", &dbl, &err); + error_free_or_abort(&err); + visit_type_any(v, "any", &any, &err); + error_free_or_abort(&err); + visit_type_null(v, "null", &err); + error_free_or_abort(&err); + visit_end_struct(v, NULL); +} + static void test_validate_fail_list(TestInputVisitorData *data, const void *unused) { @@ -316,6 +360,8 @@ int main(int argc, char **argv) &testdata, test_validate_fail_struct); validate_test_add("/visitor/input-strict/fail/struct-nested", &testdata, test_validate_fail_struct_nested); + validate_test_add("/visitor/input-strict/fail/struct-missing", + &testdata, test_validate_fail_struct_missing); validate_test_add("/visitor/input-strict/fail/list", &testdata, test_validate_fail_list); validate_test_add("/visitor/input-strict/fail/union-flat", From 5d0cbbcfeb59e1e3f5ee7d26b8a215382f6d9abd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Fri, 30 Sep 2016 13:59:46 +0400 Subject: [PATCH 04/11] qapi: add assert about root value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qiv->root should not be null, make that clearer with some assert. Signed-off-by: Marc-André Lureau Reviewed-by: Eric Blake Message-Id: <20160930095948.3154-2-marcandre.lureau@redhat.com> Reviewed-by: Markus Armbruster Signed-off-by: Markus Armbruster --- qapi/qmp-input-visitor.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c index fc91e74894..c7deca95b3 100644 --- a/qapi/qmp-input-visitor.c +++ b/qapi/qmp-input-visitor.c @@ -64,6 +64,7 @@ static QObject *qmp_input_get_object(QmpInputVisitor *qiv, if (QSLIST_EMPTY(&qiv->stack)) { /* Starting at root, name is ignored. */ + assert(qiv->root); return qiv->root; } @@ -395,6 +396,7 @@ Visitor *qmp_input_visitor_new(QObject *obj, bool strict) { QmpInputVisitor *v; + assert(obj); v = g_malloc0(sizeof(*v)); v->visitor.type = VISITOR_INPUT; From eac8e79ff749fc15e1dca4caccf1f38664ab4915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Fri, 30 Sep 2016 13:59:47 +0400 Subject: [PATCH 05/11] qapi: assert list entry has a value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This helps to figure out the expectations. Signed-off-by: Marc-André Lureau Reviewed-by: Eric Blake Message-Id: <20160930095948.3154-3-marcandre.lureau@redhat.com> Reviewed-by: Markus Armbruster Signed-off-by: Markus Armbruster --- qapi/qmp-input-visitor.c | 1 + 1 file changed, 1 insertion(+) diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c index c7deca95b3..fe097c99b3 100644 --- a/qapi/qmp-input-visitor.c +++ b/qapi/qmp-input-visitor.c @@ -84,6 +84,7 @@ static QObject *qmp_input_get_object(QmpInputVisitor *qiv, assert(qobject_type(qobj) == QTYPE_QLIST); assert(!name); ret = qlist_entry_obj(tos->entry); + assert(ret); if (consume) { tos->entry = qlist_next(tos->entry); } From 1382d4abdf9619985e4078e37e49e487cea9935e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Fri, 30 Sep 2016 13:59:48 +0400 Subject: [PATCH 06/11] qapi: return a 'missing parameter' error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'old' dispatch code returned a QERR_MISSING_PARAMETER for missing parameters, but the qapi qmp_dispatch() code uses QERR_INVALID_PARAMETER_TYPE. Improve qapi code to return QERR_MISSING_PARAMETER where appropriate. Fix expected error message in iotests. Signed-off-by: Marc-André Lureau Reviewed-by: Alberto Garcia Reviewed-by: Eric Blake Message-Id: <20160930095948.3154-4-marcandre.lureau@redhat.com> [Drop incorrect error_setg() from qmp_input_type_any() and qmp_input_type_null()] Reviewed-by: Markus Armbruster Signed-off-by: Markus Armbruster --- qapi/qmp-input-visitor.c | 67 +++++++++++++++++++++++++++----------- tests/qemu-iotests/087.out | 2 +- 2 files changed, 49 insertions(+), 20 deletions(-) diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c index fe097c99b3..37a8e1f931 100644 --- a/qapi/qmp-input-visitor.c +++ b/qapi/qmp-input-visitor.c @@ -56,7 +56,7 @@ static QmpInputVisitor *to_qiv(Visitor *v) static QObject *qmp_input_get_object(QmpInputVisitor *qiv, const char *name, - bool consume) + bool consume, Error **errp) { StackObject *tos; QObject *qobj; @@ -80,6 +80,9 @@ static QObject *qmp_input_get_object(QmpInputVisitor *qiv, bool removed = g_hash_table_remove(tos->h, name); assert(removed); } + if (!ret) { + error_setg(errp, QERR_MISSING_PARAMETER, name); + } } else { assert(qobject_type(qobj) == QTYPE_QLIST); assert(!name); @@ -165,13 +168,16 @@ static void qmp_input_start_struct(Visitor *v, const char *name, void **obj, size_t size, Error **errp) { QmpInputVisitor *qiv = to_qiv(v); - QObject *qobj = qmp_input_get_object(qiv, name, true); + QObject *qobj = qmp_input_get_object(qiv, name, true, errp); Error *err = NULL; if (obj) { *obj = NULL; } - if (!qobj || qobject_type(qobj) != QTYPE_QDICT) { + if (!qobj) { + return; + } + if (qobject_type(qobj) != QTYPE_QDICT) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", "QDict"); return; @@ -193,10 +199,13 @@ static void qmp_input_start_list(Visitor *v, const char *name, GenericList **list, size_t size, Error **errp) { QmpInputVisitor *qiv = to_qiv(v); - QObject *qobj = qmp_input_get_object(qiv, name, true); + QObject *qobj = qmp_input_get_object(qiv, name, true, errp); const QListEntry *entry; - if (!qobj || qobject_type(qobj) != QTYPE_QLIST) { + if (!qobj) { + return; + } + if (qobject_type(qobj) != QTYPE_QLIST) { if (list) { *list = NULL; } @@ -234,11 +243,10 @@ static void qmp_input_start_alternate(Visitor *v, const char *name, bool promote_int, Error **errp) { QmpInputVisitor *qiv = to_qiv(v); - QObject *qobj = qmp_input_get_object(qiv, name, false); + QObject *qobj = qmp_input_get_object(qiv, name, false, errp); if (!qobj) { *obj = NULL; - error_setg(errp, QERR_MISSING_PARAMETER, name ? name : "null"); return; } *obj = g_malloc0(size); @@ -252,8 +260,13 @@ static void qmp_input_type_int64(Visitor *v, const char *name, int64_t *obj, Error **errp) { QmpInputVisitor *qiv = to_qiv(v); - QInt *qint = qobject_to_qint(qmp_input_get_object(qiv, name, true)); + QObject *qobj = qmp_input_get_object(qiv, name, true, errp); + QInt *qint; + if (!qobj) { + return; + } + qint = qobject_to_qint(qobj); if (!qint) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", "integer"); @@ -268,8 +281,13 @@ static void qmp_input_type_uint64(Visitor *v, const char *name, uint64_t *obj, { /* FIXME: qobject_to_qint mishandles values over INT64_MAX */ QmpInputVisitor *qiv = to_qiv(v); - QInt *qint = qobject_to_qint(qmp_input_get_object(qiv, name, true)); + QObject *qobj = qmp_input_get_object(qiv, name, true, errp); + QInt *qint; + if (!qobj) { + return; + } + qint = qobject_to_qint(qobj); if (!qint) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", "integer"); @@ -283,8 +301,13 @@ static void qmp_input_type_bool(Visitor *v, const char *name, bool *obj, Error **errp) { QmpInputVisitor *qiv = to_qiv(v); - QBool *qbool = qobject_to_qbool(qmp_input_get_object(qiv, name, true)); + QObject *qobj = qmp_input_get_object(qiv, name, true, errp); + QBool *qbool; + if (!qobj) { + return; + } + qbool = qobject_to_qbool(qobj); if (!qbool) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", "boolean"); @@ -298,10 +321,15 @@ static void qmp_input_type_str(Visitor *v, const char *name, char **obj, Error **errp) { QmpInputVisitor *qiv = to_qiv(v); - QString *qstr = qobject_to_qstring(qmp_input_get_object(qiv, name, true)); + QObject *qobj = qmp_input_get_object(qiv, name, true, errp); + QString *qstr; + *obj = NULL; + if (!qobj) { + return; + } + qstr = qobject_to_qstring(qobj); if (!qstr) { - *obj = NULL; error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", "string"); return; @@ -314,10 +342,13 @@ static void qmp_input_type_number(Visitor *v, const char *name, double *obj, Error **errp) { QmpInputVisitor *qiv = to_qiv(v); - QObject *qobj = qmp_input_get_object(qiv, name, true); + QObject *qobj = qmp_input_get_object(qiv, name, true, errp); QInt *qint; QFloat *qfloat; + if (!qobj) { + return; + } qint = qobject_to_qint(qobj); if (qint) { *obj = qint_get_int(qobject_to_qint(qobj)); @@ -338,11 +369,10 @@ static void qmp_input_type_any(Visitor *v, const char *name, QObject **obj, Error **errp) { QmpInputVisitor *qiv = to_qiv(v); - QObject *qobj = qmp_input_get_object(qiv, name, true); + QObject *qobj = qmp_input_get_object(qiv, name, true, errp); + *obj = NULL; if (!qobj) { - error_setg(errp, QERR_MISSING_PARAMETER, name ? name : "null"); - *obj = NULL; return; } @@ -353,10 +383,9 @@ static void qmp_input_type_any(Visitor *v, const char *name, QObject **obj, static void qmp_input_type_null(Visitor *v, const char *name, Error **errp) { QmpInputVisitor *qiv = to_qiv(v); - QObject *qobj = qmp_input_get_object(qiv, name, true); + QObject *qobj = qmp_input_get_object(qiv, name, true, errp); if (!qobj) { - error_setg(errp, QERR_MISSING_PARAMETER, name ? name : "null"); return; } @@ -369,7 +398,7 @@ static void qmp_input_type_null(Visitor *v, const char *name, Error **errp) static void qmp_input_optional(Visitor *v, const char *name, bool *present) { QmpInputVisitor *qiv = to_qiv(v); - QObject *qobj = qmp_input_get_object(qiv, name, false); + QObject *qobj = qmp_input_get_object(qiv, name, false, NULL); if (!qobj) { *present = false; diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out index cd02eaed4c..dc6baf9366 100644 --- a/tests/qemu-iotests/087.out +++ b/tests/qemu-iotests/087.out @@ -56,7 +56,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on Testing: -S QMP_VERSION {"return": {}} -{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'driver', expected: string"}} +{"error": {"class": "GenericError", "desc": "Parameter 'driver' is missing"}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"} From c833fb4aeb01c124093a7569c0c333f80967d337 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Wed, 28 Sep 2016 19:33:41 +0200 Subject: [PATCH 07/11] MAINTAINERS: Pass the HMP staff from Luiz to David David graciously volunteered to take this off Luiz's hands. Signed-off-by: Markus Armbruster Message-Id: <1475084022-30117-2-git-send-email-armbru@redhat.com> Reviewed-by: Dr. David Alan Gilbert Acked-by: Luiz Capitulino --- MAINTAINERS | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 76a0fdb2c4..851cda76be 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1176,12 +1176,11 @@ F: qemu-timer.c F: vl.c Human Monitor (HMP) -M: Luiz Capitulino +M: Dr. David Alan Gilbert S: Maintained F: monitor.c F: hmp.c F: hmp-commands.hx -T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp Network device backends M: Jason Wang From daf5dc7806f7bbb825506054a7c00a90b841b7cc Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Wed, 28 Sep 2016 19:33:42 +0200 Subject: [PATCH 08/11] MAINTAINERS: Pass the QObject staff from Luiz to Markus QObject is fairly tightly coupled to QAPI these days, and I've been effectively maintaining it together with QAPI for a while. Update MAINTAINERS to reflect that. Signed-off-by: Markus Armbruster Message-Id: <1475084022-30117-3-git-send-email-armbru@redhat.com> Acked-by: Luiz Capitulino --- MAINTAINERS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 851cda76be..5355a5edcd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1245,8 +1245,8 @@ F: qapi/*.json T: git git://repo.or.cz/qemu/armbru.git qapi-next QObject -M: Luiz Capitulino -S: Maintained +M: Markus Armbruster +S: Supported F: qobject/ F: include/qapi/qmp/ X: include/qapi/qmp/dispatch.h @@ -1256,7 +1256,7 @@ F: tests/check-qint.c F: tests/check-qjson.c F: tests/check-qlist.c F: tests/check-qstring.c -T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp +T: git git://repo.or.cz/qemu/armbru.git qapi-next QEMU Guest Agent M: Michael Roth From 728b1429b16ebcc09ca7936d8689db9e006acbef Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 5 Oct 2016 16:49:01 -0300 Subject: [PATCH 09/11] qmp: Disable query-cpu-* commands when they're unavailable Instead of requiring clients to actually call the query-cpu-* commands to find out if they are implemented, remove them from the output of "query-commands", so clients know they are not available. This is implemented by extending the existing hack at qmp_unregister_commands_hack(). I wish I could avoid adding even more #ifdefs to that code, but that's the solution we have today. Signed-off-by: Eduardo Habkost Message-Id: <1475696941-8056-1-git-send-email-ehabkost@redhat.com> Reviewed-by: Eric Blake Reviewed-by: Markus Armbruster Signed-off-by: Markus Armbruster --- monitor.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/monitor.c b/monitor.c index 83c4edfce0..4ff74b7fd0 100644 --- a/monitor.c +++ b/monitor.c @@ -992,6 +992,15 @@ static void qmp_unregister_commands_hack(void) #ifndef TARGET_ARM qmp_unregister_command("query-gic-capabilities"); #endif +#if !defined(TARGET_S390X) + qmp_unregister_command("query-cpu-model-expansion"); + qmp_unregister_command("query-cpu-model-baseline"); + qmp_unregister_command("query-cpu-model-comparison"); +#endif +#if !defined(TARGET_PPC) && !defined(TARGET_ARM) && !defined(TARGET_I386) \ + && !defined(TARGET_S390X) + qmp_unregister_command("query-cpu-definitions"); +#endif } static void qmp_init_marshal(void) From fd11080b9ffa50c713137d0c2bc21d87af9074a9 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 22 Sep 2016 14:16:03 +0200 Subject: [PATCH 10/11] docs: Belatedly update for move of qmp-commands.txt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Missed in commit d076a2a and commit bd6092e. Signed-off-by: Markus Armbruster Message-Id: <1474546563-16332-1-git-send-email-armbru@redhat.com> Reviewed-by: Marc-André Lureau --- docs/xen-save-devices-state.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/xen-save-devices-state.txt b/docs/xen-save-devices-state.txt index 92e08dbf6a..a72ecc8081 100644 --- a/docs/xen-save-devices-state.txt +++ b/docs/xen-save-devices-state.txt @@ -9,7 +9,7 @@ however it is also possible to save the state of all devices to file, without saving the RAM or the block devices of the VM. This operation is called "xen-save-devices-state" (see -QMP/qmp-commands.txt) +qmp-commands.txt) The binary format used in the file is the following: From 77a6da267c37781331c2dc8c4ac7f68d46a2a461 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 6 Oct 2016 17:10:00 +0200 Subject: [PATCH 11/11] docs: Belatedly update for move of QMP/* to docs/ Missed in commit 7537fe0 and commit 9b89b6a. Signed-off-by: Markus Armbruster Message-Id: <1475766600-7273-1-git-send-email-armbru@redhat.com> Reviewed-by: Eric Blake --- docs/qmp-commands.txt | 2 +- docs/writing-qmp-commands.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/qmp-commands.txt b/docs/qmp-commands.txt index e0adcebc67..b289391b4e 100644 --- a/docs/qmp-commands.txt +++ b/docs/qmp-commands.txt @@ -20,7 +20,7 @@ Also, the following notation is used to denote data flow: -> data issued by the Client <- Server data response -Please, refer to the QMP specification (QMP/qmp-spec.txt) for detailed +Please, refer to the QMP specification (docs/qmp-spec.txt) for detailed information on the Server command and response formats. NOTE: This document is temporary and will be replaced soon. diff --git a/docs/writing-qmp-commands.txt b/docs/writing-qmp-commands.txt index cfa6fe7c0d..44c14db418 100644 --- a/docs/writing-qmp-commands.txt +++ b/docs/writing-qmp-commands.txt @@ -7,8 +7,8 @@ This document doesn't discuss QMP protocol level details, nor does it dive into the QAPI framework implementation. For an in-depth introduction to the QAPI framework, please refer to -docs/qapi-code-gen.txt. For documentation about the QMP protocol, please -check the files in QMP/. +docs/qapi-code-gen.txt. For documentation about the QMP protocol, +start with docs/qmp-intro.txt. == Overview ==