qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL 00/22]: QMP queue
@ 2011-12-06 17:54 Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 01/22] docs: Add writing-qmp-commands.txt Luiz Capitulino
                   ` (22 more replies)
  0 siblings, 23 replies; 28+ messages in thread
From: Luiz Capitulino @ 2011-12-06 17:54 UTC (permalink / raw)
  To: aliguori; +Cc: qemu-devel

Anthony,

This pull request contains my round 3 QAPI conversion patches, the new QMP
visitor tests, some documentation and the qmp test tool.

The changes (since 217bfb445b54db618a30f3a39170bebd9fd9dbf2) are available
in the following repository:

    git://repo.or.cz/qemu/qmp-unstable.git queue/qmp

Luiz Capitulino (21):
      docs: Add writing-qmp-commands.txt
      configure: Don't mix glib and libcheck tests
      Introduce test-qmp-output-visitor
      Introduce test-qmp-input-visitor
      Drop test-visitor
      qapi: Complete system_powerdown conversion
      console: Drop unused prototypes
      QError: Introduce QERR_IO_ERROR
      qapi: Convert memsave
      qapi: Convert pmemsave
      qapi: Convert cont
      qapi: Convert inject-nmi
      qapi: Convert set_link
      qapi: Convert block_passwd
      qapi: Convert balloon
      qapi: Convert block_resize
      qapi: Convert blockdev_snapshot_sync
      qapi: Convert human-monitor-command
      qapi: Convert migrate_cancel
      qapi: Convert migrate_set_downtime
      qapi: Convert migrate_set_speed

Mark Wu (1):
      qmp: add test tool for QMP

 Makefile                      |    9 +-
 QMP/qmp                       |  126 ++++++++
 balloon.c                     |   28 +--
 balloon.h                     |    3 -
 blockdev.c                    |   89 +++----
 blockdev.h                    |    4 -
 configure                     |    5 +-
 console.h                     |    2 -
 cpus.c                        |   90 ++++++
 docs/writing-qmp-commands.txt |  642 +++++++++++++++++++++++++++++++++++++++++
 hmp-commands.hx               |   36 +--
 hmp.c                         |  148 ++++++++++
 hmp.h                         |   12 +
 migration.c                   |   28 +--
 migration.h                   |    7 -
 monitor.c                     |  201 ++-----------
 monitor.h                     |    3 +
 net.c                         |   10 +-
 net.h                         |    1 -
 qapi-schema-test.json         |    6 +
 qapi-schema.json              |  267 +++++++++++++++++
 qerror.c                      |    4 +
 qerror.h                      |    3 +
 qmp-commands.hx               |   77 +----
 qmp.c                         |   37 +++
 test-qmp-input-visitor.c      |  270 +++++++++++++++++
 test-qmp-output-visitor.c     |  423 +++++++++++++++++++++++++++
 test-visitor.c                |  338 ----------------------
 28 files changed, 2153 insertions(+), 716 deletions(-)

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

* [Qemu-devel] [PATCH 01/22] docs: Add writing-qmp-commands.txt
  2011-12-06 17:54 [Qemu-devel] [PULL 00/22]: QMP queue Luiz Capitulino
@ 2011-12-06 17:54 ` Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 02/22] qmp: add test tool for QMP Luiz Capitulino
                   ` (21 subsequent siblings)
  22 siblings, 0 replies; 28+ messages in thread
From: Luiz Capitulino @ 2011-12-06 17:54 UTC (permalink / raw)
  To: aliguori; +Cc: qemu-devel

Explains how to write QMP commands using the QAPI.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 docs/writing-qmp-commands.txt |  642 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 642 insertions(+), 0 deletions(-)
 create mode 100644 docs/writing-qmp-commands.txt

diff --git a/docs/writing-qmp-commands.txt b/docs/writing-qmp-commands.txt
new file mode 100644
index 0000000..0472fc3
--- /dev/null
+++ b/docs/writing-qmp-commands.txt
@@ -0,0 +1,642 @@
+= How to write QMP commands using the QAPI framework =
+
+This document is a step-by-step guide on how to write new QMP commands using
+the QAPI framework. It also shows how to implement new style HMP commands.
+
+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/.
+
+== Overview ==
+
+Generally speaking, the following steps should be taken in order to write a
+new QMP command.
+
+1. Write the command's and type(s) specification in the QAPI schema file
+   (qapi-schema.json in the root source directory)
+
+2. Write the QMP command itself, which is a regular C function. Preferably,
+   the command should be exported by some QEMU subsystem. But it can also be
+   added to the qmp.c file
+
+3. At this point the command can be tested under the QMP protocol
+
+4. Write the HMP command equivalent. This is not required and should only be
+   done if it does make sense to have the functionality in HMP. The HMP command
+   is implemented in terms of the QMP command
+
+The following sections will demonstrate each of the steps above. We will start
+very simple and get more complex as we progress.
+
+=== Testing ===
+
+For all the examples in the next sections, the test setup is the same and is
+shown here.
+
+First, QEMU should be started as:
+
+# /path/to/your/source/qemu [...] \
+    -chardev socket,id=qmp,port=4444,host=localhost,server \
+    -mon chardev=qmp,mode=control,pretty=on
+
+Then, in a different terminal:
+
+$ telnet localhost 4444
+Trying 127.0.0.1...
+Connected to localhost.
+Escape character is '^]'.
+{
+    "QMP": {
+        "version": {
+            "qemu": {
+                "micro": 50, 
+                "minor": 15, 
+                "major": 0
+            }, 
+            "package": ""
+        }, 
+        "capabilities": [
+        ]
+    }
+}
+
+The above output is the QMP server saying you're connected. The server is
+actually in capabilities negotiation mode. To enter in command mode type:
+
+{ "execute": "qmp_capabilities" }
+
+Then the server should respond:
+
+{
+    "return": {
+    }
+}
+
+Which is QMP's way of saying "the latest command executed OK and didn't return
+any data". Now you're ready to enter the QMP example commands as explained in
+the following sections.
+
+== Writing a command that doesn't return data ==
+
+That's the most simple QMP command that can be written. Usually, this kind of
+command carries some meaningful action in QEMU but here it will just print
+"Hello, world" to the standard output.
+
+Our command will be called "hello-world". It takes no arguments, nor does it
+return any data.
+
+The first step is to add the following line to the bottom of the
+qapi-schema.json file:
+
+{ 'command': 'hello-world' }
+
+The "command" keyword defines a new QMP command. It's an JSON object. All
+schema entries are JSON objects. The line above will instruct the QAPI to
+generate any prototypes and the necessary code to marshal and unmarshal
+protocol data.
+
+The next step is to write the "hello-world" implementation. As explained
+earlier, it's preferable for commands to live in QEMU subsystems. But
+"hello-world" doesn't pertain to any, so we put its implementation in qmp.c:
+
+void qmp_hello_world(Error **errp)
+{
+    printf("Hello, world!\n");
+}
+
+There are a few things to be noticed:
+
+1. QMP command implementation functions must be prefixed with "qmp_"
+2. qmp_hello_world() returns void, this is in accordance with the fact that the
+   command doesn't return any data
+3. It takes an "Error **" argument. This is required. Later we will see how to
+   return errors and take additional arguments. The Error argument should not
+   be touched if the command doesn't return errors
+4. We won't add the function's prototype. That's automatically done by the QAPI
+5. Printing to the terminal is discouraged for QMP commands, we do it here
+   because it's the easiest way to demonstrate a QMP command
+
+Now a little hack is needed. As we're still using the old QMP server we need
+to add the new command to its internal dispatch table. This step won't be
+required in the near future. Open the qmp-commands.hx file and add the
+following in the botton:
+
+    {
+        .name       = "hello-world",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_hello_world,
+    },
+
+You're done. Now build qemu, run it as suggested in the "Testing" section,
+and then type the following QMP command:
+
+{ "execute": "hello-world" }
+
+Then check the terminal running qemu and look for the "Hello, world" string. If
+you don't see it then something went wrong.
+
+=== Arguments ===
+
+Let's add an argument called "message" to our "hello-world" command. The new
+argument will contain the string to be printed to stdout. It's an optional
+argument, if it's not present we print our default "Hello, World" string.
+
+The first change we have to do is to modify the command specification in the
+schema file to the following:
+
+{ 'command': 'hello-world', 'data': { '*message': 'str' } }
+
+Notice the new 'data' member in the schema. It's an JSON object whose each
+element is an argument to the command in question. Also notice the asterisk,
+it's used to mark the argument optional (that means that you shouldn't use it
+for mandatory arguments). Finally, 'str' is the argument's type, which
+stands for "string". The QAPI also supports integers, booleans, enumerations
+and user defined types.
+
+Now, let's update our C implementation in qmp.c:
+
+void qmp_hello_world(bool has_message, const char *message, Error **errp)
+{
+    if (has_message) {
+        printf("%s\n", message);
+    } else {
+        printf("Hello, world\n");
+    }
+}
+
+There are two important details to be noticed:
+
+1. All optional arguments are accompanied by a 'has_' boolean, which is set
+   if the optional argument is present or false otherwise
+2. The C implementation signature must follow the schema's argument ordering,
+   which is defined by the "data" member
+
+The last step is to update the qmp-commands.hx file:
+
+    {
+        .name       = "hello-world",
+        .args_type  = "message:s?",
+        .mhandler.cmd_new = qmp_marshal_input_hello_world,
+    },
+
+Notice that the "args_type" member got our "message" argument. The character
+"s" stands for "string" and "?" means it's optional. This too must be ordered
+according to the C implementation and schema file. You can look for more
+examples in the qmp-commands.hx file if you need to define more arguments.
+
+Again, this step won't be required in the future.
+
+Time to test our new version of the "hello-world" command. Build qemu, run it as
+described in the "Testing" section and then send two commands:
+
+{ "execute": "hello-world" }
+{
+    "return": {
+    }
+}
+
+{ "execute": "hello-world", "arguments": { "message": "We love qemu" } }
+{
+    "return": {
+    }
+}
+
+You should see "Hello, world" and "we love qemu" in the terminal running qemu,
+if you don't see these strings, then something went wrong.
+
+=== Errors ===
+
+QMP commands should use the error interface exported by the error.h header
+file. The basic function used to set an error is the error_set() one.
+
+Let's say we don't accept the string "message" to contain the word "love". If
+it does contain it, we want the "hello-world" command to the return the
+InvalidParameter error.
+
+Only one change is required, and it's in the C implementation:
+
+void qmp_hello_world(bool has_message, const char *message, Error **errp)
+{
+    if (has_message) {
+        if (strstr(message, "love")) {
+            error_set(errp, QERR_INVALID_PARAMETER, "message");
+            return;
+        }
+        printf("%s\n", message);
+    } else {
+        printf("Hello, world\n");
+    }
+}
+
+Let's test it. Build qemu, run it as defined in the "Testing" section, and
+then issue the following command:
+
+{ "execute": "hello-world", "arguments": { "message": "we love qemu" } }
+
+The QMP server's response should be:
+
+{
+    "error": {
+        "class": "InvalidParameter",
+        "desc": "Invalid parameter 'message'",
+        "data": {
+            "name": "message"
+        }
+    }
+}
+
+Which is the InvalidParameter error.
+
+When you have to return an error but you're unsure what error to return or
+which arguments an error takes, you should look at the qerror.h file. Note
+that you might be required to add new errors if needed.
+
+FIXME: describe better the error API and how to add new errors.
+
+=== Command Documentation ===
+
+There's only one step missing to make "hello-world"'s implementation complete,
+and that's its documentation in the schema file.
+
+This is very important. No QMP command will be accepted in QEMU without proper
+documentation.
+
+There are many examples of such documentation in the schema file already, but
+here goes "hello-world"'s new entry for the qapi-schema.json file:
+
+##
+# @hello-world
+#
+# Print a client provided string to the standard output stream.
+#
+# @message: #optional string to be printed
+#
+# Returns: Nothing on success.
+#          If @message contains "love", InvalidParameter
+#
+# Notes: if @message is not provided, the "Hello, world" string will
+#        be printed instead
+#
+# Since: <next qemu stable release, eg. 1.0>
+##
+{ 'command': 'hello-world', 'data': { '*message': 'str' } }
+
+Please, note that the "Returns" clause is optional if a command doesn't return
+any data nor any errors.
+
+=== Implementing the HMP command ===
+
+Now that the QMP command is in place, we can also make it available in the human
+monitor (HMP).
+
+With the introduction of the QAPI, HMP commands make QMP calls. Most of the
+time HMP commands are simple wrappers. All HMP commands implementation exist in
+the hmp.c file.
+
+Here's the implementation of the "hello-world" HMP command:
+
+void hmp_hello_world(Monitor *mon, const QDict *qdict)
+{
+    const char *message = qdict_get_try_str(qdict, "message");
+    Error *errp = NULL;
+
+    qmp_hello_world(!!message, message, &errp);
+    if (error_is_set(&errp)) {
+        monitor_printf(mon, "%s\n", error_get_pretty(errp));
+        error_free(errp);
+        return;
+    }
+}
+
+Also, you have to add the function's prototype to the hmp.h file.
+
+There are three important points to be noticed:
+
+1. The "mon" and "qdict" arguments are mandatory for all HMP functions. The
+   former is the monitor object. The latter is how the monitor passes
+   arguments entered by the user to the command implementation
+2. hmp_hello_world() performs error checking. In this example we just print
+   the error description to the user, but we could do more, like taking
+   different actions depending on the error qmp_hello_world() returns
+3. The "errp" variable must be initialized to NULL before performing the
+   QMP call
+
+There's one last step to actually make the command available to monitor users,
+we should add it to the hmp-commands.hx file:
+
+    {
+        .name       = "hello-world",
+        .args_type  = "message:s?",
+        .params     = "hello-world [message]",
+        .help       = "Print message to the standard output",
+        .mhandler.cmd = hmp_hello_world,
+    },
+
+STEXI
+@item hello_world @var{message}
+@findex hello_world
+Print message to the standard output
+ETEXI
+
+To test this you have to open a user monitor and issue the "hello-world"
+command. It might be instructive to check the command's documentation with
+HMP's "help" command.
+
+Please, check the "-monitor" command-line option to know how to open a user
+monitor.
+
+== Writing a command that returns data ==
+
+A QMP command is capable of returning any data the QAPI supports like integers,
+strings, booleans, enumerations and user defined types.
+
+In this section we will focus on user defined types. Please, check the QAPI
+documentation for information about the other types.
+
+=== User Defined Types ===
+
+For this example we will write the query-alarm-clock command, which returns
+information about QEMU's timer alarm. For more information about it, please
+check the "-clock" command-line option.
+
+We want to return two pieces of information. The first one is the alarm clock's
+name. The second one is when the next alarm will fire. The former information is
+returned as a string, the latter is an integer in nanoseconds (which is not
+very useful in practice, as the timer has probably already fired when the
+information reaches the client).
+
+The best way to return that data is to create a new QAPI type, as shown below:
+
+##
+# @QemuAlarmClock
+#
+# QEMU alarm clock information.
+#
+# @clock-name: The alarm clock method's name.
+#
+# @next-deadline: #optional The time (in nanoseconds) the next alarm will fire.
+#
+# Since: 1.0
+##
+{ 'type': 'QemuAlarmClock',
+  'data': { 'clock-name': 'str', '*next-deadline': 'int' } }
+
+The "type" keyword defines a new QAPI type. Its "data" member contains the
+type's members. In this example our members are the "clock-name" and the
+"next-deadline" one, which is optional.
+
+Now let's define the query-alarm-clock command:
+
+##
+# @query-alarm-clock
+#
+# Return information about QEMU's alarm clock.
+#
+# Returns a @QemuAlarmClock instance describing the alarm clock method
+# being currently used by QEMU (this is usually set by the '-clock'
+# command-line option).
+#
+# Since: 1.0
+##
+{ 'command': 'query-alarm-clock', 'returns': 'QemuAlarmClock' }
+
+Notice the "returns" keyword. As its name suggests, it's used to define the
+data returned by a command.
+
+It's time to implement the qmp_query_alarm_clock() function, you can put it
+in the qemu-timer.c file:
+
+QemuAlarmClock *qmp_query_alarm_clock(Error **errp)
+{
+    QemuAlarmClock *clock;
+    int64_t deadline;
+
+    clock = g_malloc0(sizeof(*clock));
+
+    deadline = qemu_next_alarm_deadline();
+    if (deadline > 0) {
+        clock->has_next_deadline = true;
+        clock->next_deadline = deadline;
+    }
+    clock->clock_name = g_strdup(alarm_timer->name);
+
+    return clock;
+}
+
+There are a number of things to be noticed:
+
+1. The QemuAlarmClock type is automatically generated by the QAPI framework,
+   its members correspond to the type's specification in the schema file
+2. As specified in the schema file, the function returns a QemuAlarmClock
+   instance and takes no arguments (besides the "errp" one, which is mandatory
+   for all QMP functions)
+3. The "clock" variable (which will point to our QAPI type instance) is
+   allocated by the regular g_malloc0() function. Note that we chose to
+   initialize the memory to zero. This is recomended for all QAPI types, as
+   it helps avoiding bad surprises (specially with booleans)
+4. Remember that "next_deadline" is optional? All optional members have a
+   'has_TYPE_NAME' member that should be properly set by the implementation,
+   as shown above
+5. Even static strings, such as "alarm_timer->name", should be dynamically
+   allocated by the implementation. This is so because the QAPI also generates
+   a function to free its types and it cannot distinguish between dynamically
+   or statically allocated strings
+6. You have to include the "qmp-commands.h" header file in qemu-timer.c,
+   otherwise qemu won't build
+
+The last step is to add the correspoding entry in the qmp-commands.hx file:
+
+    {
+        .name       = "query-alarm-clock",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_alarm_clock,
+    },
+
+Time to test the new command. Build qemu, run it as described in the "Testing"
+section and try this:
+
+{ "execute": "query-alarm-clock" }
+{
+    "return": {
+        "next-deadline": 2368219,
+        "clock-name": "dynticks"
+    }
+}
+
+==== The HMP command ====
+
+Here's the HMP counterpart of the query-alarm-clock command:
+
+void hmp_info_alarm_clock(Monitor *mon)
+{
+    QemuAlarmClock *clock;
+    Error *errp = NULL;
+
+    clock = qmp_query_alarm_clock(&errp);
+    if (error_is_set(&errp)) {
+        monitor_printf(mon, "Could not query alarm clock information\n");
+        error_free(errp);
+        return;
+    }
+
+    monitor_printf(mon, "Alarm clock method in use: '%s'\n", clock->clock_name);
+    if (clock->has_next_deadline) {
+        monitor_printf(mon, "Next alarm will fire in %" PRId64 " nanoseconds\n",
+                       clock->next_deadline);
+    }
+
+   qapi_free_QemuAlarmClock(clock); 
+}
+
+It's important to notice that hmp_info_alarm_clock() calls
+qapi_free_QemuAlarmClock() to free the data returned by qmp_query_alarm_clock().
+For user defined types, the QAPI will generate a qapi_free_QAPI_TYPE_NAME()
+function and that's what you have to use to free the types you define and
+qapi_free_QAPI_TYPE_NAMEList() for list types (explained in the next section).
+If the QMP call returns a string, then you should g_free() to free it.
+
+Also note that hmp_info_alarm_clock() performs error handling. That's not
+strictly required if you're sure the QMP function doesn't return errors, but
+it's good practice to always check for errors.
+
+Another important detail is that HMP's "info" commands don't go into the
+hmp-commands.hx. Instead, they go into the info_cmds[] table, which is defined
+in the monitor.c file. The entry for the "info alarmclock" follows:
+
+    {
+        .name       = "alarmclock",
+        .args_type  = "",
+        .params     = "",
+        .help       = "show information about the alarm clock",
+        .mhandler.info = hmp_info_alarm_clock,
+    },
+
+To test this, run qemu and type "info alarmclock" in the user monitor.
+
+=== Returning Lists ===
+
+For this example, we're going to return all available methods for the timer
+alarm, which is pretty much what the command-line option "-clock ?" does,
+except that we're also going to inform which method is in use.
+
+This first step is to define a new type:
+
+##
+# @TimerAlarmMethod
+#
+# Timer alarm method information.
+#
+# @method-name: The method's name.
+#
+# @current: true if this alarm method is currently in use, false otherwise
+#
+# Since: 1.0
+##
+{ 'type': 'TimerAlarmMethod',
+  'data': { 'method-name': 'str', 'current': 'bool' } }
+
+The command will be called "query-alarm-methods", here is its schema
+specification:
+
+##
+# @query-alarm-methods
+#
+# Returns information about available alarm methods.
+#
+# Returns: a list of @TimerAlarmMethod for each method
+#
+# Since: 1.0
+##
+{ 'command': 'query-alarm-methods', 'returns': ['TimerAlarmMethod'] }
+
+Notice the syntax for returning lists "'returns': ['TimerAlarmMethod']", this
+should be read as "returns a list of TimerAlarmMethod instances".
+
+The C implementation follows:
+
+TimerAlarmMethodList *qmp_query_alarm_methods(Error **errp)
+{
+    TimerAlarmMethodList *method_list = NULL;
+    const struct qemu_alarm_timer *p;
+    bool current = true;
+
+    for (p = alarm_timers; p->name; p++) {
+        TimerAlarmMethodList *info = g_malloc0(sizeof(*info));
+        info->value = g_malloc0(sizeof(*info->value));
+        info->value->method_name = g_strdup(p->name);
+        info->value->current = current;
+
+        current = false;
+
+        info->next = method_list;
+        method_list = info;
+    }
+
+    return method_list;
+}
+
+The most important difference from the previous examples is the
+TimerAlarmMethodList type, which is automatically generated by the QAPI from
+the TimerAlarmMethod type.
+
+Each list node is represented by a TimerAlarmMethodList instance. We have to
+allocate it, and that's done inside the for loop: the "info" pointer points to
+an allocated node. We also have to allocate the node's contents, which is
+stored in its "value" member. In our example, the "value" member is a pointer
+to an TimerAlarmMethod instance.
+
+Notice that the "current" variable is used as "true" only in the first
+interation of the loop. That's because the alarm timer method in use is the
+first element of the alarm_timers array. Also notice that QAPI lists are handled
+by hand and we return the head of the list.
+
+To test this you have to add the corresponding qmp-commands.hx entry:
+
+    {
+        .name       = "query-alarm-methods",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_alarm_methods,
+    },
+
+Now Build qemu, run it as explained in the "Testing" section and try our new
+command:
+
+{ "execute": "query-alarm-methods" }
+{
+    "return": [
+        {
+            "current": false, 
+            "method-name": "unix"
+        }, 
+        {
+            "current": true, 
+            "method-name": "dynticks"
+        }
+    ]
+}
+
+The HMP counterpart is a bit more complex than previous examples because it
+has to traverse the list, it's shown below for reference:
+
+void hmp_info_alarm_methods(Monitor *mon)
+{
+    TimerAlarmMethodList *method_list, *method;
+    Error *errp = NULL;
+
+    method_list = qmp_query_alarm_methods(&errp);
+    if (error_is_set(&errp)) {
+        monitor_printf(mon, "Could not query alarm methods\n");
+        error_free(errp);
+        return;
+    }
+
+    for (method = method_list; method; method = method->next) {
+        monitor_printf(mon, "%c %s\n", method->value->current ? '*' : ' ',
+                                       method->value->method_name);
+    }
+
+    qapi_free_TimerAlarmMethodList(method_list);
+}
-- 
1.7.8.110.g4cb5d1.dirty

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

* [Qemu-devel] [PATCH 02/22] qmp: add test tool for QMP
  2011-12-06 17:54 [Qemu-devel] [PULL 00/22]: QMP queue Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 01/22] docs: Add writing-qmp-commands.txt Luiz Capitulino
@ 2011-12-06 17:54 ` Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 03/22] configure: Don't mix glib and libcheck tests Luiz Capitulino
                   ` (20 subsequent siblings)
  22 siblings, 0 replies; 28+ messages in thread
From: Luiz Capitulino @ 2011-12-06 17:54 UTC (permalink / raw)
  To: aliguori; +Cc: Mark Wu, qemu-devel

From: Mark Wu <wudxw@linux.vnet.ibm.com>

Anthony wrote this quickly to aid in testing.  It's similar to qmp-shell with
a few important differences:

1) It is not interactive.  That makes it useful for scripting.

2) qmp-shell:

(QEMU) set_password protocol=vnc password=foo

3) qmp:

$ qmp set_password --protocol=vnc --password=foo

4) Extensible, git-style interface.  If an invalid command name is
passed, it will try to exec qmp-$1.

5) It attempts to pretty print the JSON responses in a shell friendly
format such that tools can work with the output.

Hope others will also find it useful.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Mark Wu <wudxw@linux.vnet.ibm.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 QMP/qmp |  126 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 126 insertions(+), 0 deletions(-)
 create mode 100755 QMP/qmp

diff --git a/QMP/qmp b/QMP/qmp
new file mode 100755
index 0000000..1db3c7f
--- /dev/null
+++ b/QMP/qmp
@@ -0,0 +1,126 @@
+#!/usr/bin/python
+#
+# QMP command line tool
+#
+# Copyright IBM, Corp. 2011
+#
+# Authors:
+#  Anthony Liguori <aliguori@us.ibm.com>
+#
+# This work is licensed under the terms of the GNU GPLv2 or later.
+# See the COPYING file in the top-level directory.
+
+import sys, os
+from qmp import QEMUMonitorProtocol
+
+def print_response(rsp, prefix=[]):
+    if type(rsp) == list:
+        i = 0
+        for item in rsp:
+            if prefix == []:
+                prefix = ['item']
+            print_response(item, prefix[:-1] + ['%s[%d]' % (prefix[-1], i)])
+            i += 1
+    elif type(rsp) == dict:
+        for key in rsp.keys():
+            print_response(rsp[key], prefix + [key])
+    else:
+        if len(prefix):
+            print '%s: %s' % ('.'.join(prefix), rsp)
+        else:
+            print '%s' % (rsp)
+
+def main(args):
+    path = None
+
+    # Use QMP_PATH if it's set
+    if os.environ.has_key('QMP_PATH'):
+        path = os.environ['QMP_PATH']
+
+    while len(args):
+        arg = args[0]
+
+        if arg.startswith('--'):
+            arg = arg[2:]
+            if arg.find('=') == -1:
+                value = True
+            else:
+                arg, value = arg.split('=', 1)
+
+            if arg in ['path']:
+                if type(value) == str:
+                    path = value
+            elif arg in ['help']:
+                os.execlp('man', 'man', 'qmp')
+            else:
+                print 'Unknown argument "%s"' % arg
+
+            args = args[1:]
+        else:
+            break
+
+    if not path:
+        print "QMP path isn't set, use --path=qmp-monitor-address or set QMP_PATH"
+        return 1
+
+    if len(args):
+        command, args = args[0], args[1:]
+    else:
+        print 'No command found'
+        print 'Usage: "qmp [--path=qmp-monitor-address] qmp-cmd arguments"'
+        return 1
+
+    if command in ['help']:
+        os.execlp('man', 'man', 'qmp')
+
+    srv = QEMUMonitorProtocol(path)
+    srv.connect()
+
+    def do_command(srv, cmd, **kwds):
+        rsp = srv.cmd(cmd, kwds)
+        if rsp.has_key('error'):
+            raise Exception(rsp['error']['desc'])
+        return rsp['return']
+
+    commands = map(lambda x: x['name'], do_command(srv, 'query-commands'))
+
+    srv.close()
+
+    if command not in commands:
+        fullcmd = 'qmp-%s' % command
+        try:
+            os.environ['QMP_PATH'] = path
+            os.execvp(fullcmd, [fullcmd] + args)
+        except OSError, (errno, msg):
+            if errno == 2:
+                print 'Command "%s" not found.' % (fullcmd)
+                return 1
+            raise
+        return 0
+
+    srv = QEMUMonitorProtocol(path)
+    srv.connect()
+
+    arguments = {}
+    for arg in args:
+        if not arg.startswith('--'):
+            print 'Unknown argument "%s"' % arg
+            return 1
+
+        arg = arg[2:]
+        if arg.find('=') == -1:
+            value = True
+        else:
+            arg, value = arg.split('=', 1)
+
+        if arg in ['help']:
+            os.execlp('man', 'man', 'qmp-%s' % command)
+            return 1
+
+        arguments[arg] = value
+
+    rsp = do_command(srv, command, **arguments)
+    print_response(rsp)
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv[1:]))
-- 
1.7.8.110.g4cb5d1.dirty

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

* [Qemu-devel] [PATCH 03/22] configure: Don't mix glib and libcheck tests
  2011-12-06 17:54 [Qemu-devel] [PULL 00/22]: QMP queue Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 01/22] docs: Add writing-qmp-commands.txt Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 02/22] qmp: add test tool for QMP Luiz Capitulino
@ 2011-12-06 17:54 ` Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 04/22] Introduce test-qmp-output-visitor Luiz Capitulino
                   ` (19 subsequent siblings)
  22 siblings, 0 replies; 28+ messages in thread
From: Luiz Capitulino @ 2011-12-06 17:54 UTC (permalink / raw)
  To: aliguori; +Cc: qemu-devel

test-coroutine is listed as a libcheck test in the 'checks' variable. This
is not right because 'make check' won't run test-coroutine if libcheck
tests are not enabled (either because libcheck isn't detected or because
--disable-check-utests is passed).

Tests using the glib test framework are independent from libcheck and
afaik are always present (although having a configure switch to disable
them is probably worth it).

Untangle test-coroutine from the libcheck tests by introducing the
'test_progs' variable and using it to generate the test list used by
'make check'.

Reviewed-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 configure |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/configure b/configure
index 5fbd812..d88288b 100755
--- a/configure
+++ b/configure
@@ -2743,8 +2743,9 @@ if test "$softmmu" = yes ; then
     fi
     if [ "$check_utests" = "yes" ]; then
       checks="check-qint check-qstring check-qdict check-qlist"
-      checks="check-qfloat check-qjson test-coroutine $checks"
+      checks="check-qfloat check-qjson $checks"
     fi
+    test_progs="$checks test-coroutine"
   fi
 fi
 
@@ -3230,7 +3231,7 @@ if test "$trace_default" = "yes"; then
 fi
 
 echo "TOOLS=$tools" >> $config_host_mak
-echo "CHECKS=$checks" >> $config_host_mak
+echo "CHECKS=$test_progs" >> $config_host_mak
 echo "ROMS=$roms" >> $config_host_mak
 echo "MAKE=$make" >> $config_host_mak
 echo "INSTALL=$install" >> $config_host_mak
-- 
1.7.8.110.g4cb5d1.dirty

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

* [Qemu-devel] [PATCH 04/22] Introduce test-qmp-output-visitor
  2011-12-06 17:54 [Qemu-devel] [PULL 00/22]: QMP queue Luiz Capitulino
                   ` (2 preceding siblings ...)
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 03/22] configure: Don't mix glib and libcheck tests Luiz Capitulino
@ 2011-12-06 17:54 ` Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 05/22] Introduce test-qmp-input-visitor Luiz Capitulino
                   ` (18 subsequent siblings)
  22 siblings, 0 replies; 28+ messages in thread
From: Luiz Capitulino @ 2011-12-06 17:54 UTC (permalink / raw)
  To: aliguori; +Cc: qemu-devel

Contains unit-tests for the QMP output visitor implementation.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 Makefile                  |    5 +-
 configure                 |    2 +-
 qapi-schema-test.json     |    6 +
 test-qmp-output-visitor.c |  423 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 434 insertions(+), 2 deletions(-)
 create mode 100644 test-qmp-output-visitor.c

diff --git a/Makefile b/Makefile
index 301c75e..206854a 100644
--- a/Makefile
+++ b/Makefile
@@ -169,7 +169,7 @@ test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y)
 
 $(qapi-obj-y): $(GENERATED_HEADERS)
 qapi-dir := $(BUILD_DIR)/qapi-generated
-test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
+test-qmp-output-visitor.o test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
 qemu-ga$(EXESUF): LIBS = $(LIBS_QGA)
 
 $(qapi-dir)/test-qapi-types.c $(qapi-dir)/test-qapi-types.h :\
@@ -205,6 +205,9 @@ $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py
 test-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
 test-visitor: test-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
 
+test-qmp-output-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
+test-qmp-output-visitor: test-qmp-output-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
+
 test-qmp-commands.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h test-qmp-marshal.c test-qmp-commands.h) $(qapi-obj-y)
 test-qmp-commands: test-qmp-commands.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o $(qapi-dir)/test-qmp-marshal.o module.o
 
diff --git a/configure b/configure
index d88288b..cae1f03 100755
--- a/configure
+++ b/configure
@@ -2745,7 +2745,7 @@ if test "$softmmu" = yes ; then
       checks="check-qint check-qstring check-qdict check-qlist"
       checks="check-qfloat check-qjson $checks"
     fi
-    test_progs="$checks test-coroutine"
+    test_progs="$checks test-coroutine test-qmp-output-visitor"
   fi
 fi
 
diff --git a/qapi-schema-test.json b/qapi-schema-test.json
index 3acedad..2b38919 100644
--- a/qapi-schema-test.json
+++ b/qapi-schema-test.json
@@ -16,6 +16,12 @@
                       'dict': { 'userdef': 'UserDefOne', 'string': 'str' },
                       '*dict2': { 'userdef': 'UserDefOne', 'string': 'str' } } } }
 
+{ 'type': 'UserDefNested',
+  'data': { 'string0': 'str',
+            'dict1': { 'string1': 'str',
+                       'dict2': { 'userdef1': 'UserDefOne', 'string2': 'str' },
+                       '*dict3': { 'userdef2': 'UserDefOne', 'string3': 'str' } } } }
+
 # testing commands
 { 'command': 'user_def_cmd', 'data': {} }
 { 'command': 'user_def_cmd1', 'data': {'ud1a': 'UserDefOne'} }
diff --git a/test-qmp-output-visitor.c b/test-qmp-output-visitor.c
new file mode 100644
index 0000000..c94c208
--- /dev/null
+++ b/test-qmp-output-visitor.c
@@ -0,0 +1,423 @@
+/*
+ * QMP Output Visitor unit-tests.
+ *
+ * Copyright (C) 2011 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino@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 <glib.h>
+
+#include "qapi/qmp-output-visitor.h"
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "qemu-objects.h"
+
+typedef struct TestOutputVisitorData {
+    QmpOutputVisitor *qov;
+    Visitor *ov;
+} TestOutputVisitorData;
+
+static void visitor_output_setup(TestOutputVisitorData *data,
+                                 const void *unused)
+{
+    data->qov = qmp_output_visitor_new();
+    g_assert(data->qov != NULL);
+
+    data->ov = qmp_output_get_visitor(data->qov);
+    g_assert(data->ov != NULL);
+}
+
+static void visitor_output_teardown(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    qmp_output_visitor_cleanup(data->qov);
+    data->qov = NULL;
+    data->ov = NULL;
+}
+
+static void test_visitor_out_int(TestOutputVisitorData *data,
+                                 const void *unused)
+{
+    int64_t value = -42;
+    Error *errp = NULL;
+    QObject *obj;
+
+    visit_type_int(data->ov, &value, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QINT);
+    g_assert_cmpint(qint_get_int(qobject_to_qint(obj)), ==, value);
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_bool(TestOutputVisitorData *data,
+                                  const void *unused)
+{
+    Error *errp = NULL;
+    bool value = true;
+    QObject *obj;
+
+    visit_type_bool(data->ov, &value, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QBOOL);
+    g_assert(qbool_get_int(qobject_to_qbool(obj)) == value);
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_number(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    double value = 3.14;
+    Error *errp = NULL;
+    QObject *obj;
+
+    visit_type_number(data->ov, &value, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QFLOAT);
+    g_assert(qfloat_get_double(qobject_to_qfloat(obj)) == value);
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_string(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    char *string = (char *) "Q E M U";
+    Error *errp = NULL;
+    QObject *obj;
+
+    visit_type_str(data->ov, &string, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QSTRING);
+    g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, string);
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_no_string(TestOutputVisitorData *data,
+                                       const void *unused)
+{
+    char *string = NULL;
+    Error *errp = NULL;
+    QObject *obj;
+
+    /* A null string should return "" */
+    visit_type_str(data->ov, &string, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QSTRING);
+    g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, "");
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_enum(TestOutputVisitorData *data,
+                                  const void *unused)
+{
+    Error *errp = NULL;
+    QObject *obj;
+    EnumOne i;
+
+    for (i = 0; i < ENUM_ONE_MAX; i++) {
+        visit_type_EnumOne(data->ov, &i, "unused", &errp);
+        g_assert(!error_is_set(&errp));
+
+        obj = qmp_output_get_qobject(data->qov);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QSTRING);
+        g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==,
+                        EnumOne_lookup[i]);
+        qobject_decref(obj);
+    }
+}
+
+static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
+                                         const void *unused)
+{
+    EnumOne i, bad_values[] = { ENUM_ONE_MAX, -1 };
+    Error *errp;
+
+    for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
+        errp = NULL;
+        visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp);
+        g_assert(error_is_set(&errp) == true);
+        error_free(errp);
+    }
+}
+
+typedef struct TestStruct
+{
+    int64_t integer;
+    bool boolean;
+    char *string;
+} TestStruct;
+
+static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
+                                  const char *name, Error **errp)
+{
+    visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
+                       errp);
+
+    visit_type_int(v, &(*obj)->integer, "integer", errp);
+    visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
+    visit_type_str(v, &(*obj)->string, "string", errp);
+
+    visit_end_struct(v, errp);
+}
+
+static void test_visitor_out_struct(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    TestStruct test_struct = { .integer = 42,
+                               .boolean = false,
+                               .string = (char *) "foo"};
+    TestStruct *p = &test_struct;
+    Error *errp = NULL;
+    QObject *obj;
+    QDict *qdict;
+
+    visit_type_TestStruct(data->ov, &p, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QDICT);
+
+    qdict = qobject_to_qdict(obj);
+    g_assert_cmpint(qdict_size(qdict), ==, 3);
+    g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 42);
+    g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, 0);
+    g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "foo");
+
+    QDECREF(qdict);
+}
+
+static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
+                                           const void *unused)
+{
+    int64_t value = 42;
+    Error *errp = NULL;
+    UserDefNested *ud2;
+    QObject *obj;
+    QDict *qdict, *dict1, *dict2, *dict3, *userdef;
+    const char *string = "user def string";
+    const char *strings[] = { "fourty two", "fourty three", "fourty four",
+                              "fourty five" };
+
+    ud2 = g_malloc0(sizeof(*ud2));
+    ud2->string0 = g_strdup(strings[0]);
+
+    ud2->dict1.string1 = g_strdup(strings[1]);
+    ud2->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
+    ud2->dict1.dict2.userdef1->string = g_strdup(string);
+    ud2->dict1.dict2.userdef1->integer = value;
+    ud2->dict1.dict2.string2 = g_strdup(strings[2]);
+
+    ud2->dict1.has_dict3 = true;
+    ud2->dict1.dict3.userdef2 = g_malloc0(sizeof(UserDefOne));
+    ud2->dict1.dict3.userdef2->string = g_strdup(string);
+    ud2->dict1.dict3.userdef2->integer = value;
+    ud2->dict1.dict3.string3 = g_strdup(strings[3]);
+
+    visit_type_UserDefNested(data->ov, &ud2, "unused", &errp);
+    g_assert(!error_is_set(&errp));
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QDICT);
+
+    qdict = qobject_to_qdict(obj);
+    g_assert_cmpint(qdict_size(qdict), ==, 2);
+    g_assert_cmpstr(qdict_get_str(qdict, "string0"), ==, strings[0]);
+
+    dict1 = qdict_get_qdict(qdict, "dict1");
+    g_assert_cmpint(qdict_size(dict1), ==, 3);
+    g_assert_cmpstr(qdict_get_str(dict1, "string1"), ==, strings[1]);
+
+    dict2 = qdict_get_qdict(dict1, "dict2");
+    g_assert_cmpint(qdict_size(dict2), ==, 2);
+    g_assert_cmpstr(qdict_get_str(dict2, "string2"), ==, strings[2]);
+    userdef = qdict_get_qdict(dict2, "userdef1");
+    g_assert_cmpint(qdict_size(userdef), ==, 2);
+    g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
+    g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
+
+    dict3 = qdict_get_qdict(dict1, "dict3");
+    g_assert_cmpint(qdict_size(dict3), ==, 2);
+    g_assert_cmpstr(qdict_get_str(dict3, "string3"), ==, strings[3]);
+    userdef = qdict_get_qdict(dict3, "userdef2");
+    g_assert_cmpint(qdict_size(userdef), ==, 2);
+    g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
+    g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
+
+    QDECREF(qdict);
+    qapi_free_UserDefNested(ud2);
+}
+
+typedef struct TestStructList
+{
+    TestStruct *value;
+    struct TestStructList *next;
+} TestStructList;
+
+static void visit_type_TestStructList(Visitor *v, TestStructList **obj,
+                                      const char *name, Error **errp)
+{
+    GenericList *i, **head = (GenericList **)obj;
+
+    visit_start_list(v, name, errp);
+
+    for (*head = i = visit_next_list(v, head, errp); i; i = visit_next_list(v, &i, errp)) {
+        TestStructList *native_i = (TestStructList *)i;
+        visit_type_TestStruct(v, &native_i->value, NULL, errp);
+    }
+
+    visit_end_list(v, errp);
+}
+
+static void test_visitor_out_list(TestOutputVisitorData *data,
+                                  const void *unused)
+{
+    char *value_str = (char *) "list value";
+    TestStructList *p, *head = NULL;
+    const int max_items = 10;
+    bool value_bool = true;
+    int value_int = 10;
+    Error *errp = NULL;
+    QListEntry *entry;
+    QObject *obj;
+    QList *qlist;
+    int i;
+
+    for (i = 0; i < max_items; i++) {
+        p = g_malloc0(sizeof(*p));
+        p->value = g_malloc0(sizeof(*p->value));
+        p->value->integer = value_int;
+        p->value->boolean = value_bool;
+        p->value->string = value_str;
+
+        p->next = head;
+        head = p;
+    }
+
+    visit_type_TestStructList(data->ov, &head, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QLIST);
+
+    qlist = qobject_to_qlist(obj);
+    g_assert(!qlist_empty(qlist));
+
+    i = 0;
+    QLIST_FOREACH_ENTRY(qlist, entry) {
+        QDict *qdict;
+
+        g_assert(qobject_type(entry->value) == QTYPE_QDICT);
+        qdict = qobject_to_qdict(entry->value);
+        g_assert_cmpint(qdict_size(qdict), ==, 3);
+        g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, value_int);
+        g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, value_bool);
+        g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, value_str);
+        i++;
+    }
+    g_assert_cmpint(i, ==, max_items);
+
+    QDECREF(qlist);
+
+    for (p = head; p;) {
+        TestStructList *tmp = p->next;
+        g_free(p->value);
+        g_free(p);
+        p = tmp;
+    }
+}
+
+static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
+                                            const void *unused)
+{
+    UserDefNestedList *p, *head = NULL;
+    const char string[] = "foo bar";
+    int i, max_count = 1024;
+
+    for (i = 0; i < max_count; i++) {
+        p = g_malloc0(sizeof(*p));
+        p->value = g_malloc0(sizeof(*p->value));
+
+        p->value->string0 = g_strdup(string);
+        p->value->dict1.string1 = g_strdup(string);
+        p->value->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
+        p->value->dict1.dict2.userdef1->string = g_strdup(string);
+        p->value->dict1.dict2.userdef1->integer = 42;
+        p->value->dict1.dict2.string2 = g_strdup(string);
+        p->value->dict1.has_dict3 = false;
+
+        p->next = head;
+        head = p;
+    }
+
+    qapi_free_UserDefNestedList(head);
+}
+
+static void output_visitor_test_add(const char *testpath,
+                                    TestOutputVisitorData *data,
+                                    void (*test_func)(TestOutputVisitorData *data, const void *user_data))
+{
+    g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup,
+               test_func, visitor_output_teardown);
+}
+
+int main(int argc, char **argv)
+{
+    TestOutputVisitorData out_visitor_data;
+
+    g_test_init(&argc, &argv, NULL);
+
+    output_visitor_test_add("/visitor/output/int",
+                            &out_visitor_data, test_visitor_out_int);
+    output_visitor_test_add("/visitor/output/bool",
+                            &out_visitor_data, test_visitor_out_bool);
+    output_visitor_test_add("/visitor/output/number",
+                            &out_visitor_data, test_visitor_out_number);
+    output_visitor_test_add("/visitor/output/string",
+                            &out_visitor_data, test_visitor_out_string);
+    output_visitor_test_add("/visitor/output/no-string",
+                            &out_visitor_data, test_visitor_out_no_string);
+    output_visitor_test_add("/visitor/output/enum",
+                            &out_visitor_data, test_visitor_out_enum);
+    output_visitor_test_add("/visitor/output/enum-errors",
+                            &out_visitor_data, test_visitor_out_enum_errors);
+    output_visitor_test_add("/visitor/output/struct",
+                            &out_visitor_data, test_visitor_out_struct);
+    output_visitor_test_add("/visitor/output/struct-nested",
+                            &out_visitor_data, test_visitor_out_struct_nested);
+    output_visitor_test_add("/visitor/output/list",
+                            &out_visitor_data, test_visitor_out_list);
+    output_visitor_test_add("/visitor/output/list-qapi-free",
+                            &out_visitor_data, test_visitor_out_list_qapi_free);
+
+    g_test_run();
+
+    return 0;
+}
-- 
1.7.8.110.g4cb5d1.dirty

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

* [Qemu-devel] [PATCH 05/22] Introduce test-qmp-input-visitor
  2011-12-06 17:54 [Qemu-devel] [PULL 00/22]: QMP queue Luiz Capitulino
                   ` (3 preceding siblings ...)
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 04/22] Introduce test-qmp-output-visitor Luiz Capitulino
@ 2011-12-06 17:54 ` Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 06/22] Drop test-visitor Luiz Capitulino
                   ` (17 subsequent siblings)
  22 siblings, 0 replies; 28+ messages in thread
From: Luiz Capitulino @ 2011-12-06 17:54 UTC (permalink / raw)
  To: aliguori; +Cc: qemu-devel

Contains unit-tests for the QMP input visitor implementation.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 Makefile                 |    5 +-
 configure                |    2 +-
 test-qmp-input-visitor.c |  270 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 275 insertions(+), 2 deletions(-)
 create mode 100644 test-qmp-input-visitor.c

diff --git a/Makefile b/Makefile
index 206854a..c4884fc 100644
--- a/Makefile
+++ b/Makefile
@@ -169,7 +169,7 @@ test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y)
 
 $(qapi-obj-y): $(GENERATED_HEADERS)
 qapi-dir := $(BUILD_DIR)/qapi-generated
-test-qmp-output-visitor.o test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
+test-qmp-input-visitor.o test-qmp-output-visitor.o test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
 qemu-ga$(EXESUF): LIBS = $(LIBS_QGA)
 
 $(qapi-dir)/test-qapi-types.c $(qapi-dir)/test-qapi-types.h :\
@@ -208,6 +208,9 @@ test-visitor: test-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qap
 test-qmp-output-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
 test-qmp-output-visitor: test-qmp-output-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
 
+test-qmp-input-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
+test-qmp-input-visitor: test-qmp-input-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
+
 test-qmp-commands.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h test-qmp-marshal.c test-qmp-commands.h) $(qapi-obj-y)
 test-qmp-commands: test-qmp-commands.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o $(qapi-dir)/test-qmp-marshal.o module.o
 
diff --git a/configure b/configure
index cae1f03..21fa406 100755
--- a/configure
+++ b/configure
@@ -2745,7 +2745,7 @@ if test "$softmmu" = yes ; then
       checks="check-qint check-qstring check-qdict check-qlist"
       checks="check-qfloat check-qjson $checks"
     fi
-    test_progs="$checks test-coroutine test-qmp-output-visitor"
+    test_progs="$checks test-coroutine test-qmp-output-visitor test-qmp-input-visitor"
   fi
 fi
 
diff --git a/test-qmp-input-visitor.c b/test-qmp-input-visitor.c
new file mode 100644
index 0000000..1f3ab03
--- /dev/null
+++ b/test-qmp-input-visitor.c
@@ -0,0 +1,270 @@
+/*
+ * QMP Input Visitor unit-tests.
+ *
+ * Copyright (C) 2011 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino@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 <glib.h>
+#include <stdarg.h>
+
+#include "qapi/qmp-input-visitor.h"
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "qemu-objects.h"
+
+typedef struct TestInputVisitorData {
+    QObject *obj;
+    QmpInputVisitor *qiv;
+} TestInputVisitorData;
+
+static void visitor_input_teardown(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    qobject_decref(data->obj);
+    data->obj = NULL;
+
+    if (data->qiv) {
+        qmp_input_visitor_cleanup(data->qiv);
+        data->qiv = NULL;
+    }
+}
+
+/* This is provided instead of a test setup function so that the JSON
+   string used by the tests are kept in the test functions (and not
+   int main()) */
+static Visitor *visitor_input_test_init(TestInputVisitorData *data,
+                                        const char *json_string, ...)
+{
+    Visitor *v;
+    va_list ap;
+
+    va_start(ap, json_string);
+    data->obj = qobject_from_jsonv(json_string, &ap);
+    va_end(ap);
+
+    g_assert(data->obj != NULL);
+
+    data->qiv = qmp_input_visitor_new(data->obj);
+    g_assert(data->qiv != NULL);
+
+    v = qmp_input_get_visitor(data->qiv);
+    g_assert(v != NULL);
+
+    return v;
+}
+
+static void test_visitor_in_int(TestInputVisitorData *data,
+                                const void *unused)
+{
+    int64_t res = 0, value = -42;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "%d", value);
+
+    visit_type_int(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(res, ==, value);
+}
+
+static void test_visitor_in_bool(TestInputVisitorData *data,
+                                 const void *unused)
+{
+    Error *errp = NULL;
+    bool res = false;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "true");
+
+    visit_type_bool(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(res, ==, true);
+}
+
+static void test_visitor_in_number(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    double res = 0, value = 3.14;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "%f", value);
+
+    visit_type_number(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpfloat(res, ==, value);
+}
+
+static void test_visitor_in_string(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    char *res = NULL, *value = (char *) "Q E M U";
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "%s", value);
+
+    visit_type_str(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpstr(res, ==, value);
+
+    g_free(res);
+}
+
+static void test_visitor_in_enum(TestInputVisitorData *data,
+                                 const void *unused)
+{
+    Error *errp = NULL;
+    Visitor *v;
+    EnumOne i;
+
+    for (i = 0; EnumOne_lookup[i]; i++) {
+        EnumOne res = -1;
+
+        v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);
+
+        visit_type_EnumOne(v, &res, NULL, &errp);
+        g_assert(!error_is_set(&errp));
+        g_assert_cmpint(i, ==, res);
+
+        visitor_input_teardown(data, NULL);
+    }
+
+    data->obj = NULL;
+    data->qiv = NULL;
+}
+
+typedef struct TestStruct
+{
+    int64_t integer;
+    bool boolean;
+    char *string;
+} TestStruct;
+
+static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
+                                  const char *name, Error **errp)
+{
+    visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
+                       errp);
+
+    visit_type_int(v, &(*obj)->integer, "integer", errp);
+    visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
+    visit_type_str(v, &(*obj)->string, "string", errp);
+
+    visit_end_struct(v, errp);
+}
+
+static void test_visitor_in_struct(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    TestStruct *p = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
+
+    visit_type_TestStruct(v, &p, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(p->integer, ==, -42);
+    g_assert(p->boolean == true);
+    g_assert_cmpstr(p->string, ==, "foo");
+
+    g_free(p->string);
+    g_free(p);
+}
+
+static void check_and_free_str(char *str, const char *cmp)
+{
+    g_assert_cmpstr(str, ==, cmp);
+    g_free(str);
+}
+
+static void test_visitor_in_struct_nested(TestInputVisitorData *data,
+                                          const void *unused)
+{
+    UserDefNested *udp = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string' }, 'string2': 'string2'}}}");
+
+    visit_type_UserDefNested(v, &udp, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+
+    check_and_free_str(udp->string0, "string0");
+    check_and_free_str(udp->dict1.string1, "string1");
+    g_assert_cmpint(udp->dict1.dict2.userdef1->integer, ==, 42);
+    check_and_free_str(udp->dict1.dict2.userdef1->string, "string");
+    check_and_free_str(udp->dict1.dict2.string2, "string2");
+    g_assert(udp->dict1.has_dict3 == false);
+
+    g_free(udp->dict1.dict2.userdef1);
+    g_free(udp);
+}
+
+static void test_visitor_in_list(TestInputVisitorData *data,
+                                 const void *unused)
+{
+    UserDefOneList *item, *head = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+    int i;
+
+    v = visitor_input_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
+
+    visit_type_UserDefOneList(v, &head, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert(head != NULL);
+
+    for (i = 0, item = head; item; item = item->next, i++) {
+        char string[12];
+
+        snprintf(string, sizeof(string), "string%d", i);
+        g_assert_cmpstr(item->value->string, ==, string);
+        g_assert_cmpint(item->value->integer, ==, 42 + i);
+    }
+
+    qapi_free_UserDefOneList(head);
+}
+
+static void input_visitor_test_add(const char *testpath,
+                                   TestInputVisitorData *data,
+                                   void (*test_func)(TestInputVisitorData *data, const void *user_data))
+{
+    g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
+               visitor_input_teardown);
+}
+
+int main(int argc, char **argv)
+{
+    TestInputVisitorData in_visitor_data;
+
+    g_test_init(&argc, &argv, NULL);
+
+    input_visitor_test_add("/visitor/input/int",
+                           &in_visitor_data, test_visitor_in_int);
+    input_visitor_test_add("/visitor/input/bool",
+                           &in_visitor_data, test_visitor_in_bool);
+    input_visitor_test_add("/visitor/input/number",
+                           &in_visitor_data, test_visitor_in_number);
+    input_visitor_test_add("/visitor/input/string",
+                            &in_visitor_data, test_visitor_in_string);
+    input_visitor_test_add("/visitor/input/enum",
+                            &in_visitor_data, test_visitor_in_enum);
+    input_visitor_test_add("/visitor/input/struct",
+                            &in_visitor_data, test_visitor_in_struct);
+    input_visitor_test_add("/visitor/input/struct-nested",
+                            &in_visitor_data, test_visitor_in_struct_nested);
+    input_visitor_test_add("/visitor/input/list",
+                            &in_visitor_data, test_visitor_in_list);
+
+    g_test_run();
+
+    return 0;
+}
-- 
1.7.8.110.g4cb5d1.dirty

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

* [Qemu-devel] [PATCH 06/22] Drop test-visitor
  2011-12-06 17:54 [Qemu-devel] [PULL 00/22]: QMP queue Luiz Capitulino
                   ` (4 preceding siblings ...)
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 05/22] Introduce test-qmp-input-visitor Luiz Capitulino
@ 2011-12-06 17:54 ` Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 07/22] qapi: Complete system_powerdown conversion Luiz Capitulino
                   ` (16 subsequent siblings)
  22 siblings, 0 replies; 28+ messages in thread
From: Luiz Capitulino @ 2011-12-06 17:54 UTC (permalink / raw)
  To: aliguori; +Cc: qemu-devel

It has been superseded by the two previous commits, which introduced
the test-qmp-output-visitor and test-qmp-input-visitor tests.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 Makefile       |    5 +-
 test-visitor.c |  338 --------------------------------------------------------
 2 files changed, 1 insertions(+), 342 deletions(-)
 delete mode 100644 test-visitor.c

diff --git a/Makefile b/Makefile
index c4884fc..2c03055 100644
--- a/Makefile
+++ b/Makefile
@@ -169,7 +169,7 @@ test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y)
 
 $(qapi-obj-y): $(GENERATED_HEADERS)
 qapi-dir := $(BUILD_DIR)/qapi-generated
-test-qmp-input-visitor.o test-qmp-output-visitor.o test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
+test-qmp-input-visitor.o test-qmp-output-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
 qemu-ga$(EXESUF): LIBS = $(LIBS_QGA)
 
 $(qapi-dir)/test-qapi-types.c $(qapi-dir)/test-qapi-types.h :\
@@ -202,9 +202,6 @@ qmp-commands.h qmp-marshal.c :\
 $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py -m -o "." < $<, "  GEN   $@")
 
-test-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
-test-visitor: test-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
-
 test-qmp-output-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
 test-qmp-output-visitor: test-qmp-output-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
 
diff --git a/test-visitor.c b/test-visitor.c
deleted file mode 100644
index f90b711..0000000
--- a/test-visitor.c
+++ /dev/null
@@ -1,338 +0,0 @@
-#include <glib.h>
-#include "qapi/qmp-output-visitor.h"
-#include "qapi/qmp-input-visitor.h"
-#include "test-qapi-types.h"
-#include "test-qapi-visit.h"
-#include "qemu-objects.h"
-
-typedef struct TestStruct
-{
-    int64_t x;
-    int64_t y;
-} TestStruct;
-
-typedef struct TestStructList
-{
-    TestStruct *value;
-    struct TestStructList *next;
-} TestStructList;
-
-static void visit_type_TestStruct(Visitor *v, TestStruct **obj, const char *name, Error **errp)
-{
-    visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct), errp);
-    visit_type_int(v, &(*obj)->x, "x", errp);
-    visit_type_int(v, &(*obj)->y, "y", errp);
-    visit_end_struct(v, errp);
-}
-
-static void visit_type_TestStructList(Visitor *m, TestStructList ** obj, const char *name, Error **errp)
-{
-    GenericList *i, **head = (GenericList **)obj;
-
-    visit_start_list(m, name, errp);
-
-    for (*head = i = visit_next_list(m, head, errp); i; i = visit_next_list(m, &i, errp)) {
-        TestStructList *native_i = (TestStructList *)i;
-        visit_type_TestStruct(m, &native_i->value, NULL, errp);
-    }
-
-    visit_end_list(m, errp);
-}
-
-/* test core visitor methods */
-static void test_visitor_core(void)
-{
-    QmpOutputVisitor *mo;
-    QmpInputVisitor *mi;
-    Visitor *v;
-    TestStruct ts = { 42, 82 };
-    TestStruct *pts = &ts;
-    TestStructList *lts = NULL;
-    Error *err = NULL;
-    QObject *obj;
-    QList *qlist;
-    QDict *qdict;
-    QString *str;
-    int64_t value = 0;
-
-    mo = qmp_output_visitor_new();
-    v = qmp_output_get_visitor(mo);
-
-    visit_type_TestStruct(v, &pts, NULL, &err);
-
-    obj = qmp_output_get_qobject(mo);
-
-    str = qobject_to_json(obj);
-
-    printf("%s\n", qstring_get_str(str));
-
-    QDECREF(str);
-
-    obj = QOBJECT(qint_from_int(0x42));
-
-    mi = qmp_input_visitor_new(obj);
-    v = qmp_input_get_visitor(mi);
-
-    visit_type_int(v, &value, NULL, &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-
-    g_assert(value == 0x42);
-
-    qobject_decref(obj);
-
-    obj = qobject_from_json("{'x': 42, 'y': 84}");
-    mi = qmp_input_visitor_new(obj);
-    v = qmp_input_get_visitor(mi);
-
-    pts = NULL;
-
-    visit_type_TestStruct(v, &pts, NULL, &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-
-    g_assert(pts != NULL);
-    g_assert(pts->x == 42);
-    g_assert(pts->y == 84);
-
-    qobject_decref(obj);
-    g_free(pts);
-
-    /* test list input visitor */
-    obj = qobject_from_json("[{'x': 42, 'y': 84}, {'x': 12, 'y': 24}]");
-    mi = qmp_input_visitor_new(obj);
-    v = qmp_input_get_visitor(mi);
-
-    visit_type_TestStructList(v, &lts, NULL, &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-
-    g_assert(lts != NULL);
-    g_assert(lts->value->x == 42);
-    g_assert(lts->value->y == 84);
-
-    g_assert(lts->next != NULL);
-    g_assert(lts->next->value->x == 12);
-    g_assert(lts->next->value->y == 24);
-    g_assert(lts->next->next == NULL);
-
-    qobject_decref(obj);
-
-    /* test list output visitor */
-    mo = qmp_output_visitor_new();
-    v = qmp_output_get_visitor(mo);
-    visit_type_TestStructList(v, &lts, NULL, &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-    obj = qmp_output_get_qobject(mo);
-    g_print("obj: %s\n", qstring_get_str(qobject_to_json(obj)));
-
-    qlist = qobject_to_qlist(obj);
-    assert(qlist);
-    obj = qlist_pop(qlist);
-    qdict = qobject_to_qdict(obj);
-    assert(qdict);
-    assert(qdict_get_int(qdict, "x") == 42);
-    assert(qdict_get_int(qdict, "y") == 84);
-    qobject_decref(obj);
-
-    obj = qlist_pop(qlist);
-    qdict = qobject_to_qdict(obj);
-    assert(qdict);
-    assert(qdict_get_int(qdict, "x") == 12);
-    assert(qdict_get_int(qdict, "y") == 24);
-    qobject_decref(obj);
-
-    qmp_output_visitor_cleanup(mo);
-    QDECREF(qlist);
-}
-
-/* test deep nesting with refs to other user-defined types */
-static void test_nested_structs(void)
-{
-    QmpOutputVisitor *mo;
-    QmpInputVisitor *mi;
-    Visitor *v;
-    UserDefOne ud1;
-    UserDefOne *ud1_p = &ud1, *ud1c_p = NULL;
-    UserDefTwo ud2;
-    UserDefTwo *ud2_p = &ud2, *ud2c_p = NULL;
-    Error *err = NULL;
-    QObject *obj;
-    QString *str;
-
-    ud1.integer = 42;
-    ud1.string = strdup("forty two");
-
-    /* sanity check */
-    mo = qmp_output_visitor_new();
-    v = qmp_output_get_visitor(mo);
-    visit_type_UserDefOne(v, &ud1_p, "o_O", &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-    obj = qmp_output_get_qobject(mo);
-    g_assert(obj);
-    qobject_decref(obj);
-
-    ud2.string = strdup("forty three");
-    ud2.dict.string = strdup("forty four");
-    ud2.dict.dict.userdef = ud1_p;
-    ud2.dict.dict.string = strdup("forty five");
-    ud2.dict.has_dict2 = true;
-    ud2.dict.dict2.userdef = ud1_p;
-    ud2.dict.dict2.string = strdup("forty six");
-
-    /* c type -> qobject */
-    mo = qmp_output_visitor_new();
-    v = qmp_output_get_visitor(mo);
-    visit_type_UserDefTwo(v, &ud2_p, "unused", &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-    obj = qmp_output_get_qobject(mo);
-    g_assert(obj);
-    str = qobject_to_json_pretty(obj);
-    g_print("%s\n", qstring_get_str(str));
-    QDECREF(str);
-
-    /* qobject -> c type, should match original struct */
-    mi = qmp_input_visitor_new(obj);
-    v = qmp_input_get_visitor(mi);
-    visit_type_UserDefTwo(v, &ud2c_p, NULL, &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-
-    g_assert(!g_strcmp0(ud2c_p->string, ud2.string));
-    g_assert(!g_strcmp0(ud2c_p->dict.string, ud2.dict.string));
-
-    ud1c_p = ud2c_p->dict.dict.userdef;
-    g_assert(ud1c_p->integer == ud1_p->integer);
-    g_assert(!g_strcmp0(ud1c_p->string, ud1_p->string));
-
-    g_assert(!g_strcmp0(ud2c_p->dict.dict.string, ud2.dict.dict.string));
-
-    ud1c_p = ud2c_p->dict.dict2.userdef;
-    g_assert(ud1c_p->integer == ud1_p->integer);
-    g_assert(!g_strcmp0(ud1c_p->string, ud1_p->string));
-
-    g_assert(!g_strcmp0(ud2c_p->dict.dict2.string, ud2.dict.dict2.string));
-    g_free(ud1.string);
-    g_free(ud2.string);
-    g_free(ud2.dict.string);
-    g_free(ud2.dict.dict.string);
-    g_free(ud2.dict.dict2.string);
-
-    qapi_free_UserDefTwo(ud2c_p);
-
-    qobject_decref(obj);
-}
-
-/* test enum values */
-static void test_enums(void)
-{
-    QmpOutputVisitor *mo;
-    QmpInputVisitor *mi;
-    Visitor *v;
-    EnumOne enum1 = ENUM_ONE_VALUE2, enum1_cpy = ENUM_ONE_VALUE1;
-    Error *err = NULL;
-    QObject *obj;
-    QString *str;
-
-    /* C type -> QObject */
-    mo = qmp_output_visitor_new();
-    v = qmp_output_get_visitor(mo);
-    visit_type_EnumOne(v, &enum1, "unused", &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-    obj = qmp_output_get_qobject(mo);
-    g_assert(obj);
-    str = qobject_to_json_pretty(obj);
-    g_print("%s\n", qstring_get_str(str));
-    QDECREF(str);
-    g_assert(g_strcmp0(qstring_get_str(qobject_to_qstring(obj)), "value2") == 0);
-
-    /* QObject -> C type */
-    mi = qmp_input_visitor_new(obj);
-    v = qmp_input_get_visitor(mi);
-    visit_type_EnumOne(v, &enum1_cpy, "unused", &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-    g_debug("enum1_cpy, enum1: %d, %d", enum1_cpy, enum1);
-    g_assert(enum1_cpy == enum1);
-
-    qobject_decref(obj);
-}
-
-/* test enum values nested in schema-defined structs */
-static void test_nested_enums(void)
-{
-    QmpOutputVisitor *mo;
-    QmpInputVisitor *mi;
-    Visitor *v;
-    NestedEnumsOne *nested_enums, *nested_enums_cpy = NULL;
-    Error *err = NULL;
-    QObject *obj;
-    QString *str;
-
-    nested_enums = g_malloc0(sizeof(NestedEnumsOne));
-    nested_enums->enum1 = ENUM_ONE_VALUE1;
-    nested_enums->enum2 = ENUM_ONE_VALUE2;
-    nested_enums->enum3 = ENUM_ONE_VALUE3;
-    nested_enums->enum4 = ENUM_ONE_VALUE3;
-    nested_enums->has_enum2 = false;
-    nested_enums->has_enum4 = true;
-
-    /* C type -> QObject */
-    mo = qmp_output_visitor_new();
-    v = qmp_output_get_visitor(mo);
-    visit_type_NestedEnumsOne(v, &nested_enums, NULL, &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-    obj = qmp_output_get_qobject(mo);
-    g_assert(obj);
-    str = qobject_to_json_pretty(obj);
-    g_print("%s\n", qstring_get_str(str));
-    QDECREF(str);
-
-    /* QObject -> C type */
-    mi = qmp_input_visitor_new(obj);
-    v = qmp_input_get_visitor(mi);
-    visit_type_NestedEnumsOne(v, &nested_enums_cpy, NULL, &err);
-    if (err) {
-        g_error("%s", error_get_pretty(err));
-    }
-    g_assert(nested_enums_cpy);
-    g_assert(nested_enums_cpy->enum1 == nested_enums->enum1);
-    g_assert(nested_enums_cpy->enum3 == nested_enums->enum3);
-    g_assert(nested_enums_cpy->enum4 == nested_enums->enum4);
-    g_assert(nested_enums_cpy->has_enum2 == false);
-    g_assert(nested_enums_cpy->has_enum4 == true);
-
-    qmp_output_visitor_cleanup(mo);
-    qmp_input_visitor_cleanup(mi);
-    qapi_free_NestedEnumsOne(nested_enums);
-    qapi_free_NestedEnumsOne(nested_enums_cpy);
-}
-
-int main(int argc, char **argv)
-{
-    g_test_init(&argc, &argv, NULL);
-
-    g_test_add_func("/0.15/visitor_core", test_visitor_core);
-    g_test_add_func("/0.15/nested_structs", test_nested_structs);
-    g_test_add_func("/0.15/enums", test_enums);
-    g_test_add_func("/0.15/nested_enums", test_nested_enums);
-
-    g_test_run();
-
-    return 0;
-}
-- 
1.7.8.110.g4cb5d1.dirty

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

* [Qemu-devel] [PATCH 07/22] qapi: Complete system_powerdown conversion
  2011-12-06 17:54 [Qemu-devel] [PULL 00/22]: QMP queue Luiz Capitulino
                   ` (5 preceding siblings ...)
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 06/22] Drop test-visitor Luiz Capitulino
@ 2011-12-06 17:54 ` Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 08/22] console: Drop unused prototypes Luiz Capitulino
                   ` (15 subsequent siblings)
  22 siblings, 0 replies; 28+ messages in thread
From: Luiz Capitulino @ 2011-12-06 17:54 UTC (permalink / raw)
  To: aliguori; +Cc: qemu-devel

Commit 5bc465e4b1b6f4582a400c0a7033a1c841744278 converted only
the HMP part of the system_powerdown command to the QAPI, this
commit completes it by converting the QMP part too.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 monitor.c       |   10 ----------
 qmp-commands.hx |    5 +----
 2 files changed, 1 insertions(+), 14 deletions(-)

diff --git a/monitor.c b/monitor.c
index 1be222e..344b196 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1796,16 +1796,6 @@ static void do_boot_set(Monitor *mon, const QDict *qdict)
     }
 }
 
-/**
- * do_system_powerdown(): Issue a machine powerdown
- */
-static int do_system_powerdown(Monitor *mon, const QDict *qdict,
-                               QObject **ret_data)
-{
-    qemu_system_powerdown_request();
-    return 0;
-}
-
 #if defined(TARGET_I386)
 static void print_pte(Monitor *mon, target_phys_addr_t addr,
                       target_phys_addr_t pte,
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 94da2a8..4fcb92c 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -244,10 +244,7 @@ EQMP
     {
         .name       = "system_powerdown",
         .args_type  = "",
-        .params     = "",
-        .help       = "send system power down event",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_system_powerdown,
+        .mhandler.cmd_new = qmp_marshal_input_system_powerdown,
     },
 
 SQMP
-- 
1.7.8.110.g4cb5d1.dirty

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

* [Qemu-devel] [PATCH 08/22] console: Drop unused prototypes
  2011-12-06 17:54 [Qemu-devel] [PULL 00/22]: QMP queue Luiz Capitulino
                   ` (6 preceding siblings ...)
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 07/22] qapi: Complete system_powerdown conversion Luiz Capitulino
@ 2011-12-06 17:54 ` Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 09/22] QError: Introduce QERR_IO_ERROR Luiz Capitulino
                   ` (14 subsequent siblings)
  22 siblings, 0 replies; 28+ messages in thread
From: Luiz Capitulino @ 2011-12-06 17:54 UTC (permalink / raw)
  To: aliguori; +Cc: qemu-devel

Commit e235cec3762d2aa20b548114ea7b172113690463 converted the query-mice
command to the QAPI but forgot to remove two prototypes used by the old
QAPI. Drop them.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 console.h |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/console.h b/console.h
index 6ac4ed3..9466886 100644
--- a/console.h
+++ b/console.h
@@ -74,8 +74,6 @@ struct MouseTransformInfo {
     int a[7];
 };
 
-void do_info_mice_print(Monitor *mon, const QObject *data);
-void do_info_mice(Monitor *mon, QObject **ret_data);
 void do_mouse_set(Monitor *mon, const QDict *qdict);
 
 /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx
-- 
1.7.8.110.g4cb5d1.dirty

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

* [Qemu-devel] [PATCH 09/22] QError: Introduce QERR_IO_ERROR
  2011-12-06 17:54 [Qemu-devel] [PULL 00/22]: QMP queue Luiz Capitulino
                   ` (7 preceding siblings ...)
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 08/22] console: Drop unused prototypes Luiz Capitulino
@ 2011-12-06 17:54 ` Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 10/22] qapi: Convert memsave Luiz Capitulino
                   ` (13 subsequent siblings)
  22 siblings, 0 replies; 28+ messages in thread
From: Luiz Capitulino @ 2011-12-06 17:54 UTC (permalink / raw)
  To: aliguori; +Cc: qemu-devel

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 qerror.c |    4 ++++
 qerror.h |    3 +++
 2 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/qerror.c b/qerror.c
index 656efc2..b544ced 100644
--- a/qerror.c
+++ b/qerror.c
@@ -149,6 +149,10 @@ static const QErrorStringTable qerror_table[] = {
         .desc      = "Password incorrect",
     },
     {
+        .error_fmt = QERR_IO_ERROR,
+        .desc      = "An IO error has occurred",
+    },
+    {
         .error_fmt = QERR_JSON_PARSING,
         .desc      = "Invalid JSON syntax",
     },
diff --git a/qerror.h b/qerror.h
index 161d654..1fee39d 100644
--- a/qerror.h
+++ b/qerror.h
@@ -126,6 +126,9 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_INVALID_PASSWORD \
     "{ 'class': 'InvalidPassword', 'data': {} }"
 
+#define QERR_IO_ERROR \
+    "{ 'class': 'IOError', 'data': {} }"
+
 #define QERR_JSON_PARSING \
     "{ 'class': 'JSONParsing', 'data': {} }"
 
-- 
1.7.8.110.g4cb5d1.dirty

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

* [Qemu-devel] [PATCH 10/22] qapi: Convert memsave
  2011-12-06 17:54 [Qemu-devel] [PULL 00/22]: QMP queue Luiz Capitulino
                   ` (8 preceding siblings ...)
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 09/22] QError: Introduce QERR_IO_ERROR Luiz Capitulino
@ 2011-12-06 17:54 ` Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 11/22] qapi: Convert pmemsave Luiz Capitulino
                   ` (12 subsequent siblings)
  22 siblings, 0 replies; 28+ messages in thread
From: Luiz Capitulino @ 2011-12-06 17:54 UTC (permalink / raw)
  To: aliguori; +Cc: qemu-devel

Please, note that the QMP command has a new 'cpu-index' parameter.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 cpus.c           |   47 +++++++++++++++++++++++++++++++++++++++++++++++
 hmp-commands.hx  |    3 +--
 hmp.c            |   19 +++++++++++++++++++
 hmp.h            |    1 +
 monitor.c        |   38 --------------------------------------
 qapi-schema.json |   26 ++++++++++++++++++++++++++
 qmp-commands.hx  |   10 +++-------
 7 files changed, 97 insertions(+), 47 deletions(-)

diff --git a/cpus.c b/cpus.c
index ca46ec6..0f2ce60 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1136,3 +1136,50 @@ CpuInfoList *qmp_query_cpus(Error **errp)
 
     return head;
 }
+
+void qmp_memsave(int64_t addr, int64_t size, const char *filename,
+                 bool has_cpu, int64_t cpu_index, Error **errp)
+{
+    FILE *f;
+    uint32_t l;
+    CPUState *env;
+    uint8_t buf[1024];
+
+    if (!has_cpu) {
+        cpu_index = 0;
+    }
+
+    for (env = first_cpu; env; env = env->next_cpu) {
+        if (cpu_index == env->cpu_index) {
+            break;
+        }
+    }
+
+    if (env == NULL) {
+        error_set(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index",
+                  "a CPU number");
+        return;
+    }
+
+    f = fopen(filename, "wb");
+    if (!f) {
+        error_set(errp, QERR_OPEN_FILE_FAILED, filename);
+        return;
+    }
+
+    while (size != 0) {
+        l = sizeof(buf);
+        if (l > size)
+            l = size;
+        cpu_memory_rw_debug(env, addr, buf, l, 0);
+        if (fwrite(buf, 1, l, f) != l) {
+            error_set(errp, QERR_IO_ERROR);
+            goto exit;
+        }
+        addr += l;
+        size -= l;
+    }
+
+exit:
+    fclose(f);
+}
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 79a9195..dac0b47 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -689,8 +689,7 @@ ETEXI
         .args_type  = "val:l,size:i,filename:s",
         .params     = "addr size file",
         .help       = "save to disk virtual memory dump starting at 'addr' of size 'size'",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_memory_save,
+        .mhandler.cmd = hmp_memsave,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index dfab7ad..67b3eb3 100644
--- a/hmp.c
+++ b/hmp.c
@@ -14,6 +14,14 @@
 #include "hmp.h"
 #include "qmp-commands.h"
 
+static void hmp_handle_error(Monitor *mon, Error **errp)
+{
+    if (error_is_set(errp)) {
+        monitor_printf(mon, "%s\n", error_get_pretty(*errp));
+        error_free(*errp);
+    }
+}
+
 void hmp_info_name(Monitor *mon)
 {
     NameInfo *info;
@@ -531,3 +539,14 @@ void hmp_cpu(Monitor *mon, const QDict *qdict)
         monitor_printf(mon, "invalid CPU index\n");
     }
 }
+
+void hmp_memsave(Monitor *mon, const QDict *qdict)
+{
+    uint32_t size = qdict_get_int(qdict, "size");
+    const char *filename = qdict_get_str(qdict, "filename");
+    uint64_t addr = qdict_get_int(qdict, "val");
+    Error *errp = NULL;
+
+    qmp_memsave(addr, size, filename, true, monitor_get_cpu_index(), &errp);
+    hmp_handle_error(mon, &errp);
+}
diff --git a/hmp.h b/hmp.h
index 4422578..dd8ad0c 100644
--- a/hmp.h
+++ b/hmp.h
@@ -37,5 +37,6 @@ void hmp_stop(Monitor *mon, const QDict *qdict);
 void hmp_system_reset(Monitor *mon, const QDict *qdict);
 void hmp_system_powerdown(Monitor *mon, const QDict *qdict);
 void hmp_cpu(Monitor *mon, const QDict *qdict);
+void hmp_memsave(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/monitor.c b/monitor.c
index 344b196..7272014 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1370,44 +1370,6 @@ static void do_print(Monitor *mon, const QDict *qdict)
     monitor_printf(mon, "\n");
 }
 
-static int do_memory_save(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
-    FILE *f;
-    uint32_t size = qdict_get_int(qdict, "size");
-    const char *filename = qdict_get_str(qdict, "filename");
-    target_long addr = qdict_get_int(qdict, "val");
-    uint32_t l;
-    CPUState *env;
-    uint8_t buf[1024];
-    int ret = -1;
-
-    env = mon_get_cpu();
-
-    f = fopen(filename, "wb");
-    if (!f) {
-        qerror_report(QERR_OPEN_FILE_FAILED, filename);
-        return -1;
-    }
-    while (size != 0) {
-        l = sizeof(buf);
-        if (l > size)
-            l = size;
-        cpu_memory_rw_debug(env, addr, buf, l, 0);
-        if (fwrite(buf, 1, l, f) != l) {
-            monitor_printf(mon, "fwrite() error in do_memory_save\n");
-            goto exit;
-        }
-        addr += l;
-        size -= l;
-    }
-
-    ret = 0;
-
-exit:
-    fclose(f);
-    return ret;
-}
-
 static int do_physical_memory_save(Monitor *mon, const QDict *qdict,
                                     QObject **ret_data)
 {
diff --git a/qapi-schema.json b/qapi-schema.json
index fbbdbe0..dbf6170 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -901,3 +901,29 @@
 # Notes: Do not use this command.
 ##
 { 'command': 'cpu', 'data': {'index': 'int'} }
+
+##
+# @memsave:
+#
+# Save a portion of guest memory to a file.
+#
+# @val: the virtual address of the guest to start from
+#
+# @size: the size of memory region to save
+#
+# @filename: the file to save the memory to as binary data
+#
+# @cpu-index: #optional the index of the virtual CPU to use for translating the
+#                       virtual address (defaults to CPU 0)
+#
+# Returns: Nothing on success
+#          If @cpu is not a valid VCPU, InvalidParameterValue
+#          If @filename cannot be opened, OpenFileFailed
+#          If an I/O error occurs while writing the file, IOError
+#
+# Since: 0.14.0
+#
+# Notes: Errors were not reliably returned until 1.1
+##
+{ 'command': 'memsave',
+  'data': {'val': 'int', 'size': 'int', 'filename': 'str', '*cpu-index': 'int'} }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 4fcb92c..0e2f392 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -352,11 +352,8 @@ EQMP
 
     {
         .name       = "memsave",
-        .args_type  = "val:l,size:i,filename:s",
-        .params     = "addr size file",
-        .help       = "save to disk virtual memory dump starting at 'addr' of size 'size'",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_memory_save,
+        .args_type  = "val:l,size:i,filename:s,cpu:i?",
+        .mhandler.cmd_new = qmp_marshal_input_memsave,
     },
 
 SQMP
@@ -370,6 +367,7 @@ Arguments:
 - "val": the starting address (json-int)
 - "size": the memory size, in bytes (json-int)
 - "filename": file path (json-string)
+- "cpu": virtual CPU index (json-int, optional)
 
 Example:
 
@@ -379,8 +377,6 @@ Example:
                             "filename": "/tmp/virtual-mem-dump" } }
 <- { "return": {} }
 
-Note: Depends on the current CPU.
-
 EQMP
 
     {
-- 
1.7.8.110.g4cb5d1.dirty

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

* [Qemu-devel] [PATCH 11/22] qapi: Convert pmemsave
  2011-12-06 17:54 [Qemu-devel] [PULL 00/22]: QMP queue Luiz Capitulino
                   ` (9 preceding siblings ...)
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 10/22] qapi: Convert memsave Luiz Capitulino
@ 2011-12-06 17:54 ` Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 12/22] qapi: Convert cont Luiz Capitulino
                   ` (11 subsequent siblings)
  22 siblings, 0 replies; 28+ messages in thread
From: Luiz Capitulino @ 2011-12-06 17:54 UTC (permalink / raw)
  To: aliguori; +Cc: qemu-devel

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 cpus.c           |   30 ++++++++++++++++++++++++++++++
 hmp-commands.hx  |    3 +--
 hmp.c            |   11 +++++++++++
 hmp.h            |    1 +
 monitor.c        |   37 -------------------------------------
 qapi-schema.json |   22 ++++++++++++++++++++++
 qmp-commands.hx  |    5 +----
 7 files changed, 66 insertions(+), 43 deletions(-)

diff --git a/cpus.c b/cpus.c
index 0f2ce60..e916137 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1183,3 +1183,33 @@ void qmp_memsave(int64_t addr, int64_t size, const char *filename,
 exit:
     fclose(f);
 }
+
+void qmp_pmemsave(int64_t addr, int64_t size, const char *filename,
+                  Error **errp)
+{
+    FILE *f;
+    uint32_t l;
+    uint8_t buf[1024];
+
+    f = fopen(filename, "wb");
+    if (!f) {
+        error_set(errp, QERR_OPEN_FILE_FAILED, filename);
+        return;
+    }
+
+    while (size != 0) {
+        l = sizeof(buf);
+        if (l > size)
+            l = size;
+        cpu_physical_memory_rw(addr, buf, l, 0);
+        if (fwrite(buf, 1, l, f) != l) {
+            error_set(errp, QERR_IO_ERROR);
+            goto exit;
+        }
+        addr += l;
+        size -= l;
+    }
+
+exit:
+    fclose(f);
+}
diff --git a/hmp-commands.hx b/hmp-commands.hx
index dac0b47..0a721cc 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -703,8 +703,7 @@ ETEXI
         .args_type  = "val:l,size:i,filename:s",
         .params     = "addr size file",
         .help       = "save to disk physical memory dump starting at 'addr' of size 'size'",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_physical_memory_save,
+        .mhandler.cmd = hmp_pmemsave,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index 67b3eb3..96e3ce1 100644
--- a/hmp.c
+++ b/hmp.c
@@ -550,3 +550,14 @@ void hmp_memsave(Monitor *mon, const QDict *qdict)
     qmp_memsave(addr, size, filename, true, monitor_get_cpu_index(), &errp);
     hmp_handle_error(mon, &errp);
 }
+
+void hmp_pmemsave(Monitor *mon, const QDict *qdict)
+{
+    uint32_t size = qdict_get_int(qdict, "size");
+    const char *filename = qdict_get_str(qdict, "filename");
+    uint64_t addr = qdict_get_int(qdict, "val");
+    Error *errp = NULL;
+
+    qmp_pmemsave(addr, size, filename, &errp);
+    hmp_handle_error(mon, &errp);
+}
diff --git a/hmp.h b/hmp.h
index dd8ad0c..4882bea 100644
--- a/hmp.h
+++ b/hmp.h
@@ -38,5 +38,6 @@ void hmp_system_reset(Monitor *mon, const QDict *qdict);
 void hmp_system_powerdown(Monitor *mon, const QDict *qdict);
 void hmp_cpu(Monitor *mon, const QDict *qdict);
 void hmp_memsave(Monitor *mon, const QDict *qdict);
+void hmp_pmemsave(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/monitor.c b/monitor.c
index 7272014..a1b46b3 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1370,43 +1370,6 @@ static void do_print(Monitor *mon, const QDict *qdict)
     monitor_printf(mon, "\n");
 }
 
-static int do_physical_memory_save(Monitor *mon, const QDict *qdict,
-                                    QObject **ret_data)
-{
-    FILE *f;
-    uint32_t l;
-    uint8_t buf[1024];
-    uint32_t size = qdict_get_int(qdict, "size");
-    const char *filename = qdict_get_str(qdict, "filename");
-    target_phys_addr_t addr = qdict_get_int(qdict, "val");
-    int ret = -1;
-
-    f = fopen(filename, "wb");
-    if (!f) {
-        qerror_report(QERR_OPEN_FILE_FAILED, filename);
-        return -1;
-    }
-    while (size != 0) {
-        l = sizeof(buf);
-        if (l > size)
-            l = size;
-        cpu_physical_memory_read(addr, buf, l);
-        if (fwrite(buf, 1, l, f) != l) {
-            monitor_printf(mon, "fwrite() error in do_physical_memory_save\n");
-            goto exit;
-        }
-        fflush(f);
-        addr += l;
-        size -= l;
-    }
-
-    ret = 0;
-
-exit:
-    fclose(f);
-    return ret;
-}
-
 static void do_sum(Monitor *mon, const QDict *qdict)
 {
     uint32_t addr;
diff --git a/qapi-schema.json b/qapi-schema.json
index dbf6170..7f9aa94 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -927,3 +927,25 @@
 ##
 { 'command': 'memsave',
   'data': {'val': 'int', 'size': 'int', 'filename': 'str', '*cpu-index': 'int'} }
+
+##
+# @pmemsave:
+#
+# Save a portion of guest physical memory to a file.
+#
+# @val: the physical address of the guest to start from
+#
+# @size: the size of memory region to save
+#
+# @filename: the file to save the memory to as binary data
+#
+# Returns: Nothing on success
+#          If @filename cannot be opened, OpenFileFailed
+#          If an I/O error occurs while writing the file, IOError
+#
+# Since: 0.14.0
+#
+# Notes: Errors were not reliably returned until 1.1
+##
+{ 'command': 'pmemsave',
+  'data': {'val': 'int', 'size': 'int', 'filename': 'str'} }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 0e2f392..5093ac9 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -382,10 +382,7 @@ EQMP
     {
         .name       = "pmemsave",
         .args_type  = "val:l,size:i,filename:s",
-        .params     = "addr size file",
-        .help       = "save to disk physical memory dump starting at 'addr' of size 'size'",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_physical_memory_save,
+        .mhandler.cmd_new = qmp_marshal_input_pmemsave,
     },
 
 SQMP
-- 
1.7.8.110.g4cb5d1.dirty

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

* [Qemu-devel] [PATCH 12/22] qapi: Convert cont
  2011-12-06 17:54 [Qemu-devel] [PULL 00/22]: QMP queue Luiz Capitulino
                   ` (10 preceding siblings ...)
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 11/22] qapi: Convert pmemsave Luiz Capitulino
@ 2011-12-06 17:54 ` Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 13/22] qapi: Convert inject-nmi Luiz Capitulino
                   ` (10 subsequent siblings)
  22 siblings, 0 replies; 28+ messages in thread
From: Luiz Capitulino @ 2011-12-06 17:54 UTC (permalink / raw)
  To: aliguori; +Cc: qemu-devel

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 hmp-commands.hx  |    3 +-
 hmp.c            |   32 +++++++++++++++++++++++
 hmp.h            |    1 +
 monitor.c        |   74 +++++++++++-------------------------------------------
 monitor.h        |    3 ++
 qapi-schema.json |   17 ++++++++++++
 qmp-commands.hx  |    5 +---
 qmp.c            |   37 +++++++++++++++++++++++++++
 8 files changed, 107 insertions(+), 65 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 0a721cc..9503751 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -304,8 +304,7 @@ ETEXI
         .args_type  = "",
         .params     = "",
         .help       = "resume emulation",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_cont,
+        .mhandler.cmd = hmp_cont,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index 96e3ce1..d623526 100644
--- a/hmp.c
+++ b/hmp.c
@@ -561,3 +561,35 @@ void hmp_pmemsave(Monitor *mon, const QDict *qdict)
     qmp_pmemsave(addr, size, filename, &errp);
     hmp_handle_error(mon, &errp);
 }
+
+static void hmp_cont_cb(void *opaque, int err)
+{
+    Monitor *mon = opaque;
+
+    if (!err) {
+        hmp_cont(mon, NULL);
+    }
+}
+
+void hmp_cont(Monitor *mon, const QDict *qdict)
+{
+    Error *errp = NULL;
+
+    qmp_cont(&errp);
+    if (error_is_set(&errp)) {
+        if (error_is_type(errp, QERR_DEVICE_ENCRYPTED)) {
+            const char *device;
+
+            /* The device is encrypted. Ask the user for the password
+               and retry */
+
+            device = error_get_field(errp, "device");
+            assert(device != NULL);
+
+            monitor_read_block_device_key(mon, device, hmp_cont_cb, mon);
+            error_free(errp);
+            return;
+        }
+        hmp_handle_error(mon, &errp);
+    }
+}
diff --git a/hmp.h b/hmp.h
index 4882bea..b034704 100644
--- a/hmp.h
+++ b/hmp.h
@@ -39,5 +39,6 @@ void hmp_system_powerdown(Monitor *mon, const QDict *qdict);
 void hmp_cpu(Monitor *mon, const QDict *qdict);
 void hmp_memsave(Monitor *mon, const QDict *qdict);
 void hmp_pmemsave(Monitor *mon, const QDict *qdict);
+void hmp_cont(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/monitor.c b/monitor.c
index a1b46b3..b0d1862 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1073,65 +1073,6 @@ static void do_singlestep(Monitor *mon, const QDict *qdict)
     }
 }
 
-static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs);
-
-struct bdrv_iterate_context {
-    Monitor *mon;
-    int err;
-};
-
-static void iostatus_bdrv_it(void *opaque, BlockDriverState *bs)
-{
-    bdrv_iostatus_reset(bs);
-}
-
-/**
- * do_cont(): Resume emulation.
- */
-static int do_cont(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
-    struct bdrv_iterate_context context = { mon, 0 };
-
-    if (runstate_check(RUN_STATE_INMIGRATE)) {
-        qerror_report(QERR_MIGRATION_EXPECTED);
-        return -1;
-    } else if (runstate_check(RUN_STATE_INTERNAL_ERROR) ||
-               runstate_check(RUN_STATE_SHUTDOWN)) {
-        qerror_report(QERR_RESET_REQUIRED);
-        return -1;
-    }
-
-    bdrv_iterate(iostatus_bdrv_it, NULL);
-    bdrv_iterate(encrypted_bdrv_it, &context);
-    /* only resume the vm if all keys are set and valid */
-    if (!context.err) {
-        vm_start();
-        return 0;
-    } else {
-        return -1;
-    }
-}
-
-static void bdrv_key_cb(void *opaque, int err)
-{
-    Monitor *mon = opaque;
-
-    /* another key was set successfully, retry to continue */
-    if (!err)
-        do_cont(mon, NULL, NULL);
-}
-
-static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs)
-{
-    struct bdrv_iterate_context *context = opaque;
-
-    if (!context->err && bdrv_key_required(bs)) {
-        context->err = -EBUSY;
-        monitor_read_bdrv_key_start(context->mon, bs, bdrv_key_cb,
-                                    context->mon);
-    }
-}
-
 static void do_gdbserver(Monitor *mon, const QDict *qdict)
 {
     const char *device = qdict_get_try_str(qdict, "device");
@@ -4858,3 +4799,18 @@ int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
 
     return err;
 }
+
+int monitor_read_block_device_key(Monitor *mon, const char *device,
+                                  BlockDriverCompletionFunc *completion_cb,
+                                  void *opaque)
+{
+    BlockDriverState *bs;
+
+    bs = bdrv_find(device);
+    if (!bs) {
+        monitor_printf(mon, "Device not found %s\n", device);
+        return -1;
+    }
+
+    return monitor_read_bdrv_key_start(mon, bs, completion_cb, opaque);
+}
diff --git a/monitor.h b/monitor.h
index e76795f..052f1cb 100644
--- a/monitor.h
+++ b/monitor.h
@@ -49,6 +49,9 @@ void monitor_resume(Monitor *mon);
 int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
                                 BlockDriverCompletionFunc *completion_cb,
                                 void *opaque);
+int monitor_read_block_device_key(Monitor *mon, const char *device,
+                                  BlockDriverCompletionFunc *completion_cb,
+                                  void *opaque);
 
 int monitor_get_fd(Monitor *mon, const char *fdname);
 
diff --git a/qapi-schema.json b/qapi-schema.json
index 7f9aa94..b6fd3f1 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -949,3 +949,20 @@
 ##
 { 'command': 'pmemsave',
   'data': {'val': 'int', 'size': 'int', 'filename': 'str'} }
+
+##
+# @cont:
+#
+# Resume guest VCPU execution.
+#
+# Since:  0.14.0
+#
+# Returns:  If successful, nothing
+#           If the QEMU is waiting for an incoming migration, MigrationExpected
+#           If QEMU was started with an encrypted block device and a key has
+#              not yet been set, DeviceEncrypted.
+#
+# Notes:  This command will succeed if the guest is currently running.
+##
+{ 'command': 'cont' }
+
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 5093ac9..03b2617 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -199,10 +199,7 @@ EQMP
     {
         .name       = "cont",
         .args_type  = "",
-        .params     = "",
-        .help       = "resume emulation",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_cont,
+        .mhandler.cmd_new = qmp_marshal_input_cont,
     },
 
 SQMP
diff --git a/qmp.c b/qmp.c
index 511dd62..d71ceb4 100644
--- a/qmp.c
+++ b/qmp.c
@@ -117,3 +117,40 @@ SpiceInfo *qmp_query_spice(Error **errp)
     return NULL;
 };
 #endif
+
+static void iostatus_bdrv_it(void *opaque, BlockDriverState *bs)
+{
+    bdrv_iostatus_reset(bs);
+}
+
+static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs)
+{
+    Error **err = opaque;
+
+    if (!error_is_set(err) && bdrv_key_required(bs)) {
+        error_set(err, QERR_DEVICE_ENCRYPTED, bdrv_get_device_name(bs));
+    }
+}
+
+void qmp_cont(Error **errp)
+{
+    Error *local_err = NULL;
+
+    if (runstate_check(RUN_STATE_INMIGRATE)) {
+        error_set(errp, QERR_MIGRATION_EXPECTED);
+        return;
+    } else if (runstate_check(RUN_STATE_INTERNAL_ERROR) ||
+               runstate_check(RUN_STATE_SHUTDOWN)) {
+        error_set(errp, QERR_RESET_REQUIRED);
+        return;
+    }
+
+    bdrv_iterate(iostatus_bdrv_it, NULL);
+    bdrv_iterate(encrypted_bdrv_it, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    vm_start();
+}
-- 
1.7.8.110.g4cb5d1.dirty

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

* [Qemu-devel] [PATCH 13/22] qapi: Convert inject-nmi
  2011-12-06 17:54 [Qemu-devel] [PULL 00/22]: QMP queue Luiz Capitulino
                   ` (11 preceding siblings ...)
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 12/22] qapi: Convert cont Luiz Capitulino
@ 2011-12-06 17:54 ` Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 14/22] qapi: Convert set_link Luiz Capitulino
                   ` (9 subsequent siblings)
  22 siblings, 0 replies; 28+ messages in thread
From: Luiz Capitulino @ 2011-12-06 17:54 UTC (permalink / raw)
  To: aliguori; +Cc: qemu-devel

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 cpus.c           |   13 +++++++++++++
 hmp-commands.hx  |    3 +--
 hmp.c            |    8 ++++++++
 hmp.h            |    1 +
 monitor.c        |   19 -------------------
 qapi-schema.json |   13 +++++++++++++
 qmp-commands.hx  |    5 +----
 7 files changed, 37 insertions(+), 25 deletions(-)

diff --git a/cpus.c b/cpus.c
index e916137..7b9f8eb 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1213,3 +1213,16 @@ void qmp_pmemsave(int64_t addr, int64_t size, const char *filename,
 exit:
     fclose(f);
 }
+
+void qmp_inject_nmi(Error **errp)
+{
+#if defined(TARGET_I386)
+    CPUState *env;
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        cpu_interrupt(env, CPU_INTERRUPT_NMI);
+    }
+#else
+    error_set(errp, QERR_UNSUPPORTED);
+#endif
+}
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 9503751..b82aff8 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -736,8 +736,7 @@ ETEXI
         .args_type  = "",
         .params     = "",
         .help       = "inject an NMI on all guest's CPUs",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_inject_nmi,
+        .mhandler.cmd = hmp_inject_nmi,
     },
 #endif
 STEXI
diff --git a/hmp.c b/hmp.c
index d623526..0ebc398 100644
--- a/hmp.c
+++ b/hmp.c
@@ -593,3 +593,11 @@ void hmp_cont(Monitor *mon, const QDict *qdict)
         hmp_handle_error(mon, &errp);
     }
 }
+
+void hmp_inject_nmi(Monitor *mon, const QDict *qdict)
+{
+    Error *errp = NULL;
+
+    qmp_inject_nmi(&errp);
+    hmp_handle_error(mon, &errp);
+}
diff --git a/hmp.h b/hmp.h
index b034704..8a31f87 100644
--- a/hmp.h
+++ b/hmp.h
@@ -40,5 +40,6 @@ void hmp_cpu(Monitor *mon, const QDict *qdict);
 void hmp_memsave(Monitor *mon, const QDict *qdict);
 void hmp_pmemsave(Monitor *mon, const QDict *qdict);
 void hmp_cont(Monitor *mon, const QDict *qdict);
+void hmp_inject_nmi(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/monitor.c b/monitor.c
index b0d1862..62b1747 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2204,25 +2204,6 @@ static void do_wav_capture(Monitor *mon, const QDict *qdict)
 }
 #endif
 
-#if defined(TARGET_I386)
-static int do_inject_nmi(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
-    CPUState *env;
-
-    for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        cpu_interrupt(env, CPU_INTERRUPT_NMI);
-    }
-
-    return 0;
-}
-#else
-static int do_inject_nmi(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
-    qerror_report(QERR_UNSUPPORTED);
-    return -1;
-}
-#endif
-
 static qemu_acl *find_acl(Monitor *mon, const char *name)
 {
     qemu_acl *acl = qemu_acl_find(name);
diff --git a/qapi-schema.json b/qapi-schema.json
index b6fd3f1..fea513f 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -966,3 +966,16 @@
 ##
 { 'command': 'cont' }
 
+##
+# @inject-nmi:
+#
+# Injects an Non-Maskable Interrupt into all guest's VCPUs.
+#
+# Returns:  If successful, nothing
+#           If the Virtual Machine doesn't support NMI injection, Unsupported
+#
+# Since:  0.14.0
+#
+# Notes: Only x86 Virtual Machines support this command.
+##
+{ 'command': 'inject-nmi' }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 03b2617..2e76708 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -407,10 +407,7 @@ EQMP
     {
         .name       = "inject-nmi",
         .args_type  = "",
-        .params     = "",
-        .help       = "",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_inject_nmi,
+        .mhandler.cmd_new = qmp_marshal_input_inject_nmi,
     },
 
 SQMP
-- 
1.7.8.110.g4cb5d1.dirty

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

* [Qemu-devel] [PATCH 14/22] qapi: Convert set_link
  2011-12-06 17:54 [Qemu-devel] [PULL 00/22]: QMP queue Luiz Capitulino
                   ` (12 preceding siblings ...)
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 13/22] qapi: Convert inject-nmi Luiz Capitulino
@ 2011-12-06 17:54 ` Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 15/22] qapi: Convert block_passwd Luiz Capitulino
                   ` (8 subsequent siblings)
  22 siblings, 0 replies; 28+ messages in thread
From: Luiz Capitulino @ 2011-12-06 17:54 UTC (permalink / raw)
  To: aliguori; +Cc: qemu-devel

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 hmp-commands.hx  |    3 +--
 hmp.c            |   10 ++++++++++
 hmp.h            |    1 +
 net.c            |   10 ++++------
 net.h            |    1 -
 qapi-schema.json |   20 ++++++++++++++++++++
 qmp-commands.hx  |    5 +----
 7 files changed, 37 insertions(+), 13 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index b82aff8..93d4a7e 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1038,8 +1038,7 @@ ETEXI
         .args_type  = "name:s,up:b",
         .params     = "name on|off",
         .help       = "change the link status of a network adapter",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_set_link,
+        .mhandler.cmd = hmp_set_link,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index 0ebc398..5d1687d 100644
--- a/hmp.c
+++ b/hmp.c
@@ -601,3 +601,13 @@ void hmp_inject_nmi(Monitor *mon, const QDict *qdict)
     qmp_inject_nmi(&errp);
     hmp_handle_error(mon, &errp);
 }
+
+void hmp_set_link(Monitor *mon, const QDict *qdict)
+{
+    const char *name = qdict_get_str(qdict, "name");
+    int up = qdict_get_bool(qdict, "up");
+    Error *errp = NULL;
+
+    qmp_set_link(name, up, &errp);
+    hmp_handle_error(mon, &errp);
+}
diff --git a/hmp.h b/hmp.h
index 8a31f87..32d7f68 100644
--- a/hmp.h
+++ b/hmp.h
@@ -41,5 +41,6 @@ void hmp_memsave(Monitor *mon, const QDict *qdict);
 void hmp_pmemsave(Monitor *mon, const QDict *qdict);
 void hmp_cont(Monitor *mon, const QDict *qdict);
 void hmp_inject_nmi(Monitor *mon, const QDict *qdict);
+void hmp_set_link(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/net.c b/net.c
index cb52050..f7bebf8 100644
--- a/net.c
+++ b/net.c
@@ -34,6 +34,7 @@
 #include "monitor.h"
 #include "qemu-common.h"
 #include "qemu_socket.h"
+#include "qmp-commands.h"
 #include "hw/qdev.h"
 #include "iov.h"
 
@@ -1258,12 +1259,10 @@ void do_info_network(Monitor *mon)
     }
 }
 
-int do_set_link(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void qmp_set_link(const char *name, bool up, Error **errp)
 {
     VLANState *vlan;
     VLANClientState *vc = NULL;
-    const char *name = qdict_get_str(qdict, "name");
-    int up = qdict_get_bool(qdict, "up");
 
     QTAILQ_FOREACH(vlan, &vlans, next) {
         QTAILQ_FOREACH(vc, &vlan->clients, next) {
@@ -1280,8 +1279,8 @@ int do_set_link(Monitor *mon, const QDict *qdict, QObject **ret_data)
 done:
 
     if (!vc) {
-        qerror_report(QERR_DEVICE_NOT_FOUND, name);
-        return -1;
+        error_set(errp, QERR_DEVICE_NOT_FOUND, name);
+        return;
     }
 
     vc->link_down = !up;
@@ -1300,7 +1299,6 @@ done:
     if (vc->peer && vc->peer->info->link_status_changed) {
         vc->peer->info->link_status_changed(vc->peer);
     }
-    return 0;
 }
 
 void net_cleanup(void)
diff --git a/net.h b/net.h
index 9f633f8..c6b4190 100644
--- a/net.h
+++ b/net.h
@@ -122,7 +122,6 @@ int qemu_find_nic_model(NICInfo *nd, const char * const *models,
                         const char *default_model);
 
 void do_info_network(Monitor *mon);
-int do_set_link(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
 /* NIC info */
 
diff --git a/qapi-schema.json b/qapi-schema.json
index fea513f..1d6fb4d 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -979,3 +979,23 @@
 # Notes: Only x86 Virtual Machines support this command.
 ##
 { 'command': 'inject-nmi' }
+
+##
+# @set_link:
+#
+# Sets the link status of a virtual network adapter.
+#
+# @name: the device name of the virtual network adapter
+#
+# @up: true to set the link status to be up
+#
+# Returns: Nothing on success
+#          If @name is not a valid network device, DeviceNotFound
+#
+# Since: 0.14.0
+#
+# Notes: Not all network adapters support setting link status.  This command
+#        will succeed even if the network adapter does not support link status
+#        notification.
+##
+{ 'command': 'set_link', 'data': {'name': 'str', 'up': 'bool'} }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 2e76708..5054da3 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -730,10 +730,7 @@ EQMP
     {
         .name       = "set_link",
         .args_type  = "name:s,up:b",
-        .params     = "name on|off",
-        .help       = "change the link status of a network adapter",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_set_link,
+        .mhandler.cmd_new = qmp_marshal_input_set_link,
     },
 
 SQMP
-- 
1.7.8.110.g4cb5d1.dirty

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

* [Qemu-devel] [PATCH 15/22] qapi: Convert block_passwd
  2011-12-06 17:54 [Qemu-devel] [PULL 00/22]: QMP queue Luiz Capitulino
                   ` (13 preceding siblings ...)
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 14/22] qapi: Convert set_link Luiz Capitulino
@ 2011-12-06 17:54 ` Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 16/22] qapi: Convert balloon Luiz Capitulino
                   ` (7 subsequent siblings)
  22 siblings, 0 replies; 28+ messages in thread
From: Luiz Capitulino @ 2011-12-06 17:54 UTC (permalink / raw)
  To: aliguori; +Cc: qemu-devel

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 blockdev.c       |   22 ++++++++++------------
 blockdev.h       |    1 -
 hmp-commands.hx  |    3 +--
 hmp.c            |   10 ++++++++++
 hmp.h            |    1 +
 qapi-schema.json |   33 +++++++++++++++++++++++++++++++++
 qmp-commands.hx  |    5 +----
 7 files changed, 56 insertions(+), 19 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index dbf0251..aba7aaf 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -15,6 +15,7 @@
 #include "qemu-config.h"
 #include "sysemu.h"
 #include "block_int.h"
+#include "qmp-commands.h"
 
 static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
 
@@ -710,28 +711,25 @@ int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data)
     return eject_device(mon, bs, force);
 }
 
-int do_block_set_passwd(Monitor *mon, const QDict *qdict,
-                        QObject **ret_data)
+void qmp_block_passwd(const char *device, const char *password, Error **errp)
 {
     BlockDriverState *bs;
     int err;
 
-    bs = bdrv_find(qdict_get_str(qdict, "device"));
+    bs = bdrv_find(device);
     if (!bs) {
-        qerror_report(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device"));
-        return -1;
+        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+        return;
     }
 
-    err = bdrv_set_key(bs, qdict_get_str(qdict, "password"));
+    err = bdrv_set_key(bs, password);
     if (err == -EINVAL) {
-        qerror_report(QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs));
-        return -1;
+        error_set(errp, QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs));
+        return;
     } else if (err < 0) {
-        qerror_report(QERR_INVALID_PASSWORD);
-        return -1;
+        error_set(errp, QERR_INVALID_PASSWORD);
+        return;
     }
-
-    return 0;
 }
 
 int do_change_block(Monitor *mon, const char *device,
diff --git a/blockdev.h b/blockdev.h
index 1b48a75..93311a9 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -59,7 +59,6 @@ DriveInfo *add_init_drive(const char *opts);
 
 void do_commit(Monitor *mon, const QDict *qdict);
 int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data);
-int do_block_set_passwd(Monitor *mon, const QDict *qdict, QObject **ret_data);
 int do_change_block(Monitor *mon, const char *device,
                     const char *filename, const char *fmt);
 int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 93d4a7e..0bf8896 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1198,8 +1198,7 @@ ETEXI
         .args_type  = "device:B,password:s",
         .params     = "block_passwd device password",
         .help       = "set the password of encrypted block devices",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_block_set_passwd,
+        .mhandler.cmd = hmp_block_passwd,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index 5d1687d..3893d59 100644
--- a/hmp.c
+++ b/hmp.c
@@ -611,3 +611,13 @@ void hmp_set_link(Monitor *mon, const QDict *qdict)
     qmp_set_link(name, up, &errp);
     hmp_handle_error(mon, &errp);
 }
+
+void hmp_block_passwd(Monitor *mon, const QDict *qdict)
+{
+    const char *device = qdict_get_str(qdict, "device");
+    const char *password = qdict_get_str(qdict, "password");
+    Error *errp = NULL;
+
+    qmp_block_passwd(device, password, &errp);
+    hmp_handle_error(mon, &errp);
+}
diff --git a/hmp.h b/hmp.h
index 32d7f68..d6aa232 100644
--- a/hmp.h
+++ b/hmp.h
@@ -42,5 +42,6 @@ void hmp_pmemsave(Monitor *mon, const QDict *qdict);
 void hmp_cont(Monitor *mon, const QDict *qdict);
 void hmp_inject_nmi(Monitor *mon, const QDict *qdict);
 void hmp_set_link(Monitor *mon, const QDict *qdict);
+void hmp_block_passwd(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/qapi-schema.json b/qapi-schema.json
index 1d6fb4d..569aa74 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -999,3 +999,36 @@
 #        notification.
 ##
 { 'command': 'set_link', 'data': {'name': 'str', 'up': 'bool'} }
+
+##
+# @block_passwd:
+#
+# This command sets the password of a block device that has not been open
+# with a password and requires one.
+#
+# The two cases where this can happen are a block device is created through
+# QEMU's initial command line or a block device is changed through the legacy
+# @change interface.
+#
+# In the event that the block device is created through the initial command
+# line, the VM will start in the stopped state regardless of whether '-S' is
+# used.  The intention is for a management tool to query the block devices to
+# determine which ones are encrypted, set the passwords with this command, and
+# then start the guest with the @cont command.
+#
+# @device:   the name of the device to set the password on
+#
+# @password: the password to use for the device
+#
+# Returns: nothing on success
+#          If @device is not a valid block device, DeviceNotFound
+#          If @device is not encrypted, DeviceNotEncrypted
+#          If @password is not valid for this device, InvalidPassword
+#
+# Notes:  Not all block formats support encryption and some that do are not
+#         able to validate that a password is correct.  Disk corruption may
+#         occur if an invalid password is specified.
+#
+# Since: 0.14.0
+##
+{ 'command': 'block_passwd', 'data': {'device': 'str', 'password': 'str'} }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 5054da3..bbf9bfc 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -806,10 +806,7 @@ EQMP
     {
         .name       = "block_passwd",
         .args_type  = "device:B,password:s",
-        .params     = "block_passwd device password",
-        .help       = "set the password of encrypted block devices",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_block_set_passwd,
+        .mhandler.cmd_new = qmp_marshal_input_block_passwd,
     },
 
 SQMP
-- 
1.7.8.110.g4cb5d1.dirty

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

* [Qemu-devel] [PATCH 16/22] qapi: Convert balloon
  2011-12-06 17:54 [Qemu-devel] [PULL 00/22]: QMP queue Luiz Capitulino
                   ` (14 preceding siblings ...)
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 15/22] qapi: Convert block_passwd Luiz Capitulino
@ 2011-12-06 17:54 ` Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 17/22] qapi: Convert block_resize Luiz Capitulino
                   ` (6 subsequent siblings)
  22 siblings, 0 replies; 28+ messages in thread
From: Luiz Capitulino @ 2011-12-06 17:54 UTC (permalink / raw)
  To: aliguori; +Cc: qemu-devel

Note that the command being dropped uses the deprecated MONITOR_CMD_ASYNC
API, but the new command is a regular synchronous command. There shouldn't
be visible differences though, as MONITOR_CMD_ASYNC is internal only.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 balloon.c        |   28 ++++++++--------------------
 balloon.h        |    3 ---
 hmp-commands.hx  |    4 +---
 hmp.c            |   12 ++++++++++++
 hmp.h            |    1 +
 qapi-schema.json |   20 ++++++++++++++++++++
 qmp-commands.hx  |    6 +-----
 7 files changed, 43 insertions(+), 31 deletions(-)

diff --git a/balloon.c b/balloon.c
index e1cd5fa..0166744 100644
--- a/balloon.c
+++ b/balloon.c
@@ -100,31 +100,19 @@ BalloonInfo *qmp_query_balloon(Error **errp)
     return info;
 }
 
-/**
- * do_balloon(): Request VM to change its memory allocation
- */
-int do_balloon(Monitor *mon, const QDict *params,
-	       MonitorCompletion cb, void *opaque)
+void qmp_balloon(int64_t value, Error **errp)
 {
-    int64_t target;
-    int ret;
-
     if (kvm_enabled() && !kvm_has_sync_mmu()) {
-        qerror_report(QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
-        return -1;
+        error_set(errp, QERR_KVM_MISSING_CAP, "synchronous MMU", "balloon");
+        return;
     }
 
-    target = qdict_get_int(params, "value");
-    if (target <= 0) {
+    if (value <= 0) {
         qerror_report(QERR_INVALID_PARAMETER_VALUE, "target", "a size");
-        return -1;
+        return;
     }
-    ret = qemu_balloon(target);
-    if (ret == 0) {
-        qerror_report(QERR_DEVICE_NOT_ACTIVE, "balloon");
-        return -1;
+    
+    if (qemu_balloon(value) == 0) {
+        error_set(errp, QERR_DEVICE_NOT_ACTIVE, "balloon");
     }
-
-    cb(opaque, NULL);
-    return 0;
 }
diff --git a/balloon.h b/balloon.h
index b36abea..b60fd5d 100644
--- a/balloon.h
+++ b/balloon.h
@@ -24,7 +24,4 @@ int qemu_add_balloon_handler(QEMUBalloonEvent *event_func,
 			     QEMUBalloonStatus *stat_func, void *opaque);
 void qemu_remove_balloon_handler(void *opaque);
 
-int do_balloon(Monitor *mon, const QDict *params,
-               MonitorCompletion cb, void *opaque);
-
 #endif
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 0bf8896..ea52271 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1022,9 +1022,7 @@ ETEXI
         .args_type  = "value:M",
         .params     = "target",
         .help       = "request VM to change its memory allocation (in MB)",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_async = do_balloon,
-        .flags      = MONITOR_CMD_ASYNC,
+        .mhandler.cmd = hmp_balloon,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index 3893d59..e9d1711 100644
--- a/hmp.c
+++ b/hmp.c
@@ -621,3 +621,15 @@ void hmp_block_passwd(Monitor *mon, const QDict *qdict)
     qmp_block_passwd(device, password, &errp);
     hmp_handle_error(mon, &errp);
 }
+
+void hmp_balloon(Monitor *mon, const QDict *qdict)
+{
+    int64_t value = qdict_get_int(qdict, "value");
+    Error *errp = NULL;
+
+    qmp_balloon(value, &errp);
+    if (error_is_set(&errp)) {
+        monitor_printf(mon, "balloon: %s\n", error_get_pretty(errp));
+        error_free(errp);
+    }
+}
diff --git a/hmp.h b/hmp.h
index d6aa232..b0984ac 100644
--- a/hmp.h
+++ b/hmp.h
@@ -43,5 +43,6 @@ void hmp_cont(Monitor *mon, const QDict *qdict);
 void hmp_inject_nmi(Monitor *mon, const QDict *qdict);
 void hmp_set_link(Monitor *mon, const QDict *qdict);
 void hmp_block_passwd(Monitor *mon, const QDict *qdict);
+void hmp_balloon(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/qapi-schema.json b/qapi-schema.json
index 569aa74..9bfdc39 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1032,3 +1032,23 @@
 # Since: 0.14.0
 ##
 { 'command': 'block_passwd', 'data': {'device': 'str', 'password': 'str'} }
+
+##
+# @balloon:
+#
+# Request the balloon driver to change its balloon size.
+#
+# @value: the target size of the balloon in bytes
+#
+# Returns: Nothing on success
+#          If the balloon driver is enabled but not functional because the KVM
+#            kernel module cannot support it, KvmMissingCap
+#          If no balloon device is present, DeviceNotActive
+#
+# Notes: This command just issues a request to the guest.  When it returns,
+#        the balloon size may not have changed.  A guest can change the balloon
+#        size independent of this command.
+#
+# Since: 0.14.0
+##
+{ 'command': 'balloon', 'data': {'value': 'int'} }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index bbf9bfc..7c377f0 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -703,11 +703,7 @@ EQMP
     {
         .name       = "balloon",
         .args_type  = "value:M",
-        .params     = "target",
-        .help       = "request VM to change its memory allocation (in MB)",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_async = do_balloon,
-        .flags      = MONITOR_CMD_ASYNC,
+        .mhandler.cmd_new = qmp_marshal_input_balloon,
     },
 
 SQMP
-- 
1.7.8.110.g4cb5d1.dirty

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

* [Qemu-devel] [PATCH 17/22] qapi: Convert block_resize
  2011-12-06 17:54 [Qemu-devel] [PULL 00/22]: QMP queue Luiz Capitulino
                   ` (15 preceding siblings ...)
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 16/22] qapi: Convert balloon Luiz Capitulino
@ 2011-12-06 17:54 ` Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 18/22] qapi: Convert blockdev_snapshot_sync Luiz Capitulino
                   ` (5 subsequent siblings)
  22 siblings, 0 replies; 28+ messages in thread
From: Luiz Capitulino @ 2011-12-06 17:54 UTC (permalink / raw)
  To: aliguori; +Cc: qemu-devel

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 blockdev.c       |   18 +++++++-----------
 blockdev.h       |    1 -
 hmp-commands.hx  |    3 +--
 hmp.c            |   10 ++++++++++
 hmp.h            |    1 +
 qapi-schema.json |   18 ++++++++++++++++++
 qmp-commands.hx  |    5 +----
 7 files changed, 38 insertions(+), 18 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index aba7aaf..5270404 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -861,27 +861,23 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
  * existing QERR_ macro mess is cleaned up.  A good example for better
  * error reports can be found in the qemu-img resize code.
  */
-int do_block_resize(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void qmp_block_resize(const char *device, int64_t size, Error **errp)
 {
-    const char *device = qdict_get_str(qdict, "device");
-    int64_t size = qdict_get_int(qdict, "size");
     BlockDriverState *bs;
 
     bs = bdrv_find(device);
     if (!bs) {
-        qerror_report(QERR_DEVICE_NOT_FOUND, device);
-        return -1;
+        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+        return;
     }
 
     if (size < 0) {
-        qerror_report(QERR_UNDEFINED_ERROR);
-        return -1;
+        error_set(errp, QERR_UNDEFINED_ERROR);
+        return;
     }
 
     if (bdrv_truncate(bs, size)) {
-        qerror_report(QERR_UNDEFINED_ERROR);
-        return -1;
+        error_set(errp, QERR_UNDEFINED_ERROR);
+        return;
     }
-
-    return 0;
 }
diff --git a/blockdev.h b/blockdev.h
index 93311a9..b69a549 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -65,6 +65,5 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
 int do_block_set_io_throttle(Monitor *mon,
                              const QDict *qdict, QObject **ret_data);
 int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data);
-int do_block_resize(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
 #endif
diff --git a/hmp-commands.hx b/hmp-commands.hx
index ea52271..734a364 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -57,8 +57,7 @@ ETEXI
         .args_type  = "device:B,size:o",
         .params     = "device size",
         .help       = "resize a block image",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_block_resize,
+        .mhandler.cmd = hmp_block_resize,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index e9d1711..db199b2 100644
--- a/hmp.c
+++ b/hmp.c
@@ -633,3 +633,13 @@ void hmp_balloon(Monitor *mon, const QDict *qdict)
         error_free(errp);
     }
 }
+
+void hmp_block_resize(Monitor *mon, const QDict *qdict)
+{
+    const char *device = qdict_get_str(qdict, "device");
+    int64_t size = qdict_get_int(qdict, "size");
+    Error *errp = NULL;
+
+    qmp_block_resize(device, size, &errp);
+    hmp_handle_error(mon, &errp);
+}
diff --git a/hmp.h b/hmp.h
index b0984ac..c236fd2 100644
--- a/hmp.h
+++ b/hmp.h
@@ -44,5 +44,6 @@ void hmp_inject_nmi(Monitor *mon, const QDict *qdict);
 void hmp_set_link(Monitor *mon, const QDict *qdict);
 void hmp_block_passwd(Monitor *mon, const QDict *qdict);
 void hmp_balloon(Monitor *mon, const QDict *qdict);
+void hmp_block_resize(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/qapi-schema.json b/qapi-schema.json
index 9bfdc39..f33fe00 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1052,3 +1052,21 @@
 # Since: 0.14.0
 ##
 { 'command': 'balloon', 'data': {'value': 'int'} }
+
+##
+# @block_resize
+#
+# Resize a block image while a guest is running.
+#
+# @device:  the name of the device to get the image resized
+#
+# @size:  new image size in bytes
+#
+# Returns: nothing on success
+#          If @device is not a valid block device, DeviceNotFound
+#
+# Notes: This command returns UndefinedError in a number of error conditions.
+#
+# Since: 0.14.0
+##
+{ 'command': 'block_resize', 'data': { 'device': 'str', 'size': 'int' }}
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 7c377f0..721b157 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -642,10 +642,7 @@ EQMP
     {
         .name       = "block_resize",
         .args_type  = "device:B,size:o",
-        .params     = "device size",
-        .help       = "resize a block image",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_block_resize,
+        .mhandler.cmd_new = qmp_marshal_input_block_resize,
     },
 
 SQMP
-- 
1.7.8.110.g4cb5d1.dirty

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

* [Qemu-devel] [PATCH 18/22] qapi: Convert blockdev_snapshot_sync
  2011-12-06 17:54 [Qemu-devel] [PULL 00/22]: QMP queue Luiz Capitulino
                   ` (16 preceding siblings ...)
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 17/22] qapi: Convert block_resize Luiz Capitulino
@ 2011-12-06 17:54 ` Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 19/22] qapi: Convert human-monitor-command Luiz Capitulino
                   ` (4 subsequent siblings)
  22 siblings, 0 replies; 28+ messages in thread
From: Luiz Capitulino @ 2011-12-06 17:54 UTC (permalink / raw)
  To: aliguori; +Cc: qemu-devel

Unfortunately, this conversion required an additional change.

In the old QMP command, the 'snapshot-file' argument is specified as
optional. The idea is to take the snapshot internally if 'snapshot-file'
is not passed. However, internal snapshots are not supported yet so
the command returns a MissingParamater error if 'snapshot-file' is not
passed. Which makes the argument actually required and will cause
compatibility breakage if we change that in the future.

To fix this the QAPI converted blockdev_snapshot_sync command makes the
'snapshot-file' argument required. Again, in practice it's actually required,
so this is not incompatible.

If we do implement internal snapshots someday, we'll need a new argument
for it.

Note that this discussion doesn't affect HMP.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 blockdev.c       |   49 +++++++++++++++++--------------------------------
 blockdev.h       |    2 --
 hmp-commands.hx  |    2 +-
 hmp.c            |   19 +++++++++++++++++++
 hmp.h            |    1 +
 qapi-schema.json |   29 +++++++++++++++++++++++++++++
 qmp-commands.hx  |    6 ++----
 7 files changed, 69 insertions(+), 39 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 5270404..c832782 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -601,28 +601,20 @@ void do_commit(Monitor *mon, const QDict *qdict)
     }
 }
 
-int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file,
+                                bool has_format, const char *format,
+                                Error **errp)
 {
-    const char *device = qdict_get_str(qdict, "device");
-    const char *filename = qdict_get_try_str(qdict, "snapshot-file");
-    const char *format = qdict_get_try_str(qdict, "format");
     BlockDriverState *bs;
     BlockDriver *drv, *old_drv, *proto_drv;
     int ret = 0;
     int flags;
     char old_filename[1024];
 
-    if (!filename) {
-        qerror_report(QERR_MISSING_PARAMETER, "snapshot-file");
-        ret = -1;
-        goto out;
-    }
-
     bs = bdrv_find(device);
     if (!bs) {
-        qerror_report(QERR_DEVICE_NOT_FOUND, device);
-        ret = -1;
-        goto out;
+        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+        return;
     }
 
     pstrcpy(old_filename, sizeof(old_filename), bs->filename);
@@ -630,35 +622,34 @@ int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
     old_drv = bs->drv;
     flags = bs->open_flags;
 
-    if (!format) {
+    if (!has_format) {
         format = "qcow2";
     }
 
     drv = bdrv_find_format(format);
     if (!drv) {
-        qerror_report(QERR_INVALID_BLOCK_FORMAT, format);
-        ret = -1;
-        goto out;
+        error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
+        return;
     }
 
-    proto_drv = bdrv_find_protocol(filename);
+    proto_drv = bdrv_find_protocol(snapshot_file);
     if (!proto_drv) {
-        qerror_report(QERR_INVALID_BLOCK_FORMAT, format);
-        ret = -1;
-        goto out;
+        error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
+        return;
     }
 
-    ret = bdrv_img_create(filename, format, bs->filename,
+    ret = bdrv_img_create(snapshot_file, format, bs->filename,
                           bs->drv->format_name, NULL, -1, flags);
     if (ret) {
-        goto out;
+        error_set(errp, QERR_UNDEFINED_ERROR);
+        return;
     }
 
     bdrv_drain_all();
     bdrv_flush(bs);
 
     bdrv_close(bs);
-    ret = bdrv_open(bs, filename, flags, drv);
+    ret = bdrv_open(bs, snapshot_file, flags, drv);
     /*
      * If reopening the image file we just created fails, fall back
      * and try to re-open the original image. If that fails too, we
@@ -667,17 +658,11 @@ int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
     if (ret != 0) {
         ret = bdrv_open(bs, old_filename, flags, old_drv);
         if (ret != 0) {
-            qerror_report(QERR_OPEN_FILE_FAILED, old_filename);
+            error_set(errp, QERR_OPEN_FILE_FAILED, old_filename);
         } else {
-            qerror_report(QERR_OPEN_FILE_FAILED, filename);
+            error_set(errp, QERR_OPEN_FILE_FAILED, snapshot_file);
         }
     }
-out:
-    if (ret) {
-        ret = -1;
-    }
-
-    return ret;
 }
 
 static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
diff --git a/blockdev.h b/blockdev.h
index b69a549..f1b6396 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -64,6 +64,4 @@ int do_change_block(Monitor *mon, const char *device,
 int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
 int do_block_set_io_throttle(Monitor *mon,
                              const QDict *qdict, QObject **ret_data);
-int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data);
-
 #endif
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 734a364..131b21c 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -840,7 +840,7 @@ ETEXI
                       "If format is specified, the snapshot file will\n\t\t\t"
                       "be created in that format. Otherwise the\n\t\t\t"
                       "snapshot will be internal! (currently unsupported)",
-        .mhandler.cmd_new = do_snapshot_blkdev,
+        .mhandler.cmd = hmp_snapshot_blkdev,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index db199b2..934e931 100644
--- a/hmp.c
+++ b/hmp.c
@@ -643,3 +643,22 @@ void hmp_block_resize(Monitor *mon, const QDict *qdict)
     qmp_block_resize(device, size, &errp);
     hmp_handle_error(mon, &errp);
 }
+
+void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict)
+{
+    const char *device = qdict_get_str(qdict, "device");
+    const char *filename = qdict_get_try_str(qdict, "snapshot-file");
+    const char *format = qdict_get_try_str(qdict, "format");
+    Error *errp = NULL;
+
+    if (!filename) {
+        /* In the future, if 'snapshot-file' is not specified, the snapshot
+           will be taken internally. Today it's actually required. */
+        error_set(&errp, QERR_MISSING_PARAMETER, "snapshot-file");
+        hmp_handle_error(mon, &errp);
+        return;
+    }
+
+    qmp_blockdev_snapshot_sync(device, filename, !!format, format, &errp);
+    hmp_handle_error(mon, &errp);
+}
diff --git a/hmp.h b/hmp.h
index c236fd2..e4227d3 100644
--- a/hmp.h
+++ b/hmp.h
@@ -45,5 +45,6 @@ void hmp_set_link(Monitor *mon, const QDict *qdict);
 void hmp_block_passwd(Monitor *mon, const QDict *qdict);
 void hmp_balloon(Monitor *mon, const QDict *qdict);
 void hmp_block_resize(Monitor *mon, const QDict *qdict);
+void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/qapi-schema.json b/qapi-schema.json
index f33fe00..0ed39f3 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1070,3 +1070,32 @@
 # Since: 0.14.0
 ##
 { 'command': 'block_resize', 'data': { 'device': 'str', 'size': 'int' }}
+
+##
+# @blockdev-snapshot-sync
+#
+# Generates a synchronous snapshot of a block device.
+#
+# @device:  the name of the device to generate the snapshot from.
+#
+# @snapshot-file: the target of the new image. If the file exists, or if it
+#                 is a device, the snapshot will be created in the existing
+#                 file/device. If does not exist, a new file will be created.
+#
+# @format: #optional the format of the snapshot image, default is 'qcow2'.
+#
+# Returns: nothing on success
+#          If @device is not a valid block device, DeviceNotFound
+#          If @snapshot-file can't be opened, OpenFileFailed
+#          If @format is invalid, InvalidBlockFormat
+#
+# Notes: One of the last steps taken by this command is to close the current
+#        image being used by @device and open the @snapshot-file one. If that
+#        fails, the command will try to reopen the original image file. If
+#        that also fails OpenFileFailed will be returned and the guest may get
+#        unexpected errors.
+#
+# Since 0.14.0
+##
+{ 'command': 'blockdev-snapshot-sync',
+  'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str' } }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 721b157..9d68206 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -665,10 +665,8 @@ EQMP
 
     {
         .name       = "blockdev-snapshot-sync",
-        .args_type  = "device:B,snapshot-file:s?,format:s?",
-        .params     = "device [new-image-file] [format]",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_snapshot_blkdev,
+        .args_type  = "device:B,snapshot-file:s,format:s?",
+        .mhandler.cmd_new = qmp_marshal_input_blockdev_snapshot_sync,
     },
 
 SQMP
-- 
1.7.8.110.g4cb5d1.dirty

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

* [Qemu-devel] [PATCH 19/22] qapi: Convert human-monitor-command
  2011-12-06 17:54 [Qemu-devel] [PULL 00/22]: QMP queue Luiz Capitulino
                   ` (17 preceding siblings ...)
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 18/22] qapi: Convert blockdev_snapshot_sync Luiz Capitulino
@ 2011-12-06 17:54 ` Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 20/22] qapi: Convert migrate_cancel Luiz Capitulino
                   ` (3 subsequent siblings)
  22 siblings, 0 replies; 28+ messages in thread
From: Luiz Capitulino @ 2011-12-06 17:54 UTC (permalink / raw)
  To: aliguori; +Cc: qemu-devel

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 monitor.c        |   23 ++++++++++++++---------
 qapi-schema.json |   28 ++++++++++++++++++++++++++++
 qmp-commands.hx  |    5 +----
 3 files changed, 43 insertions(+), 13 deletions(-)

diff --git a/monitor.c b/monitor.c
index 62b1747..7334401 100644
--- a/monitor.c
+++ b/monitor.c
@@ -513,10 +513,10 @@ static int do_qmp_capabilities(Monitor *mon, const QDict *params,
 
 static void handle_user_command(Monitor *mon, const char *cmdline);
 
-static int do_hmp_passthrough(Monitor *mon, const QDict *params,
-                              QObject **ret_data)
+char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
+                                int64_t cpu_index, Error **errp)
 {
-    int ret = 0;
+    char *output = NULL;
     Monitor *old_mon, hmp;
     CharDriverState mchar;
 
@@ -527,25 +527,30 @@ static int do_hmp_passthrough(Monitor *mon, const QDict *params,
     old_mon = cur_mon;
     cur_mon = &hmp;
 
-    if (qdict_haskey(params, "cpu-index")) {
-        ret = monitor_set_cpu(qdict_get_int(params, "cpu-index"));
+    if (has_cpu_index) {
+        int ret = monitor_set_cpu(cpu_index);
         if (ret < 0) {
             cur_mon = old_mon;
-            qerror_report(QERR_INVALID_PARAMETER_VALUE, "cpu-index", "a CPU number");
+            error_set(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index",
+                      "a CPU number");
             goto out;
         }
     }
 
-    handle_user_command(&hmp, qdict_get_str(params, "command-line"));
+    handle_user_command(&hmp, command_line);
     cur_mon = old_mon;
 
     if (qemu_chr_mem_osize(hmp.chr) > 0) {
-        *ret_data = QOBJECT(qemu_chr_mem_to_qs(hmp.chr));
+        QString *str = qemu_chr_mem_to_qs(hmp.chr);
+        output = g_strdup(qstring_get_str(str));
+        QDECREF(str);
+    } else {
+        output = g_strdup("");
     }
 
 out:
     qemu_chr_close_mem(hmp.chr);
-    return ret;
+    return output;
 }
 
 static int compare_cmd(const char *name, const char *list)
diff --git a/qapi-schema.json b/qapi-schema.json
index 0ed39f3..39bcc06 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1099,3 +1099,31 @@
 ##
 { 'command': 'blockdev-snapshot-sync',
   'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str' } }
+
+##
+# @human-monitor-command:
+#
+# Execute a command on the human monitor and return the output.
+#
+# @command-line: the command to execute in the human monitor
+#
+# @cpu-index: #optional The CPU to use for commands that require an implicit CPU
+#
+# Returns: the output of the command as a string
+#
+# Since: 0.14.0
+#
+# Notes: This command only exists as a stop-gap.  It's use is highly
+#        discouraged.  The semantics of this command are not guaranteed.
+#
+#        Known limitations:
+#
+#        o This command is stateless, this means that commands that depend
+#          on state information (such as getfd) might not work
+#
+#       o Commands that prompt the user for data (eg. 'cont' when the block
+#         device is encrypted) don't currently work
+##
+{ 'command': 'human-monitor-command',
+  'data': {'command-line': 'str', '*cpu-index': 'int'},
+  'returns': 'str' } 
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 9d68206..d101426 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -970,10 +970,7 @@ EQMP
     {
         .name       = "human-monitor-command",
         .args_type  = "command-line:s,cpu-index:i?",
-        .params     = "",
-        .help       = "",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_hmp_passthrough,
+        .mhandler.cmd_new = qmp_marshal_input_human_monitor_command,
     },
 
 SQMP
-- 
1.7.8.110.g4cb5d1.dirty

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

* [Qemu-devel] [PATCH 20/22] qapi: Convert migrate_cancel
  2011-12-06 17:54 [Qemu-devel] [PULL 00/22]: QMP queue Luiz Capitulino
                   ` (18 preceding siblings ...)
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 19/22] qapi: Convert human-monitor-command Luiz Capitulino
@ 2011-12-06 17:54 ` Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 21/22] qapi: Convert migrate_set_downtime Luiz Capitulino
                   ` (2 subsequent siblings)
  22 siblings, 0 replies; 28+ messages in thread
From: Luiz Capitulino @ 2011-12-06 17:54 UTC (permalink / raw)
  To: aliguori; +Cc: qemu-devel

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 hmp-commands.hx  |    3 +--
 hmp.c            |    5 +++++
 hmp.h            |    1 +
 migration.c      |    3 +--
 migration.h      |    2 --
 qapi-schema.json |   13 +++++++++++++
 qmp-commands.hx  |    5 +----
 7 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 131b21c..e48c2ca 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -771,8 +771,7 @@ ETEXI
         .args_type  = "",
         .params     = "",
         .help       = "cancel the current VM migration",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_migrate_cancel,
+        .mhandler.cmd = hmp_migrate_cancel,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index 934e931..92bb08f 100644
--- a/hmp.c
+++ b/hmp.c
@@ -662,3 +662,8 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict)
     qmp_blockdev_snapshot_sync(device, filename, !!format, format, &errp);
     hmp_handle_error(mon, &errp);
 }
+
+void hmp_migrate_cancel(Monitor *mon, const QDict *qdict)
+{
+    qmp_migrate_cancel(NULL);
+}
diff --git a/hmp.h b/hmp.h
index e4227d3..2b0c1e4 100644
--- a/hmp.h
+++ b/hmp.h
@@ -46,5 +46,6 @@ void hmp_block_passwd(Monitor *mon, const QDict *qdict);
 void hmp_balloon(Monitor *mon, const QDict *qdict);
 void hmp_block_resize(Monitor *mon, const QDict *qdict);
 void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict);
+void hmp_migrate_cancel(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/migration.c b/migration.c
index 8280d71..fa603d6 100644
--- a/migration.c
+++ b/migration.c
@@ -468,10 +468,9 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
     return 0;
 }
 
-int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void qmp_migrate_cancel(Error **errp)
 {
     migrate_fd_cancel(migrate_get_current());
-    return 0;
 }
 
 int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data)
diff --git a/migration.h b/migration.h
index 0682179..ff2e40b 100644
--- a/migration.h
+++ b/migration.h
@@ -42,8 +42,6 @@ int qemu_start_incoming_migration(const char *uri);
 
 int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
-int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data);
-
 int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
 uint64_t migrate_max_downtime(void);
diff --git a/qapi-schema.json b/qapi-schema.json
index 39bcc06..d638f12 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1127,3 +1127,16 @@
 { 'command': 'human-monitor-command',
   'data': {'command-line': 'str', '*cpu-index': 'int'},
   'returns': 'str' } 
+
+##
+# @migrate_cancel
+#
+# Cancel the current executing migration process.
+#
+# Returns: nothing on success
+#
+# Notes: This command succeeds even if there is no migration process running.
+#
+# Since: 0.14.0
+##
+{ 'command': 'migrate_cancel' }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index d101426..5eb4b76 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -471,10 +471,7 @@ EQMP
     {
         .name       = "migrate_cancel",
         .args_type  = "",
-        .params     = "",
-        .help       = "cancel the current VM migration",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_migrate_cancel,
+        .mhandler.cmd_new = qmp_marshal_input_migrate_cancel,
     },
 
 SQMP
-- 
1.7.8.110.g4cb5d1.dirty

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

* [Qemu-devel] [PATCH 21/22] qapi: Convert migrate_set_downtime
  2011-12-06 17:54 [Qemu-devel] [PULL 00/22]: QMP queue Luiz Capitulino
                   ` (19 preceding siblings ...)
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 20/22] qapi: Convert migrate_cancel Luiz Capitulino
@ 2011-12-06 17:54 ` Luiz Capitulino
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 22/22] qapi: Convert migrate_set_speed Luiz Capitulino
  2011-12-12 16:34 ` [Qemu-devel] [PULL 00/22]: QMP queue Anthony Liguori
  22 siblings, 0 replies; 28+ messages in thread
From: Luiz Capitulino @ 2011-12-06 17:54 UTC (permalink / raw)
  To: aliguori; +Cc: qemu-devel

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 hmp-commands.hx  |    3 +--
 hmp.c            |    6 ++++++
 hmp.h            |    1 +
 migration.c      |   13 ++++---------
 migration.h      |    3 ---
 qapi-schema.json |   13 +++++++++++++
 qmp-commands.hx  |    5 +----
 7 files changed, 26 insertions(+), 18 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index e48c2ca..6ba694d 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -801,8 +801,7 @@ ETEXI
         .args_type  = "value:T",
         .params     = "value",
         .help       = "set maximum tolerated downtime (in seconds) for migrations",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_migrate_set_downtime,
+        .mhandler.cmd = hmp_migrate_set_downtime,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index 92bb08f..04e6b73 100644
--- a/hmp.c
+++ b/hmp.c
@@ -667,3 +667,9 @@ void hmp_migrate_cancel(Monitor *mon, const QDict *qdict)
 {
     qmp_migrate_cancel(NULL);
 }
+
+void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict)
+{
+    double value = qdict_get_double(qdict, "value");
+    qmp_migrate_set_downtime(value, NULL);
+}
diff --git a/hmp.h b/hmp.h
index 2b0c1e4..9182622 100644
--- a/hmp.h
+++ b/hmp.h
@@ -47,5 +47,6 @@ void hmp_balloon(Monitor *mon, const QDict *qdict);
 void hmp_block_resize(Monitor *mon, const QDict *qdict);
 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);
 
 #endif
diff --git a/migration.c b/migration.c
index fa603d6..a563162 100644
--- a/migration.c
+++ b/migration.c
@@ -490,14 +490,9 @@ int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data)
     return 0;
 }
 
-int do_migrate_set_downtime(Monitor *mon, const QDict *qdict,
-                            QObject **ret_data)
+void qmp_migrate_set_downtime(double value, Error **errp)
 {
-    double d;
-
-    d = qdict_get_double(qdict, "value") * 1e9;
-    d = MAX(0, MIN(UINT64_MAX, d));
-    max_downtime = (uint64_t)d;
-
-    return 0;
+    value *= 1e9;
+    value = MAX(0, MIN(UINT64_MAX, value));
+    max_downtime = (uint64_t)value;
 }
diff --git a/migration.h b/migration.h
index ff2e40b..539f8f1 100644
--- a/migration.h
+++ b/migration.h
@@ -46,9 +46,6 @@ int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
 uint64_t migrate_max_downtime(void);
 
-int do_migrate_set_downtime(Monitor *mon, const QDict *qdict,
-                            QObject **ret_data);
-
 void do_info_migrate_print(Monitor *mon, const QObject *data);
 
 void do_info_migrate(Monitor *mon, QObject **ret_data);
diff --git a/qapi-schema.json b/qapi-schema.json
index d638f12..d9b9fa1 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1140,3 +1140,16 @@
 # Since: 0.14.0
 ##
 { 'command': 'migrate_cancel' }
+
+##
+# @migrate_set_downtime
+#
+# Set maximum tolerated downtime for migration.
+#
+# @value: maximum downtime in seconds
+#
+# Returns: nothing on success
+#
+# Since: 0.14.0
+##
+{ 'command': 'migrate_set_downtime', 'data': {'value': 'number'} }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 5eb4b76..b4cadeb 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -518,10 +518,7 @@ EQMP
     {
         .name       = "migrate_set_downtime",
         .args_type  = "value:T",
-        .params     = "value",
-        .help       = "set maximum tolerated downtime (in seconds) for migrations",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_migrate_set_downtime,
+        .mhandler.cmd_new = qmp_marshal_input_migrate_set_downtime,
     },
 
 SQMP
-- 
1.7.8.110.g4cb5d1.dirty

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

* [Qemu-devel] [PATCH 22/22] qapi: Convert migrate_set_speed
  2011-12-06 17:54 [Qemu-devel] [PULL 00/22]: QMP queue Luiz Capitulino
                   ` (20 preceding siblings ...)
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 21/22] qapi: Convert migrate_set_downtime Luiz Capitulino
@ 2011-12-06 17:54 ` Luiz Capitulino
  2011-12-12 16:34 ` [Qemu-devel] [PULL 00/22]: QMP queue Anthony Liguori
  22 siblings, 0 replies; 28+ messages in thread
From: Luiz Capitulino @ 2011-12-06 17:54 UTC (permalink / raw)
  To: aliguori; +Cc: qemu-devel

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 hmp-commands.hx  |    3 +--
 hmp.c            |    6 ++++++
 hmp.h            |    1 +
 migration.c      |   12 ++++--------
 migration.h      |    2 --
 qapi-schema.json |   15 +++++++++++++++
 qmp-commands.hx  |    5 +----
 7 files changed, 28 insertions(+), 16 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 6ba694d..fdbed15 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -786,8 +786,7 @@ ETEXI
         .params     = "value",
         .help       = "set maximum speed (in bytes) for migrations. "
 	"Defaults to MB if no size suffix is specified, ie. B/K/M/G/T",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_migrate_set_speed,
+        .mhandler.cmd = hmp_migrate_set_speed,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index 04e6b73..e7659d5 100644
--- a/hmp.c
+++ b/hmp.c
@@ -673,3 +673,9 @@ void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict)
     double value = qdict_get_double(qdict, "value");
     qmp_migrate_set_downtime(value, NULL);
 }
+
+void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict)
+{
+    int64_t value = qdict_get_int(qdict, "value");
+    qmp_migrate_set_speed(value, NULL);
+}
diff --git a/hmp.h b/hmp.h
index 9182622..093242d 100644
--- a/hmp.h
+++ b/hmp.h
@@ -48,5 +48,6 @@ void hmp_block_resize(Monitor *mon, const QDict *qdict);
 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);
 
 #endif
diff --git a/migration.c b/migration.c
index a563162..75d4f02 100644
--- a/migration.c
+++ b/migration.c
@@ -473,21 +473,17 @@ void qmp_migrate_cancel(Error **errp)
     migrate_fd_cancel(migrate_get_current());
 }
 
-int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void qmp_migrate_set_speed(int64_t value, Error **errp)
 {
-    int64_t d;
     MigrationState *s;
 
-    d = qdict_get_int(qdict, "value");
-    if (d < 0) {
-        d = 0;
+    if (value < 0) {
+        value = 0;
     }
 
     s = migrate_get_current();
-    s->bandwidth_limit = d;
+    s->bandwidth_limit = value;
     qemu_file_set_rate_limit(s->file, s->bandwidth_limit);
-
-    return 0;
 }
 
 void qmp_migrate_set_downtime(double value, Error **errp)
diff --git a/migration.h b/migration.h
index 539f8f1..999d60f 100644
--- a/migration.h
+++ b/migration.h
@@ -42,8 +42,6 @@ int qemu_start_incoming_migration(const char *uri);
 
 int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
-int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data);
-
 uint64_t migrate_max_downtime(void);
 
 void do_info_migrate_print(Monitor *mon, const QObject *data);
diff --git a/qapi-schema.json b/qapi-schema.json
index d9b9fa1..f358b49 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1153,3 +1153,18 @@
 # Since: 0.14.0
 ##
 { 'command': 'migrate_set_downtime', 'data': {'value': 'number'} }
+
+##
+# @migrate_set_speed
+#
+# Set maximum speed for migration.
+#
+# @value: maximum speed in bytes.
+#
+# Returns: nothing on success
+#
+# Notes: A value lesser than zero will be automatically round up to zero.
+#
+# Since: 0.14.0
+##
+{ 'command': 'migrate_set_speed', 'data': {'value': 'int'} }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index b4cadeb..002e7e8 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -492,10 +492,7 @@ EQMP
     {
         .name       = "migrate_set_speed",
         .args_type  = "value:o",
-        .params     = "value",
-        .help       = "set maximum speed (in bytes) for migrations",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_migrate_set_speed,
+        .mhandler.cmd_new = qmp_marshal_input_migrate_set_speed,
     },
 
 SQMP
-- 
1.7.8.110.g4cb5d1.dirty

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

* Re: [Qemu-devel] [PULL 00/22]: QMP queue
  2011-12-06 17:54 [Qemu-devel] [PULL 00/22]: QMP queue Luiz Capitulino
                   ` (21 preceding siblings ...)
  2011-12-06 17:54 ` [Qemu-devel] [PATCH 22/22] qapi: Convert migrate_set_speed Luiz Capitulino
@ 2011-12-12 16:34 ` Anthony Liguori
  22 siblings, 0 replies; 28+ messages in thread
From: Anthony Liguori @ 2011-12-12 16:34 UTC (permalink / raw)
  To: Luiz Capitulino; +Cc: qemu-devel

On 12/06/2011 11:54 AM, Luiz Capitulino wrote:
> Anthony,
>
> This pull request contains my round 3 QAPI conversion patches, the new QMP
> visitor tests, some documentation and the qmp test tool.
>
> The changes (since 217bfb445b54db618a30f3a39170bebd9fd9dbf2) are available
> in the following repository:
>
>      git://repo.or.cz/qemu/qmp-unstable.git queue/qmp

Pulled.  Thanks.

Regards,

Anthony Liguori

>
> Luiz Capitulino (21):
>        docs: Add writing-qmp-commands.txt
>        configure: Don't mix glib and libcheck tests
>        Introduce test-qmp-output-visitor
>        Introduce test-qmp-input-visitor
>        Drop test-visitor
>        qapi: Complete system_powerdown conversion
>        console: Drop unused prototypes
>        QError: Introduce QERR_IO_ERROR
>        qapi: Convert memsave
>        qapi: Convert pmemsave
>        qapi: Convert cont
>        qapi: Convert inject-nmi
>        qapi: Convert set_link
>        qapi: Convert block_passwd
>        qapi: Convert balloon
>        qapi: Convert block_resize
>        qapi: Convert blockdev_snapshot_sync
>        qapi: Convert human-monitor-command
>        qapi: Convert migrate_cancel
>        qapi: Convert migrate_set_downtime
>        qapi: Convert migrate_set_speed
>
> Mark Wu (1):
>        qmp: add test tool for QMP
>
>   Makefile                      |    9 +-
>   QMP/qmp                       |  126 ++++++++
>   balloon.c                     |   28 +--
>   balloon.h                     |    3 -
>   blockdev.c                    |   89 +++----
>   blockdev.h                    |    4 -
>   configure                     |    5 +-
>   console.h                     |    2 -
>   cpus.c                        |   90 ++++++
>   docs/writing-qmp-commands.txt |  642 +++++++++++++++++++++++++++++++++++++++++
>   hmp-commands.hx               |   36 +--
>   hmp.c                         |  148 ++++++++++
>   hmp.h                         |   12 +
>   migration.c                   |   28 +--
>   migration.h                   |    7 -
>   monitor.c                     |  201 ++-----------
>   monitor.h                     |    3 +
>   net.c                         |   10 +-
>   net.h                         |    1 -
>   qapi-schema-test.json         |    6 +
>   qapi-schema.json              |  267 +++++++++++++++++
>   qerror.c                      |    4 +
>   qerror.h                      |    3 +
>   qmp-commands.hx               |   77 +----
>   qmp.c                         |   37 +++
>   test-qmp-input-visitor.c      |  270 +++++++++++++++++
>   test-qmp-output-visitor.c     |  423 +++++++++++++++++++++++++++
>   test-visitor.c                |  338 ----------------------
>   28 files changed, 2153 insertions(+), 716 deletions(-)
>
>
>

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

* [Qemu-devel] [PULL 00/22] QMP queue
@ 2014-02-13 15:30 Luiz Capitulino
  2014-02-15 15:36 ` Peter Maydell
  0 siblings, 1 reply; 28+ messages in thread
From: Luiz Capitulino @ 2014-02-13 15:30 UTC (permalink / raw)
  To: peter.maydell; +Cc: qemu-devel, anthony

The following changes since commit 9d74f6fef0801ca2ce5c9d38d59b85bf03c27669:

  Merge remote-tracking branch 'remotes/alon/pull-libcacard.glusterfs' into staging (2014-02-12 17:53:31 +0000)

are available in the git repository at:


  git://repo.or.cz/qemu/qmp-unstable.git queue/qmp

for you to fetch changes up to ebdc5cbd04a47af74f8b853f8ec95ab6291c7b53:

  monitor: Add object_add class argument completion. (2014-02-13 08:49:35 -0500)

----------------------------------------------------------------
Ekaterina Tumanova (1):
      dump: Define the architecture for compressed dump format.

Hani Benhabiles (4):
      monitor: Add device_del id argument completion.
      monitor: Add device_add device argument completion.
      monitor: Add object_del id argument completion.
      monitor: Add object_add class argument completion.

Markus Armbruster (1):
      Use error_is_set() only when necessary

Martin Kletzander (1):
      qmp: expose list of supported character device backends

Soramichi AKIYAMA (1):
      hmp: migrate command (without -d) now blocks correctly

Stefan Hajnoczi (1):
      QMP: allow JSON dict arguments in qmp-shell

qiaonuohan (13):
      dump: const-qualify the buf of WriteCoreDumpFunction
      dump: add argument to write_elfxx_notes
      dump: add API to write header of flatten format
      dump: add API to write vmcore
      dump: add API to write elf notes to buffer
      dump: add support for lzo/snappy
      dump: add members to DumpState and init some of them
      dump: add API to write dump header
      dump: add API to write dump_bitmap
      dump: add APIs to operate DataCache
      dump: add API to write dump pages
      dump: make kdump-compressed format available for 'dump-guest-memory'
      dump: add 'query-dump-guest-memory-capability' command

 block.c                            |  16 +-
 block/blkdebug.c                   |   4 +-
 block/blkverify.c                  |   2 +-
 block/curl.c                       |   2 +-
 block/gluster.c                    |   2 +-
 block/iscsi.c                      |   2 +-
 block/nbd.c                        |   2 +-
 block/qapi.c                       |   4 +-
 block/qcow2.c                      |   6 +-
 block/raw-posix.c                  |  12 +-
 block/raw-win32.c                  |   4 +-
 block/raw_bsd.c                    |   2 +-
 block/rbd.c                        |   2 +-
 block/sheepdog.c                   |   2 +-
 block/snapshot.c                   |   2 +-
 block/vvfat.c                      |   2 +-
 blockdev.c                         |  42 +-
 blockjob.c                         |   4 +-
 configure                          |  54 +++
 dump.c                             | 960 ++++++++++++++++++++++++++++++++++++-
 hmp.c                              |  16 +-
 hw/pci/pci-hotplug-old.c           |   4 +-
 hw/usb/dev-network.c               |   2 +-
 include/qom/cpu.h                  |   3 +-
 include/sysemu/dump.h              | 138 ++++++
 monitor.c                          |  95 ++++
 net/net.c                          |  12 +-
 qapi-schema.json                   |  71 ++-
 qdev-monitor.c                     |   2 +-
 qemu-char.c                        |  25 +-
 qemu-img.c                         |   8 +-
 qga/commands-posix.c               |  18 +-
 qga/commands-win32.c               |   2 +-
 qmp-commands.hx                    |  68 ++-
 savevm.c                           |   4 +-
 scripts/qmp/qmp-shell              |   3 +
 target-i386/cpu.h                  |   2 +
 target-s390x/cpu.h                 |   1 +
 tests/test-qmp-input-strict.c      |  16 +-
 tests/test-qmp-input-visitor.c     |  20 +-
 tests/test-qmp-output-visitor.c    |  22 +-
 tests/test-string-input-visitor.c  |  20 +-
 tests/test-string-output-visitor.c |  14 +-
 tpm.c                              |   2 +-
 util/qemu-config.c                 |  16 +-
 util/qemu-option.c                 |  22 +-
 vl.c                               |   2 +-
 47 files changed, 1557 insertions(+), 177 deletions(-)

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

* Re: [Qemu-devel] [PULL 00/22] QMP queue
  2014-02-13 15:30 [Qemu-devel] [PULL 00/22] " Luiz Capitulino
@ 2014-02-15 15:36 ` Peter Maydell
  2014-02-17 17:46   ` Luiz Capitulino
  0 siblings, 1 reply; 28+ messages in thread
From: Peter Maydell @ 2014-02-15 15:36 UTC (permalink / raw)
  To: Luiz Capitulino; +Cc: QEMU Developers, Anthony Liguori

On 13 February 2014 15:30, Luiz Capitulino <lcapitulino@redhat.com> wrote:
> The following changes since commit 9d74f6fef0801ca2ce5c9d38d59b85bf03c27669:
>
>   Merge remote-tracking branch 'remotes/alon/pull-libcacard.glusterfs' into staging (2014-02-12 17:53:31 +0000)
>
> are available in the git repository at:
>
>
>   git://repo.or.cz/qemu/qmp-unstable.git queue/qmp
>
> for you to fetch changes up to ebdc5cbd04a47af74f8b853f8ec95ab6291c7b53:
>
>   monitor: Add object_add class argument completion. (2014-02-13 08:49:35 -0500)

Hi. This doesn't build on 32 bit hosts, I'm afraid:

  CC    aarch64-softmmu/dump.o
/root/qemu/dump.c: In function 'write_dump_pages':
/root/qemu/dump.c:1356:21: error: passing argument 2 of 'compress2'
from incompatible pointer type [-Werror]
In file included from /root/qemu/dump.c:28:0:
/usr/include/zlib.h:1157:12: note: expected 'uLongf *' but argument is
of type 'size_t *'
cc1: all warnings being treated as errors

thanks
-- PMM

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

* Re: [Qemu-devel] [PULL 00/22] QMP queue
  2014-02-15 15:36 ` Peter Maydell
@ 2014-02-17 17:46   ` Luiz Capitulino
  2014-02-20 13:07     ` Peter Maydell
  0 siblings, 1 reply; 28+ messages in thread
From: Luiz Capitulino @ 2014-02-17 17:46 UTC (permalink / raw)
  To: Peter Maydell; +Cc: QEMU Developers, Anthony Liguori

On Sat, 15 Feb 2014 15:36:05 +0000
Peter Maydell <peter.maydell@linaro.org> wrote:

> On 13 February 2014 15:30, Luiz Capitulino <lcapitulino@redhat.com> wrote:
> > The following changes since commit 9d74f6fef0801ca2ce5c9d38d59b85bf03c27669:
> >
> >   Merge remote-tracking branch 'remotes/alon/pull-libcacard.glusterfs' into staging (2014-02-12 17:53:31 +0000)
> >
> > are available in the git repository at:
> >
> >
> >   git://repo.or.cz/qemu/qmp-unstable.git queue/qmp
> >
> > for you to fetch changes up to ebdc5cbd04a47af74f8b853f8ec95ab6291c7b53:
> >
> >   monitor: Add object_add class argument completion. (2014-02-13 08:49:35 -0500)
> 
> Hi. This doesn't build on 32 bit hosts, I'm afraid:
> 
>   CC    aarch64-softmmu/dump.o
> /root/qemu/dump.c: In function 'write_dump_pages':
> /root/qemu/dump.c:1356:21: error: passing argument 2 of 'compress2'
> from incompatible pointer type [-Werror]
> In file included from /root/qemu/dump.c:28:0:
> /usr/include/zlib.h:1157:12: note: expected 'uLongf *' but argument is
> of type 'size_t *'
> cc1: all warnings being treated as errors

I dropped the offending series, can you try again please?

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

* Re: [Qemu-devel] [PULL 00/22] QMP queue
  2014-02-17 17:46   ` Luiz Capitulino
@ 2014-02-20 13:07     ` Peter Maydell
  0 siblings, 0 replies; 28+ messages in thread
From: Peter Maydell @ 2014-02-20 13:07 UTC (permalink / raw)
  To: Luiz Capitulino; +Cc: QEMU Developers, Anthony Liguori

On 17 February 2014 17:46, Luiz Capitulino <lcapitulino@redhat.com> wrote:
> On Sat, 15 Feb 2014 15:36:05 +0000
> Peter Maydell <peter.maydell@linaro.org> wrote:
>
>> On 13 February 2014 15:30, Luiz Capitulino <lcapitulino@redhat.com> wrote:
>> > The following changes since commit 9d74f6fef0801ca2ce5c9d38d59b85bf03c27669:
>> >
>> >   Merge remote-tracking branch 'remotes/alon/pull-libcacard.glusterfs' into staging (2014-02-12 17:53:31 +0000)
>> >
>> > are available in the git repository at:
>> >
>> >
>> >   git://repo.or.cz/qemu/qmp-unstable.git queue/qmp
>> >
>> > for you to fetch changes up to ebdc5cbd04a47af74f8b853f8ec95ab6291c7b53:
>> >
>> >   monitor: Add object_add class argument completion. (2014-02-13 08:49:35 -0500)
>>
>> Hi. This doesn't build on 32 bit hosts, I'm afraid:
>>
>>   CC    aarch64-softmmu/dump.o
>> /root/qemu/dump.c: In function 'write_dump_pages':
>> /root/qemu/dump.c:1356:21: error: passing argument 2 of 'compress2'
>> from incompatible pointer type [-Werror]
>> In file included from /root/qemu/dump.c:28:0:
>> /usr/include/zlib.h:1157:12: note: expected 'uLongf *' but argument is
>> of type 'size_t *'
>> cc1: all warnings being treated as errors
>
> I dropped the offending series, can you try again please?

Updated branch applied, thanks.

-- PMM

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

end of thread, other threads:[~2014-02-20 13:08 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-12-06 17:54 [Qemu-devel] [PULL 00/22]: QMP queue Luiz Capitulino
2011-12-06 17:54 ` [Qemu-devel] [PATCH 01/22] docs: Add writing-qmp-commands.txt Luiz Capitulino
2011-12-06 17:54 ` [Qemu-devel] [PATCH 02/22] qmp: add test tool for QMP Luiz Capitulino
2011-12-06 17:54 ` [Qemu-devel] [PATCH 03/22] configure: Don't mix glib and libcheck tests Luiz Capitulino
2011-12-06 17:54 ` [Qemu-devel] [PATCH 04/22] Introduce test-qmp-output-visitor Luiz Capitulino
2011-12-06 17:54 ` [Qemu-devel] [PATCH 05/22] Introduce test-qmp-input-visitor Luiz Capitulino
2011-12-06 17:54 ` [Qemu-devel] [PATCH 06/22] Drop test-visitor Luiz Capitulino
2011-12-06 17:54 ` [Qemu-devel] [PATCH 07/22] qapi: Complete system_powerdown conversion Luiz Capitulino
2011-12-06 17:54 ` [Qemu-devel] [PATCH 08/22] console: Drop unused prototypes Luiz Capitulino
2011-12-06 17:54 ` [Qemu-devel] [PATCH 09/22] QError: Introduce QERR_IO_ERROR Luiz Capitulino
2011-12-06 17:54 ` [Qemu-devel] [PATCH 10/22] qapi: Convert memsave Luiz Capitulino
2011-12-06 17:54 ` [Qemu-devel] [PATCH 11/22] qapi: Convert pmemsave Luiz Capitulino
2011-12-06 17:54 ` [Qemu-devel] [PATCH 12/22] qapi: Convert cont Luiz Capitulino
2011-12-06 17:54 ` [Qemu-devel] [PATCH 13/22] qapi: Convert inject-nmi Luiz Capitulino
2011-12-06 17:54 ` [Qemu-devel] [PATCH 14/22] qapi: Convert set_link Luiz Capitulino
2011-12-06 17:54 ` [Qemu-devel] [PATCH 15/22] qapi: Convert block_passwd Luiz Capitulino
2011-12-06 17:54 ` [Qemu-devel] [PATCH 16/22] qapi: Convert balloon Luiz Capitulino
2011-12-06 17:54 ` [Qemu-devel] [PATCH 17/22] qapi: Convert block_resize Luiz Capitulino
2011-12-06 17:54 ` [Qemu-devel] [PATCH 18/22] qapi: Convert blockdev_snapshot_sync Luiz Capitulino
2011-12-06 17:54 ` [Qemu-devel] [PATCH 19/22] qapi: Convert human-monitor-command Luiz Capitulino
2011-12-06 17:54 ` [Qemu-devel] [PATCH 20/22] qapi: Convert migrate_cancel Luiz Capitulino
2011-12-06 17:54 ` [Qemu-devel] [PATCH 21/22] qapi: Convert migrate_set_downtime Luiz Capitulino
2011-12-06 17:54 ` [Qemu-devel] [PATCH 22/22] qapi: Convert migrate_set_speed Luiz Capitulino
2011-12-12 16:34 ` [Qemu-devel] [PULL 00/22]: QMP queue Anthony Liguori
  -- strict thread matches above, loose matches on Subject: below --
2014-02-13 15:30 [Qemu-devel] [PULL 00/22] " Luiz Capitulino
2014-02-15 15:36 ` Peter Maydell
2014-02-17 17:46   ` Luiz Capitulino
2014-02-20 13:07     ` Peter Maydell

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).