[Qemu-devel] [PATCH V10 06/15] monitor: call sortcmdlist() only one time

2013-08-27 Thread Wenchao Xia
It doesn't need to be done for every monitor, so change it.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
---
 monitor.c |3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/monitor.c b/monitor.c
index fffb434..db4d441 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4762,6 +4762,7 @@ void monitor_init(CharDriverState *chr, int flags)
 
 if (is_first_init) {
 monitor_protocol_event_init();
+sortcmdlist();
 is_first_init = 0;
 }
 
@@ -4791,8 +4792,6 @@ void monitor_init(CharDriverState *chr, int flags)
 QLIST_INSERT_HEAD(mon_list, mon, entry);
 if (!default_mon || (flags  MONITOR_IS_DEFAULT))
 default_mon = mon;
-
-sortcmdlist();
 }
 
 static void bdrv_password_cb(Monitor *mon, const char *password, void *opaque)
-- 
1.7.1





[Qemu-devel] [PATCH V10 12/15] monitor: refine monitor_find_completion()

2013-08-27 Thread Wenchao Xia
In order to support sub command in auto completion, a reentrant function
is needed, so monitor_find_completion() is split into two parts. The
first part does parsing of user input which need to be done only once,
the second part does the auto completion job according to the parsing
result, which contains the necessary code to support sub command and
works as the reentrant function. The global info_cmds is still used
in second part, which will be replaced by sub command code later.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
Reviewed-by: Eric Blake ebl...@redhat.com
---
 monitor.c |   65 
 1 files changed, 39 insertions(+), 26 deletions(-)

diff --git a/monitor.c b/monitor.c
index c8855d2..9d1b0cb 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4229,34 +4229,17 @@ static const char *next_arg_type(const char *typestr)
 return (p != NULL ? ++p : typestr);
 }
 
-static void monitor_find_completion(Monitor *mon,
-const char *cmdline)
+static void monitor_find_completion_by_table(Monitor *mon,
+ const mon_cmd_t *cmd_table,
+ char **args,
+ int nb_args)
 {
 const char *cmdname;
-char *args[MAX_ARGS];
-int nb_args, i, len;
+int i;
 const char *ptype, *str;
 const mon_cmd_t *cmd;
 MonitorBlockComplete mbs;
 
-if (parse_cmdline(cmdline, nb_args, args)  0) {
-return;
-}
-#ifdef DEBUG_COMPLETION
-for (i = 0; i  nb_args; i++) {
-monitor_printf(mon, arg%d = '%s'\n, i, args[i]);
-}
-#endif
-
-/* if the line ends with a space, it means we want to complete the
-   next arg */
-len = strlen(cmdline);
-if (len  0  qemu_isspace(cmdline[len - 1])) {
-if (nb_args = MAX_ARGS) {
-goto cleanup;
-}
-args[nb_args++] = g_strdup();
-}
 if (nb_args = 1) {
 /* command completion */
 if (nb_args == 0)
@@ -4264,18 +4247,18 @@ static void monitor_find_completion(Monitor *mon,
 else
 cmdname = args[0];
 readline_set_completion_index(mon-rs, strlen(cmdname));
-for (cmd = mon-cmd_table; cmd-name != NULL; cmd++) {
+for (cmd = cmd_table; cmd-name != NULL; cmd++) {
 cmd_completion(mon, cmdname, cmd-name);
 }
 } else {
 /* find the command */
-for (cmd = mon-cmd_table; cmd-name != NULL; cmd++) {
+for (cmd = cmd_table; cmd-name != NULL; cmd++) {
 if (compare_cmd(args[0], cmd-name)) {
 break;
 }
 }
 if (!cmd-name) {
-goto cleanup;
+return;
 }
 
 ptype = next_arg_type(cmd-args_type);
@@ -4320,7 +4303,7 @@ static void monitor_find_completion(Monitor *mon,
 }
 } else if (!strcmp(cmd-name, help|?)) {
 readline_set_completion_index(mon-rs, strlen(str));
-for (cmd = mon-cmd_table; cmd-name != NULL; cmd++) {
+for (cmd = cmd_table; cmd-name != NULL; cmd++) {
 cmd_completion(mon, str, cmd-name);
 }
 }
@@ -4329,6 +4312,36 @@ static void monitor_find_completion(Monitor *mon,
 break;
 }
 }
+}
+
+static void monitor_find_completion(Monitor *mon,
+const char *cmdline)
+{
+char *args[MAX_ARGS];
+int nb_args, len;
+
+/* 1. parse the cmdline */
+if (parse_cmdline(cmdline, nb_args, args)  0) {
+return;
+}
+#ifdef DEBUG_COMPLETION
+for (i = 0; i  nb_args; i++) {
+monitor_printf(mon, arg%d = '%s'\n, i, args[i]);
+}
+#endif
+
+/* if the line ends with a space, it means we want to complete the
+   next arg */
+len = strlen(cmdline);
+if (len  0  qemu_isspace(cmdline[len - 1])) {
+if (nb_args = MAX_ARGS) {
+goto cleanup;
+}
+args[nb_args++] = g_strdup();
+}
+
+/* 2. auto complete according to args */
+monitor_find_completion_by_table(mon, mon-cmd_table, args, nb_args);
 
 cleanup:
 free_cmdline_args(args, nb_args);
-- 
1.7.1





[Qemu-devel] [PATCH V10 04/15] monitor: avoid use of global *cur_mon in monitor_find_completion()

2013-08-27 Thread Wenchao Xia
Parameter *mon is added, and local variable *mon added in previous patch
is removed. The caller readline_completion(), pass rs-mon as value, which
should be initialized in readline_init() called by monitor_init().

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
Reviewed-by: Eric Blake ebl...@redhat.com
---
 include/monitor/readline.h |3 ++-
 monitor.c  |   18 +-
 readline.c |2 +-
 3 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/include/monitor/readline.h b/include/monitor/readline.h
index fc9806e..0faf6e1 100644
--- a/include/monitor/readline.h
+++ b/include/monitor/readline.h
@@ -8,7 +8,8 @@
 #define READLINE_MAX_COMPLETIONS 256
 
 typedef void ReadLineFunc(Monitor *mon, const char *str, void *opaque);
-typedef void ReadLineCompletionFunc(const char *cmdline);
+typedef void ReadLineCompletionFunc(Monitor *mon,
+const char *cmdline);
 
 typedef struct ReadLineState {
 char cmd_buf[READLINE_CMD_BUF_SIZE + 1];
diff --git a/monitor.c b/monitor.c
index d1a6bda..fffb434 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4140,20 +4140,20 @@ static const char *next_arg_type(const char *typestr)
 return (p != NULL ? ++p : typestr);
 }
 
-static void monitor_find_completion(const char *cmdline)
+static void monitor_find_completion(Monitor *mon,
+const char *cmdline)
 {
 const char *cmdname;
 char *args[MAX_ARGS];
 int nb_args, i, len;
 const char *ptype, *str;
 const mon_cmd_t *cmd;
-Monitor *mon = cur_mon;
 MonitorBlockComplete mbs;
 
 parse_cmdline(cmdline, nb_args, args);
 #ifdef DEBUG_COMPLETION
-for(i = 0; i  nb_args; i++) {
-monitor_printf(cur_mon, arg%d = '%s'\n, i, (char *)args[i]);
+for (i = 0; i  nb_args; i++) {
+monitor_printf(mon, arg%d = '%s'\n, i, args[i]);
 }
 #endif
 
@@ -4172,7 +4172,7 @@ static void monitor_find_completion(const char *cmdline)
 cmdname = ;
 else
 cmdname = args[0];
-readline_set_completion_index(cur_mon-rs, strlen(cmdname));
+readline_set_completion_index(mon-rs, strlen(cmdname));
 for(cmd = mon_cmds; cmd-name != NULL; cmd++) {
 cmd_completion(mon, cmdname, cmd-name);
 }
@@ -4202,7 +4202,7 @@ static void monitor_find_completion(const char *cmdline)
 switch(*ptype) {
 case 'F':
 /* file completion */
-readline_set_completion_index(cur_mon-rs, strlen(str));
+readline_set_completion_index(mon-rs, strlen(str));
 file_completion(mon, str);
 break;
 case 'B':
@@ -4215,7 +4215,7 @@ static void monitor_find_completion(const char *cmdline)
 case 's':
 /* XXX: more generic ? */
 if (!strcmp(cmd-name, info)) {
-readline_set_completion_index(cur_mon-rs, strlen(str));
+readline_set_completion_index(mon-rs, strlen(str));
 for(cmd = info_cmds; cmd-name != NULL; cmd++) {
 cmd_completion(mon, str, cmd-name);
 }
@@ -4223,12 +4223,12 @@ static void monitor_find_completion(const char *cmdline)
 char *sep = strrchr(str, '-');
 if (sep)
 str = sep + 1;
-readline_set_completion_index(cur_mon-rs, strlen(str));
+readline_set_completion_index(mon-rs, strlen(str));
 for (i = 0; i  Q_KEY_CODE_MAX; i++) {
 cmd_completion(mon, str, QKeyCode_lookup[i]);
 }
 } else if (!strcmp(cmd-name, help|?)) {
-readline_set_completion_index(cur_mon-rs, strlen(str));
+readline_set_completion_index(mon-rs, strlen(str));
 for (cmd = mon_cmds; cmd-name != NULL; cmd++) {
 cmd_completion(mon, str, cmd-name);
 }
diff --git a/readline.c b/readline.c
index 1c0f7ee..c91b324 100644
--- a/readline.c
+++ b/readline.c
@@ -285,7 +285,7 @@ static void readline_completion(ReadLineState *rs)
 cmdline = g_malloc(rs-cmd_buf_index + 1);
 memcpy(cmdline, rs-cmd_buf, rs-cmd_buf_index);
 cmdline[rs-cmd_buf_index] = '\0';
-rs-completion_finder(cmdline);
+rs-completion_finder(rs-mon, cmdline);
 g_free(cmdline);
 
 /* no completion found */
-- 
1.7.1





[Qemu-devel] [PATCH V10 02/15] monitor: avoid use of global *cur_mon in file_completion()

2013-08-27 Thread Wenchao Xia
Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
Reviewed-by: Eric Blake ebl...@redhat.com
---
 monitor.c |8 
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/monitor.c b/monitor.c
index 31b527d..a59a402 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4034,7 +4034,7 @@ static void cmd_completion(Monitor *mon, const char 
*name, const char *list)
 }
 }
 
-static void file_completion(const char *input)
+static void file_completion(Monitor *mon, const char *input)
 {
 DIR *ffs;
 struct dirent *d;
@@ -4057,7 +4057,7 @@ static void file_completion(const char *input)
 pstrcpy(file_prefix, sizeof(file_prefix), p + 1);
 }
 #ifdef DEBUG_COMPLETION
-monitor_printf(cur_mon, input='%s' path='%s' prefix='%s'\n,
+monitor_printf(mon, input='%s' path='%s' prefix='%s'\n,
input, path, file_prefix);
 #endif
 ffs = opendir(path);
@@ -4084,7 +4084,7 @@ static void file_completion(const char *input)
 if (stat(file, sb) == 0  S_ISDIR(sb.st_mode)) {
 pstrcat(file, sizeof(file), /);
 }
-readline_add_completion(cur_mon-rs, file);
+readline_add_completion(mon-rs, file);
 }
 }
 closedir(ffs);
@@ -4195,7 +4195,7 @@ static void monitor_find_completion(const char *cmdline)
 case 'F':
 /* file completion */
 readline_set_completion_index(cur_mon-rs, strlen(str));
-file_completion(str);
+file_completion(mon, str);
 break;
 case 'B':
 /* block device name completion */
-- 
1.7.1





[Qemu-devel] [PATCH V10 14/15] monitor: allow help show message for single command in sub group

2013-08-27 Thread Wenchao Xia
A new parameter type 'S' is introduced to allow user input any string.
help info block works normal now.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
Reviewed-by: Eric Blake ebl...@redhat.com
---
 hmp-commands.hx |2 +-
 monitor.c   |   27 +++
 2 files changed, 28 insertions(+), 1 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 8c6b91a..c161fe9 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -11,7 +11,7 @@ ETEXI
 
 {
 .name   = help|?,
-.args_type  = name:s?,
+.args_type  = name:S?,
 .params = [cmd],
 .help   = show the help,
 .mhandler.cmd = do_help_cmd,
diff --git a/monitor.c b/monitor.c
index d3f357c..81f41e6 100644
--- a/monitor.c
+++ b/monitor.c
@@ -83,6 +83,7 @@
  * 'F'  filename
  * 'B'  block device name
  * 's'  string (accept optional quote)
+ * 'S'  it just appends the rest of the string (accept optional quote)
  * 'O'  option string of the form NAME=VALUE,...
  *  parsed according to QemuOptsList given by its name
  *  Example: 'device:O' uses qemu_device_opts.
@@ -4046,6 +4047,31 @@ static const mon_cmd_t *monitor_parse_command(Monitor 
*mon,
 }
 }
 break;
+case 'S':
+{
+/* package all remaining string */
+int len;
+
+while (qemu_isspace(*p)) {
+p++;
+}
+if (*typestr == '?') {
+typestr++;
+if (*p == '\0') {
+/* no remaining string: NULL argument */
+break;
+}
+}
+len = strlen(p);
+if (len = 0) {
+monitor_printf(mon, %s: string expected\n,
+   cmdname);
+break;
+}
+qdict_put(qdict, key, qstring_from_str(p));
+p += len;
+}
+break;
 default:
 bad_type:
 monitor_printf(mon, %s: unknown type '%c'\n, cmdname, c);
@@ -4293,6 +4319,7 @@ static void monitor_find_completion_by_table(Monitor *mon,
 bdrv_iterate(block_completion_it, mbs);
 break;
 case 's':
+case 'S':
 if (!strcmp(cmd-name, sendkey)) {
 char *sep = strrchr(str, '-');
 if (sep)
-- 
1.7.1





[Qemu-devel] [PATCH V10 07/15] monitor: split off monitor_data_init()

2013-08-27 Thread Wenchao Xia
In qmp_human_monitor_command(), the monitor need to initialized for
basic functionalities, and later more init code will be added, so
split off this function. Note that it is different with QMP mode
monitor which accept json string from monitor's input,
qmp_human_monitor_command() retrieve the human style command from
QMP input, then send the command to a normal mode monitor.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
---
 monitor.c |   20 +++-
 1 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/monitor.c b/monitor.c
index db4d441..bd02112 100644
--- a/monitor.c
+++ b/monitor.c
@@ -683,14 +683,24 @@ static int do_qmp_capabilities(Monitor *mon, const QDict 
*params,
 
 static void handle_user_command(Monitor *mon, const char *cmdline);
 
+static void monitor_data_init(Monitor *mon)
+{
+memset(mon, 0, sizeof(Monitor));
+mon-outbuf = qstring_new();
+}
+
+static void monitor_data_destroy(Monitor *mon)
+{
+QDECREF(mon-outbuf);
+}
+
 char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
 int64_t cpu_index, Error **errp)
 {
 char *output = NULL;
 Monitor *old_mon, hmp;
 
-memset(hmp, 0, sizeof(hmp));
-hmp.outbuf = qstring_new();
+monitor_data_init(hmp);
 hmp.skip_flush = true;
 
 old_mon = cur_mon;
@@ -716,7 +726,7 @@ char *qmp_human_monitor_command(const char *command_line, 
bool has_cpu_index,
 }
 
 out:
-QDECREF(hmp.outbuf);
+monitor_data_destroy(hmp);
 return output;
 }
 
@@ -4766,8 +4776,8 @@ void monitor_init(CharDriverState *chr, int flags)
 is_first_init = 0;
 }
 
-mon = g_malloc0(sizeof(*mon));
-mon-outbuf = qstring_new();
+mon = g_malloc(sizeof(*mon));
+monitor_data_init(mon);
 
 mon-chr = chr;
 mon-flags = flags;
-- 
1.7.1





[Qemu-devel] [PATCH V10 11/15] monitor: support sub command in help

2013-08-27 Thread Wenchao Xia
The old code in help_cmd() uses global 'info_cmds' and treats it as a
special case. Actually 'info_cmds' is a sub command group of 'mon_cmds',
in order to avoid direct use of it, help_cmd() needs to change its work
mechanism to support sub command and not treat it as a special case
any more.

To support sub command, help_cmd() will first parse the input and then call
help_cmd_dump(), which works as a reentrant function. When it meets a sub
command, it simply enters the function again. Since help dumping needs to
know whole input to printf full help message include prefix, for example,
help info block need to printf prefix info, so help_cmd_dump() takes all
args from input and extra parameter arg_index to identify the progress.
Another function help_cmd_dump_one() is introduced to printf the prefix
and command's help message.

Now help supports sub command, so later if another sub command group is
added in any depth, help will automatically work for it. Still help info
block will show error since command parser reject additional parameter,
which can be improved later. log is still treated as a special case.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
---
 monitor.c |   62 +++-
 1 files changed, 52 insertions(+), 10 deletions(-)

diff --git a/monitor.c b/monitor.c
index 2a9dfb2..c8855d2 100644
--- a/monitor.c
+++ b/monitor.c
@@ -880,33 +880,75 @@ static int parse_cmdline(const char *cmdline,
 return -1;
 }
 
+static void help_cmd_dump_one(Monitor *mon,
+  const mon_cmd_t *cmd,
+  char **prefix_args,
+  int prefix_args_nb)
+{
+int i;
+
+for (i = 0; i  prefix_args_nb; i++) {
+monitor_printf(mon, %s , prefix_args[i]);
+}
+monitor_printf(mon, %s %s -- %s\n, cmd-name, cmd-params, cmd-help);
+}
+
+/* @args[@arg_index] is the valid command need to find in @cmds */
 static void help_cmd_dump(Monitor *mon, const mon_cmd_t *cmds,
-  const char *prefix, const char *name)
+  char **args, int nb_args, int arg_index)
 {
 const mon_cmd_t *cmd;
 
-for(cmd = cmds; cmd-name != NULL; cmd++) {
-if (!name || !strcmp(name, cmd-name))
-monitor_printf(mon, %s%s %s -- %s\n, prefix, cmd-name,
-   cmd-params, cmd-help);
+/* No valid arg need to compare with, dump all in *cmds */
+if (arg_index = nb_args) {
+for (cmd = cmds; cmd-name != NULL; cmd++) {
+help_cmd_dump_one(mon, cmd, args, arg_index);
+}
+return;
+}
+
+/* Find one entry to dump */
+for (cmd = cmds; cmd-name != NULL; cmd++) {
+if (compare_cmd(args[arg_index], cmd-name)) {
+if (cmd-sub_table) {
+/* continue with next arg */
+help_cmd_dump(mon, cmd-sub_table,
+  args, nb_args, arg_index + 1);
+} else {
+help_cmd_dump_one(mon, cmd, args, arg_index);
+}
+break;
+}
 }
 }
 
 static void help_cmd(Monitor *mon, const char *name)
 {
-if (name  !strcmp(name, info)) {
-help_cmd_dump(mon, info_cmds, info , NULL);
-} else {
-help_cmd_dump(mon, mon-cmd_table, , name);
-if (name  !strcmp(name, log)) {
+char *args[MAX_ARGS];
+int nb_args = 0;
+
+/* 1. parse user input */
+if (name) {
+/* special case for log, directly dump and return */
+if (!strcmp(name, log)) {
 const QEMULogItem *item;
 monitor_printf(mon, Log items (comma separated):\n);
 monitor_printf(mon, %-10s %s\n, none, remove all logs);
 for (item = qemu_log_items; item-mask != 0; item++) {
 monitor_printf(mon, %-10s %s\n, item-name, item-help);
 }
+return;
+}
+
+if (parse_cmdline(name, nb_args, args)  0) {
+return;
 }
 }
+
+/* 2. dump the contents according to parsed args */
+help_cmd_dump(mon, mon-cmd_table, args, nb_args, 0);
+
+free_cmdline_args(args, nb_args);
 }
 
 static void do_help_cmd(Monitor *mon, const QDict *qdict)
-- 
1.7.1





[Qemu-devel] [PATCH V10 15/15] monitor: improve auto complete of help for single command in sub group

2013-08-27 Thread Wenchao Xia
Now special case help * in auto completion can work with sub commands,
such as help info u*.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
Reviewed-by: Eric Blake ebl...@redhat.com
---
 monitor.c |6 ++
 1 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/monitor.c b/monitor.c
index 81f41e6..8d07f9c 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4329,10 +4329,8 @@ static void monitor_find_completion_by_table(Monitor 
*mon,
 cmd_completion(mon, str, QKeyCode_lookup[i]);
 }
 } else if (!strcmp(cmd-name, help|?)) {
-readline_set_completion_index(mon-rs, strlen(str));
-for (cmd = cmd_table; cmd-name != NULL; cmd++) {
-cmd_completion(mon, str, cmd-name);
-}
+monitor_find_completion_by_table(mon, cmd_table,
+ args[1], nb_args - 1);
 }
 break;
 default:
-- 
1.7.1





[Qemu-devel] [PATCH V10 10/15] monitor: refine parse_cmdline()

2013-08-27 Thread Wenchao Xia
Since this function will be used by help_cmd() later, so improve
it to make it more generic and easier to use. free_cmdline_args()
is added too as paired function to free the result.

One change of this function is that, when the valid args in input
exceed the limit of MAX_ARGS, it fails now, instead of return with
MAX_ARGS of parsed args in old code. This should not impact much
since it is rare that user input many args in monitor's help and
auto complete scenario.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
Reviewed-by: Eric Blake ebl...@redhat.com
---
 monitor.c |   51 ---
 1 files changed, 40 insertions(+), 11 deletions(-)

diff --git a/monitor.c b/monitor.c
index 46191d3..2a9dfb2 100644
--- a/monitor.c
+++ b/monitor.c
@@ -821,9 +821,33 @@ static int get_str(char *buf, int buf_size, const char 
**pp)
 
 #define MAX_ARGS 16
 
-/* NOTE: this parser is an approximate form of the real command parser */
-static void parse_cmdline(const char *cmdline,
-  int *pnb_args, char **args)
+static void free_cmdline_args(char **args, int nb_args)
+{
+int i;
+
+assert(nb_args = MAX_ARGS);
+
+for (i = 0; i  nb_args; i++) {
+g_free(args[i]);
+}
+
+}
+
+/*
+ * Parse the command line to get valid args.
+ * @cmdline: command line to be parsed.
+ * @pnb_args: location to store the number of args, must NOT be NULL.
+ * @args: location to store the args, which should be freed by caller, must
+ *NOT be NULL.
+ *
+ * Returns 0 on success, negative on failure.
+ *
+ * NOTE: this parser is an approximate form of the real command parser. Number
+ *   of args have a limit of MAX_ARGS. If cmdline contains more, it will
+ *   return with failure.
+ */
+static int parse_cmdline(const char *cmdline,
+ int *pnb_args, char **args)
 {
 const char *p;
 int nb_args, ret;
@@ -839,16 +863,21 @@ static void parse_cmdline(const char *cmdline,
 break;
 }
 if (nb_args = MAX_ARGS) {
-break;
+goto fail;
 }
 ret = get_str(buf, sizeof(buf), p);
-args[nb_args] = g_strdup(buf);
-nb_args++;
 if (ret  0) {
-break;
+goto fail;
 }
+args[nb_args] = g_strdup(buf);
+nb_args++;
 }
 *pnb_args = nb_args;
+return 0;
+
+ fail:
+free_cmdline_args(args, nb_args);
+return -1;
 }
 
 static void help_cmd_dump(Monitor *mon, const mon_cmd_t *cmds,
@@ -4168,7 +4197,9 @@ static void monitor_find_completion(Monitor *mon,
 const mon_cmd_t *cmd;
 MonitorBlockComplete mbs;
 
-parse_cmdline(cmdline, nb_args, args);
+if (parse_cmdline(cmdline, nb_args, args)  0) {
+return;
+}
 #ifdef DEBUG_COMPLETION
 for (i = 0; i  nb_args; i++) {
 monitor_printf(mon, arg%d = '%s'\n, i, args[i]);
@@ -4258,9 +4289,7 @@ static void monitor_find_completion(Monitor *mon,
 }
 
 cleanup:
-for (i = 0; i  nb_args; i++) {
-g_free(args[i]);
-}
+free_cmdline_args(args, nb_args);
 }
 
 static int monitor_can_read(void *opaque)
-- 
1.7.1





Re: [Qemu-devel] [PATCH V9 00/15] monitor: support sub command group in auto completion and help

2013-08-27 Thread Wenchao Xia

于 2013-8-27 9:43, Wenchao Xia 写道:

于 2013-8-26 23:55, Luiz Capitulino 写道:

On Fri, 23 Aug 2013 16:17:52 +0800
Wenchao Xia xiaw...@linux.vnet.ibm.com wrote:


This series make auto completion and help functions works normal for sub
command, by using reentrant functions. In order to do that, global
variables
are not directly used in those functions any more. With this series,
cmd_table
is a member of structure Monitor so it is possible to create a
monitor with
different command table now, auto completion will work in that
monitor. In
short, info is not treated as a special case now, this series
ensure help
and auto complete function works normal for any sub command added in
the future.

Patch 5 replaced cur_mon with rs-mon, it is safe because:
monitor_init() calls readline_init() which initialize mon-rs, result is
mon-rs-mon == mon. Then qemu_chr_add_handlers() is called, which make
monitor_read() function take *mon as its opaque. Later, when user input,
monitor_read() is called, where cur_mon is set to *mon by cur_mon =
opaque.
If qemu's monitors run in one thread, then later in
readline_handle_byte()
and readline_comletion(), cur_mon is actually equal to rs-mon, in
another
word, it points to the monitor instance, so it is safe to replace
*cur_mon
in those functions.

Thanks for Luiz and Eric for reviewing.


This one doesn't even build :(

/home/lcapitulino/work/src/upstream/qmp-unstable/monitor.c: In
function ‘help_cmd’:
/home/lcapitulino/work/src/upstream/qmp-unstable/monitor.c:952:1:
error: label ‘cleanup’ defined but not used [-Werror=unused-label]
cc1: all warnings being treated as errors
make[1]: *** [monitor.o] Error 1
make[1]: *** Waiting for unfinished jobs
make: *** [subdir-x86_64-softmmu] Error 2


   Sorry for it, I missed that CC flag in my configure, will fix.
It would be great if you can share your configure settings.


  Respined v10 and tested with -Werror=unused-label, hope no other
issue is missed in my test.

--
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH V2 1/3] qemu-iotests: add unix socket help program

2013-08-27 Thread Wenchao Xia

于 2013-8-28 9:11, Eric Blake 写道:

On 08/26/2013 08:52 PM, Wenchao Xia wrote:

This program can do a sendmsg call to transfer fd with unix
socket, which is not supported in python2.

The built binary will not be deleted in clean, but it is a
existing issue in ./tests, which should be solved in another
patch.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
---



+++ b/tests/qemu-iotests/socket_scm_helper.c
@@ -0,0 +1,119 @@
+/*
+ * SCM_RIGHT with unix socket help program for test


s/SCM_RIGHT/S/


+
+static int send_fd(int fd, int fd_to_send, const char *data, size_t len)
+{
+struct msghdr msg;
+struct iovec iov[1];
+int ret;
+char control[CMSG_SPACE(sizeof(int))];
+struct cmsghdr *cmsg;
+
+if (fd  0) {
+fprintf(stderr, Socket fd is invalid.\n);
+return -1;
+}
+if (fd_to_send  0) {
+fprintf(stderr, Fd to send is invalid.\n);
+return -1;
+}
+if (data == NULL || len = 0) {


len cannot be  0, since it is size_t (or did you mean for it to be
ssize_t?)



+if (ret  0) {
+fprintf(stderr, Failed to send msg, reason: %s.\n, strerror(errno));


Messages typically shouldn't end with '.'; especially when ending the
message with strerror.


+}
+
+return ret;
+}
+
+/*
+ * To make things simple, the caller need to specify:


s/need/needs/


+ * 1. socket fd.
+ * 2. fd to send.
+ * 3. msg to send.
+ */
+int main(int argc, char **argv, char **envp)
+{
+int sock, fd, ret, buflen;
+const char *buf;
+#ifdef SOCKET_SCM_DEBUG
+int i;
+for (i = 0; i  argc; i++) {
+fprintf(stderr, Parameter %d: %s.\n, i, argv[i]);


Another useless ending '.' (and elsewhere throughout the patch)


+}
+#endif
+
+if (argc  4) {
+fprintf(stderr,
+Invalid parameter, use it as:\n
+%s SOCKET_FD FD_TO_SEND MSG.\n,
+argv[0]);


This rejects too few, but not too many, arguments.  Should the condition
be: if (argc != 4)


+return 1;


I prefer EXIT_FAILURE over the magic number 1 (multiple instances).


+}
+
+errno = 0;
+sock = strtol(argv[1], NULL, 10);


Failure to pass in a second argument means you cannot distinguish 
from 0 from 0a - all three input strings for argv[1] result in
sock==0 without you knowing any better.  If you're going to use
strtol(), use it correctly; if you don't care about garbage, then atoi()
is just as (in)correct and with less typing.


I will check error more carefully with other issues addressed in
next version. Since the build system is modified, I'd like to wait a
few days to see if more comment comes.


+if (errno) {
+fprintf(stderr, Failed in strtol for socket fd, reason: %s.\n,
+strerror(errno));
+return 1;
+}
+fd = strtol(argv[2], NULL, 10);
+if (errno) {
+fprintf(stderr, Failed in strtol for fd to send, reason: %s.\n,
+strerror(errno));
+return 1;
+}
+
+buf = argv[3];
+buflen = strlen(buf);
+
+ret = send_fd(sock, fd, buf, buflen);
+if (ret  0) {
+return 1;
+}
+return 0;


I prefer EXIT_SUCCESS over the magic number 0.


+}






--
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH V9 00/15] monitor: support sub command group in auto completion and help

2013-08-27 Thread Wenchao Xia

于 2013-8-27 21:19, Luiz Capitulino 写道:

On Tue, 27 Aug 2013 20:39:37 +0800
Wenchao Xia xiaw...@linux.vnet.ibm.com wrote:


于 2013-8-27 9:43, Wenchao Xia 写道:

于 2013-8-26 23:55, Luiz Capitulino 写道:

On Fri, 23 Aug 2013 16:17:52 +0800
Wenchao Xia xiaw...@linux.vnet.ibm.com wrote:


This series make auto completion and help functions works normal for sub
command, by using reentrant functions. In order to do that, global
variables
are not directly used in those functions any more. With this series,
cmd_table
is a member of structure Monitor so it is possible to create a
monitor with
different command table now, auto completion will work in that
monitor. In
short, info is not treated as a special case now, this series
ensure help
and auto complete function works normal for any sub command added in
the future.

Patch 5 replaced cur_mon with rs-mon, it is safe because:
monitor_init() calls readline_init() which initialize mon-rs, result is
mon-rs-mon == mon. Then qemu_chr_add_handlers() is called, which make
monitor_read() function take *mon as its opaque. Later, when user input,
monitor_read() is called, where cur_mon is set to *mon by cur_mon =
opaque.
If qemu's monitors run in one thread, then later in
readline_handle_byte()
and readline_comletion(), cur_mon is actually equal to rs-mon, in
another
word, it points to the monitor instance, so it is safe to replace
*cur_mon
in those functions.

Thanks for Luiz and Eric for reviewing.


This one doesn't even build :(

/home/lcapitulino/work/src/upstream/qmp-unstable/monitor.c: In
function ‘help_cmd’:
/home/lcapitulino/work/src/upstream/qmp-unstable/monitor.c:952:1:
error: label ‘cleanup’ defined but not used [-Werror=unused-label]
cc1: all warnings being treated as errors
make[1]: *** [monitor.o] Error 1
make[1]: *** Waiting for unfinished jobs
make: *** [subdir-x86_64-softmmu] Error 2


Sorry for it, I missed that CC flag in my configure, will fix.
It would be great if you can share your configure settings.


Respined v10 and tested with -Werror=unused-label, hope no other
issue is missed in my test.


My configure line doesn't have anything special:

  ../configure --target-list=x86_64-softmmu


  I used special cc warn flag before, it seems that by default more
flags would be set, will double check with default configure.

--
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH V8 00/13] monitor: support sub command group in auto completion and help

2013-08-27 Thread Wenchao Xia

于 2013-8-22 21:12, Luiz Capitulino 写道:

On Thu, 22 Aug 2013 17:16:23 +0800
Wenchao Xia xiaw...@linux.vnet.ibm.com wrote:


于 2013-8-20 22:04, Luiz Capitulino 写道:

On Tue, 30 Jul 2013 12:03:11 -0400
Luiz Capitulino lcapitul...@redhat.com wrote:


On Fri, 26 Jul 2013 11:20:29 +0800
Wenchao Xia xiaw...@linux.vnet.ibm.com wrote:


This series make auto completion and help functions works normal for sub
command, by using reentrant functions. In order to do that, global variables
are not directly used in those functions any more. With this series, cmd_table
is a member of structure Monitor so it is possible to create a monitor with
different command table now, auto completion will work in that monitor. In
short, info is not treated as a special case now, this series ensure help
and auto complete function works normal for any sub command added in the future.

Patch 5 replaced cur_mon with rs-mon, it is safe because:
monitor_init() calls readline_init() which initialize mon-rs, result is
mon-rs-mon == mon. Then qemu_chr_add_handlers() is called, which make
monitor_read() function take *mon as its opaque. Later, when user input,
monitor_read() is called, where cur_mon is set to *mon by cur_mon = opaque.
If qemu's monitors run in one thread, then later in readline_handle_byte()
and readline_comletion(), cur_mon is actually equal to rs-mon, in another
word, it points to the monitor instance, so it is safe to replace *cur_mon
in those functions.


I've applied this to qmp-next with the change I suggested for
patch 09/13.


Unfortunately this series brakes make check:

GTESTER check-qtest-x86_64
Broken pipe
GTester: last random seed: R02S3492bd34f44dd17460851643383be44d
main-loop: WARNING: I/O thread spun for 1000 iterations
make: *** [check-qtest-x86_64] Error 1

I debugged it (with some help from Laszlo) and the problem is that it
broke the human-monitor-command command. Any usage of this command
triggers the bug like:

{ execute: human-monitor-command,
   arguments: { command-line: info registers } }

It seems simple to fix, I think you just have to initialize
mon-cmd_table in qmp_human_monitor_command(), but I'd recommend two
things:

   1. It's better to split off some/all QMP initialization from
  monitor_init() and call it from qmp_human_monitor_command()

   2. Can you please take the opportunity and test all commands using
  cur_mon? Just grep for it

Sorry for noticing this only now, but I only run make check before
sending a pull request (although this very likely shows you didn't
run it either).


About the fd related qmp interface, to test it, send_msg() is needed,
which was not supported in python 2, but new added python 3.3. I think
there are three ways to add test cases for fd qmp APIs:
1 test only when python  3.3.
2 python plus C: compile a .so and call it with ctypes.
3 a new test framework: pure C code to call qmp interfaces.
Which one do you prefer?


Can't we have a C program plus a shell script to test this? Anyway, if
this gets complicated you can skip having the test-case. This series took
a long way already and holding it because of that test-case isn't fair.


  C program can work, I tested it with currently qemu-iotest infra,
when fork() the fd wouldn't be closed in child process, so the child
C program can use the fds openned in parent python program. With shell
script I need to build up some basic infra such as vm boot up, monitor
connect, json parsing, so used qemu-iotest python infra instead of shell
script.
  Based on that, I have sent a separate series to add the test case.
http://lists.nongnu.org/archive/html/qemu-devel/2013-08/msg03978.html

--
Best Regards

Wenchao Xia




Re: [Qemu-devel] [RFC] aio: add aio_context_acquire() and aio_context_release()

2013-08-27 Thread Wenchao Xia
 void test_notify(void)
  g_assert(!aio_poll(ctx, false));
  }

+typedef struct {
+QemuMutex start_lock;
+bool thread_acquired;
+} AcquireTestData;
+
+static void *test_acquire_thread(void *opaque)
+{
+AcquireTestData *data = opaque;
+
+/* Wait for other thread to let us start */
+qemu_mutex_lock(data-start_lock);
+qemu_mutex_unlock(data-start_lock);
+
+aio_context_acquire(ctx);
+aio_context_release(ctx);
+
+data-thread_acquired = true; /* success, we got here */
+
+return NULL;
+}
+
+static void dummy_notifier_read(EventNotifier *unused)
+{
+g_assert(false); /* should never be invoked */
+}
+
+static void test_acquire(void)
+{
+QemuThread thread;
+EventNotifier notifier;
+AcquireTestData data;
+
+/* Dummy event notifier ensures aio_poll() will block */
+event_notifier_init(notifier, false);
+aio_set_event_notifier(ctx, notifier, dummy_notifier_read);
+g_assert(!aio_poll(ctx, false)); /* consume aio_notify() */
+
+qemu_mutex_init(data.start_lock);
+qemu_mutex_lock(data.start_lock);
+data.thread_acquired = false;
+
+qemu_thread_create(thread, test_acquire_thread,
+   data, QEMU_THREAD_JOINABLE);
+
+/* Block in aio_poll(), let other thread kick us and acquire context */
+aio_context_acquire(ctx);
+qemu_mutex_unlock(data.start_lock); /* let the thread run */
+g_assert(!aio_poll(ctx, true));
+aio_context_release(ctx);
+
+qemu_thread_join(thread);
+aio_set_event_notifier(ctx, notifier, NULL);
+event_notifier_cleanup(notifier);
+
+g_assert(data.thread_acquired);
+}
+
  static void test_bh_schedule(void)
  {
  BHTestData data = { .n = 0 };
@@ -639,6 +696,7 @@ int main(int argc, char **argv)

  g_test_init(argc, argv, NULL);
  g_test_add_func(/aio/notify,  test_notify);
+g_test_add_func(/aio/acquire, test_acquire);
  g_test_add_func(/aio/bh/schedule, test_bh_schedule);
  g_test_add_func(/aio/bh/schedule10,   test_bh_schedule10);
  g_test_add_func(/aio/bh/cancel,   test_bh_cancel);







--
Best Regards

Wenchao Xia




Re: [Qemu-devel] [RFC] aio: add aio_context_acquire() and aio_context_release()

2013-08-27 Thread Wenchao Xia
 */
 +qemu_mutex_lock(data-start_lock);
 +qemu_mutex_unlock(data-start_lock);
 +
 +aio_context_acquire(ctx);
 +aio_context_release(ctx);
 +
 +data-thread_acquired = true; /* success, we got here */
 +
 +return NULL;
 +}
 +
 +static void dummy_notifier_read(EventNotifier *unused)
 +{
 +g_assert(false); /* should never be invoked */
 +}
 +
 +static void test_acquire(void)
 +{
 +QemuThread thread;
 +EventNotifier notifier;
 +AcquireTestData data;
 +
 +/* Dummy event notifier ensures aio_poll() will block */
 +event_notifier_init(notifier, false);
 +aio_set_event_notifier(ctx, notifier, dummy_notifier_read);
 +g_assert(!aio_poll(ctx, false)); /* consume aio_notify() */
 +
 +qemu_mutex_init(data.start_lock);
 +qemu_mutex_lock(data.start_lock);
 +data.thread_acquired = false;
 +
 +qemu_thread_create(thread, test_acquire_thread,
 +   data, QEMU_THREAD_JOINABLE);
 +
 +/* Block in aio_poll(), let other thread kick us and acquire context */
 +aio_context_acquire(ctx);
 +qemu_mutex_unlock(data.start_lock); /* let the thread run */
 +g_assert(!aio_poll(ctx, true));
 +aio_context_release(ctx);
 +
 +qemu_thread_join(thread);
 +aio_set_event_notifier(ctx, notifier, NULL);
 +event_notifier_cleanup(notifier);
 +
 +g_assert(data.thread_acquired);
 +}
 +
   static void test_bh_schedule(void)
   {
   BHTestData data = { .n = 0 };
 @@ -639,6 +696,7 @@ int main(int argc, char **argv)
 
   g_test_init(argc, argv, NULL);
   g_test_add_func(/aio/notify,  test_notify);
 +g_test_add_func(/aio/acquire, test_acquire);
   g_test_add_func(/aio/bh/schedule, test_bh_schedule);
   g_test_add_func(/aio/bh/schedule10,   test_bh_schedule10);
   g_test_add_func(/aio/bh/cancel,   test_bh_cancel);
 


-- 
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH 03/16] ipack: Pass size to ipack_bus_new_inplace()

2013-08-26 Thread Wenchao Xia

 To be passed to qbus_create_inplace().


Simplify DEVICE() cast to avoid parent field access.

  s-dev will always point to pci_dev, so this change is safe.

Reviewed-by: Wenchao Xia xiaw...@linux.vnet.ibm.com




Signed-off-by: Andreas Färber afaer...@suse.de
---
  hw/char/ipack.c   | 3 ++-
  hw/char/ipack.h   | 3 ++-
  hw/char/tpci200.c | 2 +-
  3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/hw/char/ipack.c b/hw/char/ipack.c
index f890471..5fb7073 100644
--- a/hw/char/ipack.c
+++ b/hw/char/ipack.c
@@ -24,7 +24,8 @@ IPackDevice *ipack_device_find(IPackBus *bus, int32_t slot)
  return NULL;
  }

-void ipack_bus_new_inplace(IPackBus *bus, DeviceState *parent,
+void ipack_bus_new_inplace(IPackBus *bus, size_t bus_size,
+   DeviceState *parent,
 const char *name, uint8_t n_slots,
 qemu_irq_handler handler)
  {
diff --git a/hw/char/ipack.h b/hw/char/ipack.h
index f2b7a12..f8dc0f2 100644
--- a/hw/char/ipack.h
+++ b/hw/char/ipack.h
@@ -72,7 +72,8 @@ extern const VMStateDescription vmstate_ipack_device;
  VMSTATE_STRUCT(_field, _state, 1, vmstate_ipack_device, IPackDevice)

  IPackDevice *ipack_device_find(IPackBus *bus, int32_t slot);
-void ipack_bus_new_inplace(IPackBus *bus, DeviceState *parent,
+void ipack_bus_new_inplace(IPackBus *bus, size_t bus_size,
+   DeviceState *parent,
 const char *name, uint8_t n_slots,
 qemu_irq_handler handler);

diff --git a/hw/char/tpci200.c b/hw/char/tpci200.c
index d9e17b2..e04ff26 100644
--- a/hw/char/tpci200.c
+++ b/hw/char/tpci200.c
@@ -607,7 +607,7 @@ static int tpci200_initfn(PCIDevice *pci_dev)
  pci_register_bar(s-dev, 4, PCI_BASE_ADDRESS_SPACE_MEMORY, s-las2);
  pci_register_bar(s-dev, 5, PCI_BASE_ADDRESS_SPACE_MEMORY, s-las3);

-ipack_bus_new_inplace(s-bus, DEVICE(s-dev), NULL,
+ipack_bus_new_inplace(s-bus, sizeof(s-bus), DEVICE(pci_dev), NULL,
N_MODULES, tpci200_set_irq);

  return 0;




--
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH 12/16] qdev: Pass size to qbus_create_inplace()

2013-08-26 Thread Wenchao Xia
 --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 2233c54..8c7a61e 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -1309,7 +1309,8 @@ static int ccid_initfn(USBDevice *dev)

  usb_desc_create_serial(dev);
  usb_desc_init(dev);
-qbus_create_inplace(s-bus.qbus, TYPE_CCID_BUS, dev-qdev, NULL);
+qbus_create_inplace(s-bus, sizeof(s-bus), TYPE_CCID_BUS, DEVICE(dev),
+NULL);
  s-intr = usb_ep_get(dev, USB_TOKEN_IN, CCID_INT_IN_EP);
  s-bus.qbus.allow_hotplug = 1;
  s-card = NULL;
diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c
index 692979e..29cf284 100644
--- a/hw/virtio/virtio-mmio.c
+++ b/hw/virtio/virtio-mmio.c
@@ -392,7 +392,7 @@ static void virtio_mmio_bus_new(VirtioBusState *bus, size_t 
bus_size,
  DeviceState *qdev = DEVICE(dev);
  BusState *qbus;

-qbus_create_inplace((BusState *)bus, TYPE_VIRTIO_MMIO_BUS, qdev, NULL);
+qbus_create_inplace(bus, bus_size, TYPE_VIRTIO_MMIO_BUS, qdev, NULL);
  qbus = BUS(bus);
  qbus-allow_hotplug = 0;
  }
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 313723f..a9a1893 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1512,7 +1512,7 @@ static void virtio_pci_bus_new(VirtioBusState *bus, 
size_t bus_size,
  BusState *qbus;
  char virtio_bus_name[] = virtio-bus;

-qbus_create_inplace((BusState *)bus, TYPE_VIRTIO_PCI_BUS, qdev,
+qbus_create_inplace(bus, bus_size, TYPE_VIRTIO_PCI_BUS, qdev,
  virtio_bus_name);
  qbus = BUS(bus);
  qbus-allow_hotplug = 1;
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 46972f4..a62f231 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -264,7 +264,7 @@ DeviceState *qdev_find_recursive(BusState *bus, const char 
*id);
  typedef int (qbus_walkerfn)(BusState *bus, void *opaque);
  typedef int (qdev_walkerfn)(DeviceState *dev, void *opaque);

-void qbus_create_inplace(void *bus, const char *typename,
+void qbus_create_inplace(void *bus, size_t size, const char *typename,
   DeviceState *parent, const char *name);
  BusState *qbus_create(const char *typename, DeviceState *parent, const char 
*name);
  /* Returns  0 if either devfn or busfn skip walk somewhere in cursion,




--
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH 15/16] qdev-monitor: Clean up qdev_device_add() variable naming

2013-08-26 Thread Wenchao Xia

于 2013-8-24 8:00, Andreas Färber 写道:

Avoid confusion between object and object class.

  between object class and device class?


Tidy DeviceClass variable while at it.

Signed-off-by: Andreas Färber afaer...@suse.de
---
  qdev-monitor.c | 22 +++---
  1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/qdev-monitor.c b/qdev-monitor.c
index 410cdcb..51bfec0 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -444,8 +444,8 @@ static BusState *qbus_find(const char *path)

  DeviceState *qdev_device_add(QemuOpts *opts)
  {
-ObjectClass *obj;
-DeviceClass *k;
+ObjectClass *oc;
+DeviceClass *dc;
  const char *driver, *path, *id;
  DeviceState *qdev;
  BusState *bus = NULL;
@@ -457,22 +457,22 @@ DeviceState *qdev_device_add(QemuOpts *opts)
  }

  /* find driver */
-obj = object_class_by_name(driver);
-if (!obj) {
+oc = object_class_by_name(driver);
+if (!oc) {
  const char *typename = find_typename_by_alias(driver);

  if (typename) {
  driver = typename;
-obj = object_class_by_name(driver);
+oc = object_class_by_name(driver);
  }
  }

-if (!obj) {
+if (!oc) {
  qerror_report(QERR_INVALID_PARAMETER_VALUE, driver, device type);
  return NULL;
  }

-k = DEVICE_CLASS(obj);
+dc = DEVICE_CLASS(oc);

  /* find bus */
  path = qemu_opt_get(opts, bus);
@@ -481,16 +481,16 @@ DeviceState *qdev_device_add(QemuOpts *opts)
  if (!bus) {
  return NULL;
  }
-if (!object_dynamic_cast(OBJECT(bus), k-bus_type)) {
+if (!object_dynamic_cast(OBJECT(bus), dc-bus_type)) {
  qerror_report(QERR_BAD_BUS_FOR_DEVICE,
driver, object_get_typename(OBJECT(bus)));
  return NULL;
  }
-} else if (k-bus_type != NULL) {
-bus = qbus_find_recursive(sysbus_get_default(), NULL, k-bus_type);
+} else if (dc-bus_type != NULL) {
+bus = qbus_find_recursive(sysbus_get_default(), NULL, dc-bus_type);
  if (!bus) {
  qerror_report(QERR_NO_BUS_FOR_DEVICE,
-  k-bus_type, driver);
+  dc-bus_type, driver);
  return NULL;
  }
  }




--
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH 13/16] qom: Pass available size to object_initialize()

2013-08-26 Thread Wenchao Xia
 virtio_balloon_pci_instance_init(Object *obj)
  {
  VirtIOBalloonPCI *dev = VIRTIO_BALLOON_PCI(obj);
-object_initialize(dev-vdev, TYPE_VIRTIO_BALLOON);
+object_initialize(dev-vdev, sizeof(dev-vdev), TYPE_VIRTIO_BALLOON);
  object_property_add_child(obj, virtio-backend, OBJECT(dev-vdev), 
NULL);

  object_property_add(obj, guest-stats, guest statistics,
@@ -1373,7 +1373,7 @@ static void virtio_serial_pci_class_init(ObjectClass 
*klass, void *data)
  static void virtio_serial_pci_instance_init(Object *obj)
  {
  VirtIOSerialPCI *dev = VIRTIO_SERIAL_PCI(obj);
-object_initialize(dev-vdev, TYPE_VIRTIO_SERIAL);
+object_initialize(dev-vdev, sizeof(dev-vdev), TYPE_VIRTIO_SERIAL);
  object_property_add_child(obj, virtio-backend, OBJECT(dev-vdev), 
NULL);
  }

@@ -1432,7 +1432,7 @@ static void virtio_net_pci_class_init(ObjectClass *klass, 
void *data)
  static void virtio_net_pci_instance_init(Object *obj)
  {
  VirtIONetPCI *dev = VIRTIO_NET_PCI(obj);
-object_initialize(dev-vdev, TYPE_VIRTIO_NET);
+object_initialize(dev-vdev, sizeof(dev-vdev), TYPE_VIRTIO_NET);
  object_property_add_child(obj, virtio-backend, OBJECT(dev-vdev), 
NULL);
  }

@@ -1488,7 +1488,7 @@ static void virtio_rng_pci_class_init(ObjectClass *klass, 
void *data)
  static void virtio_rng_initfn(Object *obj)
  {
  VirtIORngPCI *dev = VIRTIO_RNG_PCI(obj);
-object_initialize(dev-vdev, TYPE_VIRTIO_RNG);
+object_initialize(dev-vdev, sizeof(dev-vdev), TYPE_VIRTIO_RNG);
  object_property_add_child(obj, virtio-backend, OBJECT(dev-vdev), 
NULL);
  object_property_add_link(obj, rng, TYPE_RNG_BACKEND,
   (Object **)dev-vdev.conf.rng, NULL);
diff --git a/include/qom/object.h b/include/qom/object.h
index c463ced..1a7b71a 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -586,24 +586,26 @@ Object *object_new_with_type(Type type);
  /**
   * object_initialize_with_type:
   * @data: A pointer to the memory to be used for the object.
+ * @size: The maximum size available at @data for the object.
   * @type: The type of the object to instantiate.
   *
   * This function will initialize an object.  The memory for the object should
   * have already been allocated.  The returned object has a reference count of 
1,
   * and will be finalized when the last reference is dropped.
   */
-void object_initialize_with_type(void *data, Type type);
+void object_initialize_with_type(void *data, size_t size, Type type);

  /**
   * object_initialize:
   * @obj: A pointer to the memory to be used for the object.
+ * @size: The maximum size available at @obj for the object.
   * @typename: The name of the type of the object to instantiate.
   *
   * This function will initialize an object.  The memory for the object should
   * have already been allocated.  The returned object has a reference count of 
1,
   * and will be finalized when the last reference is dropped.
   */
-void object_initialize(void *obj, const char *typename);
+void object_initialize(void *obj, size_t size, const char *typename);

  /**
   * object_dynamic_cast:
diff --git a/qom/object.c b/qom/object.c
index 74fd241..e90e382 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -311,7 +311,7 @@ static void object_post_init_with_type(Object *obj, 
TypeImpl *ti)
  }
  }

-void object_initialize_with_type(void *data, TypeImpl *type)
+void object_initialize_with_type(void *data, size_t size, TypeImpl *type)
  {
  Object *obj = data;

@@ -320,6 +320,7 @@ void object_initialize_with_type(void *data, TypeImpl *type)

  g_assert(type-instance_size = sizeof(Object));
  g_assert(type-abstract == false);
+g_assert(size = type-instance_size);

  I paid some time to find this line for several times, so if it can be
splitted as a separate patch as qom: assert object init size, it will
make review easier.



  memset(obj, 0, type-instance_size);
  obj-class = type-class;
@@ -329,11 +330,11 @@ void object_initialize_with_type(void *data, TypeImpl 
*type)
  object_post_init_with_type(obj, type);
  }

-void object_initialize(void *data, const char *typename)
+void object_initialize(void *data, size_t size, const char *typename)
  {
  TypeImpl *type = type_get_by_name(typename);

-object_initialize_with_type(data, type);
+object_initialize_with_type(data, size, type);
  }

  static inline bool object_property_is_child(ObjectProperty *prop)
@@ -424,7 +425,7 @@ Object *object_new_with_type(Type type)
  type_initialize(type);

  obj = g_malloc(type-instance_size);
-object_initialize_with_type(obj, type);
+object_initialize_with_type(obj, type-instance_size, type);
  obj-free = g_free;

  return obj;




--
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH 00/16] qom: Assert sufficient object instance size

2013-08-26 Thread Wenchao Xia

  I have not looked deep into QOM, so only reviewed the code in this
series, and have some minor comments for patch 12, 13, and 15. For
other part,
  Reviewed-by: Wenchao Xia xiaw...@linux.vnet.ibm.com


Hello,

Peter remarked that object_initialize() on a GICState struct field would not
check whether the TypeInfo::instance_size for its typename argument exceeds
the length of the field we're initializing. This series therefore updates
all callers to explicitly pass the size available for the object.

While we don't have that many object_initialize() users yet, quite a few
devices are using qbus_create_inplace() or bus-specific functions based on it.
Still I consider this the safest solution in pushing the responsability for
supplying the length to the caller and thereby checking not only field type
lengths but also allocation lengths.

The series goes on to showcase an object_initialize() usage where we don't
know the instance_size in advance and need a QOM API to obtain it.

Based on Peter's OBJECT() elimination patch, which I have queued on qom-next.
This series conflicts with my *mpcore, virtio and ipack series among others.

Regards,
Andreas

Cc: Peter Maydell peter.mayd...@linaro.org
Cc: Anthony Liguori anth...@codemonkey.ws

Andreas Färber (16):
   qom: Fix object_initialize_with_type() argument name in documentation
   intel-hda: Pass size to hda_codec_bus_init()
   ipack: Pass size to ipack_bus_new_inplace()
   ide: Pass size to ide_bus_new()
   pci: Pass size to pci_bus_new_inplace()
   scsi: Pass size to scsi_bus_new()
   usb: Pass size to usb_bus_new()
   virtio-pci: Pass size to virtio_pci_bus_new()
   s390-virtio-bus: Pass size to virtio_s390_bus_new()
   virtio-ccw: Pass size to virtio_ccw_bus_new()
   virtio-mmio: Pass size to virtio_mmio_bus_new()
   qdev: Pass size to qbus_create_inplace()
   qom: Pass available size to object_initialize()
   qom: Introduce type_get_instance_size()
   qdev-monitor: Clean up qdev_device_add() variable naming
   qdev-monitor: Avoid aborting on out-of-memory in qdev_device_add()

  hw/audio/intel-hda.c  |  6 +++---
  hw/audio/intel-hda.h  |  2 +-
  hw/char/ipack.c   |  5 +++--
  hw/char/ipack.h   |  3 ++-
  hw/char/tpci200.c |  2 +-
  hw/char/virtio-serial-bus.c   |  4 ++--
  hw/core/qdev.c|  4 ++--
  hw/core/sysbus.c  |  4 ++--
  hw/cpu/icc_bus.c  |  3 ++-
  hw/dma/xilinx_axidma.c|  6 --
  hw/ide/ahci.c |  2 +-
  hw/ide/cmd646.c   |  2 +-
  hw/ide/internal.h |  3 ++-
  hw/ide/isa.c  |  2 +-
  hw/ide/macio.c|  2 +-
  hw/ide/mmio.c |  2 +-
  hw/ide/piix.c |  2 +-
  hw/ide/qdev.c |  5 +++--
  hw/ide/via.c  |  2 +-
  hw/intc/xics.c|  2 +-
  hw/misc/macio/cuda.c  |  4 ++--
  hw/misc/macio/macio.c | 13 +++--
  hw/net/xilinx_axienet.c   |  6 --
  hw/pci-host/prep.c|  4 ++--
  hw/pci-host/q35.c |  2 +-
  hw/pci-host/versatile.c   |  4 ++--
  hw/pci/pci.c  |  4 ++--
  hw/pci/pci_bridge.c   |  3 ++-
  hw/s390x/event-facility.c |  4 ++--
  hw/s390x/s390-virtio-bus.c| 24 +---
  hw/s390x/virtio-ccw.c | 26 ++
  hw/scsi/esp-pci.c |  2 +-
  hw/scsi/esp.c |  2 +-
  hw/scsi/lsi53c895a.c  |  2 +-
  hw/scsi/megasas.c |  3 ++-
  hw/scsi/scsi-bus.c|  6 +++---
  hw/scsi/spapr_vscsi.c |  3 ++-
  hw/scsi/virtio-scsi.c |  3 ++-
  hw/scsi/vmw_pvscsi.c  |  3 ++-
  hw/usb/bus.c  |  5 +++--
  hw/usb/dev-smartcard-reader.c |  3 ++-
  hw/usb/dev-storage.c  |  6 --
  hw/usb/dev-uas.c  |  3 ++-
  hw/usb/hcd-ehci.c |  2 +-
  hw/usb/hcd-musb.c |  2 +-
  hw/usb/hcd-ohci.c |  2 +-
  hw/usb/hcd-uhci.c |  2 +-
  hw/usb/hcd-xhci.c |  2 +-
  hw/virtio/virtio-mmio.c   | 10 ++
  hw/virtio/virtio-pci.c| 26 ++
  include/hw/pci/pci.h  |  2 +-
  include/hw/qdev-core.h|  2 +-
  include/hw/scsi/scsi.h|  4 ++--
  include/hw/usb.h  |  3 ++-
  include/qom/object.h  | 16 +---
  qdev-monitor.c| 30 ++
  qom/object.c  | 16 
  57 files changed, 185 insertions(+), 132 deletions(-)




--
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH V9 00/15] monitor: support sub command group in auto completion and help

2013-08-26 Thread Wenchao Xia

于 2013-8-26 23:55, Luiz Capitulino 写道:

On Fri, 23 Aug 2013 16:17:52 +0800
Wenchao Xia xiaw...@linux.vnet.ibm.com wrote:


This series make auto completion and help functions works normal for sub
command, by using reentrant functions. In order to do that, global variables
are not directly used in those functions any more. With this series, cmd_table
is a member of structure Monitor so it is possible to create a monitor with
different command table now, auto completion will work in that monitor. In
short, info is not treated as a special case now, this series ensure help
and auto complete function works normal for any sub command added in the future.

Patch 5 replaced cur_mon with rs-mon, it is safe because:
monitor_init() calls readline_init() which initialize mon-rs, result is
mon-rs-mon == mon. Then qemu_chr_add_handlers() is called, which make
monitor_read() function take *mon as its opaque. Later, when user input,
monitor_read() is called, where cur_mon is set to *mon by cur_mon = opaque.
If qemu's monitors run in one thread, then later in readline_handle_byte()
and readline_comletion(), cur_mon is actually equal to rs-mon, in another
word, it points to the monitor instance, so it is safe to replace *cur_mon
in those functions.

Thanks for Luiz and Eric for reviewing.


This one doesn't even build :(

/home/lcapitulino/work/src/upstream/qmp-unstable/monitor.c: In function 
‘help_cmd’:
/home/lcapitulino/work/src/upstream/qmp-unstable/monitor.c:952:1: error: label 
‘cleanup’ defined but not used [-Werror=unused-label]
cc1: all warnings being treated as errors
make[1]: *** [monitor.o] Error 1
make[1]: *** Waiting for unfinished jobs
make: *** [subdir-x86_64-softmmu] Error 2


  Sorry for it, I missed that CC flag in my configure, will fix.
It would be great if you can share your configure settings.

--
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH 0/3] qemu-iotests: add test for fd passing via SCM rights

2013-08-26 Thread Wenchao Xia
于 2013-8-26 11:13, Wenchao Xia 写道:
 This series add test case for fd passing with unix socket at runtime. Since
 getfd and closefd interface will interact with monitor's data, so it will
 help to do regression test for monitor patches. Since python2 do not support
 sendmsg(), so a C helper program is added to do the job.
 
 Wenchao Xia (3):
1 qemu-iotests: add unix socket help program
2 qemu-iotests: add infrastructure of fd passing via SCM
3 qemu-iotests: add tests for runtime fd passing via SCM rights
 
   QMP/qmp.py |6 ++
   configure  |2 +-
   tests/Makefile |4 +-
   tests/qemu-iotests/045 |   37 ++-
   tests/qemu-iotests/045.out |4 +-
   tests/qemu-iotests/check   |1 +
   tests/qemu-iotests/iotests.py  |   26 +++
   tests/qemu-iotests/socket_scm_helper.c |  119 
 
   8 files changed, 194 insertions(+), 5 deletions(-)
   create mode 100644 tests/qemu-iotests/socket_scm_helper.c
 
 
  This version have one issue in Makefile, will respin.

-- 
Best Regards

Wenchao Xia




[Qemu-devel] [PATCH V2 1/3] qemu-iotests: add unix socket help program

2013-08-26 Thread Wenchao Xia
This program can do a sendmsg call to transfer fd with unix
socket, which is not supported in python2.

The built binary will not be deleted in clean, but it is a
existing issue in ./tests, which should be solved in another
patch.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
---
 configure  |2 +-
 tests/Makefile |4 +-
 tests/qemu-iotests/socket_scm_helper.c |  119 
 3 files changed, 123 insertions(+), 2 deletions(-)
 create mode 100644 tests/qemu-iotests/socket_scm_helper.c

diff --git a/configure b/configure
index 0a55c20..5080c38 100755
--- a/configure
+++ b/configure
@@ -4544,7 +4544,7 @@ if [ $dtc_internal = yes ]; then
 fi
 
 # build tree in object directory in case the source is not in the current 
directory
-DIRS=tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos 
tests/qapi-schema tests/tcg/xtensa
+DIRS=tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos 
tests/qapi-schema tests/tcg/xtensa tests/qemu-iotests
 DIRS=$DIRS pc-bios/optionrom pc-bios/spapr-rtas pc-bios/s390-ccw
 DIRS=$DIRS roms/seabios roms/vgabios
 DIRS=$DIRS qapi-generated
diff --git a/tests/Makefile b/tests/Makefile
index baba9e9..d2f3fcb 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -172,6 +172,8 @@ tests/boot-order-test$(EXESUF): tests/boot-order-test.o 
$(libqos-obj-y)
 tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
 tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
 tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y)
+tests/qemu-iotests/socket_scm_helper$(EXESUF): 
tests/qemu-iotests/socket_scm_helper.o
+   $(call LINK, $^)
 
 # QTest rules
 
@@ -250,7 +252,7 @@ check-report.html: check-report.xml
 # Other tests
 
 .PHONY: check-tests/qemu-iotests-quick.sh
-check-tests/qemu-iotests-quick.sh: tests/qemu-iotests-quick.sh 
qemu-img$(EXESUF) qemu-io$(EXESUF)
+check-tests/qemu-iotests-quick.sh: tests/qemu-iotests-quick.sh 
qemu-img$(EXESUF) qemu-io$(EXESUF) tests/qemu-iotests/socket_scm_helper$(EXESUF)
$
 
 .PHONY: check-tests/test-qapi.py
diff --git a/tests/qemu-iotests/socket_scm_helper.c 
b/tests/qemu-iotests/socket_scm_helper.c
new file mode 100644
index 000..1955a3e
--- /dev/null
+++ b/tests/qemu-iotests/socket_scm_helper.c
@@ -0,0 +1,119 @@
+/*
+ * SCM_RIGHT with unix socket help program for test
+ *
+ * Copyright IBM, Inc. 2013
+ *
+ * Authors:
+ *  Wenchao Xiaxiaw...@linux.vnet.ibm.com
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#include stdio.h
+#include errno.h
+#include sys/socket.h
+#include sys/un.h
+#include stdlib.h
+
+/* #define SOCKET_SCM_DEBUG */
+
+static int send_fd(int fd, int fd_to_send, const char *data, size_t len)
+{
+struct msghdr msg;
+struct iovec iov[1];
+int ret;
+char control[CMSG_SPACE(sizeof(int))];
+struct cmsghdr *cmsg;
+
+if (fd  0) {
+fprintf(stderr, Socket fd is invalid.\n);
+return -1;
+}
+if (fd_to_send  0) {
+fprintf(stderr, Fd to send is invalid.\n);
+return -1;
+}
+if (data == NULL || len = 0) {
+fprintf(stderr, Data buffer must be valid.\n);
+return -1;
+}
+
+memset(msg, 0, sizeof(msg));
+memset(control, 0, sizeof(control));
+
+iov[0].iov_base = (void *)data;
+iov[0].iov_len = len;
+
+msg.msg_iov = iov;
+msg.msg_iovlen = 1;
+
+msg.msg_control = control;
+msg.msg_controllen = sizeof(control);
+
+cmsg = CMSG_FIRSTHDR(msg);
+
+cmsg-cmsg_len = CMSG_LEN(sizeof(int));
+cmsg-cmsg_level = SOL_SOCKET;
+cmsg-cmsg_type = SCM_RIGHTS;
+memcpy(CMSG_DATA(cmsg), fd, sizeof(int));
+
+do {
+ret = sendmsg(fd, msg, 0);
+} while (ret  0  errno == EINTR);
+
+if (ret  0) {
+fprintf(stderr, Failed to send msg, reason: %s.\n, strerror(errno));
+}
+
+return ret;
+}
+
+/*
+ * To make things simple, the caller need to specify:
+ * 1. socket fd.
+ * 2. fd to send.
+ * 3. msg to send.
+ */
+int main(int argc, char **argv, char **envp)
+{
+int sock, fd, ret, buflen;
+const char *buf;
+#ifdef SOCKET_SCM_DEBUG
+int i;
+for (i = 0; i  argc; i++) {
+fprintf(stderr, Parameter %d: %s.\n, i, argv[i]);
+}
+#endif
+
+if (argc  4) {
+fprintf(stderr,
+Invalid parameter, use it as:\n
+%s SOCKET_FD FD_TO_SEND MSG.\n,
+argv[0]);
+return 1;
+}
+
+errno = 0;
+sock = strtol(argv[1], NULL, 10);
+if (errno) {
+fprintf(stderr, Failed in strtol for socket fd, reason: %s.\n,
+strerror(errno));
+return 1;
+}
+fd = strtol(argv[2], NULL, 10);
+if (errno) {
+fprintf(stderr, Failed in strtol for fd to send, reason: %s.\n,
+strerror(errno));
+return 1;
+}
+
+buf = argv[3];
+buflen

[Qemu-devel] [PATCH V2 0/3] qemu-iotests: add test for fd passing via SCM rights

2013-08-26 Thread Wenchao Xia
This series add test case for fd passing with unix socket at runtime. Since
getfd and closefd interface will interact with monitor's data, so it will
help to do regression test for monitor patches. Since python2 do not support
sendmsg(), so a C helper program is added to do the job.

v2:
  1: add missing $ in the makefile rule.

Wenchao Xia (3):
  1 qemu-iotests: add unix socket help program
  2 qemu-iotests: add infrastructure of fd passing via SCM
  3 qemu-iotests: add tests for runtime fd passing via SCM rights

 QMP/qmp.py |6 ++
 configure  |2 +-
 tests/Makefile |4 +-
 tests/qemu-iotests/045 |   37 ++-
 tests/qemu-iotests/045.out |4 +-
 tests/qemu-iotests/check   |1 +
 tests/qemu-iotests/iotests.py  |   26 +++
 tests/qemu-iotests/socket_scm_helper.c |  119 
 8 files changed, 194 insertions(+), 5 deletions(-)
 create mode 100644 tests/qemu-iotests/socket_scm_helper.c





[Qemu-devel] [PATCH V2 2/3] qemu-iotests: add infrastructure of fd passing via SCM

2013-08-26 Thread Wenchao Xia
This patch make use of the compiled scm helper program to transfer
fd via unix socket at runtime.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
---
 QMP/qmp.py|6 ++
 tests/qemu-iotests/check  |1 +
 tests/qemu-iotests/iotests.py |   26 ++
 3 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/QMP/qmp.py b/QMP/qmp.py
index c551df1..074f09a 100644
--- a/QMP/qmp.py
+++ b/QMP/qmp.py
@@ -188,3 +188,9 @@ class QEMUMonitorProtocol:
 
 def settimeout(self, timeout):
 self.__sock.settimeout(timeout)
+
+def get_sock_fd(self):
+return self.__sock.fileno()
+
+def is_scm_available(self):
+return self.__sock.family == socket.AF_UNIX
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
index 74628ae..2f7f78e 100755
--- a/tests/qemu-iotests/check
+++ b/tests/qemu-iotests/check
@@ -164,6 +164,7 @@ QEMU_IO   -- $QEMU_IO
 IMGFMT-- $FULL_IMGFMT_DETAILS
 IMGPROTO  -- $FULL_IMGPROTO_DETAILS
 PLATFORM  -- $FULL_HOST_DETAILS
+SOCKET_SCM_HELPER -- $SOCKET_SCM_HELPER
 
 EOF
 #MKFS_OPTIONS  -- $FULL_MKFS_OPTIONS
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 33ad0ec..d40b2de 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -38,6 +38,8 @@ imgfmt = os.environ.get('IMGFMT', 'raw')
 imgproto = os.environ.get('IMGPROTO', 'file')
 test_dir = os.environ.get('TEST_DIR', '/var/tmp')
 
+socket_scm_helper = os.environ.get('SOCKET_SCM_HELPER', 'socket_scm_helper')
+
 def qemu_img(*args):
 '''Run qemu-img and return the exit code'''
 devnull = open('/dev/null', 'r+')
@@ -80,6 +82,12 @@ class VM(object):
  '-display', 'none', '-vga', 'none']
 self._num_drives = 0
 
+#This can be used to add unused monitor
+def add_monitor_telnet(self, ip, port):
+args = 'tcp:%s:%d,server,nowait,telnet' % (ip, port)
+self._args.append('-monitor')
+self._args.append(args)
+
 def add_drive(self, path, opts=''):
 '''Add a virtio-blk drive to the VM'''
 options = ['if=virtio',
@@ -112,6 +120,24 @@ class VM(object):
 self._args.append(','.join(options))
 return self
 
+#Sendmsg must carry out some data to get qemu's notice, so send a blank
+#by default.
+def send_fd_scm(self, fd, msg=' '):
+#In iotest.py, the qmp should always use unix socket.
+assert self._qmp.is_scm_available()
+fd_bin = socket_scm_helper
+if os.path.exists(fd_bin) == False:
+print Scm help program does not present, path %s. % fd_bin
+return -1
+fd_param = [%s % fd_bin,
+%d % self._qmp.get_sock_fd(),
+%d % fd,
+%s % msg]
+devnull = open('/dev/null', 'rb')
+p = subprocess.Popen(fd_param, stdin=devnull, stdout=sys.stdout,
+ stderr=sys.stderr)
+return p.wait()
+
 def launch(self):
 '''Launch the VM and establish a QMP connection'''
 devnull = open('/dev/null', 'rb')
-- 
1.7.1





[Qemu-devel] [PATCH V2 3/3] qemu-iotests: add tests for runtime fd passing via SCM rights

2013-08-26 Thread Wenchao Xia
This case will test whether the monitor can receive fd at runtime.
To verify better, additional monitor is created to see if qemu
can handler two monitor instance correctly.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
---
 tests/qemu-iotests/045 |   37 -
 tests/qemu-iotests/045.out |4 ++--
 2 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/tests/qemu-iotests/045 b/tests/qemu-iotests/045
index 2b6f1af..f95e5fa 100755
--- a/tests/qemu-iotests/045
+++ b/tests/qemu-iotests/045
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #
-# Tests for fdsets.
+# Tests for fdsets and getfd.
 #
 # Copyright (C) 2012 IBM Corp.
 #
@@ -125,5 +125,40 @@ class TestFdSets(iotests.QMPTestCase):
 'No file descriptor supplied via SCM_RIGHTS')
 self.vm.shutdown()
 
+#Add fd at runtime, there are two ways: monitor related or fdset related
+class TestSCMFd(iotests.QMPTestCase):
+def setUp(self):
+self.vm = iotests.VM()
+qemu_img('create', '-f', iotests.imgfmt, image0, '128K')
+self.file0 = open(image0, 'r')
+self.vm.add_monitor_telnet(0,4445)
+self.vm.launch()
+
+def tearDown(self):
+self.vm.shutdown()
+self.file0.close()
+os.remove(image0)
+
+def _send_fd_by_SCM(self):
+ret = self.vm.send_fd_scm(self.file0.fileno())
+self.assertEqual(ret, 0, 'Failed to send fd with UNIX SCM')
+
+def test_add_fd(self):
+self._send_fd_by_SCM()
+result = self.vm.qmp('add-fd', fdset_id=2, opaque='image0:r')
+self.assert_qmp(result, 'return/fdset-id', 2)
+
+def test_getfd(self):
+self._send_fd_by_SCM()
+result = self.vm.qmp('getfd', fdname='image0:r')
+self.assert_qmp(result, 'return', {})
+
+def test_closefd(self):
+self._send_fd_by_SCM()
+result = self.vm.qmp('getfd', fdname='image0:r')
+self.assert_qmp(result, 'return', {})
+result = self.vm.qmp('closefd', fdname='image0:r')
+self.assert_qmp(result, 'return', {})
+
 if __name__ == '__main__':
 iotests.main(supported_fmts=['raw'])
diff --git a/tests/qemu-iotests/045.out b/tests/qemu-iotests/045.out
index 3f8a935..dae404e 100644
--- a/tests/qemu-iotests/045.out
+++ b/tests/qemu-iotests/045.out
@@ -1,5 +1,5 @@
-..
+.
 --
-Ran 6 tests
+Ran 9 tests
 
 OK
-- 
1.7.1





[Qemu-devel] [PATCH 0/3] qemu-iotests: add test for fd passing via SCM rights

2013-08-25 Thread Wenchao Xia
This series add test case for fd passing with unix socket at runtime. Since
getfd and closefd interface will interact with monitor's data, so it will
help to do regression test for monitor patches. Since python2 do not support
sendmsg(), so a C helper program is added to do the job.

Wenchao Xia (3):
  1 qemu-iotests: add unix socket help program
  2 qemu-iotests: add infrastructure of fd passing via SCM
  3 qemu-iotests: add tests for runtime fd passing via SCM rights

 QMP/qmp.py |6 ++
 configure  |2 +-
 tests/Makefile |4 +-
 tests/qemu-iotests/045 |   37 ++-
 tests/qemu-iotests/045.out |4 +-
 tests/qemu-iotests/check   |1 +
 tests/qemu-iotests/iotests.py  |   26 +++
 tests/qemu-iotests/socket_scm_helper.c |  119 
 8 files changed, 194 insertions(+), 5 deletions(-)
 create mode 100644 tests/qemu-iotests/socket_scm_helper.c





[Qemu-devel] [PATCH 1/3] qemu-iotests: add unix socket help program

2013-08-25 Thread Wenchao Xia
This program can do a sendmsg call to transfer fd with unix
socket, which is not supported in python2.

The built binary will not be deleted in clean, but it is a
existing issue in ./tests, which should be solved in another
patch.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
---
 configure  |2 +-
 tests/Makefile |4 +-
 tests/qemu-iotests/socket_scm_helper.c |  119 
 3 files changed, 123 insertions(+), 2 deletions(-)
 create mode 100644 tests/qemu-iotests/socket_scm_helper.c

diff --git a/configure b/configure
index 18fa608..0a18038 100755
--- a/configure
+++ b/configure
@@ -4507,7 +4507,7 @@ if [ $dtc_internal = yes ]; then
 fi
 
 # build tree in object directory in case the source is not in the current 
directory
-DIRS=tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos 
tests/qapi-schema tests/tcg/xtensa
+DIRS=tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos 
tests/qapi-schema tests/tcg/xtensa tests/qemu-iotests
 DIRS=$DIRS pc-bios/optionrom pc-bios/spapr-rtas pc-bios/s390-ccw
 DIRS=$DIRS roms/seabios roms/vgabios
 DIRS=$DIRS qapi-generated
diff --git a/tests/Makefile b/tests/Makefile
index baba9e9..57131db 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -172,6 +172,8 @@ tests/boot-order-test$(EXESUF): tests/boot-order-test.o 
$(libqos-obj-y)
 tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
 tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
 tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y)
+tests/qemu-iotests/socket_scm_helper(EXESUF): 
tests/qemu-iotests/socket_scm_helper.o
+   $(call LINK, $^)
 
 # QTest rules
 
@@ -250,7 +252,7 @@ check-report.html: check-report.xml
 # Other tests
 
 .PHONY: check-tests/qemu-iotests-quick.sh
-check-tests/qemu-iotests-quick.sh: tests/qemu-iotests-quick.sh 
qemu-img$(EXESUF) qemu-io$(EXESUF)
+check-tests/qemu-iotests-quick.sh: tests/qemu-iotests-quick.sh 
qemu-img$(EXESUF) qemu-io$(EXESUF) tests/qemu-iotests/socket_scm_helper$(EXESUF)
$
 
 .PHONY: check-tests/test-qapi.py
diff --git a/tests/qemu-iotests/socket_scm_helper.c 
b/tests/qemu-iotests/socket_scm_helper.c
new file mode 100644
index 000..1955a3e
--- /dev/null
+++ b/tests/qemu-iotests/socket_scm_helper.c
@@ -0,0 +1,119 @@
+/*
+ * SCM_RIGHT with unix socket help program for test
+ *
+ * Copyright IBM, Inc. 2013
+ *
+ * Authors:
+ *  Wenchao Xiaxiaw...@linux.vnet.ibm.com
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#include stdio.h
+#include errno.h
+#include sys/socket.h
+#include sys/un.h
+#include stdlib.h
+
+/* #define SOCKET_SCM_DEBUG */
+
+static int send_fd(int fd, int fd_to_send, const char *data, size_t len)
+{
+struct msghdr msg;
+struct iovec iov[1];
+int ret;
+char control[CMSG_SPACE(sizeof(int))];
+struct cmsghdr *cmsg;
+
+if (fd  0) {
+fprintf(stderr, Socket fd is invalid.\n);
+return -1;
+}
+if (fd_to_send  0) {
+fprintf(stderr, Fd to send is invalid.\n);
+return -1;
+}
+if (data == NULL || len = 0) {
+fprintf(stderr, Data buffer must be valid.\n);
+return -1;
+}
+
+memset(msg, 0, sizeof(msg));
+memset(control, 0, sizeof(control));
+
+iov[0].iov_base = (void *)data;
+iov[0].iov_len = len;
+
+msg.msg_iov = iov;
+msg.msg_iovlen = 1;
+
+msg.msg_control = control;
+msg.msg_controllen = sizeof(control);
+
+cmsg = CMSG_FIRSTHDR(msg);
+
+cmsg-cmsg_len = CMSG_LEN(sizeof(int));
+cmsg-cmsg_level = SOL_SOCKET;
+cmsg-cmsg_type = SCM_RIGHTS;
+memcpy(CMSG_DATA(cmsg), fd, sizeof(int));
+
+do {
+ret = sendmsg(fd, msg, 0);
+} while (ret  0  errno == EINTR);
+
+if (ret  0) {
+fprintf(stderr, Failed to send msg, reason: %s.\n, strerror(errno));
+}
+
+return ret;
+}
+
+/*
+ * To make things simple, the caller need to specify:
+ * 1. socket fd.
+ * 2. fd to send.
+ * 3. msg to send.
+ */
+int main(int argc, char **argv, char **envp)
+{
+int sock, fd, ret, buflen;
+const char *buf;
+#ifdef SOCKET_SCM_DEBUG
+int i;
+for (i = 0; i  argc; i++) {
+fprintf(stderr, Parameter %d: %s.\n, i, argv[i]);
+}
+#endif
+
+if (argc  4) {
+fprintf(stderr,
+Invalid parameter, use it as:\n
+%s SOCKET_FD FD_TO_SEND MSG.\n,
+argv[0]);
+return 1;
+}
+
+errno = 0;
+sock = strtol(argv[1], NULL, 10);
+if (errno) {
+fprintf(stderr, Failed in strtol for socket fd, reason: %s.\n,
+strerror(errno));
+return 1;
+}
+fd = strtol(argv[2], NULL, 10);
+if (errno) {
+fprintf(stderr, Failed in strtol for fd to send, reason: %s.\n,
+strerror(errno));
+return 1;
+}
+
+buf = argv[3];
+buflen

[Qemu-devel] [PATCH 2/3] qemu-iotests: add infrastructure of fd passing via SCM

2013-08-25 Thread Wenchao Xia
This patch make use of the compiled scm helper program to transfer
fd via unix socket at runtime.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
---
 QMP/qmp.py|6 ++
 tests/qemu-iotests/check  |1 +
 tests/qemu-iotests/iotests.py |   26 ++
 3 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/QMP/qmp.py b/QMP/qmp.py
index c551df1..074f09a 100644
--- a/QMP/qmp.py
+++ b/QMP/qmp.py
@@ -188,3 +188,9 @@ class QEMUMonitorProtocol:
 
 def settimeout(self, timeout):
 self.__sock.settimeout(timeout)
+
+def get_sock_fd(self):
+return self.__sock.fileno()
+
+def is_scm_available(self):
+return self.__sock.family == socket.AF_UNIX
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
index 74628ae..2f7f78e 100755
--- a/tests/qemu-iotests/check
+++ b/tests/qemu-iotests/check
@@ -164,6 +164,7 @@ QEMU_IO   -- $QEMU_IO
 IMGFMT-- $FULL_IMGFMT_DETAILS
 IMGPROTO  -- $FULL_IMGPROTO_DETAILS
 PLATFORM  -- $FULL_HOST_DETAILS
+SOCKET_SCM_HELPER -- $SOCKET_SCM_HELPER
 
 EOF
 #MKFS_OPTIONS  -- $FULL_MKFS_OPTIONS
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 33ad0ec..d40b2de 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -38,6 +38,8 @@ imgfmt = os.environ.get('IMGFMT', 'raw')
 imgproto = os.environ.get('IMGPROTO', 'file')
 test_dir = os.environ.get('TEST_DIR', '/var/tmp')
 
+socket_scm_helper = os.environ.get('SOCKET_SCM_HELPER', 'socket_scm_helper')
+
 def qemu_img(*args):
 '''Run qemu-img and return the exit code'''
 devnull = open('/dev/null', 'r+')
@@ -80,6 +82,12 @@ class VM(object):
  '-display', 'none', '-vga', 'none']
 self._num_drives = 0
 
+#This can be used to add unused monitor
+def add_monitor_telnet(self, ip, port):
+args = 'tcp:%s:%d,server,nowait,telnet' % (ip, port)
+self._args.append('-monitor')
+self._args.append(args)
+
 def add_drive(self, path, opts=''):
 '''Add a virtio-blk drive to the VM'''
 options = ['if=virtio',
@@ -112,6 +120,24 @@ class VM(object):
 self._args.append(','.join(options))
 return self
 
+#Sendmsg must carry out some data to get qemu's notice, so send a blank
+#by default.
+def send_fd_scm(self, fd, msg=' '):
+#In iotest.py, the qmp should always use unix socket.
+assert self._qmp.is_scm_available()
+fd_bin = socket_scm_helper
+if os.path.exists(fd_bin) == False:
+print Scm help program does not present, path %s. % fd_bin
+return -1
+fd_param = [%s % fd_bin,
+%d % self._qmp.get_sock_fd(),
+%d % fd,
+%s % msg]
+devnull = open('/dev/null', 'rb')
+p = subprocess.Popen(fd_param, stdin=devnull, stdout=sys.stdout,
+ stderr=sys.stderr)
+return p.wait()
+
 def launch(self):
 '''Launch the VM and establish a QMP connection'''
 devnull = open('/dev/null', 'rb')
-- 
1.7.1





[Qemu-devel] [PATCH 3/3] qemu-iotests: add tests for runtime fd passing via SCM rights

2013-08-25 Thread Wenchao Xia
This case will test whether the monitor can receive fd at runtime.
To verify better, additional monitor is created to see if qemu
can handler two monitor instance correctly.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
---
 tests/qemu-iotests/045 |   37 -
 tests/qemu-iotests/045.out |4 ++--
 2 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/tests/qemu-iotests/045 b/tests/qemu-iotests/045
index 2b6f1af..f95e5fa 100755
--- a/tests/qemu-iotests/045
+++ b/tests/qemu-iotests/045
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #
-# Tests for fdsets.
+# Tests for fdsets and getfd.
 #
 # Copyright (C) 2012 IBM Corp.
 #
@@ -125,5 +125,40 @@ class TestFdSets(iotests.QMPTestCase):
 'No file descriptor supplied via SCM_RIGHTS')
 self.vm.shutdown()
 
+#Add fd at runtime, there are two ways: monitor related or fdset related
+class TestSCMFd(iotests.QMPTestCase):
+def setUp(self):
+self.vm = iotests.VM()
+qemu_img('create', '-f', iotests.imgfmt, image0, '128K')
+self.file0 = open(image0, 'r')
+self.vm.add_monitor_telnet(0,4445)
+self.vm.launch()
+
+def tearDown(self):
+self.vm.shutdown()
+self.file0.close()
+os.remove(image0)
+
+def _send_fd_by_SCM(self):
+ret = self.vm.send_fd_scm(self.file0.fileno())
+self.assertEqual(ret, 0, 'Failed to send fd with UNIX SCM')
+
+def test_add_fd(self):
+self._send_fd_by_SCM()
+result = self.vm.qmp('add-fd', fdset_id=2, opaque='image0:r')
+self.assert_qmp(result, 'return/fdset-id', 2)
+
+def test_getfd(self):
+self._send_fd_by_SCM()
+result = self.vm.qmp('getfd', fdname='image0:r')
+self.assert_qmp(result, 'return', {})
+
+def test_closefd(self):
+self._send_fd_by_SCM()
+result = self.vm.qmp('getfd', fdname='image0:r')
+self.assert_qmp(result, 'return', {})
+result = self.vm.qmp('closefd', fdname='image0:r')
+self.assert_qmp(result, 'return', {})
+
 if __name__ == '__main__':
 iotests.main(supported_fmts=['raw'])
diff --git a/tests/qemu-iotests/045.out b/tests/qemu-iotests/045.out
index 3f8a935..dae404e 100644
--- a/tests/qemu-iotests/045.out
+++ b/tests/qemu-iotests/045.out
@@ -1,5 +1,5 @@
-..
+.
 --
-Ran 6 tests
+Ran 9 tests
 
 OK
-- 
1.7.1





[Qemu-devel] [PATCH V9 08/15] monitor: avoid direct use of global variable *mon_cmds

2013-08-23 Thread Wenchao Xia
New member *cmd_table is added in structure Monitor to avoid direct usage of
*mon_cmds. Now monitor have an associated command table, when global variable
*info_cmds is also discarded, structure Monitor would gain full control about
how to deal with user input.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
---
 monitor.c |   13 -
 1 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/monitor.c b/monitor.c
index 3ac98ef..8152607 100644
--- a/monitor.c
+++ b/monitor.c
@@ -195,6 +195,7 @@ struct Monitor {
 CPUState *mon_cpu;
 BlockDriverCompletionFunc *password_completion_cb;
 void *password_opaque;
+mon_cmd_t *cmd_table;
 QError *error;
 QLIST_HEAD(,mon_fd_t) fds;
 QLIST_ENTRY(Monitor) entry;
@@ -687,6 +688,8 @@ static void monitor_data_init(Monitor *mon)
 {
 memset(mon, 0, sizeof(Monitor));
 mon-outbuf = qstring_new();
+/* Use *mon_cmds by default. */
+mon-cmd_table = mon_cmds;
 }
 
 static void monitor_data_destroy(Monitor *mon)
@@ -767,7 +770,7 @@ static void help_cmd(Monitor *mon, const char *name)
 if (name  !strcmp(name, info)) {
 help_cmd_dump(mon, info_cmds, info , NULL);
 } else {
-help_cmd_dump(mon, mon_cmds, , name);
+help_cmd_dump(mon, mon-cmd_table, , name);
 if (name  !strcmp(name, log)) {
 const QEMULogItem *item;
 monitor_printf(mon, Log items (comma separated):\n);
@@ -3994,7 +3997,7 @@ static void handle_user_command(Monitor *mon, const char 
*cmdline)
 
 qdict = qdict_new();
 
-cmd = monitor_parse_command(mon, cmdline, 0, mon_cmds, qdict);
+cmd = monitor_parse_command(mon, cmdline, 0, mon-cmd_table, qdict);
 if (!cmd)
 goto out;
 
@@ -4183,12 +4186,12 @@ static void monitor_find_completion(Monitor *mon,
 else
 cmdname = args[0];
 readline_set_completion_index(mon-rs, strlen(cmdname));
-for(cmd = mon_cmds; cmd-name != NULL; cmd++) {
+for (cmd = mon-cmd_table; cmd-name != NULL; cmd++) {
 cmd_completion(mon, cmdname, cmd-name);
 }
 } else {
 /* find the command */
-for (cmd = mon_cmds; cmd-name != NULL; cmd++) {
+for (cmd = mon-cmd_table; cmd-name != NULL; cmd++) {
 if (compare_cmd(args[0], cmd-name)) {
 break;
 }
@@ -4239,7 +4242,7 @@ static void monitor_find_completion(Monitor *mon,
 }
 } else if (!strcmp(cmd-name, help|?)) {
 readline_set_completion_index(mon-rs, strlen(str));
-for (cmd = mon_cmds; cmd-name != NULL; cmd++) {
+for (cmd = mon-cmd_table; cmd-name != NULL; cmd++) {
 cmd_completion(mon, str, cmd-name);
 }
 }
-- 
1.7.1





[Qemu-devel] [PATCH V9 03/15] monitor: avoid use of global *cur_mon in block_completion_it()

2013-08-23 Thread Wenchao Xia
Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
Reviewed-by: Eric Blake ebl...@redhat.com
---
 monitor.c |   18 ++
 1 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/monitor.c b/monitor.c
index 30819fa..6171c75 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4090,14 +4090,21 @@ static void file_completion(Monitor *mon, const char 
*input)
 closedir(ffs);
 }
 
+typedef struct MonitorBlockComplete {
+Monitor *mon;
+const char *input;
+} MonitorBlockComplete;
+
 static void block_completion_it(void *opaque, BlockDriverState *bs)
 {
 const char *name = bdrv_get_device_name(bs);
-const char *input = opaque;
+MonitorBlockComplete *mbc = opaque;
+Monitor *mon = mbc-mon;
+const char *input = mbc-input;
 
 if (input[0] == '\0' ||
 !strncmp(name, (char *)input, strlen(input))) {
-readline_add_completion(cur_mon-rs, name);
+readline_add_completion(mon-rs, name);
 }
 }
 
@@ -4141,6 +4148,7 @@ static void monitor_find_completion(const char *cmdline)
 const char *ptype, *str;
 const mon_cmd_t *cmd;
 Monitor *mon = cur_mon;
+MonitorBlockComplete mbs;
 
 parse_cmdline(cmdline, nb_args, args);
 #ifdef DEBUG_COMPLETION
@@ -4199,8 +4207,10 @@ static void monitor_find_completion(const char *cmdline)
 break;
 case 'B':
 /* block device name completion */
-readline_set_completion_index(cur_mon-rs, strlen(str));
-bdrv_iterate(block_completion_it, (void *)str);
+mbs.mon = mon;
+mbs.input = str;
+readline_set_completion_index(mon-rs, strlen(str));
+bdrv_iterate(block_completion_it, mbs);
 break;
 case 's':
 /* XXX: more generic ? */
-- 
1.7.1





[Qemu-devel] [PATCH V9 01/15] monitor: avoid use of global *cur_mon in cmd_completion()

2013-08-23 Thread Wenchao Xia
A new local variable *mon is added in monitor_find_completion()
to make compile pass, which will be removed later in
conversion patch for monitor_find_completion().

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
Reviewed-by: Eric Blake ebl...@redhat.com
---
 monitor.c |   13 +++--
 1 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/monitor.c b/monitor.c
index da9c9a2..e0154a8 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4008,7 +4008,7 @@ out:
 QDECREF(qdict);
 }
 
-static void cmd_completion(const char *name, const char *list)
+static void cmd_completion(Monitor *mon, const char *name, const char *list)
 {
 const char *p, *pstart;
 char cmd[128];
@@ -4026,7 +4026,7 @@ static void cmd_completion(const char *name, const char 
*list)
 memcpy(cmd, pstart, len);
 cmd[len] = '\0';
 if (name[0] == '\0' || !strncmp(name, cmd, strlen(name))) {
-readline_add_completion(cur_mon-rs, cmd);
+readline_add_completion(mon-rs, cmd);
 }
 if (*p == '\0')
 break;
@@ -4140,6 +4140,7 @@ static void monitor_find_completion(const char *cmdline)
 int nb_args, i, len;
 const char *ptype, *str;
 const mon_cmd_t *cmd;
+Monitor *mon = cur_mon;
 
 parse_cmdline(cmdline, nb_args, args);
 #ifdef DEBUG_COMPLETION
@@ -4165,7 +4166,7 @@ static void monitor_find_completion(const char *cmdline)
 cmdname = args[0];
 readline_set_completion_index(cur_mon-rs, strlen(cmdname));
 for(cmd = mon_cmds; cmd-name != NULL; cmd++) {
-cmd_completion(cmdname, cmd-name);
+cmd_completion(mon, cmdname, cmd-name);
 }
 } else {
 /* find the command */
@@ -4206,7 +4207,7 @@ static void monitor_find_completion(const char *cmdline)
 if (!strcmp(cmd-name, info)) {
 readline_set_completion_index(cur_mon-rs, strlen(str));
 for(cmd = info_cmds; cmd-name != NULL; cmd++) {
-cmd_completion(str, cmd-name);
+cmd_completion(mon, str, cmd-name);
 }
 } else if (!strcmp(cmd-name, sendkey)) {
 char *sep = strrchr(str, '-');
@@ -4214,12 +4215,12 @@ static void monitor_find_completion(const char *cmdline)
 str = sep + 1;
 readline_set_completion_index(cur_mon-rs, strlen(str));
 for (i = 0; i  Q_KEY_CODE_MAX; i++) {
-cmd_completion(str, QKeyCode_lookup[i]);
+cmd_completion(mon, str, QKeyCode_lookup[i]);
 }
 } else if (!strcmp(cmd-name, help|?)) {
 readline_set_completion_index(cur_mon-rs, strlen(str));
 for (cmd = mon_cmds; cmd-name != NULL; cmd++) {
-cmd_completion(str, cmd-name);
+cmd_completion(mon, str, cmd-name);
 }
 }
 break;
-- 
1.7.1





[Qemu-devel] [PATCH V9 00/15] monitor: support sub command group in auto completion and help

2013-08-23 Thread Wenchao Xia
This series make auto completion and help functions works normal for sub
command, by using reentrant functions. In order to do that, global variables
are not directly used in those functions any more. With this series, cmd_table
is a member of structure Monitor so it is possible to create a monitor with
different command table now, auto completion will work in that monitor. In
short, info is not treated as a special case now, this series ensure help
and auto complete function works normal for any sub command added in the future.

Patch 5 replaced cur_mon with rs-mon, it is safe because:
monitor_init() calls readline_init() which initialize mon-rs, result is
mon-rs-mon == mon. Then qemu_chr_add_handlers() is called, which make
monitor_read() function take *mon as its opaque. Later, when user input,
monitor_read() is called, where cur_mon is set to *mon by cur_mon = opaque.
If qemu's monitors run in one thread, then later in readline_handle_byte()
and readline_comletion(), cur_mon is actually equal to rs-mon, in another
word, it points to the monitor instance, so it is safe to replace *cur_mon
in those functions.

Thanks for Luiz and Eric for reviewing.

V2:
  General:
  To discard *info_comds more graceful, help related function is modified to 
support
sub command too.
  Patch 6/7 are added to improve help related functions.
  Patch 5: not directly return to make sure args are freed.

  Address Luiz's comments:
  Split patch into small series.
  struct mon_cmd_t was not moved into header file, instead mon_cmnd_t 
*cmd_table is
added as a member in struct Monitor.
  5/7: drop original code comments for info in monitor_find_completion().

v3:
  5/7: add parameter **args_cmdline in parse_cmdline() to tell next valid
parameter's position. This fix the issue in case command length in input is not
equal to its name's length such as help|?, and the case input start with
space such as   s. 
  7/7: better commit message.

v4:
  Address Eric's comments:
  1/7, 2/7, 4/7: better commit title and message.
  1/7 remove useless (char *) in old code, add space around for () in old 
code.
  3/7: separate code moving patch before usage.
  4/7: add space around for () in old code, add min(nb_args, MAX_ARGS) in free
to make code stronger.

v5:
  4/7: use a  b ? a : b instead of macro min.

v6:
  Address Luiz's comments:
  1/13 ~ 5/13: splitted small patches.
  5/13: added commit message about the correctness of replacing of cur_mon and
test result.
  6/13: better comments in code.
  7/13: added commit message about the reason of code moving.
  8/13: new patch to improve parse_cmdline(), since it is a more generic
function now.
  9/13: reworked the commit message, better commentes in code, use
free_cmdline_args() in clean. It is a bit hard to split this patch into
smaller meaning ful ones, so kepted this patch as a relative larger one,
with better commit message.
  12/13: put case 'S' with case 's' in monitor_find_completion_by_table().
moved this patch ahead of patch 13/13.
  13/13: this patch is moved behind patch 12/13.

  Generic change:
  10/13: splitted patch which moved out the reentrant part into a separate
function, make review easier. This also avoided re-parsing the command line
which does in previous version.
  11/13: splitted patch, which simply remove usage of info_cmds and support
sub command by re-enter the function.

v7:
  Address Luiz's comments:
  5/13: moved the comments why the change is safe, to cover-letter.
  8/13: use assert in free_cmdline_args(), fail when args in input exceed
the limit in parse_cmdline().

v8:
  Address Eric's comments:
  Fix typo in commit messages.

V9:
  General:
  6: new patch, I found that call can be optimized, so move it.
  Address Luiz's comments:
  7: split function to init the monitor.
  8: move the cmd_table init code to parse_cmdlinethe splitted function.
  11: directly return in fail calling parse_cmdline(), in help_cmd_dump().
  Other:
  After discuss with Luiz, it would be good to add test case for qmp fd-add
related stuff. Current test case is 045, which doesn't cover the case
that fd is added by SCM at runtime, and that case is related to monitor.
I have drafted a version, which can pass both on upstream and this series,
but it may require a bit more code, so send it later as another series.

Wenchao Xia (15):
  1 monitor: avoid use of global *cur_mon in cmd_completion()
  2 monitor: avoid use of global *cur_mon in file_completion()
  3 monitor: avoid use of global *cur_mon in block_completion_it()
  4 monitor: avoid use of global *cur_mon in monitor_find_completion()
  5 monitor: avoid use of global *cur_mon in readline_completion()
  6 monitor: call sortcmdlist() only one time
  7 monitor: split off monitor_data_init()
  8 monitor: avoid direct use of global variable *mon_cmds
  9 monitor: code move for parse_cmdline()
  10 monitor: refine parse_cmdline()
  11 monitor: support sub command in help
  12 monitor: refine monitor_find_completion()
  13 monitor: support

[Qemu-devel] [PATCH V9 04/15] monitor: avoid use of global *cur_mon in monitor_find_completion()

2013-08-23 Thread Wenchao Xia
Parameter *mon is added, and local variable *mon added in previous patch
is removed. The caller readline_completion(), pass rs-mon as value, which
should be initialized in readline_init() called by monitor_init().

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
Reviewed-by: Eric Blake ebl...@redhat.com
---
 include/monitor/readline.h |3 ++-
 monitor.c  |   18 +-
 readline.c |2 +-
 3 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/include/monitor/readline.h b/include/monitor/readline.h
index fc9806e..0faf6e1 100644
--- a/include/monitor/readline.h
+++ b/include/monitor/readline.h
@@ -8,7 +8,8 @@
 #define READLINE_MAX_COMPLETIONS 256
 
 typedef void ReadLineFunc(Monitor *mon, const char *str, void *opaque);
-typedef void ReadLineCompletionFunc(const char *cmdline);
+typedef void ReadLineCompletionFunc(Monitor *mon,
+const char *cmdline);
 
 typedef struct ReadLineState {
 char cmd_buf[READLINE_CMD_BUF_SIZE + 1];
diff --git a/monitor.c b/monitor.c
index 6171c75..63a779f 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4140,20 +4140,20 @@ static const char *next_arg_type(const char *typestr)
 return (p != NULL ? ++p : typestr);
 }
 
-static void monitor_find_completion(const char *cmdline)
+static void monitor_find_completion(Monitor *mon,
+const char *cmdline)
 {
 const char *cmdname;
 char *args[MAX_ARGS];
 int nb_args, i, len;
 const char *ptype, *str;
 const mon_cmd_t *cmd;
-Monitor *mon = cur_mon;
 MonitorBlockComplete mbs;
 
 parse_cmdline(cmdline, nb_args, args);
 #ifdef DEBUG_COMPLETION
-for(i = 0; i  nb_args; i++) {
-monitor_printf(cur_mon, arg%d = '%s'\n, i, (char *)args[i]);
+for (i = 0; i  nb_args; i++) {
+monitor_printf(mon, arg%d = '%s'\n, i, args[i]);
 }
 #endif
 
@@ -4172,7 +4172,7 @@ static void monitor_find_completion(const char *cmdline)
 cmdname = ;
 else
 cmdname = args[0];
-readline_set_completion_index(cur_mon-rs, strlen(cmdname));
+readline_set_completion_index(mon-rs, strlen(cmdname));
 for(cmd = mon_cmds; cmd-name != NULL; cmd++) {
 cmd_completion(mon, cmdname, cmd-name);
 }
@@ -4202,7 +4202,7 @@ static void monitor_find_completion(const char *cmdline)
 switch(*ptype) {
 case 'F':
 /* file completion */
-readline_set_completion_index(cur_mon-rs, strlen(str));
+readline_set_completion_index(mon-rs, strlen(str));
 file_completion(mon, str);
 break;
 case 'B':
@@ -4215,7 +4215,7 @@ static void monitor_find_completion(const char *cmdline)
 case 's':
 /* XXX: more generic ? */
 if (!strcmp(cmd-name, info)) {
-readline_set_completion_index(cur_mon-rs, strlen(str));
+readline_set_completion_index(mon-rs, strlen(str));
 for(cmd = info_cmds; cmd-name != NULL; cmd++) {
 cmd_completion(mon, str, cmd-name);
 }
@@ -4223,12 +4223,12 @@ static void monitor_find_completion(const char *cmdline)
 char *sep = strrchr(str, '-');
 if (sep)
 str = sep + 1;
-readline_set_completion_index(cur_mon-rs, strlen(str));
+readline_set_completion_index(mon-rs, strlen(str));
 for (i = 0; i  Q_KEY_CODE_MAX; i++) {
 cmd_completion(mon, str, QKeyCode_lookup[i]);
 }
 } else if (!strcmp(cmd-name, help|?)) {
-readline_set_completion_index(cur_mon-rs, strlen(str));
+readline_set_completion_index(mon-rs, strlen(str));
 for (cmd = mon_cmds; cmd-name != NULL; cmd++) {
 cmd_completion(mon, str, cmd-name);
 }
diff --git a/readline.c b/readline.c
index 1c0f7ee..c91b324 100644
--- a/readline.c
+++ b/readline.c
@@ -285,7 +285,7 @@ static void readline_completion(ReadLineState *rs)
 cmdline = g_malloc(rs-cmd_buf_index + 1);
 memcpy(cmdline, rs-cmd_buf, rs-cmd_buf_index);
 cmdline[rs-cmd_buf_index] = '\0';
-rs-completion_finder(cmdline);
+rs-completion_finder(rs-mon, cmdline);
 g_free(cmdline);
 
 /* no completion found */
-- 
1.7.1





[Qemu-devel] [PATCH V9 06/15] monitor: call sortcmdlist() only one time

2013-08-23 Thread Wenchao Xia
It doesn't need to be done for every monitor, so change it.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
---
 monitor.c |3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/monitor.c b/monitor.c
index 63a779f..bf019e2 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4762,6 +4762,7 @@ void monitor_init(CharDriverState *chr, int flags)
 
 if (is_first_init) {
 monitor_protocol_event_init();
+sortcmdlist();
 is_first_init = 0;
 }
 
@@ -4791,8 +4792,6 @@ void monitor_init(CharDriverState *chr, int flags)
 QLIST_INSERT_HEAD(mon_list, mon, entry);
 if (!default_mon || (flags  MONITOR_IS_DEFAULT))
 default_mon = mon;
-
-sortcmdlist();
 }
 
 static void bdrv_password_cb(Monitor *mon, const char *password, void *opaque)
-- 
1.7.1





[Qemu-devel] [PATCH V9 10/15] monitor: refine parse_cmdline()

2013-08-23 Thread Wenchao Xia
Since this function will be used by help_cmd() later, so improve
it to make it more generic and easier to use. free_cmdline_args()
is added too as paired function to free the result.

One change of this function is that, when the valid args in input
exceed the limit of MAX_ARGS, it fails now, instead of return with
MAX_ARGS of parsed args in old code. This should not impact much
since it is rare that user input many args in monitor's help and
auto complete scenario.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
Reviewed-by: Eric Blake ebl...@redhat.com
---
 monitor.c |   51 ---
 1 files changed, 40 insertions(+), 11 deletions(-)

diff --git a/monitor.c b/monitor.c
index 1db0117..8897291 100644
--- a/monitor.c
+++ b/monitor.c
@@ -821,9 +821,33 @@ static int get_str(char *buf, int buf_size, const char 
**pp)
 
 #define MAX_ARGS 16
 
-/* NOTE: this parser is an approximate form of the real command parser */
-static void parse_cmdline(const char *cmdline,
-  int *pnb_args, char **args)
+static void free_cmdline_args(char **args, int nb_args)
+{
+int i;
+
+assert(nb_args = MAX_ARGS);
+
+for (i = 0; i  nb_args; i++) {
+g_free(args[i]);
+}
+
+}
+
+/*
+ * Parse the command line to get valid args.
+ * @cmdline: command line to be parsed.
+ * @pnb_args: location to store the number of args, must NOT be NULL.
+ * @args: location to store the args, which should be freed by caller, must
+ *NOT be NULL.
+ *
+ * Returns 0 on success, negative on failure.
+ *
+ * NOTE: this parser is an approximate form of the real command parser. Number
+ *   of args have a limit of MAX_ARGS. If cmdline contains more, it will
+ *   return with failure.
+ */
+static int parse_cmdline(const char *cmdline,
+ int *pnb_args, char **args)
 {
 const char *p;
 int nb_args, ret;
@@ -839,16 +863,21 @@ static void parse_cmdline(const char *cmdline,
 break;
 }
 if (nb_args = MAX_ARGS) {
-break;
+goto fail;
 }
 ret = get_str(buf, sizeof(buf), p);
-args[nb_args] = g_strdup(buf);
-nb_args++;
 if (ret  0) {
-break;
+goto fail;
 }
+args[nb_args] = g_strdup(buf);
+nb_args++;
 }
 *pnb_args = nb_args;
+return 0;
+
+ fail:
+free_cmdline_args(args, nb_args);
+return -1;
 }
 
 static void help_cmd_dump(Monitor *mon, const mon_cmd_t *cmds,
@@ -4168,7 +4197,9 @@ static void monitor_find_completion(Monitor *mon,
 const mon_cmd_t *cmd;
 MonitorBlockComplete mbs;
 
-parse_cmdline(cmdline, nb_args, args);
+if (parse_cmdline(cmdline, nb_args, args)  0) {
+return;
+}
 #ifdef DEBUG_COMPLETION
 for (i = 0; i  nb_args; i++) {
 monitor_printf(mon, arg%d = '%s'\n, i, args[i]);
@@ -4258,9 +4289,7 @@ static void monitor_find_completion(Monitor *mon,
 }
 
 cleanup:
-for (i = 0; i  nb_args; i++) {
-g_free(args[i]);
-}
+free_cmdline_args(args, nb_args);
 }
 
 static int monitor_can_read(void *opaque)
-- 
1.7.1





[Qemu-devel] [PATCH V9 11/15] monitor: support sub command in help

2013-08-23 Thread Wenchao Xia
The old code in help_cmd() uses global 'info_cmds' and treats it as a
special case. Actually 'info_cmds' is a sub command group of 'mon_cmds',
in order to avoid direct use of it, help_cmd() needs to change its work
mechanism to support sub command and not treat it as a special case
any more.

To support sub command, help_cmd() will first parse the input and then call
help_cmd_dump(), which works as a reentrant function. When it meets a sub
command, it simply enters the function again. Since help dumping needs to
know whole input to printf full help message include prefix, for example,
help info block need to printf prefix info, so help_cmd_dump() takes all
args from input and extra parameter arg_index to identify the progress.
Another function help_cmd_dump_one() is introduced to printf the prefix
and command's help message.

Now help supports sub command, so later if another sub command group is
added in any depth, help will automatically work for it. Still help info
block will show error since command parser reject additional parameter,
which can be improved later. log is still treated as a special case.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
Reviewed-by: Eric Blake ebl...@redhat.com
---
 monitor.c |   63 +++-
 1 files changed, 53 insertions(+), 10 deletions(-)

diff --git a/monitor.c b/monitor.c
index 8897291..1ace29e 100644
--- a/monitor.c
+++ b/monitor.c
@@ -880,33 +880,76 @@ static int parse_cmdline(const char *cmdline,
 return -1;
 }
 
+static void help_cmd_dump_one(Monitor *mon,
+  const mon_cmd_t *cmd,
+  char **prefix_args,
+  int prefix_args_nb)
+{
+int i;
+
+for (i = 0; i  prefix_args_nb; i++) {
+monitor_printf(mon, %s , prefix_args[i]);
+}
+monitor_printf(mon, %s %s -- %s\n, cmd-name, cmd-params, cmd-help);
+}
+
+/* @args[@arg_index] is the valid command need to find in @cmds */
 static void help_cmd_dump(Monitor *mon, const mon_cmd_t *cmds,
-  const char *prefix, const char *name)
+  char **args, int nb_args, int arg_index)
 {
 const mon_cmd_t *cmd;
 
-for(cmd = cmds; cmd-name != NULL; cmd++) {
-if (!name || !strcmp(name, cmd-name))
-monitor_printf(mon, %s%s %s -- %s\n, prefix, cmd-name,
-   cmd-params, cmd-help);
+/* No valid arg need to compare with, dump all in *cmds */
+if (arg_index = nb_args) {
+for (cmd = cmds; cmd-name != NULL; cmd++) {
+help_cmd_dump_one(mon, cmd, args, arg_index);
+}
+return;
+}
+
+/* Find one entry to dump */
+for (cmd = cmds; cmd-name != NULL; cmd++) {
+if (compare_cmd(args[arg_index], cmd-name)) {
+if (cmd-sub_table) {
+/* continue with next arg */
+help_cmd_dump(mon, cmd-sub_table,
+  args, nb_args, arg_index + 1);
+} else {
+help_cmd_dump_one(mon, cmd, args, arg_index);
+}
+break;
+}
 }
 }
 
 static void help_cmd(Monitor *mon, const char *name)
 {
-if (name  !strcmp(name, info)) {
-help_cmd_dump(mon, info_cmds, info , NULL);
-} else {
-help_cmd_dump(mon, mon-cmd_table, , name);
-if (name  !strcmp(name, log)) {
+char *args[MAX_ARGS];
+int nb_args = 0;
+
+/* 1. parse user input */
+if (name) {
+/* special case for log, directly dump and return */
+if (!strcmp(name, log)) {
 const QEMULogItem *item;
 monitor_printf(mon, Log items (comma separated):\n);
 monitor_printf(mon, %-10s %s\n, none, remove all logs);
 for (item = qemu_log_items; item-mask != 0; item++) {
 monitor_printf(mon, %-10s %s\n, item-name, item-help);
 }
+return;
+}
+
+if (parse_cmdline(name, nb_args, args)  0) {
+return;
 }
 }
+
+/* 2. dump the contents according to parsed args */
+help_cmd_dump(mon, mon-cmd_table, args, nb_args, 0);
+
+cleanup:
+free_cmdline_args(args, nb_args);
 }
 
 static void do_help_cmd(Monitor *mon, const QDict *qdict)
-- 
1.7.1





[Qemu-devel] [PATCH V9 05/15] monitor: avoid use of global *cur_mon in readline_completion()

2013-08-23 Thread Wenchao Xia
Now all completion functions do not use *cur_mon any more, instead
they use rs-mon. In short, structure ReadLineState decide where
the complete action would be taken now.

Tested with the case that qemu have two telnet monitors, auto
completion function works normal.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
Reviewed-by: Eric Blake ebl...@redhat.com
---
 readline.c |3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/readline.c b/readline.c
index c91b324..abf27dd 100644
--- a/readline.c
+++ b/readline.c
@@ -276,7 +276,6 @@ void readline_set_completion_index(ReadLineState *rs, int 
index)
 
 static void readline_completion(ReadLineState *rs)
 {
-Monitor *mon = cur_mon;
 int len, i, j, max_width, nb_cols, max_prefix;
 char *cmdline;
 
@@ -300,7 +299,7 @@ static void readline_completion(ReadLineState *rs)
 if (len  0  rs-completions[0][len - 1] != '/')
 readline_insert_char(rs, ' ');
 } else {
-monitor_printf(mon, \n);
+monitor_printf(rs-mon, \n);
 max_width = 0;
 max_prefix = 0;
 for(i = 0; i  rs-nb_completions; i++) {
-- 
1.7.1





[Qemu-devel] [PATCH V9 02/15] monitor: avoid use of global *cur_mon in file_completion()

2013-08-23 Thread Wenchao Xia
Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
Reviewed-by: Eric Blake ebl...@redhat.com
---
 monitor.c |8 
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/monitor.c b/monitor.c
index e0154a8..30819fa 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4034,7 +4034,7 @@ static void cmd_completion(Monitor *mon, const char 
*name, const char *list)
 }
 }
 
-static void file_completion(const char *input)
+static void file_completion(Monitor *mon, const char *input)
 {
 DIR *ffs;
 struct dirent *d;
@@ -4057,7 +4057,7 @@ static void file_completion(const char *input)
 pstrcpy(file_prefix, sizeof(file_prefix), p + 1);
 }
 #ifdef DEBUG_COMPLETION
-monitor_printf(cur_mon, input='%s' path='%s' prefix='%s'\n,
+monitor_printf(mon, input='%s' path='%s' prefix='%s'\n,
input, path, file_prefix);
 #endif
 ffs = opendir(path);
@@ -4084,7 +4084,7 @@ static void file_completion(const char *input)
 if (stat(file, sb) == 0  S_ISDIR(sb.st_mode)) {
 pstrcat(file, sizeof(file), /);
 }
-readline_add_completion(cur_mon-rs, file);
+readline_add_completion(mon-rs, file);
 }
 }
 closedir(ffs);
@@ -4195,7 +4195,7 @@ static void monitor_find_completion(const char *cmdline)
 case 'F':
 /* file completion */
 readline_set_completion_index(cur_mon-rs, strlen(str));
-file_completion(str);
+file_completion(mon, str);
 break;
 case 'B':
 /* block device name completion */
-- 
1.7.1





[Qemu-devel] [PATCH V9 12/15] monitor: refine monitor_find_completion()

2013-08-23 Thread Wenchao Xia
In order to support sub command in auto completion, a reentrant function
is needed, so monitor_find_completion() is split into two parts. The
first part does parsing of user input which need to be done only once,
the second part does the auto completion job according to the parsing
result, which contains the necessary code to support sub command and
works as the reentrant function. The global info_cmds is still used
in second part, which will be replaced by sub command code later.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
Reviewed-by: Eric Blake ebl...@redhat.com
---
 monitor.c |   65 
 1 files changed, 39 insertions(+), 26 deletions(-)

diff --git a/monitor.c b/monitor.c
index 1ace29e..49a5a88 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4230,34 +4230,17 @@ static const char *next_arg_type(const char *typestr)
 return (p != NULL ? ++p : typestr);
 }
 
-static void monitor_find_completion(Monitor *mon,
-const char *cmdline)
+static void monitor_find_completion_by_table(Monitor *mon,
+ const mon_cmd_t *cmd_table,
+ char **args,
+ int nb_args)
 {
 const char *cmdname;
-char *args[MAX_ARGS];
-int nb_args, i, len;
+int i;
 const char *ptype, *str;
 const mon_cmd_t *cmd;
 MonitorBlockComplete mbs;
 
-if (parse_cmdline(cmdline, nb_args, args)  0) {
-return;
-}
-#ifdef DEBUG_COMPLETION
-for (i = 0; i  nb_args; i++) {
-monitor_printf(mon, arg%d = '%s'\n, i, args[i]);
-}
-#endif
-
-/* if the line ends with a space, it means we want to complete the
-   next arg */
-len = strlen(cmdline);
-if (len  0  qemu_isspace(cmdline[len - 1])) {
-if (nb_args = MAX_ARGS) {
-goto cleanup;
-}
-args[nb_args++] = g_strdup();
-}
 if (nb_args = 1) {
 /* command completion */
 if (nb_args == 0)
@@ -4265,18 +4248,18 @@ static void monitor_find_completion(Monitor *mon,
 else
 cmdname = args[0];
 readline_set_completion_index(mon-rs, strlen(cmdname));
-for (cmd = mon-cmd_table; cmd-name != NULL; cmd++) {
+for (cmd = cmd_table; cmd-name != NULL; cmd++) {
 cmd_completion(mon, cmdname, cmd-name);
 }
 } else {
 /* find the command */
-for (cmd = mon-cmd_table; cmd-name != NULL; cmd++) {
+for (cmd = cmd_table; cmd-name != NULL; cmd++) {
 if (compare_cmd(args[0], cmd-name)) {
 break;
 }
 }
 if (!cmd-name) {
-goto cleanup;
+return;
 }
 
 ptype = next_arg_type(cmd-args_type);
@@ -4321,7 +4304,7 @@ static void monitor_find_completion(Monitor *mon,
 }
 } else if (!strcmp(cmd-name, help|?)) {
 readline_set_completion_index(mon-rs, strlen(str));
-for (cmd = mon-cmd_table; cmd-name != NULL; cmd++) {
+for (cmd = cmd_table; cmd-name != NULL; cmd++) {
 cmd_completion(mon, str, cmd-name);
 }
 }
@@ -4330,6 +4313,36 @@ static void monitor_find_completion(Monitor *mon,
 break;
 }
 }
+}
+
+static void monitor_find_completion(Monitor *mon,
+const char *cmdline)
+{
+char *args[MAX_ARGS];
+int nb_args, len;
+
+/* 1. parse the cmdline */
+if (parse_cmdline(cmdline, nb_args, args)  0) {
+return;
+}
+#ifdef DEBUG_COMPLETION
+for (i = 0; i  nb_args; i++) {
+monitor_printf(mon, arg%d = '%s'\n, i, args[i]);
+}
+#endif
+
+/* if the line ends with a space, it means we want to complete the
+   next arg */
+len = strlen(cmdline);
+if (len  0  qemu_isspace(cmdline[len - 1])) {
+if (nb_args = MAX_ARGS) {
+goto cleanup;
+}
+args[nb_args++] = g_strdup();
+}
+
+/* 2. auto complete according to args */
+monitor_find_completion_by_table(mon, mon-cmd_table, args, nb_args);
 
 cleanup:
 free_cmdline_args(args, nb_args);
-- 
1.7.1





[Qemu-devel] [PATCH V9 07/15] monitor: split off monitor_data_init()

2013-08-23 Thread Wenchao Xia
In qmp_human_monitor_command(), the monitor need to initialized for
basic functionalities, and later more init code will be added, so
split off this function. Note that it is different with QMP mode
monitor which accept json string from monitor's input,
qmp_human_monitor_command() retrieve the human style command from
QMP input, then send the command to a normal mode monitor.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
---
 monitor.c |   20 +++-
 1 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/monitor.c b/monitor.c
index bf019e2..3ac98ef 100644
--- a/monitor.c
+++ b/monitor.c
@@ -683,14 +683,24 @@ static int do_qmp_capabilities(Monitor *mon, const QDict 
*params,
 
 static void handle_user_command(Monitor *mon, const char *cmdline);
 
+static void monitor_data_init(Monitor *mon)
+{
+memset(mon, 0, sizeof(Monitor));
+mon-outbuf = qstring_new();
+}
+
+static void monitor_data_destroy(Monitor *mon)
+{
+QDECREF(mon-outbuf);
+}
+
 char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
 int64_t cpu_index, Error **errp)
 {
 char *output = NULL;
 Monitor *old_mon, hmp;
 
-memset(hmp, 0, sizeof(hmp));
-hmp.outbuf = qstring_new();
+monitor_data_init(hmp);
 hmp.skip_flush = true;
 
 old_mon = cur_mon;
@@ -716,7 +726,7 @@ char *qmp_human_monitor_command(const char *command_line, 
bool has_cpu_index,
 }
 
 out:
-QDECREF(hmp.outbuf);
+monitor_data_destroy(hmp);
 return output;
 }
 
@@ -4766,8 +4776,8 @@ void monitor_init(CharDriverState *chr, int flags)
 is_first_init = 0;
 }
 
-mon = g_malloc0(sizeof(*mon));
-mon-outbuf = qstring_new();
+mon = g_malloc(sizeof(*mon));
+monitor_data_init(mon);
 
 mon-chr = chr;
 mon-flags = flags;
-- 
1.7.1





[Qemu-devel] [PATCH V9 15/15] monitor: improve auto complete of help for single command in sub group

2013-08-23 Thread Wenchao Xia
Now special case help * in auto completion can work with sub commands,
such as help info u*.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
Reviewed-by: Eric Blake ebl...@redhat.com
---
 monitor.c |6 ++
 1 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/monitor.c b/monitor.c
index b657c85..62fc433 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4330,10 +4330,8 @@ static void monitor_find_completion_by_table(Monitor 
*mon,
 cmd_completion(mon, str, QKeyCode_lookup[i]);
 }
 } else if (!strcmp(cmd-name, help|?)) {
-readline_set_completion_index(mon-rs, strlen(str));
-for (cmd = cmd_table; cmd-name != NULL; cmd++) {
-cmd_completion(mon, str, cmd-name);
-}
+monitor_find_completion_by_table(mon, cmd_table,
+ args[1], nb_args - 1);
 }
 break;
 default:
-- 
1.7.1





[Qemu-devel] [PATCH V9 09/15] monitor: code move for parse_cmdline()

2013-08-23 Thread Wenchao Xia
help_cmd() need this function later, so move it. get_str() is called by
parse_cmdline() so it is moved also. Some code style error reported by
check script, is also fixed.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
Reviewed-by: Eric Blake ebl...@redhat.com
---
 monitor.c |  191 +++--
 1 files changed, 98 insertions(+), 93 deletions(-)

diff --git a/monitor.c b/monitor.c
index 8152607..1db0117 100644
--- a/monitor.c
+++ b/monitor.c
@@ -753,6 +753,104 @@ static int compare_cmd(const char *name, const char *list)
 return 0;
 }
 
+static int get_str(char *buf, int buf_size, const char **pp)
+{
+const char *p;
+char *q;
+int c;
+
+q = buf;
+p = *pp;
+while (qemu_isspace(*p)) {
+p++;
+}
+if (*p == '\0') {
+fail:
+*q = '\0';
+*pp = p;
+return -1;
+}
+if (*p == '\') {
+p++;
+while (*p != '\0'  *p != '\') {
+if (*p == '\\') {
+p++;
+c = *p++;
+switch (c) {
+case 'n':
+c = '\n';
+break;
+case 'r':
+c = '\r';
+break;
+case '\\':
+case '\'':
+case '\':
+break;
+default:
+qemu_printf(unsupported escape code: '\\%c'\n, c);
+goto fail;
+}
+if ((q - buf)  buf_size - 1) {
+*q++ = c;
+}
+} else {
+if ((q - buf)  buf_size - 1) {
+*q++ = *p;
+}
+p++;
+}
+}
+if (*p != '\') {
+qemu_printf(unterminated string\n);
+goto fail;
+}
+p++;
+} else {
+while (*p != '\0'  !qemu_isspace(*p)) {
+if ((q - buf)  buf_size - 1) {
+*q++ = *p;
+}
+p++;
+}
+}
+*q = '\0';
+*pp = p;
+return 0;
+}
+
+#define MAX_ARGS 16
+
+/* NOTE: this parser is an approximate form of the real command parser */
+static void parse_cmdline(const char *cmdline,
+  int *pnb_args, char **args)
+{
+const char *p;
+int nb_args, ret;
+char buf[1024];
+
+p = cmdline;
+nb_args = 0;
+for (;;) {
+while (qemu_isspace(*p)) {
+p++;
+}
+if (*p == '\0') {
+break;
+}
+if (nb_args = MAX_ARGS) {
+break;
+}
+ret = get_str(buf, sizeof(buf), p);
+args[nb_args] = g_strdup(buf);
+nb_args++;
+if (ret  0) {
+break;
+}
+}
+*pnb_args = nb_args;
+}
+
 static void help_cmd_dump(Monitor *mon, const mon_cmd_t *cmds,
   const char *prefix, const char *name)
 {
@@ -3433,71 +3531,6 @@ static int get_double(Monitor *mon, double *pval, const 
char **pp)
 return 0;
 }
 
-static int get_str(char *buf, int buf_size, const char **pp)
-{
-const char *p;
-char *q;
-int c;
-
-q = buf;
-p = *pp;
-while (qemu_isspace(*p))
-p++;
-if (*p == '\0') {
-fail:
-*q = '\0';
-*pp = p;
-return -1;
-}
-if (*p == '\') {
-p++;
-while (*p != '\0'  *p != '\') {
-if (*p == '\\') {
-p++;
-c = *p++;
-switch(c) {
-case 'n':
-c = '\n';
-break;
-case 'r':
-c = '\r';
-break;
-case '\\':
-case '\'':
-case '\':
-break;
-default:
-qemu_printf(unsupported escape code: '\\%c'\n, c);
-goto fail;
-}
-if ((q - buf)  buf_size - 1) {
-*q++ = c;
-}
-} else {
-if ((q - buf)  buf_size - 1) {
-*q++ = *p;
-}
-p++;
-}
-}
-if (*p != '\') {
-qemu_printf(unterminated string\n);
-goto fail;
-}
-p++;
-} else {
-while (*p != '\0'  !qemu_isspace(*p)) {
-if ((q - buf)  buf_size - 1) {
-*q++ = *p;
-}
-p++;
-}
-}
-*q = '\0';
-*pp = p;
-return 0;
-}
-
 /*
  * Store the command-name in cmdname, and return a pointer to
  * the remaining of the command string.
@@ -3554,8 +3587,6 @@ static char *key_get_info(const char *type, char **key)
 static int default_fmt_format = 'x';
 static int default_fmt_size = 4;
 
-#define MAX_ARGS 16
-
 static int is_valid_option(const char *c, const char *typestr)
 {
 char option[3

[Qemu-devel] [PATCH V9 14/15] monitor: allow help show message for single command in sub group

2013-08-23 Thread Wenchao Xia
A new parameter type 'S' is introduced to allow user input any string.
help info block works normal now.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
Reviewed-by: Eric Blake ebl...@redhat.com
---
 hmp-commands.hx |2 +-
 monitor.c   |   27 +++
 2 files changed, 28 insertions(+), 1 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 8c6b91a..c161fe9 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -11,7 +11,7 @@ ETEXI
 
 {
 .name   = help|?,
-.args_type  = name:s?,
+.args_type  = name:S?,
 .params = [cmd],
 .help   = show the help,
 .mhandler.cmd = do_help_cmd,
diff --git a/monitor.c b/monitor.c
index 47791b4..b657c85 100644
--- a/monitor.c
+++ b/monitor.c
@@ -83,6 +83,7 @@
  * 'F'  filename
  * 'B'  block device name
  * 's'  string (accept optional quote)
+ * 'S'  it just appends the rest of the string (accept optional quote)
  * 'O'  option string of the form NAME=VALUE,...
  *  parsed according to QemuOptsList given by its name
  *  Example: 'device:O' uses qemu_device_opts.
@@ -4047,6 +4048,31 @@ static const mon_cmd_t *monitor_parse_command(Monitor 
*mon,
 }
 }
 break;
+case 'S':
+{
+/* package all remaining string */
+int len;
+
+while (qemu_isspace(*p)) {
+p++;
+}
+if (*typestr == '?') {
+typestr++;
+if (*p == '\0') {
+/* no remaining string: NULL argument */
+break;
+}
+}
+len = strlen(p);
+if (len = 0) {
+monitor_printf(mon, %s: string expected\n,
+   cmdname);
+break;
+}
+qdict_put(qdict, key, qstring_from_str(p));
+p += len;
+}
+break;
 default:
 bad_type:
 monitor_printf(mon, %s: unknown type '%c'\n, cmdname, c);
@@ -4294,6 +4320,7 @@ static void monitor_find_completion_by_table(Monitor *mon,
 bdrv_iterate(block_completion_it, mbs);
 break;
 case 's':
+case 'S':
 if (!strcmp(cmd-name, sendkey)) {
 char *sep = strrchr(str, '-');
 if (sep)
-- 
1.7.1





[Qemu-devel] [PATCH V9 13/15] monitor: support sub command in auto completion

2013-08-23 Thread Wenchao Xia
This patch allows auto completion work normal for sub command case,
info block [DEVICE] can auto complete now, by re-enter the completion
function. In original code info is treated as a special case, now it
is treated as a sub command group, global variable info_cmds is not used
any more.

help command is still treated as a special case, since it is not a sub
command group but want to auto complete command in root command table.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
Reviewed-by: Eric Blake ebl...@redhat.com
---
 monitor.c |   14 +++---
 1 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/monitor.c b/monitor.c
index 49a5a88..47791b4 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4262,6 +4262,12 @@ static void monitor_find_completion_by_table(Monitor 
*mon,
 return;
 }
 
+if (cmd-sub_table) {
+/* do the job again */
+return monitor_find_completion_by_table(mon, cmd-sub_table,
+args[1], nb_args - 1);
+}
+
 ptype = next_arg_type(cmd-args_type);
 for(i = 0; i  nb_args - 2; i++) {
 if (*ptype != '\0') {
@@ -4288,13 +4294,7 @@ static void monitor_find_completion_by_table(Monitor 
*mon,
 bdrv_iterate(block_completion_it, mbs);
 break;
 case 's':
-/* XXX: more generic ? */
-if (!strcmp(cmd-name, info)) {
-readline_set_completion_index(mon-rs, strlen(str));
-for(cmd = info_cmds; cmd-name != NULL; cmd++) {
-cmd_completion(mon, str, cmd-name);
-}
-} else if (!strcmp(cmd-name, sendkey)) {
+if (!strcmp(cmd-name, sendkey)) {
 char *sep = strrchr(str, '-');
 if (sep)
 str = sep + 1;
-- 
1.7.1





Re: [Qemu-devel] [PATCH V8 00/13] monitor: support sub command group in auto completion and help

2013-08-22 Thread Wenchao Xia

于 2013-8-20 22:04, Luiz Capitulino 写道:

On Tue, 30 Jul 2013 12:03:11 -0400
Luiz Capitulino lcapitul...@redhat.com wrote:


On Fri, 26 Jul 2013 11:20:29 +0800
Wenchao Xia xiaw...@linux.vnet.ibm.com wrote:


This series make auto completion and help functions works normal for sub
command, by using reentrant functions. In order to do that, global variables
are not directly used in those functions any more. With this series, cmd_table
is a member of structure Monitor so it is possible to create a monitor with
different command table now, auto completion will work in that monitor. In
short, info is not treated as a special case now, this series ensure help
and auto complete function works normal for any sub command added in the future.

Patch 5 replaced cur_mon with rs-mon, it is safe because:
monitor_init() calls readline_init() which initialize mon-rs, result is
mon-rs-mon == mon. Then qemu_chr_add_handlers() is called, which make
monitor_read() function take *mon as its opaque. Later, when user input,
monitor_read() is called, where cur_mon is set to *mon by cur_mon = opaque.
If qemu's monitors run in one thread, then later in readline_handle_byte()
and readline_comletion(), cur_mon is actually equal to rs-mon, in another
word, it points to the monitor instance, so it is safe to replace *cur_mon
in those functions.


I've applied this to qmp-next with the change I suggested for
patch 09/13.


Unfortunately this series brakes make check:

GTESTER check-qtest-x86_64
Broken pipe
GTester: last random seed: R02S3492bd34f44dd17460851643383be44d
main-loop: WARNING: I/O thread spun for 1000 iterations
make: *** [check-qtest-x86_64] Error 1

I debugged it (with some help from Laszlo) and the problem is that it
broke the human-monitor-command command. Any usage of this command
triggers the bug like:

{ execute: human-monitor-command,
  arguments: { command-line: info registers } }

It seems simple to fix, I think you just have to initialize
mon-cmd_table in qmp_human_monitor_command(), but I'd recommend two
things:

  1. It's better to split off some/all QMP initialization from
 monitor_init() and call it from qmp_human_monitor_command()

  2. Can you please take the opportunity and test all commands using
 cur_mon? Just grep for it

Sorry for noticing this only now, but I only run make check before
sending a pull request (although this very likely shows you didn't
run it either).


  About the fd related qmp interface, to test it, send_msg() is needed,
which was not supported in python 2, but new added python 3.3. I think
there are three ways to add test cases for fd qmp APIs:
1 test only when python  3.3.
2 python plus C: compile a .so and call it with ctypes.
3 a new test framework: pure C code to call qmp interfaces.
  Which one do you prefer?

--
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH v5 0/8] Implement reference count for BlockDriverState [resend]

2013-08-22 Thread Wenchao Xia

于 2013-8-22 19:38, Stefan Hajnoczi 写道:

On Fri, Aug 09, 2013 at 06:01:53PM +0800, Fam Zheng wrote:

[resend to the correct list]

BlockDriverState lifecycle management is needed by future features such as
image fleecing and blockdev-add. This series adds reference count to
BlockDriverState.

The first two patches clean up two odd BlockDriverState use cases, so all code
uses bdrv_new() to create BlockDriverState instance.

Then implemented bdrv_ref() and bdrv_unref() to operate on refcnt: Initially,
refcnt is 1, which means bdrv_unref is effectively a bdrv_delete() here. So
patch 04 has a search and replace to convert bdrv_delete to bdrv_unref, before
bdrv_ref is used anywhere. 05~08 patches calls bdrv_ref for device attach,
block-migration and nbd.

The rule is: Either bdrv_ref() or bdrv_new() must have a matching
bdrv_unref() call, and the last matching bdrv_unref deletes the bs.

v4:
 08: Added, let block job use BDS reference.
 02: Fix leak of bs.opaque

v3:
 03: Removed unnecessary bdrv_close() call.

v2:
 05: Removed: block: use BlockDriverState refcnt for device attach/detach
 07: Fix xen_disk blk_disconnect() as it depended on device attach refcnt.


Sorry, can't merge this because it breaks qemu-iotests 041 and 055:

   $ ./check -qcow2 055 041

Please always run qemu-iotests before submitting patches.

Stefan


Hi,
  What is the correct steps to run full qemu-iotests?
I modified qemu-iotests-quick.sh as:

#!/bin/sh

# We don't know which of the system emulator binaries there is (or if 
there is

# any at all), so the 'quick' group doesn't contain any tests that require
# running qemu proper. Assign a fake binary name so that qemu-iotests 
doesn't

# complain about the missing binary.
export QEMU_PROG=$(pwd)/x86_64-softmmu/qemu-system-x86_64

export QEMU_IMG_PROG=$(pwd)/qemu-img
export QEMU_IO_PROG=$(pwd)/qemu-io
export QEMU_NBD_PROG=$(pwd)/qemu-nbd

cd $SRC_PATH/tests/qemu-iotests

ret=0
./check -T -nocache -qcow2 || ret=1

exit $ret

  Then make check-block, 026 038 fail, 038 sometimes fail.
The code from is upstream, host is RH6.3 @ x86_64. Do I missed some
steps?
--
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH V8 00/13] monitor: support sub command group in auto completion and help

2013-08-21 Thread Wenchao Xia

于 2013-8-20 22:04, Luiz Capitulino 写道:

On Tue, 30 Jul 2013 12:03:11 -0400
Luiz Capitulino lcapitul...@redhat.com wrote:


On Fri, 26 Jul 2013 11:20:29 +0800
Wenchao Xia xiaw...@linux.vnet.ibm.com wrote:


This series make auto completion and help functions works normal for sub
command, by using reentrant functions. In order to do that, global variables
are not directly used in those functions any more. With this series, cmd_table
is a member of structure Monitor so it is possible to create a monitor with
different command table now, auto completion will work in that monitor. In
short, info is not treated as a special case now, this series ensure help
and auto complete function works normal for any sub command added in the future.

Patch 5 replaced cur_mon with rs-mon, it is safe because:
monitor_init() calls readline_init() which initialize mon-rs, result is
mon-rs-mon == mon. Then qemu_chr_add_handlers() is called, which make
monitor_read() function take *mon as its opaque. Later, when user input,
monitor_read() is called, where cur_mon is set to *mon by cur_mon = opaque.
If qemu's monitors run in one thread, then later in readline_handle_byte()
and readline_comletion(), cur_mon is actually equal to rs-mon, in another
word, it points to the monitor instance, so it is safe to replace *cur_mon
in those functions.


I've applied this to qmp-next with the change I suggested for
patch 09/13.


Unfortunately this series brakes make check:

GTESTER check-qtest-x86_64
Broken pipe
GTester: last random seed: R02S3492bd34f44dd17460851643383be44d
main-loop: WARNING: I/O thread spun for 1000 iterations
make: *** [check-qtest-x86_64] Error 1

I debugged it (with some help from Laszlo) and the problem is that it
broke the human-monitor-command command. Any usage of this command
triggers the bug like:

{ execute: human-monitor-command,
  arguments: { command-line: info registers } }

It seems simple to fix, I think you just have to initialize
mon-cmd_table in qmp_human_monitor_command(), but I'd recommend two
things:

  1. It's better to split off some/all QMP initialization from
 monitor_init() and call it from qmp_human_monitor_command()

  2. Can you please take the opportunity and test all commands using
 cur_mon? Just grep for it

Sorry for noticing this only now, but I only run make check before
sending a pull request (although this very likely shows you didn't
run it either).


  My bad that not ran make check before, will fix and retry, sorry for
the trouble.

--
Best Regards

Wenchao Xia




Re: [Qemu-devel] [RFC] Convert AioContext to Gsource sub classes

2013-08-21 Thread Wenchao Xia

于 2013-8-21 16:45, Stefan Hajnoczi 写道:

On Tue, Aug 20, 2013 at 05:59:58PM +0800, Wenchao Xia wrote:

于 2013-8-16 16:12, Wenchao Xia 写道:

于 2013-8-16 15:15, Wenchao Xia 写道:

于 2013-8-16 0:32, Michael Roth 写道:

Quoting Michael Roth (2013-08-15 10:23:20)

Quoting Wenchao Xia (2013-08-13 03:44:39)

于 2013-8-13 1:01, Michael Roth 写道:

Quoting Paolo Bonzini (2013-08-12 02:30:28)

1) rename AioContext to AioSource.
This is my major purpose, which declare it is not a context
concept,
and GMainContext is the entity represent the thread's activity.


Note that the nested event loops in QEMU are _very_ different from
glib nested event loops.  In QEMU, nested event loops only run block
layer events.  In glib, they run all events.  That's why you need
AioContext.


Would it be possible to use glib for our nested loops as well by just
setting a higher priority for the AioContext GSource?

Stefan and I were considering how we could make use of his drop
ioflush patches to use a common mechanism to register fd events, but
still allow us to distinguish between AioContext and non-AioContext
for nested loops. I was originally thinking of using prepare()
functions
to filter out non-AioContext events, but that requires we implement
on GSource's with that in mind, and non make use of pre-baked ones
like GIOChannel's, and bakes block stuff into every event source
implementation.


Besides priority, also g_source_set_can_recurse() can help.
With a deeper think, I found a harder problem:
g_main_context_acquire() and g_main_context_release(). In release,
pending BH/IO call back need to be cleared, but this action can't
be triggered automatically when user call g_main_context_release().


I don't understand why this is a requirement, gmctx_acquire/release
ensure
that only one thread attempts to iterate the main loop at a time. this
isn't currently an issue in qemu, and if we re-implemented
qemu_aio_wait()
to use the same glib interfaces, the tracking of in-flight requests
would
be moved to the block layer via Stefan's 'drop io_flush' patches, which
moves that block-specific logic out of the main loop/AioContext GSource
by design. Are there other areas where you see this as a problem?


I think I understand better what you're referring to, you mean that
if qemu_aio_wait was called, and was implementated to essentially call
g_main_context_iterate(), that after, say, 1 iteration, the
iothread/dataplane thread might acquire the main loop and dispatch
block/non-block events between qemu_aio_wait() returned? The simple
approach would be to have qemu_aio_wait() call
g_main_context_acquire/release
at the start end of the function, which would ensure that this never
happens.


   qemu_aio_wait() is relative simple to resolve by
g_main_context_acquire(), but also shows additional code needed
for a thread switch:
(guess following is the plan to implement qemu_aio_wait())
qemu_aio_wait(GMainContext *ctx)
{
 return g_main_context(ctx, PRI_BLOCK);
}
at caller:
{
 while (qemu_aio_wait(ctx) {
 ;
 }
 g_main_context_release(ctx);
}
   The above code shows that, in *ctx switch operation, there is
more than glib's own event loop API envolved, qemu_aio_wait(). So
it referenced to a question: what data structure
should be used to represent context concept and control the thread
switching behavior?  It is better to have a clear layer, GMainContext or
GlibQContext, instead of GMainContext plus custom function. The caller
reference to at least two: nested user block layer, flat user above
block layer.
   In my opinion, this problem is brought by Gsource AioContext, Take
the call path of bdrv_aio_readv(*bdrv_cb) on raw linux file as
an example, there are aync following operations involved for AioContext:
1 the bdrv_cb() will be executed in bdrv_co_em_bh().
2 bdrv_co_io_em_complete() will be executed in event_notfier_ready().
3 aio_worker() will be executed in worker_thread().
   Operation 2 and 3 are tracked by block layer's queue after Stefan's
dropping io_flush() series.
   Now if we stick to GMainContext to represent context concept,
then when thread B want to aquire GMainContext used by thread A,
all works setupped by A should be finished before B aquire it,
otherwise B will execute some function supposed to work in A. The
work refers to the three kind of aync functions above.
   For this issue, we can solve it by different means:
1 the event loop API doesn't guarentee work setupped by thread A
will always be finished in A. This put a limitation to caller to
consider thread switching. I talked on IRC with Stefan, and thinks
it is possible for the nested user block layer, but I still want to
avoid this to the flat user above block layer.
2 ask caller to finish all pending operations.
   2.1 glib GMainContext API plus custom API such as aio_wait(). This is
bad that detail under GMainContext is exposed to caller. Since
operation 1 mentioned before is not tracked yet, to make sure bdrv_cb()
is called in thread setupped

Re: [Qemu-devel] [PATCHv11 13/31] aio / timers: aio_ctx_prepare sets timeout from AioContext timers

2013-08-20 Thread Wenchao Xia

于 2013-8-20 14:48, Alex Bligh 写道:


  for (bh = ctx-first_bh; bh; bh = bh-next) {
  if (!bh-deleted  bh-scheduled) {
  if (bh-idle) {
  /* idle bottom halves will be polled at least
   * every 10ms */
-*timeout = 10;
+*timeout = qemu_soonest_timeout(*timeout, 10);

glib will not set *timeout to a meaningful value before calling
aio_ctx_prepare(), right? If so, *timeout = 10 should be used.



I don't think that's correct. Each _prepare routine is called
and has the abilitiy to alter the timeout but need not
set it at all. Indeed it should not set it as there may already
be a shorter timeout there.

Here's the code before I touched it:

aio_ctx_prepare(GSource *source, gint*timeout)
{
 AioContext *ctx = (AioContext *) source;
 QEMUBH *bh;

 for (bh = ctx-first_bh; bh; bh = bh-next) {
 if (!bh-deleted  bh-scheduled) {
 if (bh-idle) {
 /* idle bottom halves will be polled at least
  * every 10ms */
 *timeout = 10;
 } else {
 /* non-idle bottom halves will be executed
  * immediately */
 *timeout = 0;
 return true;
 }
 }
 }

 return false;
}

You'll note that what this does is:
a) if there are no bottom halves, leaves *timeout as is
b) if there is a non-idle bottom half, set timeout to 0
c) else set timeout to 10 if there are only idle bottom
halves.

Arguably (c) is a bug if timeout was shorter than 10
on entry but the whole of idle bhs are a bit of a bodge.
This is fixed by my series.

If you are asking WHERE it gets set to -1, I don't claim
to be a glib expert but I believe it's the line
   gint source_timeout = -1
around line 2816 in glib/gmain.c


  Thanks for the explanation. It seems *timeout is always set
to -1 before calling GSource's prepare(), so
*timeout = qemu_soonest_timeout(*timeout, 10);
will always get *timeout = 10, so this call can be saved.
--
Best Regards

Wenchao Xia




Re: [Qemu-devel] [RFC] Convert AioContext to Gsource sub classes

2013-08-20 Thread Wenchao Xia

于 2013-8-16 16:12, Wenchao Xia 写道:

于 2013-8-16 15:15, Wenchao Xia 写道:

于 2013-8-16 0:32, Michael Roth 写道:

Quoting Michael Roth (2013-08-15 10:23:20)

Quoting Wenchao Xia (2013-08-13 03:44:39)

于 2013-8-13 1:01, Michael Roth 写道:

Quoting Paolo Bonzini (2013-08-12 02:30:28)

1) rename AioContext to AioSource.
This is my major purpose, which declare it is not a context
concept,
and GMainContext is the entity represent the thread's activity.


Note that the nested event loops in QEMU are _very_ different from
glib nested event loops.  In QEMU, nested event loops only run block
layer events.  In glib, they run all events.  That's why you need
AioContext.


Would it be possible to use glib for our nested loops as well by just
setting a higher priority for the AioContext GSource?

Stefan and I were considering how we could make use of his drop
ioflush patches to use a common mechanism to register fd events, but
still allow us to distinguish between AioContext and non-AioContext
for nested loops. I was originally thinking of using prepare()
functions
to filter out non-AioContext events, but that requires we implement
on GSource's with that in mind, and non make use of pre-baked ones
like GIOChannel's, and bakes block stuff into every event source
implementation.


Besides priority, also g_source_set_can_recurse() can help.
With a deeper think, I found a harder problem:
g_main_context_acquire() and g_main_context_release(). In release,
pending BH/IO call back need to be cleared, but this action can't
be triggered automatically when user call g_main_context_release().


I don't understand why this is a requirement, gmctx_acquire/release
ensure
that only one thread attempts to iterate the main loop at a time. this
isn't currently an issue in qemu, and if we re-implemented
qemu_aio_wait()
to use the same glib interfaces, the tracking of in-flight requests
would
be moved to the block layer via Stefan's 'drop io_flush' patches, which
moves that block-specific logic out of the main loop/AioContext GSource
by design. Are there other areas where you see this as a problem?


I think I understand better what you're referring to, you mean that
if qemu_aio_wait was called, and was implementated to essentially call
g_main_context_iterate(), that after, say, 1 iteration, the
iothread/dataplane thread might acquire the main loop and dispatch
block/non-block events between qemu_aio_wait() returned? The simple
approach would be to have qemu_aio_wait() call
g_main_context_acquire/release
at the start end of the function, which would ensure that this never
happens.


   qemu_aio_wait() is relative simple to resolve by
g_main_context_acquire(), but also shows additional code needed
for a thread switch:
(guess following is the plan to implement qemu_aio_wait())
qemu_aio_wait(GMainContext *ctx)
{
 return g_main_context(ctx, PRI_BLOCK);
}
at caller:
{
 while (qemu_aio_wait(ctx) {
 ;
 }
 g_main_context_release(ctx);
}
   The above code shows that, in *ctx switch operation, there is
more than glib's own event loop API envolved, qemu_aio_wait(). So
it referenced to a question: what data structure
should be used to represent context concept and control the thread
switching behavior?  It is better to have a clear layer, GMainContext or
GlibQContext, instead of GMainContext plus custom function. The caller
reference to at least two: nested user block layer, flat user above
block layer.
   In my opinion, this problem is brought by Gsource AioContext, Take
the call path of bdrv_aio_readv(*bdrv_cb) on raw linux file as
an example, there are aync following operations involved for AioContext:
1 the bdrv_cb() will be executed in bdrv_co_em_bh().
2 bdrv_co_io_em_complete() will be executed in event_notfier_ready().
3 aio_worker() will be executed in worker_thread().
   Operation 2 and 3 are tracked by block layer's queue after Stefan's
dropping io_flush() series.
   Now if we stick to GMainContext to represent context concept,
then when thread B want to aquire GMainContext used by thread A,
all works setupped by A should be finished before B aquire it,
otherwise B will execute some function supposed to work in A. The
work refers to the three kind of aync functions above.
   For this issue, we can solve it by different means:
1 the event loop API doesn't guarentee work setupped by thread A
will always be finished in A. This put a limitation to caller to
consider thread switching. I talked on IRC with Stefan, and thinks
it is possible for the nested user block layer, but I still want to
avoid this to the flat user above block layer.
2 ask caller to finish all pending operations.
   2.1 glib GMainContext API plus custom API such as aio_wait(). This is
bad that detail under GMainContext is exposed to caller. Since
operation 1 mentioned before is not tracked yet, to make sure bdrv_cb()
is called in thread setupped it, 1 need to be added in the track
queue, or in the call chain of aio_wait(), check the queue plus

Re: [Qemu-devel] [PATCHv11 13/31] aio / timers: aio_ctx_prepare sets timeout from AioContext timers

2013-08-20 Thread Wenchao Xia

于 2013-8-20 17:29, Alex Bligh 写道:


On 20 Aug 2013, at 08:19, Wenchao Xia wrote:


  Thanks for the explanation. It seems *timeout is always set
to -1 before calling GSource's prepare(), so
*timeout = qemu_soonest_timeout(*timeout, 10);
will always get *timeout = 10, so this call can be saved.


I believe that's incorrect too. glib *currently* calls
the API that way, but there's nothing to say a future
or past glub couldn't call each g_source with the same
timeout pointer, with each g_source adjusting the timeout
downwards. Or (for instance) call it with 0 for a

  So it is an undefined value, should avoid use it?
For example, other gsource have minimum timeout of 5, and
aio_ctx_prepare() is called with 0, then returned timeout
is 0, but it is supposed to work with timeout 5 as the glib
doc described:
https://developer.gnome.org/glib/2.32/glib-The-Main-Event-Loop.html#GSourceFuncs

That is my opinion, but I haven't read other project's
code about prepare() usage, so can't be sure. Guess maintainer
can give a conclusion.



non-blocking prepare. Therefore the implemented way
is safer (only reducing the timeout).


--
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCHv11 13/31] aio / timers: aio_ctx_prepare sets timeout from AioContext timers

2013-08-19 Thread Wenchao Xia
于 2013-8-16 4:34, Alex Bligh 写道:
 Calculate the timeout in aio_ctx_prepare taking into account
 the timers attached to the AioContext.
 
 Alter aio_ctx_check similarly.
 
 Signed-off-by: Alex Bligh a...@alex.org.uk
 ---
   async.c |   13 +++--
   1 file changed, 11 insertions(+), 2 deletions(-)
 
 diff --git a/async.c b/async.c
 index 2b9ba9b..d8656cc 100644
 --- a/async.c
 +++ b/async.c
 @@ -150,13 +150,14 @@ aio_ctx_prepare(GSource *source, gint*timeout)
   {
   AioContext *ctx = (AioContext *) source;
   QEMUBH *bh;
 +int deadline;
 
   for (bh = ctx-first_bh; bh; bh = bh-next) {
   if (!bh-deleted  bh-scheduled) {
   if (bh-idle) {
   /* idle bottom halves will be polled at least
* every 10ms */
 -*timeout = 10;
 +*timeout = qemu_soonest_timeout(*timeout, 10);
glib will not set *timeout to a meaningful value before calling
aio_ctx_prepare(), right? If so, *timeout = 10 should be used.

   } else {
   /* non-idle bottom halves will be executed
* immediately */
 @@ -166,6 +167,14 @@ aio_ctx_prepare(GSource *source, gint*timeout)
   }
   }
 
 +deadline = qemu_timeout_ns_to_ms(timerlistgroup_deadline_ns(ctx-tlg));
 +if (deadline == 0) {
 +*timeout = 0;
 +return true;
 +} else {
 +*timeout = qemu_soonest_timeout(*timeout, deadline);
 +}
 +
   return false;
   }
 
 @@ -180,7 +189,7 @@ aio_ctx_check(GSource *source)
   return true;
   }
   }
 -return aio_pending(ctx);
 +return aio_pending(ctx) || (timerlistgroup_deadline_ns(ctx-tlg) == 0);
   }
 
   static gboolean
 


-- 
Best Regards

Wenchao Xia




Re: [Qemu-devel] [RFC] Convert AioContext to Gsource sub classes

2013-08-16 Thread Wenchao Xia

于 2013-8-16 0:32, Michael Roth 写道:

Quoting Michael Roth (2013-08-15 10:23:20)

Quoting Wenchao Xia (2013-08-13 03:44:39)

于 2013-8-13 1:01, Michael Roth 写道:

Quoting Paolo Bonzini (2013-08-12 02:30:28)

1) rename AioContext to AioSource.
This is my major purpose, which declare it is not a context concept,
and GMainContext is the entity represent the thread's activity.


Note that the nested event loops in QEMU are _very_ different from
glib nested event loops.  In QEMU, nested event loops only run block
layer events.  In glib, they run all events.  That's why you need
AioContext.


Would it be possible to use glib for our nested loops as well by just
setting a higher priority for the AioContext GSource?

Stefan and I were considering how we could make use of his drop
ioflush patches to use a common mechanism to register fd events, but
still allow us to distinguish between AioContext and non-AioContext
for nested loops. I was originally thinking of using prepare() functions
to filter out non-AioContext events, but that requires we implement
on GSource's with that in mind, and non make use of pre-baked ones
like GIOChannel's, and bakes block stuff into every event source
implementation.


Besides priority, also g_source_set_can_recurse() can help.
With a deeper think, I found a harder problem:
g_main_context_acquire() and g_main_context_release(). In release,
pending BH/IO call back need to be cleared, but this action can't
be triggered automatically when user call g_main_context_release().


I don't understand why this is a requirement, gmctx_acquire/release ensure
that only one thread attempts to iterate the main loop at a time. this
isn't currently an issue in qemu, and if we re-implemented qemu_aio_wait()
to use the same glib interfaces, the tracking of in-flight requests would
be moved to the block layer via Stefan's 'drop io_flush' patches, which
moves that block-specific logic out of the main loop/AioContext GSource
by design. Are there other areas where you see this as a problem?


I think I understand better what you're referring to, you mean that
if qemu_aio_wait was called, and was implementated to essentially call
g_main_context_iterate(), that after, say, 1 iteration, the
iothread/dataplane thread might acquire the main loop and dispatch
block/non-block events between qemu_aio_wait() returned? The simple
approach would be to have qemu_aio_wait() call g_main_context_acquire/release
at the start end of the function, which would ensure that this never
happens.

  qemu_aio_wait() is relative simple to resolve by 
g_main_context_acquire(), but also shows additional code needed

for a thread switch:
(guess following is the plan to implement qemu_aio_wait())
qemu_aio_wait(GMainContext *ctx)
{
return g_main_context(ctx, PRI_BLOCK);
}
at caller:
{
while (qemu_aio_wait(ctx) {
;
}
g_main_context_release(ctx);
}
  The above code shows that, in *ctx switch operation, there is
more than glib's own event loop API envolved, qemu_aio_wait(). So
it referenced to a question: what data structure
should be used to represent context concept and control the thread
switching behavior?  It is better to have a clear layer, GMainContext or
GlibQContext, instead of GMainContext plus custom function. The caller
reference to at least two: nested user block layer, flat user above
block layer.
  In my opinion, this problem is brought by Gsource AioContext, Take
the call path of bdrv_aio_readv(*bdrv_cb) on raw linux file as
an example, there are aync following operations involved for AioContext:
1 the bdrv_cb() will be executed in bdrv_co_em_bh().
2 bdrv_co_io_em_complete() will be executed in event_notfier_ready().
3 aio_worker() will be executed in worker_thread().
  Operation 2 and 3 are tracked by block layer's queue after Stefan's
dropping io_flush() series.
  Now if we stick to GMainContext to represent context concept,
then when thread B want to aquire GMainContext used by thread A,
all works setupped by A should be finished before B aquire it,
otherwise B will execute some function supposed to work in A. The
work refers to the three kind of aync functions above.
  For this issue, we can solve it by different means:
1 the event loop API doesn't guarentee work setupped by thread A
will always be finished in A. This put a limitation to caller to
consider thread switching. I talked on IRC with Stefan, and thinks
it is possible for the nested user block layer, but I still want to
avoid this to the flat user above block layer.
2 ask caller to finish all pending operations.
  2.1 glib GMainContext API plus custom API such as aio_wait(). This is
bad that detail under GMainContext is exposed to caller. Since
operation 1 mentioned before is not tracked yet, to make sure bdrv_cb()
is called in thread setupped it, 1 need to be added in the track
queue, or in the call chain of aio_wait(), check the queue plus check
operation 1. Perhaps add a custom function ask caller to call

Re: [Qemu-devel] [RFC] Convert AioContext to Gsource sub classes

2013-08-16 Thread Wenchao Xia

于 2013-8-16 15:15, Wenchao Xia 写道:

于 2013-8-16 0:32, Michael Roth 写道:

Quoting Michael Roth (2013-08-15 10:23:20)

Quoting Wenchao Xia (2013-08-13 03:44:39)

于 2013-8-13 1:01, Michael Roth 写道:

Quoting Paolo Bonzini (2013-08-12 02:30:28)

1) rename AioContext to AioSource.
This is my major purpose, which declare it is not a context
concept,
and GMainContext is the entity represent the thread's activity.


Note that the nested event loops in QEMU are _very_ different from
glib nested event loops.  In QEMU, nested event loops only run block
layer events.  In glib, they run all events.  That's why you need
AioContext.


Would it be possible to use glib for our nested loops as well by just
setting a higher priority for the AioContext GSource?

Stefan and I were considering how we could make use of his drop
ioflush patches to use a common mechanism to register fd events, but
still allow us to distinguish between AioContext and non-AioContext
for nested loops. I was originally thinking of using prepare()
functions
to filter out non-AioContext events, but that requires we implement
on GSource's with that in mind, and non make use of pre-baked ones
like GIOChannel's, and bakes block stuff into every event source
implementation.


Besides priority, also g_source_set_can_recurse() can help.
With a deeper think, I found a harder problem:
g_main_context_acquire() and g_main_context_release(). In release,
pending BH/IO call back need to be cleared, but this action can't
be triggered automatically when user call g_main_context_release().


I don't understand why this is a requirement, gmctx_acquire/release
ensure
that only one thread attempts to iterate the main loop at a time. this
isn't currently an issue in qemu, and if we re-implemented
qemu_aio_wait()
to use the same glib interfaces, the tracking of in-flight requests
would
be moved to the block layer via Stefan's 'drop io_flush' patches, which
moves that block-specific logic out of the main loop/AioContext GSource
by design. Are there other areas where you see this as a problem?


I think I understand better what you're referring to, you mean that
if qemu_aio_wait was called, and was implementated to essentially call
g_main_context_iterate(), that after, say, 1 iteration, the
iothread/dataplane thread might acquire the main loop and dispatch
block/non-block events between qemu_aio_wait() returned? The simple
approach would be to have qemu_aio_wait() call
g_main_context_acquire/release
at the start end of the function, which would ensure that this never
happens.


   qemu_aio_wait() is relative simple to resolve by
g_main_context_acquire(), but also shows additional code needed
for a thread switch:
(guess following is the plan to implement qemu_aio_wait())
qemu_aio_wait(GMainContext *ctx)
{
 return g_main_context(ctx, PRI_BLOCK);
}
at caller:
{
 while (qemu_aio_wait(ctx) {
 ;
 }
 g_main_context_release(ctx);
}
   The above code shows that, in *ctx switch operation, there is
more than glib's own event loop API envolved, qemu_aio_wait(). So
it referenced to a question: what data structure
should be used to represent context concept and control the thread
switching behavior?  It is better to have a clear layer, GMainContext or
GlibQContext, instead of GMainContext plus custom function. The caller
reference to at least two: nested user block layer, flat user above
block layer.
   In my opinion, this problem is brought by Gsource AioContext, Take
the call path of bdrv_aio_readv(*bdrv_cb) on raw linux file as
an example, there are aync following operations involved for AioContext:
1 the bdrv_cb() will be executed in bdrv_co_em_bh().
2 bdrv_co_io_em_complete() will be executed in event_notfier_ready().
3 aio_worker() will be executed in worker_thread().
   Operation 2 and 3 are tracked by block layer's queue after Stefan's
dropping io_flush() series.
   Now if we stick to GMainContext to represent context concept,
then when thread B want to aquire GMainContext used by thread A,
all works setupped by A should be finished before B aquire it,
otherwise B will execute some function supposed to work in A. The
work refers to the three kind of aync functions above.
   For this issue, we can solve it by different means:
1 the event loop API doesn't guarentee work setupped by thread A
will always be finished in A. This put a limitation to caller to
consider thread switching. I talked on IRC with Stefan, and thinks
it is possible for the nested user block layer, but I still want to
avoid this to the flat user above block layer.
2 ask caller to finish all pending operations.
   2.1 glib GMainContext API plus custom API such as aio_wait(). This is
bad that detail under GMainContext is exposed to caller. Since
operation 1 mentioned before is not tracked yet, to make sure bdrv_cb()
is called in thread setupped it, 1 need to be added in the track
queue, or in the call chain of aio_wait(), check the queue plus check
operation 1. Perhaps add a custom

Re: [Qemu-devel] [PATCH 7/9] iohandler: associate with main event loop via a QSource

2013-08-15 Thread Wenchao Xia
,
+ IOCanReadHandler *fd_read_poll,
+ IOHandler *fd_read,
+ IOHandler *fd_write,
+ void *opaque)
  {
-IOHandlerRecord *ioh;
-
-QLIST_FOREACH(ioh, io_handlers, next) {
-int events = 0;
-
-if (ioh-deleted)
-continue;
-if (ioh-fd_read 
-(!ioh-fd_read_poll ||
- ioh-fd_read_poll(ioh-opaque) != 0)) {
-events |= G_IO_IN | G_IO_HUP | G_IO_ERR;
-}
-if (ioh-fd_write) {
-events |= G_IO_OUT | G_IO_ERR;
-}
-if (events) {
-GPollFD pfd = {
-.fd = ioh-fd,
-.events = events,
-};
-ioh-pollfds_idx = pollfds-len;
-g_array_append_val(pollfds, pfd);
-} else {
-ioh-pollfds_idx = -1;
-}
-}
+return set_fd_handler2(qemu_get_qcontext(), fd,
+   fd_read_poll, fd_read, fd_write,
+   opaque);
  }

-void qemu_iohandler_poll(GArray *pollfds, int ret)
+int qemu_set_fd_handler(int fd,
+IOHandler *fd_read,
+IOHandler *fd_write,
+void *opaque)
  {
-if (ret  0) {
-IOHandlerRecord *pioh, *ioh;
-
-QLIST_FOREACH_SAFE(ioh, io_handlers, next, pioh) {
-int revents = 0;
-
-if (!ioh-deleted  ioh-pollfds_idx != -1) {
-GPollFD *pfd = g_array_index(pollfds, GPollFD,
-  ioh-pollfds_idx);
-revents = pfd-revents;
-}
-
-if (!ioh-deleted  ioh-fd_read 
-(revents  (G_IO_IN | G_IO_HUP | G_IO_ERR))) {
-ioh-fd_read(ioh-opaque);
-}
-if (!ioh-deleted  ioh-fd_write 
-(revents  (G_IO_OUT | G_IO_ERR))) {
-ioh-fd_write(ioh-opaque);
-}
-
-/* Do this last in case read/write handlers marked it for deletion 
*/
-if (ioh-deleted) {
-QLIST_REMOVE(ioh, next);
-g_free(ioh);
-}
-}
-}
+return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque);
  }

  /* reaping of zombies.  right now we're not passing the status to
diff --git a/main-loop.c b/main-loop.c
index f46aece..ae284a6 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -27,6 +27,8 @@
  #include slirp/slirp.h
  #include qemu/main-loop.h
  #include block/aio.h
+#include qcontext/qcontext.h
+#include qcontext/glib-qcontext.h

  #ifndef _WIN32

@@ -107,6 +109,13 @@ static int qemu_signal_init(void)
  }
  #endif

+static QContext *qemu_qcontext;
+
+QContext *qemu_get_qcontext(void)
+{
+return qemu_qcontext;
+}
+
  static AioContext *qemu_aio_context;

  AioContext *qemu_get_aio_context(void)
@@ -128,6 +137,7 @@ int qemu_init_main_loop(void)
  {
  int ret;
  GSource *src;
+Error *err = NULL;

  init_clocks();
  if (init_timer_alarm()  0) {
@@ -135,6 +145,15 @@ int qemu_init_main_loop(void)
  exit(1);
  }

+qemu_qcontext = QCONTEXT(glib_qcontext_new(main, false, err));
+if (err) {
+g_warning(error initializing main qcontext);
+error_free(err);
+return -1;
+}
+
+iohandler_attach(qemu_qcontext);
+
  ret = qemu_signal_init();
  if (ret) {
  return ret;
@@ -464,9 +483,7 @@ int main_loop_wait(int nonblocking)
  slirp_update_timeout(timeout);
  slirp_pollfds_fill(gpollfds);
  #endif
-qemu_iohandler_fill(gpollfds);
  ret = os_host_main_loop_wait(timeout);
-qemu_iohandler_poll(gpollfds, ret);
  #ifdef CONFIG_SLIRP
  slirp_pollfds_poll(gpollfds, (ret  0));
  #endif







--
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH] Introduce cache images for the QCOW2 format

2013-08-15 Thread Wenchao Xia

于 2013-8-14 23:32, Kevin Wolf 写道:

Am 14.08.2013 um 16:26 hat Kaveh Razavi geschrieben:

On 08/14/2013 03:50 PM, Alex Bligh wrote:

Assuming the cache quota is not exhausted, how do you know how that
a VM has finished 'creating' the cache? At any point it might
read a bit more from the backing image.


I was assuming on shutdown.


Wait, so you're not really changing the cache while it's used, but you
only create it once and then use it like a regular backing file?  If so,
the only thing we need to talk about is the creation, because there's no
difference for using it.

Creation can use the existing copy-on-read functionality, and the only
thing you need additionally is a way to turn copy-on-read off at the
right point.

Or do I misunderstand what you're doing?

Kevin


  This cache capability seems have little to do with qcow2, but a
general block function: start/stop copy on read for one BS in a backing
chain. If so, suggest:
1 refine existing general copy on read code, not in qcow2.c but general
block code, make it able to start/stop copy on read for a BDS in the
chain.
2 add qmp interface for it.

Then the work flow will be:
step 1: prepare image, not related to qcow2 format.
qemu-img create cache.img -b base.img
qemu-img create vm1.img -b cache.img

step 2: boot vm1, vm2:
qemu -hda vm1.img -COR cache.img
qemu -hda vm2.img

--
Best Regards

Wenchao Xia




Re: [Qemu-devel] Are there plans to achieve ram live Snapshot feature?

2013-08-15 Thread Wenchao Xia

于 2013-8-15 15:49, Stefan Hajnoczi 写道:

On Thu, Aug 15, 2013 at 10:26:36AM +0800, Wenchao Xia wrote:

于 2013-8-14 15:53, Stefan Hajnoczi 写道:

On Wed, Aug 14, 2013 at 3:54 AM, Wenchao Xia xiaw...@linux.vnet.ibm.com wrote:

于 2013-8-13 16:21, Stefan Hajnoczi 写道:


On Tue, Aug 13, 2013 at 4:53 AM, Wenchao Xia xiaw...@linux.vnet.ibm.com
wrote:


于 2013-8-12 19:33, Stefan Hajnoczi 写道:


On Mon, Aug 12, 2013 at 12:26 PM, Alex Bligh a...@alex.org.uk wrote:



--On 12 August 2013 11:59:03 +0200 Stefan Hajnoczi stefa...@gmail.com
wrote:


The idea that was discussed on qemu-devel@nongnu.org uses fork(2) to
capture the state of guest RAM and then send it back to the parent
process.  The guest is only paused for a brief instant during fork(2)
and can continue to run afterwards.





How would you capture the state of emulated hardware which might not
be in the guest RAM?




Exactly the same way vmsave works today.  It calls the device's save
functions which serialize state to file.

The difference between today's vmsave and the fork(2) approach is that
QEMU does not need to wait for guest RAM to be written to file before
resuming the guest.

Stefan


 I have a worry about what glib says:

On Unix, the GLib mainloop is incompatible with fork(). Any program
using the mainloop must either exec() or exit() from the child without
returning to the mainloop. 



This is fine, the child just writes out the memory pages and exits.
It never returns to the glib mainloop.


 There is another way to do it: intercept the write in kvm.ko(or other
kernel code). Since the key is intercept the memory change, we can do
it in userspace in TCG mode, thus we can add the missing part in KVM
mode. Another benefit of this way is: the used memory can be
controlled. For example, with ioctl(), set a buffer of a fixed size
which keeps the intercepted write data by kernel code, which can avoid
frequently switch back to user space qemu code. when it is full always
return back to userspace's qemu code, let qemu code save the data into
disk. I haven't check the exactly behavior of Intel guest mode about
how to handle page fault, so can't estimate the performance caused by
switching of guest mode and root mode, but it should not be worse than
fork().



The fork(2) approach is portable, covers both KVM and TCG, and doesn't
require kernel changes.  A kvm.ko kernel change also won't be
supported on existing KVM hosts.  These are big drawbacks and the
kernel approach would need to be significantly better than plain old
fork(2) to make it worthwhile.

Stefan


I think advantage is memory usage is predictable, so memory usage
peak can be avoided, by always save the changed pages first. fork()
does not know which pages are changed. I am not sure if this would
be a serious issue when server's memory is consumed much, for example,
24G host emulate 11G*2 guest to provide powerful virtual server.


Memory usage is predictable but guest uptime is unpredictable because
it waits until memory is written out.  This defeats the point of
live savevm.  The guest may be stalled arbitrarily.


   I think it is adjustable. There is no much difference with
fork(), except get more precise control about the changed pages.
   Kernel intercept the change, and stores the changed page in another
page, similar to fork(). When userspace qemu code execute, save some
pages to disk. Buffer can be used like some lubricant. When Buffer =
MAX, it equals to fork(), guest runs more lively. When Buffer = 0,
guest runs less lively. I think it allows user to find a good balance
point with a parameter.
   It is harder to implement, just want to show the idea.


You are right.  You could set a bigger buffer size to increase guest
uptime.


The fork child can minimize the chance of out-of-memory by using
madvise(MADV_DONTNEED) after pages have been written out.

   It seems no way to make sure the written out page is the changed
pages, so it have a good chance the written one is the unchanged and
still used by the other qemu process.


The KVM dirty log tells you which pages were touched.  The fork child
process could give priority to the pages which have been touched by the
guest.  They must be written out and marked madvise(MADV_DONTNEED) as
soon as possible.

  Hmm, if dirty log still works normal in child process to reflect the
memory status in parent not child's, then the problem could be solved
by: when dirty pages is too much, child tell parent to wait some time.
But I haven't check if kvm.ko behaviors like that.



I haven't looked at the vmsave data format yet to see if memory pages
can be saved in random order, but this might work.  It reduces the
likelihood of copy-on-write memory growth.

Stefan




--
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH V7 0/8] add internal snapshot support at block device level

2013-08-15 Thread Wenchao Xia
于 2013-8-7 11:00, Wenchao Xia 写道:
This series brings internal snapshot support at block devices level, now we
 have two three methods to do block snapshot lively: 1) backing chain,
 2) internal one and 3) drive-back up approach.
 
 Comparation:
   Advantages:Disadvantages:
 1)delta data, taken fast, export, sizeperformance, delete slow.
 2)  taken fast, delete fast, performance, size   delta data, format
 3)  performance, export, format  taken slow, delta data, size, host 
 I/O
 
I think in most case, saving vmstate in an standalone file is better than
 saving it inside qcow2, So suggest treat internal snapshot as block level
 methods and not encourage user to savevm in qcow2 any more.
 
 Implemention details:
To avoid trouble, this serial have hide ID in create interfaces, this make
 sure no chaos of ID and name will be introduced by these interfaces.
There is one patch may be common to Pavel's savvm transaction, patch 1/11,
 others are not quite related. Patch 1/11 will not set errp when no snapshot
 find, since patch 3/11 need to distinguish real error case.
 
 Next steps to better full VM snapshot:
Improve internal snapshot's export capability.
Better vmstate saving.
 
Thanks Kevin to give advisement about how add it in qmp_transaction, oldest
 version comes drom Dietmar Maurer.
 
 v3:
General:
Rebased after Stenfan's driver-backup patch V6.
 
Address Eric's comments:
4/9: grammar fix and better doc.
5/9: parameter name is mandatory now. grammar fix.
6/9: redesiged interface: take both id and name as optional parameter, 
 return
 the deleted snapshot's info.
 
Address Stefan's comments:
4/9: add '' around %s in message. drop code comments about vm_clock.
9/9: better doc, refined the code and add more test case.
 
 v4:
Address Stefan's comments:
4/9: use error_setg_errno() to show error reason for 
 bdrv_snapshot_create(),
 spell fix and better doc.
5/9: better doc.
6/9: remove spurious ';' in code, spell fix and better doc.
 
 v5:
Address Kevin's comments:
3/8, 4/8, 8/8: remove the limit of numeric snapshot name.
General change:
4/8: use existing type as parameter in qapi schema.
 
 v6:
Address Stefan's comments:
2/8: macro STR_PRINT_CHAR was renamed as STR_OR_NULL, and moved into patch 
 5,
 since implement function in this patch do not printf snapshot id any more, as
 Kevin's suggestion.
Address Kevin's comments:
2/8: remove device, id, name info in the error message, use error message 
 in
 existing caller. A new function bdrv_snapshot_delete_by_id_or_name() is added
 to make the usage clear while keep logic unchanged.
3/8: remove device info in error message when name is empty. Use else if
 after call of bdrv_snapshot_find_by_id_and_name().
Other:
2/8: refined the comments in code for bdrv_snapshot_delete().
3/8: in error reporting, change format from reason is: '%s' to
 reason is: %s.
 
 v7:
rebased on upstream, target for 1.7.
 
 Wenchao Xia (8):
1 snapshot: new function bdrv_snapshot_find_by_id_and_name()
2 snapshot: distinguish id and name in snapshot delete
3 qmp: add internal snapshot support in qmp_transaction
4 qmp: add interface blockdev-snapshot-internal-sync
5 qmp: add interface blockdev-snapshot-delete-internal-sync
6 hmp: add interface hmp_snapshot_blkdev_internal
7 hmp: add interface hmp_snapshot_delete_blkdev_internal
8 qemu-iotests: add 057 internal snapshot for block device test case
 
   block/qcow2-snapshot.c |   55 +++---
   block/qcow2.h  |5 +-
   block/rbd.c|   21 -
   block/sheepdog.c   |5 +-
   block/snapshot.c   |  131 ++-
   blockdev.c |  190 
   hmp-commands.hx|   37 ++-
   hmp.c  |   22 
   hmp.h  |2 +
   include/block/block_int.h  |5 +-
   include/block/snapshot.h   |   14 +++-
   include/qemu-common.h  |3 +
   qapi-schema.json   |   66 +++-
   qemu-img.c |   11 ++-
   qmp-commands.hx|  104 --
   savevm.c   |   32 +++---
   tests/qemu-iotests/057 |  259 
 
   tests/qemu-iotests/057.out |5 +
   tests/qemu-iotests/group   |1 +
   19 files changed, 914 insertions(+), 54 deletions(-)
   create mode 100755 tests/qemu-iotests/057
   create mode 100644 tests/qemu-iotests/057.out
 
 
  Any comments for it?


-- 
Best Regards

Wenchao Xia




Re: [Qemu-devel] Are there plans to achieve ram live Snapshot feature?

2013-08-14 Thread Wenchao Xia
于 2013-8-14 15:53, Stefan Hajnoczi 写道:
 On Wed, Aug 14, 2013 at 3:54 AM, Wenchao Xia xiaw...@linux.vnet.ibm.com 
 wrote:
 于 2013-8-13 16:21, Stefan Hajnoczi 写道:

 On Tue, Aug 13, 2013 at 4:53 AM, Wenchao Xia xiaw...@linux.vnet.ibm.com
 wrote:

 于 2013-8-12 19:33, Stefan Hajnoczi 写道:

 On Mon, Aug 12, 2013 at 12:26 PM, Alex Bligh a...@alex.org.uk wrote:


 --On 12 August 2013 11:59:03 +0200 Stefan Hajnoczi stefa...@gmail.com
 wrote:

 The idea that was discussed on qemu-devel@nongnu.org uses fork(2) to
 capture the state of guest RAM and then send it back to the parent
 process.  The guest is only paused for a brief instant during fork(2)
 and can continue to run afterwards.




 How would you capture the state of emulated hardware which might not
 be in the guest RAM?



 Exactly the same way vmsave works today.  It calls the device's save
 functions which serialize state to file.

 The difference between today's vmsave and the fork(2) approach is that
 QEMU does not need to wait for guest RAM to be written to file before
 resuming the guest.

 Stefan

 I have a worry about what glib says:

 On Unix, the GLib mainloop is incompatible with fork(). Any program
 using the mainloop must either exec() or exit() from the child without
 returning to the mainloop. 


 This is fine, the child just writes out the memory pages and exits.
 It never returns to the glib mainloop.

 There is another way to do it: intercept the write in kvm.ko(or other
 kernel code). Since the key is intercept the memory change, we can do
 it in userspace in TCG mode, thus we can add the missing part in KVM
 mode. Another benefit of this way is: the used memory can be
 controlled. For example, with ioctl(), set a buffer of a fixed size
 which keeps the intercepted write data by kernel code, which can avoid
 frequently switch back to user space qemu code. when it is full always
 return back to userspace's qemu code, let qemu code save the data into
 disk. I haven't check the exactly behavior of Intel guest mode about
 how to handle page fault, so can't estimate the performance caused by
 switching of guest mode and root mode, but it should not be worse than
 fork().


 The fork(2) approach is portable, covers both KVM and TCG, and doesn't
 require kernel changes.  A kvm.ko kernel change also won't be
 supported on existing KVM hosts.  These are big drawbacks and the
 kernel approach would need to be significantly better than plain old
 fork(2) to make it worthwhile.

 Stefan

I think advantage is memory usage is predictable, so memory usage
 peak can be avoided, by always save the changed pages first. fork()
 does not know which pages are changed. I am not sure if this would
 be a serious issue when server's memory is consumed much, for example,
 24G host emulate 11G*2 guest to provide powerful virtual server.
 
 Memory usage is predictable but guest uptime is unpredictable because
 it waits until memory is written out.  This defeats the point of
 live savevm.  The guest may be stalled arbitrarily.
 
  I think it is adjustable. There is no much difference with
fork(), except get more precise control about the changed pages.
  Kernel intercept the change, and stores the changed page in another
page, similar to fork(). When userspace qemu code execute, save some
pages to disk. Buffer can be used like some lubricant. When Buffer =
MAX, it equals to fork(), guest runs more lively. When Buffer = 0,
guest runs less lively. I think it allows user to find a good balance
point with a parameter.
  It is harder to implement, just want to show the idea.

 The fork child can minimize the chance of out-of-memory by using
 madvise(MADV_DONTNEED) after pages have been written out.
  It seems no way to make sure the written out page is the changed
pages, so it have a good chance the written one is the unchanged and
still used by the other qemu process.

 
 The way fork handles memory overcommit on Linux is configurable, but I
 guess in a situation where memory runs out the Out-of-Memory Killer
 will kill a process (probably QEMU since it is hogging so much
 memory).
 
 The risk of OOM can be avoided by running the traditional vmsave which
 stops the guest instead of using live vmsave.
 
 The other option is to live migrate to file but the disadvantage there
 is that you cannot choose exactly when the state it saved, it happens
 sometime after live migration is initiated.
 
 There are trade-offs with all the approaches, it depends on what is
 most important to you.
 
 Stefan
 


-- 
Best Regards

Wenchao Xia




Re: [Qemu-devel] [RFC] Convert AioContext to Gsource sub classes

2013-08-13 Thread Wenchao Xia

于 2013-8-13 1:01, Michael Roth 写道:

Quoting Paolo Bonzini (2013-08-12 02:30:28)

1) rename AioContext to AioSource.
   This is my major purpose, which declare it is not a context concept,
and GMainContext is the entity represent the thread's activity.


Note that the nested event loops in QEMU are _very_ different from
glib nested event loops.  In QEMU, nested event loops only run block
layer events.  In glib, they run all events.  That's why you need
AioContext.


Would it be possible to use glib for our nested loops as well by just
setting a higher priority for the AioContext GSource?

Stefan and I were considering how we could make use of his drop
ioflush patches to use a common mechanism to register fd events, but
still allow us to distinguish between AioContext and non-AioContext
for nested loops. I was originally thinking of using prepare() functions
to filter out non-AioContext events, but that requires we implement
on GSource's with that in mind, and non make use of pre-baked ones
like GIOChannel's, and bakes block stuff into every event source
implementation.


  Besides priority, also g_source_set_can_recurse() can help.
  With a deeper think, I found a harder problem:
g_main_context_acquire() and g_main_context_release(). In release,
pending BH/IO call back need to be cleared, but this action can't
be triggered automatically when user call g_main_context_release().
  For the above reason, I tend to think, maybe we should t wrap all of
Glib's mainloop into custom encapsulation, such as QContext, Add the
aio poll logic in q_context_release(). Use QContext * in every caller
to hide GMainContext *, so QContext layer play the role of clear
event loop API.


Priorities didn't cross my mind though, but it seems pretty
straightfoward...

AioContext could then just be a container of sorts for managing
bottom-halves and AioContext FDs and binding them to the proper
GMainContext/MainLoop, but the underlying GSources could
still be driven by a normal glib-based mainloop, just with a specific
priority in the nested case.




2) Break AioSource into FdSource and BhSource.
   This make custom code less and simpler, one Gsource for one kind of
job. It is not necessary but IMHO it will make things clear when add
more things into main loop: add a new Gsource sub class, avoid to
always have relationship with AioContext.


But this is only complicating things work since users rely on both file-
descriptor APIs and bottom half APIs.


Taking things a step further, maybe AioContext can stop being a
block-specific construct, but actually be the QContext we've
discussed in the past for managing multiple event loops. All
the block stuff would be hidden away in the GSource priority.

For instance,

#ifndef _WIN32

qemu_aio_set_fd_handler(fd, ...):
 aio_set_fd_handler(qemu_aio_context, fd, ..., QEMU_PRIORITY_BLOCK)

qemu_set_fd_handler(fd, ...):
 aio_set_fd_handler(qemu_aio_context, fd, ..., G_PRIORITY_DEFAULT)

#else

qemu_add_wait_object(fd, ...):
 add_wait_object(qemu_aio_context, fd, ...)

qemu_set_fd_handler(fd, ...):
 set_socket_handler(qemu_aio_context, fd, ..., G_PRIORITY_DEFAULT)

#endif

qemu_bh_schedule:
 bh_schedule(qemu_aio_context, ...)

etc...

I'll be sending patches this week for moving
add_wait_object/qemu_set_fd_handler to GSources, the non-global ones use
GMainContext * to specify a non-default thread/context, but can be easily
changed, or we can just do aioctx-g_main_context at the call sites.
There's some nice possibilities in using the former though: avoiding
O(n) lookups for stuff like finding the GSource for a particular
event/event type, for instance, by storing pointers to the GSource or
some kind of hashmap lookup. But probably better to discuss that aspect
with some context so I'll try to get those patches out soon.




More reasons:
When I thinking how to bind library code to a thread context, it may
need to add Context's concept into API of block.c. If I use AioContext,
there will need a wrapper API to run the event loop. But If I got
glib's GmainContext, things become simple.


You already have it because AioContext is a GSource.  You do not need
to expose the AioContext, except as a GSource.


  I think expose GmainContext * or QContext *, is better than
GSource *.

int bdrv_read(GMainContext *ctx,
  BlockDriverState *bs,
  int64_t sector_num,
  uint8_t *buf,
  int nb_sectors)


Paolo





--
Best Regards

Wenchao Xia




Re: [Qemu-devel] Are there plans to achieve ram live Snapshot feature?

2013-08-13 Thread Wenchao Xia

于 2013-8-13 16:21, Stefan Hajnoczi 写道:

On Tue, Aug 13, 2013 at 4:53 AM, Wenchao Xia xiaw...@linux.vnet.ibm.com wrote:

于 2013-8-12 19:33, Stefan Hajnoczi 写道:


On Mon, Aug 12, 2013 at 12:26 PM, Alex Bligh a...@alex.org.uk wrote:


--On 12 August 2013 11:59:03 +0200 Stefan Hajnoczi stefa...@gmail.com
wrote:


The idea that was discussed on qemu-devel@nongnu.org uses fork(2) to
capture the state of guest RAM and then send it back to the parent
process.  The guest is only paused for a brief instant during fork(2)
and can continue to run afterwards.




How would you capture the state of emulated hardware which might not
be in the guest RAM?



Exactly the same way vmsave works today.  It calls the device's save
functions which serialize state to file.

The difference between today's vmsave and the fork(2) approach is that
QEMU does not need to wait for guest RAM to be written to file before
resuming the guest.

Stefan


   I have a worry about what glib says:

On Unix, the GLib mainloop is incompatible with fork(). Any program
using the mainloop must either exec() or exit() from the child without
returning to the mainloop. 


This is fine, the child just writes out the memory pages and exits.
It never returns to the glib mainloop.


   There is another way to do it: intercept the write in kvm.ko(or other
kernel code). Since the key is intercept the memory change, we can do
it in userspace in TCG mode, thus we can add the missing part in KVM
mode. Another benefit of this way is: the used memory can be
controlled. For example, with ioctl(), set a buffer of a fixed size
which keeps the intercepted write data by kernel code, which can avoid
frequently switch back to user space qemu code. when it is full always
return back to userspace's qemu code, let qemu code save the data into
disk. I haven't check the exactly behavior of Intel guest mode about
how to handle page fault, so can't estimate the performance caused by
switching of guest mode and root mode, but it should not be worse than
fork().


The fork(2) approach is portable, covers both KVM and TCG, and doesn't
require kernel changes.  A kvm.ko kernel change also won't be
supported on existing KVM hosts.  These are big drawbacks and the
kernel approach would need to be significantly better than plain old
fork(2) to make it worthwhile.

Stefan


  I think advantage is memory usage is predictable, so memory usage
peak can be avoided, by always save the changed pages first. fork()
does not know which pages are changed. I am not sure if this would
be a serious issue when server's memory is consumed much, for example,
24G host emulate 11G*2 guest to provide powerful virtual server.

--
Best Regards

Wenchao Xia




Re: [Qemu-devel] [RFC] Convert AioContext to Gsource sub classes

2013-08-12 Thread Wenchao Xia
 Il 10/08/2013 05:24, Wenchao Xia ha scritto:
 Hi folks,
I'd like form a series which remove AioContext's concept and
 bind to glib's main loop more closely. Since changed place will be
 a bit much so want to know your opinion before real coding:
 
 I'm not sure I understand...  What does it buy you to split AioContext
 this way?  First, BhSource and FdSource are needed by block drivers, and
 BhSource needs the notifier to interrupt the main loop.  Second,
 AioContext is _already_ a GSource exactly to integrate closely with
 GLib's main loop.  Look at the series that introduced AioContext back in
 October 2012.  The main AioContext is already added as a GSource to the
 iothread's main loop; aio_wait is used in dataplane for simplicity, but
 it could also use a separate GMainLoop and add AioContext there as a
 GSource.
 
 Paolo
 
  It has two parts:
1) rename AioContext to AioSource.
  This is my major purpose, which declare it is not a context concept,
and GMainContext is the entity represent the thread's activity. This
can prevent people add wrapper API such as g_main_context_acquire(),
g_main_context_prepare(See qcontext_prepare() in QContext patch). As a
result, standard glib's main loop API can be exposed, so I can add
GMainContext into block layer or any other API layer, instead of
custom encapsulation. For example:
int bdrv_read(GMainContext *ctx,
  BlockDriverState *bs,
  int64_t sector_num,
  uint8_t *buf,
  int nb_sectors)
  In short, it avoid wrapper for GMainContext. I agree AioContext is
_already_ a GSource sub class now, there is no difficult to add
GMainContext *ctx for AioContext's reason. But I am afraid it becomes
not true with more patches comes, since the name is mis-guiding.

2) Break AioSource into FdSource and BhSource.
  This make custom code less and simpler, one Gsource for one kind of
job. It is not necessary but IMHO it will make things clear when add
more things into main loop: add a new Gsource sub class, avoid to
always have relationship with AioContext.

 changes:
 **before patch:
 typedef struct AioContext {
  GSource source;
  int walking_handlers;
  QemuMutex bh_lock;
  struct QEMUBH *first_bh;
  int walking_bh;
  EventNotifier notifier;
  GArray *pollfds;
  struct ThreadPool *thread_pool;
 } AioContext;

 **After patch:
 typedef struct BhSource {
  GSource source;
  QemuMutex bh_lock;
  struct QEMUBH *first_bh;
  int walking_bh;
 } BhSource;

 typedef struct FdSource {
  GSource source;
  int walking_handlers;
  EventNotifier notifier;
  GArray *pollfds;
  struct ThreadPool *thread_pool;
 } FdSource;

 Benefits:
Original code have a mix of Gsource and GMainContext's concept, we
 may want to add wrapper functions around GMainContext's functions, such
 as g_main_context_acquire(), g_main_context_prepare(), which brings
 extra effort if you want to form a good and clear API layer. With
 this changes, all qemu's custom code is attached under Gsource, we
 have a clear GMainContext's API layer for event loop, no wrapper is
 needed, and the event's loop API is glib's API, a clear layer let
 me form a library or adding more things.

 before:
 qemu's mainloop caller,  BH user, fd user
|
 AioContext
|
  GMainContext


 after:
 qemu's mainloop caller
  |   BH userfd user
 GmainContext   | |
  ||--BhSource |
   |-FdSource


 Note:
FdSource could be split more into ThreadSource and FdSource, which
 distinguish more. It can be done easily if the change of this series
 is online, when found necessary.

More reasons:
When I thinking how to bind library code to a thread context, it may
 need to add Context's concept into API of block.c. If I use AioContext,
 there will need a wrapper API to run the event loop. But If I got
 glib's GmainContext, things become simple.
 


-- 
Best Regards

Wenchao Xia




Re: [Qemu-devel] [RFC] [PATCHv8 09/30] aio / timers: Add QEMUTimerListGroup and helper functions

2013-08-12 Thread Wenchao Xia

于 2013-8-10 19:05, Alex Bligh 写道:

Paolo,

On 9 Aug 2013, at 15:59, Paolo Bonzini wrote:


It's not papering over anything.

Timers right now are provided by the event loop.  If you make
AioContexts have timers, you can have a new AioContext for the timers
that the event loop handles before your patches.

It's not related to having two nested event loops.  The nested event
loops have the problem that timers do not run in them, but it's also a
feature---because you know exactly what code runs in the nested event
loop and what doesn't.  Using an entirely distinct event loop preserves
the feature.


I've submitted a first cut as a separate patch just to see whether
it works:
   http://lists.nongnu.org/archive/html/qemu-devel/2013-08/msg01412.html

It passes 'make check' anyway.

I didn't wrap TimerListGroup into a separate struct for reasons
I'll set out below.

I think there are two ways to go here:

1. Wrap TimerListGroup into a separate struct, leave all the
TimerListGroup functions in. This probably makes it easier if
(for instance) we decided to get rid of AioContexts entirely
and make them g_source subclasses (per Wenchao Xia).


  I have a quick view of this series, but not very carefully since
it is quite long.:) I have replied with Paolo's comments on my
RFC thread. Personally I like g_source sub class, which make code
clear, but let's discuss first if the direction is right in that mail.



2. Remove the TimerListGroup thing entirely and just have
an array of TimerLists of size QEMU_CLOCK_MAX. I can
leave the things that iterate that array inside qemu_timer.c
(which I'd rather do for encapsulation). Part of the
problem with the old timer code was that there were (in
my opinion) far too many files that were working out what
to iterate, and I really don't want to reintroduce that.

Despite the fact we both dislike the name TimerListGroup, I
think the way to go here is (1). (2) does not really save lines
of code (certainly not compiled instructions) - it's main saving
is removing a pile of commenting from include/qemu/timer.h,
which makes things more opaque.

I also think there may well be a use for something that wants
to use timers but not AioContext (I am thinking for instance
of a thread that does not do block IO). This permits that,
but does not require it.

WDYT?




--
Best Regards

Wenchao Xia




Re: [Qemu-devel] Are there plans to achieve ram live Snapshot feature?

2013-08-12 Thread Wenchao Xia

于 2013-8-12 19:33, Stefan Hajnoczi 写道:

On Mon, Aug 12, 2013 at 12:26 PM, Alex Bligh a...@alex.org.uk wrote:

--On 12 August 2013 11:59:03 +0200 Stefan Hajnoczi stefa...@gmail.com
wrote:


The idea that was discussed on qemu-devel@nongnu.org uses fork(2) to
capture the state of guest RAM and then send it back to the parent
process.  The guest is only paused for a brief instant during fork(2)
and can continue to run afterwards.



How would you capture the state of emulated hardware which might not
be in the guest RAM?


Exactly the same way vmsave works today.  It calls the device's save
functions which serialize state to file.

The difference between today's vmsave and the fork(2) approach is that
QEMU does not need to wait for guest RAM to be written to file before
resuming the guest.

Stefan


  I have a worry about what glib says:

On Unix, the GLib mainloop is incompatible with fork(). Any program
using the mainloop must either exec() or exit() from the child without
returning to the mainloop. 

  There is another way to do it: intercept the write in kvm.ko(or other
kernel code). Since the key is intercept the memory change, we can do
it in userspace in TCG mode, thus we can add the missing part in KVM
mode. Another benefit of this way is: the used memory can be
controlled. For example, with ioctl(), set a buffer of a fixed size
which keeps the intercepted write data by kernel code, which can avoid
frequently switch back to user space qemu code. when it is full always
return back to userspace's qemu code, let qemu code save the data into
disk. I haven't check the exactly behavior of Intel guest mode about
how to handle page fault, so can't estimate the performance caused by
switching of guest mode and root mode, but it should not be worse than
fork().


--
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH v6 00/18] aio: drop io_flush()

2013-08-09 Thread Wenchao Xia
 +
  tests/test-thread-pool.c| 24 ++--
  thread-pool.c   | 11 +-
  19 files changed, 163 insertions(+), 288 deletions(-)


Ping?


  I tried to apply this series to do more work above it, but seems
code conflict with upstream.

--
Best Regards

Wenchao Xia




[Qemu-devel] [RFC] Convert AioContext to Gsource sub classes

2013-08-09 Thread Wenchao Xia
Hi folks,
  I'd like form a series which remove AioContext's concept and
bind to glib's main loop more closely. Since changed place will be
a bit much so want to know your opinion before real coding:

changes:
**before patch:
typedef struct AioContext {
GSource source;
int walking_handlers;
QemuMutex bh_lock;
struct QEMUBH *first_bh;
int walking_bh;
EventNotifier notifier;
GArray *pollfds;
struct ThreadPool *thread_pool;
} AioContext;

**After patch:
typedef struct BhSource {
GSource source;
QemuMutex bh_lock;
struct QEMUBH *first_bh;
int walking_bh;
} BhSource;

typedef struct FdSource {
GSource source;
int walking_handlers;
EventNotifier notifier;
GArray *pollfds;
struct ThreadPool *thread_pool;
} FdSource;

Benefits:
  Original code have a mix of Gsource and GMainContext's concept, we
may want to add wrapper functions around GMainContext's functions, such
as g_main_context_acquire(), g_main_context_prepare(), which brings
extra effort if you want to form a good and clear API layer. With
this changes, all qemu's custom code is attached under Gsource, we
have a clear GMainContext's API layer for event loop, no wrapper is
needed, and the event's loop API is glib's API, a clear layer let
me form a library or adding more things.

before:
qemu's mainloop caller,  BH user, fd user
  |
   AioContext
  |
GMainContext


after:
qemu's mainloop caller
|   BH userfd user
GmainContext   | |
||--BhSource |
 |-FdSource


Note:
  FdSource could be split more into ThreadSource and FdSource, which
distinguish more. It can be done easily if the change of this series
is online, when found necessary.

  More reasons:
  When I thinking how to bind library code to a thread context, it may
need to add Context's concept into API of block.c. If I use AioContext,
there will need a wrapper API to run the event loop. But If I got
glib's GmainContext, things become simple.
-- 
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH v6 01/18] block: ensure bdrv_drain_all() works during bdrv_delete()

2013-08-06 Thread Wenchao Xia

On Fri, Jul 26, 2013 at 02:43:44PM +0800, Wenchao Xia wrote:

Reviewed-by: Wenchao Xia xiaw...@linux.vnet.ibm.com

One question: old code missed itself in bdrv_drain_all(), is that a bug?


Sorry, I don't understand the question.  Can you rephrase it?


  Before this patch, in the code path: bdrv_close()-bdrv_drain_all(),
the *bs does not exist in bdrv_states, so the code missed the chance to
drain the request on *bs. That is a bug, and this patch is actually a
bugfix?



In bdrv_delete() make sure to call bdrv_make_anon() *after* bdrv_close()
so that the device is still seen by bdrv_drain_all() when iterating
bdrv_states.

Cc: qemu-sta...@nongnu.org
Signed-off-by: Stefan Hajnoczi stefa...@redhat.com
---
   block.c | 4 ++--
   1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/block.c b/block.c
index 6cd39fa..9d68270 100644
--- a/block.c
+++ b/block.c
@@ -1600,11 +1600,11 @@ void bdrv_delete(BlockDriverState *bs)
   assert(!bs-job);
   assert(!bs-in_use);

+bdrv_close(bs);
+
   /* remove from list, if necessary */
   bdrv_make_anon(bs);

-bdrv_close(bs);
-
   g_free(bs);
   }




--
Best Regards

Wenchao Xia







--
Best Regards

Wenchao Xia




[Qemu-devel] [PATCH V7 8/8] qemu-iotests: add 057 internal snapshot for block device test case

2013-08-06 Thread Wenchao Xia
Create in transaction and deletion in single command will be tested.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
---
 tests/qemu-iotests/057 |  259 
 tests/qemu-iotests/057.out |5 +
 tests/qemu-iotests/group   |1 +
 3 files changed, 265 insertions(+), 0 deletions(-)
 create mode 100755 tests/qemu-iotests/057
 create mode 100644 tests/qemu-iotests/057.out

diff --git a/tests/qemu-iotests/057 b/tests/qemu-iotests/057
new file mode 100755
index 000..9cdd582
--- /dev/null
+++ b/tests/qemu-iotests/057
@@ -0,0 +1,259 @@
+#!/usr/bin/env python
+#
+# Tests for internal snapshot.
+#
+# Copyright (C) 2013 IBM, Inc.
+#
+# Based on 055.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see http://www.gnu.org/licenses/.
+#
+
+import time
+import os
+import iotests
+from iotests import qemu_img, qemu_io
+
+test_drv_base_name = 'drive'
+
+class ImageSnapshotTestCase(iotests.QMPTestCase):
+image_len = 120 * 1024 * 1024 # MB
+
+def __init__(self, *args):
+self.expect = []
+super(ImageSnapshotTestCase, self).__init__(*args)
+
+def _setUp(self, test_img_base_name, image_num):
+self.vm = iotests.VM()
+for i in range(0, image_num):
+filename = '%s%d' % (test_img_base_name, i)
+img = os.path.join(iotests.test_dir, filename)
+device = '%s%d' % (test_drv_base_name, i)
+qemu_img('create', '-f', iotests.imgfmt, img, str(self.image_len))
+self.vm.add_drive(img)
+self.expect.append({'image': img, 'device': device,
+'snapshots': [],
+'snapshots_name_counter': 0})
+self.vm.launch()
+
+def tearDown(self):
+self.vm.shutdown()
+for dev_expect in self.expect:
+os.remove(dev_expect['image'])
+
+def createSnapshotInTransaction(self, snapshot_num, abort = False):
+actions = []
+for dev_expect in self.expect:
+num = dev_expect['snapshots_name_counter']
+for j in range(0, snapshot_num):
+name = '%s_sn%d' % (dev_expect['device'], num)
+num = num + 1
+if abort == False:
+dev_expect['snapshots'].append({'name': name})
+dev_expect['snapshots_name_counter'] = num
+actions.append({
+'type': 'blockdev-snapshot-internal-sync',
+'data': { 'device': dev_expect['device'],
+  'name': name },
+})
+
+if abort == True:
+actions.append({
+'type': 'abort',
+'data': {},
+})
+
+result = self.vm.qmp('transaction', actions = actions)
+
+if abort == True:
+self.assert_qmp(result, 'error/class', 'GenericError')
+else:
+self.assert_qmp(result, 'return', {})
+
+def verifySnapshotInfo(self):
+result = self.vm.qmp('query-block')
+
+# Verify each expected result
+for dev_expect in self.expect:
+# 1. Find the returned image value and snapshot info
+image_result = None
+for device in result['return']:
+if device['device'] == dev_expect['device']:
+image_result = device['inserted']['image']
+break
+self.assertTrue(image_result != None)
+# Do not consider zero snapshot case now
+sn_list_result = image_result['snapshots']
+sn_list_expect = dev_expect['snapshots']
+
+# 2. Verify it with expect
+self.assertTrue(len(sn_list_result) == len(sn_list_expect))
+
+for sn_expect in sn_list_expect:
+sn_result = None
+for sn in sn_list_result:
+if sn_expect['name'] == sn['name']:
+sn_result = sn
+break
+self.assertTrue(sn_result != None)
+# Fill in the detail info
+sn_expect.update(sn_result)
+
+def deleteSnapshot(self, device, id = None, name = None):
+sn_list_expect = None
+sn_expect = None
+
+self.assertTrue(id != None or name != None)
+
+# Fill in the detail info include ID
+self.verifySnapshotInfo()
+
+#find

[Qemu-devel] [PATCH V7 2/8] snapshot: distinguish id and name in snapshot delete

2013-08-06 Thread Wenchao Xia
Snapshot creation actually already distinguish id and name since it take
a structured parameter *sn, but delete can't. Later an accurate delete
is needed in qmp_transaction abort and blockdev-snapshot-delete-sync,
so change its prototype. Also *errp is added to tip error, but return
value is kepted to let caller check what kind of error happens. Existing
caller for it are savevm, delvm and qemu-img, they are not impacted by
introducing a new function bdrv_snapshot_delete_by_id_or_name(), which
check the return value and do the operation again.

Before this patch:
  For qcow2, it search id first then name to find the one to delete.
  For rbd, it search name.
  For sheepdog, it does nothing.

After this patch:
  For qcow2, logic is the same by call it twice in caller.
  For rbd, it always fails in delete with id, but still search for name
in second try, no change to user.

Some code for *errp is based on Pavel's patch.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
Signed-off-by: Pavel Hrdina phrd...@redhat.com
---
 block/qcow2-snapshot.c|   55 ++
 block/qcow2.h |5 +++-
 block/rbd.c   |   21 +++-
 block/sheepdog.c  |5 +++-
 block/snapshot.c  |   58 ++--
 include/block/block_int.h |5 +++-
 include/block/snapshot.h  |8 +-
 qemu-img.c|   11 +---
 savevm.c  |   32 +---
 9 files changed, 157 insertions(+), 43 deletions(-)

diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 0caac90..6a0ed6b 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -288,31 +288,47 @@ static void find_new_snapshot_id(BlockDriverState *bs,
 snprintf(id_str, id_str_size, %d, id_max + 1);
 }
 
-static int find_snapshot_by_id(BlockDriverState *bs, const char *id_str)
+static int find_snapshot_by_id_and_name(BlockDriverState *bs,
+const char *id,
+const char *name)
 {
 BDRVQcowState *s = bs-opaque;
 int i;
 
-for(i = 0; i  s-nb_snapshots; i++) {
-if (!strcmp(s-snapshots[i].id_str, id_str))
-return i;
+if (id  name) {
+for (i = 0; i  s-nb_snapshots; i++) {
+if (!strcmp(s-snapshots[i].id_str, id) 
+!strcmp(s-snapshots[i].name, name)) {
+return i;
+}
+}
+} else if (id) {
+for (i = 0; i  s-nb_snapshots; i++) {
+if (!strcmp(s-snapshots[i].id_str, id)) {
+return i;
+}
+}
+} else if (name) {
+for (i = 0; i  s-nb_snapshots; i++) {
+if (!strcmp(s-snapshots[i].name, name)) {
+return i;
+}
+}
 }
+
 return -1;
 }
 
-static int find_snapshot_by_id_or_name(BlockDriverState *bs, const char *name)
+static int find_snapshot_by_id_or_name(BlockDriverState *bs,
+   const char *id_or_name)
 {
-BDRVQcowState *s = bs-opaque;
-int i, ret;
+int ret;
 
-ret = find_snapshot_by_id(bs, name);
-if (ret = 0)
+ret = find_snapshot_by_id_and_name(bs, id_or_name, NULL);
+if (ret = 0) {
 return ret;
-for(i = 0; i  s-nb_snapshots; i++) {
-if (!strcmp(s-snapshots[i].name, name))
-return i;
 }
-return -1;
+return find_snapshot_by_id_and_name(bs, NULL, id_or_name);
 }
 
 /* if no id is provided, a new one is constructed */
@@ -334,7 +350,7 @@ int qcow2_snapshot_create(BlockDriverState *bs, 
QEMUSnapshotInfo *sn_info)
 }
 
 /* Check that the ID is unique */
-if (find_snapshot_by_id(bs, sn_info-id_str) = 0) {
+if (find_snapshot_by_id_and_name(bs, sn_info-id_str, NULL) = 0) {
 return -EEXIST;
 }
 
@@ -531,15 +547,19 @@ fail:
 return ret;
 }
 
-int qcow2_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
+int qcow2_snapshot_delete(BlockDriverState *bs,
+  const char *snapshot_id,
+  const char *name,
+  Error **errp)
 {
 BDRVQcowState *s = bs-opaque;
 QCowSnapshot sn;
 int snapshot_index, ret;
 
 /* Search the snapshot */
-snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_id);
+snapshot_index = find_snapshot_by_id_and_name(bs, snapshot_id, name);
 if (snapshot_index  0) {
+error_setg(errp, Can't find the snapshot);
 return -ENOENT;
 }
 sn = s-snapshots[snapshot_index];
@@ -551,6 +571,7 @@ int qcow2_snapshot_delete(BlockDriverState *bs, const char 
*snapshot_id)
 s-nb_snapshots--;
 ret = qcow2_write_snapshots(bs);
 if (ret  0) {
+error_setg(errp, Failed to remove snapshot from snapshot list);
 return ret;
 }
 
@@ -568,6 +589,7 @@ int qcow2_snapshot_delete(BlockDriverState *bs, const char 
*snapshot_id)
 ret

Re: [Qemu-devel] [PATCH V6 0/8] add internal snapshot support at block device level

2013-08-06 Thread Wenchao Xia
于 2013-7-30 10:59, Wenchao Xia 写道:
 This series brings internal snapshot support at block devices
 level, now we
 have two three methods to do block snapshot lively: 1) backing chain,
 2) internal one and 3) drive-back up approach.

 Comparation:
Advantages:Disadvantages:
 1)delta data, taken fast, export, sizeperformance, delete slow.
 2)  taken fast, delete fast, performance, size   delta data, format
 3)  performance, export, format   taken slow, delta data, 
 size

 I think in most case, saving vmstate in an standalone file is better than
 saving it inside qcow2, So suggest treat internal snapshot as block level
 methods and not encourage user to savevm in qcow2 any more.

 Implemention details:
 To avoid trouble, this serial have hide ID in create interfaces, this 
 make
 sure no chaos of ID and name will be introduced by these interfaces.
 There is one patch may be common to Pavel's savvm transaction, patch 
 1/11,
 others are not quite related. Patch 1/11 will not set errp when no snapshot
 find, since patch 3/11 need to distinguish real error case.

 Next steps to better full VM snapshot:
 Improve internal snapshot's export capability.
 Better vmstate saving.

 Thanks Kevin to give advisement about how add it in qmp_transaction, 
 oldest
 version comes drom Dietmar Maurer.

 v3:
 General:
 Rebased after Stenfan's driver-backup patch V6.

 Address Eric's comments:
 4/9: grammar fix and better doc.
 5/9: parameter name is mandatory now. grammar fix.
 6/9: redesiged interface: take both id and name as optional parameter, 
 return
 the deleted snapshot's info.

 Address Stefan's comments:
 4/9: add '' around %s in message. drop code comments about vm_clock.
 9/9: better doc, refined the code and add more test case.

 v4:
 Address Stefan's comments:
 4/9: use error_setg_errno() to show error reason for 
 bdrv_snapshot_create(),
 spell fix and better doc.
 5/9: better doc.
 6/9: remove spurious ';' in code, spell fix and better doc.

 v5:
 Address Kevin's comments:
 3/8, 4/8, 8/8: remove the limit of numeric snapshot name.
 General change:
 4/8: use existing type as parameter in qapi schema.

 v6:
 Address Stefan's comments:
 2/8: macro STR_PRINT_CHAR was renamed as STR_OR_NULL, and moved into 
 patch 5,
 since implement function in this patch do not printf snapshot id any more, as
 Kevin's suggestion.
 Address Kevin's comments:
 2/8: remove device, id, name info in the error message, use error 
 message in
 existing caller. A new function bdrv_snapshot_delete_by_id_or_name() is added
 to make the usage clear while keep logic unchanged.
 3/8: remove device info in error message when name is empty. Use else if
 after call of bdrv_snapshot_find_by_id_and_name().
 Other:
 2/8: refined the comments in code for bdrv_snapshot_delete().
 3/8: in error reporting, change format from reason is: '%s' to
 reason is: %s.

 Wenchao Xia (8):
 1 snapshot: new function bdrv_snapshot_find_by_id_and_name()
 2 snapshot: distinguish id and name in snapshot delete
 3 qmp: add internal snapshot support in qmp_transaction
 4 qmp: add interface blockdev-snapshot-internal-sync
 5 qmp: add interface blockdev-snapshot-delete-internal-sync
 6 hmp: add interface hmp_snapshot_blkdev_internal
 7 hmp: add interface hmp_snapshot_delete_blkdev_internal
 8 qemu-iotests: add 056 internal snapshot for block device test case

block/qcow2-snapshot.c |   55 +++---
block/qcow2.h  |5 +-
block/rbd.c|   21 -
block/sheepdog.c   |5 +-
block/snapshot.c   |  131 ++-
blockdev.c |  190 
hmp-commands.hx|   37 ++-
hmp.c  |   22 
hmp.h  |2 +
include/block/block_int.h  |5 +-
include/block/snapshot.h   |   14 +++-
include/qemu-common.h  |3 +
qapi-schema.json   |   65 +++-
qemu-img.c |   11 ++-
qmp-commands.hx|  104 --
savevm.c   |   32 +++---
tests/qemu-iotests/056 |  259 
 
tests/qemu-iotests/056.out |5 +
tests/qemu-iotests/group   |1 +
19 files changed, 913 insertions(+), 54 deletions(-)
create mode 100755 tests/qemu-iotests/056
create mode 100644 tests/qemu-iotests/056.out


 Hello,
any comments for this version? I just found 056 is taken in
 upstream this morning, may respin if you like.
 
  I guess it is hard to catch 1.6, so rebased on upstream and re-target
to 1.7.

-- 
Best Regards

Wenchao Xia




[Qemu-devel] [PATCH V7 5/8] qmp: add interface blockdev-snapshot-delete-internal-sync

2013-08-06 Thread Wenchao Xia
This interface use id and name as optional parameters, to handle the
case that one image contain multiple snapshots with same name which
may be '', but with different id.

Adding parameter id is for historical compatiability reason, and
that case is not possible in qemu's new interface for internal
snapshot at block device level, but still possible in qemu-img.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
---
 blockdev.c|   61 +
 include/qemu-common.h |3 ++
 qapi-schema.json  |   27 +
 qmp-commands.hx   |   41 +
 4 files changed, 132 insertions(+), 0 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index b4754ef..13de395 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -869,6 +869,67 @@ void qmp_blockdev_snapshot_internal_sync(const char 
*device,
snapshot, errp);
 }
 
+SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
+ bool has_id,
+ const char *id,
+ bool has_name,
+ const char *name,
+ Error **errp)
+{
+BlockDriverState *bs = bdrv_find(device);
+QEMUSnapshotInfo sn;
+Error *local_err = NULL;
+SnapshotInfo *info = NULL;
+int ret;
+
+if (!bs) {
+error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+return NULL;
+}
+
+if (!has_id) {
+id = NULL;
+}
+
+if (!has_name) {
+name = NULL;
+}
+
+if (!id  !name) {
+error_setg(errp, Name or id must be provided);
+return NULL;
+}
+
+ret = bdrv_snapshot_find_by_id_and_name(bs, id, name, sn, local_err);
+if (error_is_set(local_err)) {
+error_propagate(errp, local_err);
+return NULL;
+}
+if (!ret) {
+error_setg(errp,
+   Snapshot with id '%s' and name '%s' does not exist on 
+   device '%s',
+   STR_OR_NULL(id), STR_OR_NULL(name), device);
+return NULL;
+}
+
+bdrv_snapshot_delete(bs, id, name, local_err);
+if (error_is_set(local_err)) {
+error_propagate(errp, local_err);
+return NULL;
+}
+
+info = g_malloc0(sizeof(SnapshotInfo));
+info-id = g_strdup(sn.id_str);
+info-name = g_strdup(sn.name);
+info-date_nsec = sn.date_nsec;
+info-date_sec = sn.date_sec;
+info-vm_state_size = sn.vm_state_size;
+info-vm_clock_nsec = sn.vm_clock_nsec % 10;
+info-vm_clock_sec = sn.vm_clock_nsec / 10;
+
+return info;
+}
 
 /* New and old BlockDriverState structs for group snapshots */
 
diff --git a/include/qemu-common.h b/include/qemu-common.h
index 6948bb9..5054836 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -191,6 +191,9 @@ int64_t strtosz_suffix(const char *nptr, char **end, const 
char default_suffix);
 int64_t strtosz_suffix_unit(const char *nptr, char **end,
 const char default_suffix, int64_t unit);
 
+/* used to print char* safely */
+#define STR_OR_NULL(str) ((str) ? (str) : null)
+
 /* path.c */
 void init_paths(const char *prefix);
 const char *path(const char *pathname);
diff --git a/qapi-schema.json b/qapi-schema.json
index a236cde..5a46abe 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1778,6 +1778,33 @@
   'data': 'BlockdevSnapshotInternal' }
 
 ##
+# @blockdev-snapshot-delete-internal-sync
+#
+# Synchronously delete an internal snapshot of a block device, when the format
+# of the image used support it. The snapshot is identified by name or id or
+# both. One of the name or id is required. Return SnapshotInfo for the
+# successfully deleted snapshot.
+#
+# @device: the name of the device to delete the snapshot from
+#
+# @id: optional the snapshot's ID to be deleted
+#
+# @name: optional the snapshot's name to be deleted
+#
+# Returns: SnapshotInfo on success
+#  If @device is not a valid block device, DeviceNotFound
+#  If snapshot not found, GenericError
+#  If the format of the image used does not support it,
+#  BlockFormatFeatureNotSupported
+#  If @id and @name are both not specified, GenericError
+#
+# Since 1.7
+##
+{ 'command': 'blockdev-snapshot-delete-internal-sync',
+  'data': { 'device': 'str', '*id': 'str', '*name': 'str'},
+  'returns': 'SnapshotInfo' }
+
+##
 # @human-monitor-command:
 #
 # Execute a command on the human monitor and return the output.
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 6097283..3d34a1c 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1127,6 +1127,47 @@ Example:
 EQMP
 
 {
+.name   = blockdev-snapshot-delete-internal-sync,
+.args_type  = device:B,id:s?,name:s

[Qemu-devel] [PATCH V7 3/8] qmp: add internal snapshot support in qmp_transaction

2013-08-06 Thread Wenchao Xia
Unlike savevm, the qmp_transaction interface will not generate
snapshot name automatically, saving trouble to return information
of the new created snapshot.

Although qcow2 support storing multiple snapshots with same name
but different ID, here it will fail when an snapshot with that name
already exist before the operation. Format such as rbd do not support
ID at all, and in most case, it means trouble to user when he faces
multiple snapshots with same name, so ban that case. Request with
empty name will be rejected.

Snapshot ID can't be specified in this interface.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
---
 blockdev.c   |  116 ++
 qapi-schema.json |   19 -
 qmp-commands.hx  |   34 
 3 files changed, 160 insertions(+), 9 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 41b0a49..0d717bc 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -887,6 +887,117 @@ struct BlkTransactionState {
 QSIMPLEQ_ENTRY(BlkTransactionState) entry;
 };
 
+/* internal snapshot private data */
+typedef struct InternalSnapshotState {
+BlkTransactionState common;
+BlockDriverState *bs;
+QEMUSnapshotInfo sn;
+} InternalSnapshotState;
+
+static void internal_snapshot_prepare(BlkTransactionState *common,
+  Error **errp)
+{
+const char *device;
+const char *name;
+BlockDriverState *bs;
+QEMUSnapshotInfo old_sn, *sn;
+bool ret;
+qemu_timeval tv;
+BlockdevSnapshotInternal *internal;
+InternalSnapshotState *state;
+int ret1;
+
+g_assert(common-action-kind ==
+ TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC);
+internal = common-action-blockdev_snapshot_internal_sync;
+state = DO_UPCAST(InternalSnapshotState, common, common);
+
+/* 1. parse input */
+device = internal-device;
+name = internal-name;
+
+/* 2. check for validation */
+bs = bdrv_find(device);
+if (!bs) {
+error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+return;
+}
+
+if (!bdrv_is_inserted(bs)) {
+error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
+return;
+}
+
+if (bdrv_is_read_only(bs)) {
+error_set(errp, QERR_DEVICE_IS_READ_ONLY, device);
+return;
+}
+
+if (!bdrv_can_snapshot(bs)) {
+error_set(errp, QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
+  bs-drv-format_name, device, internal snapshot);
+return;
+}
+
+if (!strlen(name)) {
+error_setg(errp, Name is empty);
+return;
+}
+
+/* check whether a snapshot with name exist */
+ret = bdrv_snapshot_find_by_id_and_name(bs, NULL, name, old_sn, errp);
+if (error_is_set(errp)) {
+return;
+} else if (ret) {
+error_setg(errp,
+   Snapshot with name '%s' already exists on device '%s',
+   name, device);
+return;
+}
+
+/* 3. take the snapshot */
+sn = state-sn;
+pstrcpy(sn-name, sizeof(sn-name), name);
+qemu_gettimeofday(tv);
+sn-date_sec = tv.tv_sec;
+sn-date_nsec = tv.tv_usec * 1000;
+sn-vm_clock_nsec = qemu_get_clock_ns(vm_clock);
+
+ret1 = bdrv_snapshot_create(bs, sn);
+if (ret1  0) {
+error_setg_errno(errp, -ret1,
+ Failed to create snapshot '%s' on device '%s',
+ name, device);
+return;
+}
+
+/* 4. succeed, mark a snapshot is created */
+state-bs = bs;
+}
+
+static void internal_snapshot_abort(BlkTransactionState *common)
+{
+InternalSnapshotState *state =
+ DO_UPCAST(InternalSnapshotState, common, common);
+BlockDriverState *bs = state-bs;
+QEMUSnapshotInfo *sn = state-sn;
+Error *local_error = NULL;
+
+if (!bs) {
+return;
+}
+
+if (bdrv_snapshot_delete(bs, sn-id_str, sn-name, local_error)  0) {
+error_report(Failed to delete snapshot with id '%s' and name '%s' on 
+ device '%s' in abort, reason is: %s,
+ sn-id_str,
+ sn-name,
+ bdrv_get_device_name(bs),
+ error_get_pretty(local_error));
+error_free(local_error);
+}
+}
+
 /* external snapshot private data */
 typedef struct ExternalSnapshotState {
 BlkTransactionState common;
@@ -1070,6 +1181,11 @@ static const BdrvActionOps actions[] = {
 .prepare = abort_prepare,
 .commit = abort_commit,
 },
+[TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC] = {
+.instance_size = sizeof(InternalSnapshotState),
+.prepare  = internal_snapshot_prepare,
+.abort = internal_snapshot_abort,
+},
 };
 
 /*
diff --git a/qapi-schema.json b/qapi-schema.json
index a51f7d2..38663c5 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1639,6 +1639,22 @@
 '*mode': 'NewImageMode

[Qemu-devel] [PATCH V7 6/8] hmp: add interface hmp_snapshot_blkdev_internal

2013-08-06 Thread Wenchao Xia
Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
---
 hmp-commands.hx |   19 +--
 hmp.c   |   10 ++
 hmp.h   |1 +
 3 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 8c6b91a..039c401 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1023,8 +1023,7 @@ ETEXI
   of device. If a new image file is specified, 
the\n\t\t\t
   new image file will become the new root image.\n\t\t\t
   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).\n\t\t\t
+  be created in that format.\n\t\t\t
   The default format is qcow2.  The -n flag requests 
QEMU\n\t\t\t
   to reuse the image found in new-image-file, instead 
of\n\t\t\t
   recreating it from scratch.,
@@ -1038,6 +1037,22 @@ Snapshot device, using snapshot file as target if 
provided
 ETEXI
 
 {
+.name   = snapshot_blkdev_internal,
+.args_type  = device:B,name:s,
+.params = device name,
+.help   = take an internal snapshot of device.\n\t\t\t
+  The format of the image used by device must\n\t\t\t
+  support it, such as qcow2.\n\t\t\t,
+.mhandler.cmd = hmp_snapshot_blkdev_internal,
+},
+
+STEXI
+@item snapshot_blkdev_internal
+@findex snapshot_blkdev_internal
+Take an internal snapshot on device if it support
+ETEXI
+
+{
 .name   = drive_mirror,
 .args_type  = reuse:-n,full:-f,device:B,target:s,format:s?,
 .params = [-n] [-f] device target [format],
diff --git a/hmp.c b/hmp.c
index c45514b..34763be 100644
--- a/hmp.c
+++ b/hmp.c
@@ -962,6 +962,16 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict)
 hmp_handle_error(mon, errp);
 }
 
+void hmp_snapshot_blkdev_internal(Monitor *mon, const QDict *qdict)
+{
+const char *device = qdict_get_str(qdict, device);
+const char *name = qdict_get_str(qdict, name);
+Error *errp = NULL;
+
+qmp_blockdev_snapshot_internal_sync(device, name, 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 6c3bdcd..cc1ca58 100644
--- a/hmp.h
+++ b/hmp.h
@@ -54,6 +54,7 @@ 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_snapshot_blkdev_internal(Monitor *mon, const QDict *qdict);
 void hmp_drive_mirror(Monitor *mon, const QDict *qdict);
 void hmp_drive_backup(Monitor *mon, const QDict *qdict);
 void hmp_migrate_cancel(Monitor *mon, const QDict *qdict);
-- 
1.7.1





[Qemu-devel] [PATCH V7 4/8] qmp: add interface blockdev-snapshot-internal-sync

2013-08-06 Thread Wenchao Xia
Snapshot ID can't be specified in this interface.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
---
 blockdev.c   |   13 +
 qapi-schema.json |   20 
 qmp-commands.hx  |   29 +
 3 files changed, 62 insertions(+), 0 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 0d717bc..b4754ef 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -856,6 +856,19 @@ void qmp_blockdev_snapshot_sync(const char *device, const 
char *snapshot_file,
snapshot, errp);
 }
 
+void qmp_blockdev_snapshot_internal_sync(const char *device,
+ const char *name,
+ Error **errp)
+{
+BlockdevSnapshotInternal snapshot = {
+.device = (char *) device,
+.name = (char *) name
+};
+
+blockdev_do_action(TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC,
+   snapshot, errp);
+}
+
 
 /* New and old BlockDriverState structs for group snapshots */
 
diff --git a/qapi-schema.json b/qapi-schema.json
index 38663c5..a236cde 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1758,6 +1758,26 @@
   'data': 'BlockdevSnapshot' }
 
 ##
+# @blockdev-snapshot-internal-sync
+#
+# Synchronously take an internal snapshot of a block device, when the format
+# of the image used supports it.
+#
+# For the arguments, see the documentation of BlockdevSnapshotInternal.
+#
+# Returns: nothing on success
+#  If @device is not a valid block device, DeviceNotFound
+#  If any snapshot matching @name exists, or @name is empty,
+#  GenericError
+#  If the format of the image used does not support it,
+#  BlockFormatFeatureNotSupported
+#
+# Since 1.7
+##
+{ 'command': 'blockdev-snapshot-internal-sync',
+  'data': 'BlockdevSnapshotInternal' }
+
+##
 # @human-monitor-command:
 #
 # Execute a command on the human monitor and return the output.
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 68a1611..6097283 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1098,6 +1098,35 @@ Example:
 EQMP
 
 {
+.name   = blockdev-snapshot-internal-sync,
+.args_type  = device:B,name:s,
+.mhandler.cmd_new = qmp_marshal_input_blockdev_snapshot_internal_sync,
+},
+
+SQMP
+blockdev-snapshot-internal-sync
+---
+
+Synchronously take an internal snapshot of a block device when the format of
+image used supports it.  If the name is an empty string, or a snapshot with
+name already exists, the operation will fail.
+
+Arguments:
+
+- device: device name to snapshot (json-string)
+- name: name of the new snapshot (json-string)
+
+Example:
+
+- { execute: blockdev-snapshot-internal-sync,
+arguments: { device: ide-hd0,
+   name: snapshot0 }
+   }
+- { return: {} }
+
+EQMP
+
+{
 .name   = drive-mirror,
 .args_type  = sync:s,device:B,target:s,speed:i?,mode:s?,format:s?,
   on-source-error:s?,on-target-error:s?,
-- 
1.7.1





[Qemu-devel] [PATCH V7 7/8] hmp: add interface hmp_snapshot_delete_blkdev_internal

2013-08-06 Thread Wenchao Xia
It is hard to make both id and name optional in hmp console as qmp
interface, so this interface require user to specify name.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
---
 hmp-commands.hx |   18 ++
 hmp.c   |   12 
 hmp.h   |1 +
 3 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 039c401..96b1874 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1053,6 +1053,24 @@ Take an internal snapshot on device if it support
 ETEXI
 
 {
+.name   = snapshot_delete_blkdev_internal,
+.args_type  = device:B,name:s,id:s?,
+.params = device name [id],
+.help   = delete an internal snapshot of device.\n\t\t\t
+  If id is specified, qemu will try delete\n\t\t\t
+  the snapshot matching both id and name.\n\t\t\t
+  The format of the image used by device must\n\t\t\t
+  support it, such as qcow2.\n\t\t\t,
+.mhandler.cmd = hmp_snapshot_delete_blkdev_internal,
+},
+
+STEXI
+@item snapshot_delete_blkdev_internal
+@findex snapshot_delete_blkdev_internal
+Delete an internal snapshot on device if it support
+ETEXI
+
+{
 .name   = drive_mirror,
 .args_type  = reuse:-n,full:-f,device:B,target:s,format:s?,
 .params = [-n] [-f] device target [format],
diff --git a/hmp.c b/hmp.c
index 34763be..e2139d0 100644
--- a/hmp.c
+++ b/hmp.c
@@ -972,6 +972,18 @@ void hmp_snapshot_blkdev_internal(Monitor *mon, const 
QDict *qdict)
 hmp_handle_error(mon, errp);
 }
 
+void hmp_snapshot_delete_blkdev_internal(Monitor *mon, const QDict *qdict)
+{
+const char *device = qdict_get_str(qdict, device);
+const char *name = qdict_get_str(qdict, name);
+const char *id = qdict_get_try_str(qdict, id);
+Error *errp = NULL;
+
+qmp_blockdev_snapshot_delete_internal_sync(device, !!id, id,
+   true, name, 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 cc1ca58..54cf71f 100644
--- a/hmp.h
+++ b/hmp.h
@@ -55,6 +55,7 @@ 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_snapshot_blkdev_internal(Monitor *mon, const QDict *qdict);
+void hmp_snapshot_delete_blkdev_internal(Monitor *mon, const QDict *qdict);
 void hmp_drive_mirror(Monitor *mon, const QDict *qdict);
 void hmp_drive_backup(Monitor *mon, const QDict *qdict);
 void hmp_migrate_cancel(Monitor *mon, const QDict *qdict);
-- 
1.7.1





[Qemu-devel] [PATCH V7 0/8] add internal snapshot support at block device level

2013-08-06 Thread Wenchao Xia
  This series brings internal snapshot support at block devices level, now we
have two three methods to do block snapshot lively: 1) backing chain,
2) internal one and 3) drive-back up approach.

Comparation:
 Advantages:Disadvantages:
1)delta data, taken fast, export, sizeperformance, delete slow.
2)  taken fast, delete fast, performance, size   delta data, format
3)  performance, export, format  taken slow, delta data, size, host I/O

  I think in most case, saving vmstate in an standalone file is better than
saving it inside qcow2, So suggest treat internal snapshot as block level
methods and not encourage user to savevm in qcow2 any more.

Implemention details:
  To avoid trouble, this serial have hide ID in create interfaces, this make
sure no chaos of ID and name will be introduced by these interfaces.
  There is one patch may be common to Pavel's savvm transaction, patch 1/11,
others are not quite related. Patch 1/11 will not set errp when no snapshot
find, since patch 3/11 need to distinguish real error case.

Next steps to better full VM snapshot:
  Improve internal snapshot's export capability.
  Better vmstate saving.

  Thanks Kevin to give advisement about how add it in qmp_transaction, oldest
version comes drom Dietmar Maurer.

v3:
  General:
  Rebased after Stenfan's driver-backup patch V6.

  Address Eric's comments:
  4/9: grammar fix and better doc.
  5/9: parameter name is mandatory now. grammar fix.
  6/9: redesiged interface: take both id and name as optional parameter, return
the deleted snapshot's info.

  Address Stefan's comments:
  4/9: add '' around %s in message. drop code comments about vm_clock.
  9/9: better doc, refined the code and add more test case.

v4:
  Address Stefan's comments:
  4/9: use error_setg_errno() to show error reason for bdrv_snapshot_create(),
spell fix and better doc.
  5/9: better doc.
  6/9: remove spurious ';' in code, spell fix and better doc.

v5:
  Address Kevin's comments:
  3/8, 4/8, 8/8: remove the limit of numeric snapshot name.
  General change:
  4/8: use existing type as parameter in qapi schema.

v6:
  Address Stefan's comments:
  2/8: macro STR_PRINT_CHAR was renamed as STR_OR_NULL, and moved into patch 5,
since implement function in this patch do not printf snapshot id any more, as
Kevin's suggestion.
  Address Kevin's comments:
  2/8: remove device, id, name info in the error message, use error message in
existing caller. A new function bdrv_snapshot_delete_by_id_or_name() is added
to make the usage clear while keep logic unchanged. 
  3/8: remove device info in error message when name is empty. Use else if
after call of bdrv_snapshot_find_by_id_and_name().
  Other:
  2/8: refined the comments in code for bdrv_snapshot_delete().
  3/8: in error reporting, change format from reason is: '%s' to
reason is: %s.

v7:
  rebased on upstream, target for 1.7.

Wenchao Xia (8):
  1 snapshot: new function bdrv_snapshot_find_by_id_and_name()
  2 snapshot: distinguish id and name in snapshot delete
  3 qmp: add internal snapshot support in qmp_transaction
  4 qmp: add interface blockdev-snapshot-internal-sync
  5 qmp: add interface blockdev-snapshot-delete-internal-sync
  6 hmp: add interface hmp_snapshot_blkdev_internal
  7 hmp: add interface hmp_snapshot_delete_blkdev_internal
  8 qemu-iotests: add 057 internal snapshot for block device test case

 block/qcow2-snapshot.c |   55 +++---
 block/qcow2.h  |5 +-
 block/rbd.c|   21 -
 block/sheepdog.c   |5 +-
 block/snapshot.c   |  131 ++-
 blockdev.c |  190 
 hmp-commands.hx|   37 ++-
 hmp.c  |   22 
 hmp.h  |2 +
 include/block/block_int.h  |5 +-
 include/block/snapshot.h   |   14 +++-
 include/qemu-common.h  |3 +
 qapi-schema.json   |   66 +++-
 qemu-img.c |   11 ++-
 qmp-commands.hx|  104 --
 savevm.c   |   32 +++---
 tests/qemu-iotests/057 |  259 
 tests/qemu-iotests/057.out |5 +
 tests/qemu-iotests/group   |1 +
 19 files changed, 914 insertions(+), 54 deletions(-)
 create mode 100755 tests/qemu-iotests/057
 create mode 100644 tests/qemu-iotests/057.out





[Qemu-devel] [PATCH V7 1/8] snapshot: new function bdrv_snapshot_find_by_id_and_name()

2013-08-06 Thread Wenchao Xia
To make it clear about id and name in searching, add this API
to distinguish them. Caller can choose to search by id or name,
*errp will be set only for exception.

Some code are modified based on Pavel's patch.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
Signed-off-by: Pavel Hrdina phrd...@redhat.com
Reviewed-by: Eric Blake ebl...@redhat.com
---
 block/snapshot.c |   73 ++
 include/block/snapshot.h |6 
 2 files changed, 79 insertions(+), 0 deletions(-)

diff --git a/block/snapshot.c b/block/snapshot.c
index 6c6d9de..481a3ee 100644
--- a/block/snapshot.c
+++ b/block/snapshot.c
@@ -48,6 +48,79 @@ int bdrv_snapshot_find(BlockDriverState *bs, 
QEMUSnapshotInfo *sn_info,
 return ret;
 }
 
+/**
+ * Look up an internal snapshot by @id and @name.
+ * @bs: block device to search
+ * @id: unique snapshot ID, or NULL
+ * @name: snapshot name, or NULL
+ * @sn_info: location to store information on the snapshot found
+ * @errp: location to store error, will be set only for exception
+ *
+ * This function will traverse snapshot list in @bs to search the matching
+ * one, @id and @name are the matching condition:
+ * If both @id and @name are specified, find the first one with id @id and
+ * name @name.
+ * If only @id is specified, find the first one with id @id.
+ * If only @name is specified, find the first one with name @name.
+ * if none is specified, abort().
+ *
+ * Returns: true when a snapshot is found and @sn_info will be filled, false
+ * when error or not found. If all operation succeed but no matching one is
+ * found, @errp will NOT be set.
+ */
+bool bdrv_snapshot_find_by_id_and_name(BlockDriverState *bs,
+   const char *id,
+   const char *name,
+   QEMUSnapshotInfo *sn_info,
+   Error **errp)
+{
+QEMUSnapshotInfo *sn_tab, *sn;
+int nb_sns, i;
+bool ret = false;
+
+assert(id || name);
+
+nb_sns = bdrv_snapshot_list(bs, sn_tab);
+if (nb_sns  0) {
+error_setg_errno(errp, -nb_sns, Failed to get a snapshot list);
+return false;
+} else if (nb_sns == 0) {
+return false;
+}
+
+if (id  name) {
+for (i = 0; i  nb_sns; i++) {
+sn = sn_tab[i];
+if (!strcmp(sn-id_str, id)  !strcmp(sn-name, name)) {
+*sn_info = *sn;
+ret = true;
+break;
+}
+}
+} else if (id) {
+for (i = 0; i  nb_sns; i++) {
+sn = sn_tab[i];
+if (!strcmp(sn-id_str, id)) {
+*sn_info = *sn;
+ret = true;
+break;
+}
+}
+} else if (name) {
+for (i = 0; i  nb_sns; i++) {
+sn = sn_tab[i];
+if (!strcmp(sn-name, name)) {
+*sn_info = *sn;
+ret = true;
+break;
+}
+}
+}
+
+g_free(sn_tab);
+return ret;
+}
+
 int bdrv_can_snapshot(BlockDriverState *bs)
 {
 BlockDriver *drv = bs-drv;
diff --git a/include/block/snapshot.h b/include/block/snapshot.h
index eaf61f0..9d06dc1 100644
--- a/include/block/snapshot.h
+++ b/include/block/snapshot.h
@@ -26,6 +26,7 @@
 #define SNAPSHOT_H
 
 #include qemu-common.h
+#include qapi/error.h
 
 typedef struct QEMUSnapshotInfo {
 char id_str[128]; /* unique snapshot id */
@@ -40,6 +41,11 @@ typedef struct QEMUSnapshotInfo {
 
 int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
const char *name);
+bool bdrv_snapshot_find_by_id_and_name(BlockDriverState *bs,
+   const char *id,
+   const char *name,
+   QEMUSnapshotInfo *sn_info,
+   Error **errp);
 int bdrv_can_snapshot(BlockDriverState *bs);
 int bdrv_snapshot_create(BlockDriverState *bs,
  QEMUSnapshotInfo *sn_info);
-- 
1.7.1





Re: [Qemu-devel] [PATCH v3 1/7] vvfat: use bdrv_new() to allocate BlockDriverState

2013-08-02 Thread Wenchao Xia
Reviewed-by: Wenchao Xia xiaw...@linux.vnet.ibm.com

 we need bdrv_new() to properly initialize BDS, don't allocate memory
 manually.
 
 Signed-off-by: Fam Zheng f...@redhat.com
 ---
   block/vvfat.c | 2 +-
   1 file changed, 1 insertion(+), 1 deletion(-)
 
 diff --git a/block/vvfat.c b/block/vvfat.c
 index cd3b8ed..a827d91 100644
 --- a/block/vvfat.c
 +++ b/block/vvfat.c
 @@ -2943,7 +2943,7 @@ static int enable_write_target(BDRVVVFATState *s)
   unlink(s-qcow_filename);
   #endif
 
 -s-bs-backing_hd = calloc(sizeof(BlockDriverState), 1);
 +s-bs-backing_hd = bdrv_new();
   s-bs-backing_hd-drv = vvfat_write_target;
   s-bs-backing_hd-opaque = g_malloc(sizeof(void*));
   *(void**)s-bs-backing_hd-opaque = s;
 


-- 
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH v3 2/7] iscsi: use bdrv_new() instead of stack structure

2013-08-02 Thread Wenchao Xia
于 2013-7-31 18:13, Fam Zheng 写道:
 BlockDriverState structure needs bdrv_new() to initialize refcnt, don't
 allocate a local structure variable and memset to 0, becasue with coming
 refcnt implementation, bdrv_unref will crash if bs-refcnt not
 initialized to 1.
 
 Signed-off-by: Fam Zheng f...@redhat.com
 ---
   block/iscsi.c | 14 +++---
   1 file changed, 7 insertions(+), 7 deletions(-)
 
 diff --git a/block/iscsi.c b/block/iscsi.c
 index 5f28c6a..db8a699 100644
 --- a/block/iscsi.c
 +++ b/block/iscsi.c
 @@ -1247,11 +1247,11 @@ static int iscsi_create(const char *filename, 
 QEMUOptionParameter *options)
   {
   int ret = 0;
   int64_t total_size = 0;
 -BlockDriverState bs;
 +BlockDriverState *bs;
   IscsiLun *iscsilun = NULL;
   QDict *bs_options;
 
 -memset(bs, 0, sizeof(BlockDriverState));
 +bs = bdrv_new();
 
   /* Read out options */
   while (options  options-name) {
 @@ -1261,12 +1261,12 @@ static int iscsi_create(const char *filename, 
 QEMUOptionParameter *options)
   options++;
   }
 
 -bs.opaque = g_malloc0(sizeof(struct IscsiLun));
 -iscsilun = bs.opaque;
 +bs-opaque = g_malloc0(sizeof(struct IscsiLun));
 +iscsilun = bs-opaque;
 
   bs_options = qdict_new();
   qdict_put(bs_options, filename, qstring_from_str(filename));
 -ret = iscsi_open(bs, bs_options, 0);
 +ret = iscsi_open(bs, bs_options, 0);
   QDECREF(bs_options);
 
   if (ret != 0) {
 @@ -1280,7 +1280,7 @@ static int iscsi_create(const char *filename, 
 QEMUOptionParameter *options)
   ret = -ENODEV;
   goto out;
   }
 -if (bs.total_sectors  total_size) {
 +if (bs-total_sectors  total_size) {
   ret = -ENOSPC;
   goto out;
   }
 @@ -1290,7 +1290,7 @@ out:
   if (iscsilun-iscsi != NULL) {
   iscsi_destroy_context(iscsilun-iscsi);
   }
 -g_free(bs.opaque);
  bs,opaque seems leaked. bdrv_delete() will not free it unless bs-drv
!= NULL.


 +bdrv_delete(bs);
   return ret;
   }
 


-- 
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH v3 3/7] block: implement reference count for BlockDriverState

2013-08-02 Thread Wenchao Xia
Reviewed-by: Wenchao Xia xiaw...@linux.vnet.ibm.com

 Introduce bdrv_ref/bdrv_unref to manage the lifecycle of
 BlockDriverState. They are unused for now but will used to replace
 bdrv_delete() later.
 
 Signed-off-by: Fam Zheng f...@redhat.com
 ---
   block.c   | 21 +
   include/block/block.h |  2 ++
   include/block/block_int.h |  1 +
   3 files changed, 24 insertions(+)
 

-- 
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH v3 4/7] block: make bdrv_delete() static

2013-08-02 Thread Wenchao Xia
Reviewed-by: Wenchao Xia xiaw...@linux.vnet.ibm.com


-- 
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH v3 5/7] migration: omit drive ref as we have bdrv_ref now

2013-08-02 Thread Wenchao Xia
There should be a section of code in device hot unplug, checking
DriverInfo's ref, fail or do nothing when ref != 1. But I haven't found
that code, so not sure whether this patch will change the behavior in
device hot unplug.

 block-migration.c does not actually use DriveInfo anywhere.  Hence it's
 safe to drive ref code, we really only care about referencing BDS.
 
 Signed-off-by: Fam Zheng f...@redhat.com
 ---
   block-migration.c | 4 ++--
   1 file changed, 2 insertions(+), 2 deletions(-)
 
 diff --git a/block-migration.c b/block-migration.c
 index f803f20..daf9ec1 100644
 --- a/block-migration.c
 +++ b/block-migration.c
 @@ -336,8 +336,8 @@ static void init_blk_migration_it(void *opaque, 
 BlockDriverState *bs)
   bmds-completed_sectors = 0;
   bmds-shared_base = block_mig_state.shared_base;
   alloc_aio_bitmap(bmds);
 -drive_get_ref(drive_get_by_blockdev(bs));
   bdrv_set_in_use(bs, 1);
 +bdrv_ref(bs);
 
   block_mig_state.total_sector_sum += sectors;
 
 @@ -575,7 +575,7 @@ static void blk_mig_cleanup(void)
   while ((bmds = QSIMPLEQ_FIRST(block_mig_state.bmds_list)) != NULL) {
   QSIMPLEQ_REMOVE_HEAD(block_mig_state.bmds_list, entry);
   bdrv_set_in_use(bmds-bs, 0);
 -drive_put_ref(drive_get_by_blockdev(bmds-bs));
 +bdrv_unref(bmds-bs);
   g_free(bmds-aio_bitmap);
   g_free(bmds);
   }
 


-- 
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH v3 6/7] xen_disk: simplify blk_disconnect with refcnt

2013-08-02 Thread Wenchao Xia
Better to split it into two patches:
1 bugfix: always call bdrv_detach_dev().
2 use refcnt to manage lifecycle.

 We call bdrv_attach_dev when initializing whether or not bs is created
 locally, so call bdrv_detach_dev and let the refcnt handle the
 lifecycle.
 
 Signed-off-by: Fam Zheng f...@redhat.com
 ---
   hw/block/xen_disk.c | 11 +--
   1 file changed, 5 insertions(+), 6 deletions(-)
 
 diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
 index 99537e8..39757d9 100644
 --- a/hw/block/xen_disk.c
 +++ b/hw/block/xen_disk.c
 @@ -812,6 +812,9 @@ static int blk_connect(struct XenDevice *xendev)
   /* setup via qemu cmdline - already setup for us */
   xen_be_printf(blkdev-xendev, 2, get configured bdrv (cmdline 
 setup)\n);
   blkdev-bs = blkdev-dinfo-bdrv;
 +/* blkdev-bs is not create by us, we get a reference
 + * so we can bdrv_unref() unconditionally */
 +bdrv_ref(blkdev-bs);
   }
   bdrv_attach_dev_nofail(blkdev-bs, blkdev);
   blkdev-file_size = bdrv_getlength(blkdev-bs);
 @@ -910,12 +913,8 @@ static void blk_disconnect(struct XenDevice *xendev)
   struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, 
 xendev);
 
   if (blkdev-bs) {
 -if (!blkdev-dinfo) {
 -/* close/delete only if we created it ourself */
 -bdrv_close(blkdev-bs);
 -bdrv_detach_dev(blkdev-bs, blkdev);
 -bdrv_unref(blkdev-bs);
 -}
 +bdrv_detach_dev(blkdev-bs, blkdev);
 +bdrv_unref(blkdev-bs);
   blkdev-bs = NULL;
   }
   xen_be_unbind_evtchn(blkdev-xendev);
 


-- 
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH v3 7/7] nbd: use BlockDriverState refcnt

2013-08-02 Thread Wenchao Xia
Reviewed-by: Wenchao Xia xiaw...@linux.vnet.ibm.com

 Previously, nbd calls drive_get_ref() on the drive of bs. A BDS doesn't
 always have associated dinfo, which nbd doesn't care either. We already
 have BDS ref count, so use it to make it safe for a BDS w/o blockdev.
 
 Signed-off-by: Fam Zheng f...@redhat.com



-- 
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH V8 00/13] monitor: support sub command group in auto completion and help

2013-07-30 Thread Wenchao Xia

于 2013-7-31 0:03, Luiz Capitulino 写道:

On Fri, 26 Jul 2013 11:20:29 +0800
Wenchao Xia xiaw...@linux.vnet.ibm.com wrote:


This series make auto completion and help functions works normal for sub
command, by using reentrant functions. In order to do that, global variables
are not directly used in those functions any more. With this series, cmd_table
is a member of structure Monitor so it is possible to create a monitor with
different command table now, auto completion will work in that monitor. In
short, info is not treated as a special case now, this series ensure help
and auto complete function works normal for any sub command added in the future.

Patch 5 replaced cur_mon with rs-mon, it is safe because:
monitor_init() calls readline_init() which initialize mon-rs, result is
mon-rs-mon == mon. Then qemu_chr_add_handlers() is called, which make
monitor_read() function take *mon as its opaque. Later, when user input,
monitor_read() is called, where cur_mon is set to *mon by cur_mon = opaque.
If qemu's monitors run in one thread, then later in readline_handle_byte()
and readline_comletion(), cur_mon is actually equal to rs-mon, in another
word, it points to the monitor instance, so it is safe to replace *cur_mon
in those functions.


I've applied this to qmp-next with the change I suggested for
patch 09/13.


  Thanks a lot!




Thanks for Luiz and Eric for reviewing.

V2:
   General:
   To discard *info_comds more graceful, help related function is modified to 
support
sub command too.
   Patch 6/7 are added to improve help related functions.
   Patch 5: not directly return to make sure args are freed.

   Address Luiz's comments:
   Split patch into small series.
   struct mon_cmd_t was not moved into header file, instead mon_cmnd_t 
*cmd_table is
added as a member in struct Monitor.
   5/7: drop original code comments for info in monitor_find_completion().

v3:
   5/7: add parameter **args_cmdline in parse_cmdline() to tell next valid
parameter's position. This fix the issue in case command length in input is not
equal to its name's length such as help|?, and the case input start with
space such as   s.
   7/7: better commit message.

v4:
   Address Eric's comments:
   1/7, 2/7, 4/7: better commit title and message.
   1/7 remove useless (char *) in old code, add space around for () in old 
code.
   3/7: separate code moving patch before usage.
   4/7: add space around for () in old code, add min(nb_args, MAX_ARGS) in 
free
to make code stronger.

v5:
   4/7: use a  b ? a : b instead of macro min.

v6:
   Address Luiz's comments:
   1/13 ~ 5/13: splitted small patches.
   5/13: added commit message about the correctness of replacing of cur_mon and
test result.
   6/13: better comments in code.
   7/13: added commit message about the reason of code moving.
   8/13: new patch to improve parse_cmdline(), since it is a more generic
function now.
   9/13: reworked the commit message, better commentes in code, use
free_cmdline_args() in clean. It is a bit hard to split this patch into
smaller meaning ful ones, so kepted this patch as a relative larger one,
with better commit message.
   12/13: put case 'S' with case 's' in monitor_find_completion_by_table().
moved this patch ahead of patch 13/13.
   13/13: this patch is moved behind patch 12/13.

   Generic change:
   10/13: splitted patch which moved out the reentrant part into a separate
function, make review easier. This also avoided re-parsing the command line
which does in previous version.
   11/13: splitted patch, which simply remove usage of info_cmds and support
sub command by re-enter the function.

v7:
   Address Luiz's comments:
   5/13: moved the comments why the change is safe, to cover-letter.
   8/13: use assert in free_cmdline_args(), fail when args in input exceed
the limit in parse_cmdline().

v8:
   Address Eric's comments:
   Fix typo in commit messages.

Wenchao Xia (13):
   1 monitor: avoid use of global *cur_mon in cmd_completion()
   2 monitor: avoid use of global *cur_mon in file_completion()
   3 monitor: avoid use of global *cur_mon in block_completion_it()
   4 monitor: avoid use of global *cur_mon in monitor_find_completion()
   5 monitor: avoid use of global *cur_mon in readline_completion()
   6 monitor: avoid direct use of global variable *mon_cmds
   7 monitor: code move for parse_cmdline()
   8 monitor: refine parse_cmdline()
   9 monitor: support sub command in help
   10 monitor: refine monitor_find_completion()
   11 monitor: support sub command in auto completion
   12 monitor: allow help show message for single command in sub group
   13 monitor: improve auto complete of help for single command in sub group

  hmp-commands.hx|2 +-
  include/monitor/readline.h |3 +-
  monitor.c  |  438 
  readline.c |5 +-
  4 files changed, 289 insertions(+), 159 deletions(-)







--
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH V8 09/13] monitor: support sub command in help

2013-07-30 Thread Wenchao Xia

于 2013-7-30 22:51, Luiz Capitulino 写道:

On Fri, 26 Jul 2013 11:20:38 +0800
Wenchao Xia xiaw...@linux.vnet.ibm.com wrote:


The old code in help_cmd() uses global 'info_cmds' and treats it as a
special case. Actually 'info_cmds' is a sub command group of 'mon_cmds',
in order to avoid direct use of it, help_cmd() needs to change its work
mechanism to support sub command and not treat it as a special case
any more.

To support sub command, help_cmd() will first parse the input and then call
help_cmd_dump(), which works as a reentrant function. When it meets a sub
command, it simply enters the function again. Since help dumping needs to
know whole input to printf full help message include prefix, for example,
help info block need to printf prefix info, so help_cmd_dump() takes all
args from input and extra parameter arg_index to identify the progress.
Another function help_cmd_dump_one() is introduced to printf the prefix
and command's help message.

Now help supports sub command, so later if another sub command group is
added in any depth, help will automatically work for it. Still help info
block will show error since command parser reject additional parameter,
which can be improved later. log is still treated as a special case.

Signed-off-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
Reviewed-by: Eric Blake ebl...@redhat.com
---
  monitor.c |   63 +++-
  1 files changed, 53 insertions(+), 10 deletions(-)

diff --git a/monitor.c b/monitor.c
index c942b77..77df88d 100644
--- a/monitor.c
+++ b/monitor.c
@@ -868,33 +868,76 @@ static int parse_cmdline(const char *cmdline,
  return -1;
  }

+static void help_cmd_dump_one(Monitor *mon,
+  const mon_cmd_t *cmd,
+  char **prefix_args,
+  int prefix_args_nb)
+{
+int i;
+
+for (i = 0; i  prefix_args_nb; i++) {
+monitor_printf(mon, %s , prefix_args[i]);
+}
+monitor_printf(mon, %s %s -- %s\n, cmd-name, cmd-params, cmd-help);
+}
+
+/* @args[@arg_index] is the valid command need to find in @cmds */
  static void help_cmd_dump(Monitor *mon, const mon_cmd_t *cmds,
-  const char *prefix, const char *name)
+  char **args, int nb_args, int arg_index)
  {
  const mon_cmd_t *cmd;

-for(cmd = cmds; cmd-name != NULL; cmd++) {
-if (!name || !strcmp(name, cmd-name))
-monitor_printf(mon, %s%s %s -- %s\n, prefix, cmd-name,
-   cmd-params, cmd-help);
+/* No valid arg need to compare with, dump all in *cmds */
+if (arg_index = nb_args) {
+for (cmd = cmds; cmd-name != NULL; cmd++) {
+help_cmd_dump_one(mon, cmd, args, arg_index);
+}
+return;
+}
+
+/* Find one entry to dump */
+for (cmd = cmds; cmd-name != NULL; cmd++) {
+if (compare_cmd(args[arg_index], cmd-name)) {
+if (cmd-sub_table) {
+/* continue with next arg */
+help_cmd_dump(mon, cmd-sub_table,
+  args, nb_args, arg_index + 1);
+} else {
+help_cmd_dump_one(mon, cmd, args, arg_index);
+}
+break;
+}
  }
  }

  static void help_cmd(Monitor *mon, const char *name)
  {
-if (name  !strcmp(name, info)) {
-help_cmd_dump(mon, info_cmds, info , NULL);
-} else {
-help_cmd_dump(mon, mon-cmd_table, , name);
-if (name  !strcmp(name, log)) {
+char *args[MAX_ARGS];
+int nb_args = 0;
+
+/* 1. parse user input */
+if (name) {
+/* special case for log, directly dump and return */
+if (!strcmp(name, log)) {
  const QEMULogItem *item;
  monitor_printf(mon, Log items (comma separated):\n);
  monitor_printf(mon, %-10s %s\n, none, remove all logs);
  for (item = qemu_log_items; item-mask != 0; item++) {
  monitor_printf(mon, %-10s %s\n, item-name, item-help);
  }
+return;
+}
+
+if (parse_cmdline(name, nb_args, args)  0) {
+goto cleanup;


Won't this result in a double-free if parse_cmdline() fails?

The fix is just to return instead of going to cleanup. I can do this
change if you agree and if I don't spot another bug.


  nb_args = 0 in that case, I think it would not free again. Still,  I
am OK to do this change, since the parse_cmdline() already does the
clean up, not need to ask caller to do it again.


  }
  }
+
+/* 2. dump the contents according to parsed args */
+help_cmd_dump(mon, mon-cmd_table, args, nb_args, 0);
+
+cleanup:
+free_cmdline_args(args, nb_args);
  }

  static void do_help_cmd(Monitor *mon, const QDict *qdict)





--
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH v6 02/18] block: stop relying on io_flush() in bdrv_drain_all()

2013-07-29 Thread Wenchao Xia
Reviewed-by: Wenchao Xia xiaw...@linux.vnet.ibm.com



-- 
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH v6 03/18] dataplane/virtio-blk: check exit conditions before aio_poll()

2013-07-29 Thread Wenchao Xia
 Check exit conditions before entering blocking aio_poll().  This is
 mainly for consistency since it's unlikely that we are stopping in the
 first event loop iteration.
 
 Signed-off-by: Stefan Hajnoczi stefa...@redhat.com
 ---
   hw/block/dataplane/virtio-blk.c | 4 ++--
   1 file changed, 2 insertions(+), 2 deletions(-)
 
 diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
 index 2faed43..8d3e145 100644
 --- a/hw/block/dataplane/virtio-blk.c
 +++ b/hw/block/dataplane/virtio-blk.c
 @@ -379,9 +379,9 @@ static void *data_plane_thread(void *opaque)
   {
   VirtIOBlockDataPlane *s = opaque;
 
 -do {
 +while (!s-stopping || s-num_reqs  0) {
   aio_poll(s-ctx, true);
 -} while (!s-stopping || s-num_reqs  0);
 +}
   return NULL;
   }

It seems more likely a bug fix.

Reviewed-by: Wenchao Xia xiaw...@linux.vnet.ibm.com

-- 
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH v6 04/18] tests: adjust test-aio to new aio_poll() semantics

2013-07-29 Thread Wenchao Xia
Reviewed-by: Wenchao Xia xiaw...@linux.vnet.ibm.com
 aio_poll(ctx, true) will soon block if any fd handlers have been set.
 Previously it would only block when .io_flush() returned true.
 
 This means that callers must check their wait condition *before*
 aio_poll() to avoid deadlock.
 
 Reviewed-by: Paolo Bonzini pbonz...@redhat.com
 Signed-off-by: Stefan Hajnoczi stefa...@redhat.com
 ---
   tests/test-aio.c | 26 +-
   1 file changed, 17 insertions(+), 9 deletions(-)
 
 diff --git a/tests/test-aio.c b/tests/test-aio.c
 index c173870..20bf5e6 100644
 --- a/tests/test-aio.c
 +++ b/tests/test-aio.c
 @@ -15,6 +15,13 @@
 
   AioContext *ctx;
 
 +typedef struct {
 +EventNotifier e;
 +int n;
 +int active;
 +bool auto_set;
 +} EventNotifierTestData;
 +
   /* Wait until there are no more BHs or AIO requests */
   static void wait_for_aio(void)
   {
 @@ -23,6 +30,14 @@ static void wait_for_aio(void)
   }
   }
 
 +/* Wait until event notifier becomes inactive */
 +static void wait_until_inactive(EventNotifierTestData *data)
 +{
 +while (data-active  0) {
 +aio_poll(ctx, true);
 +}
 +}
 +
   /* Simple callbacks for testing.  */
 
   typedef struct {
 @@ -50,13 +65,6 @@ static void bh_delete_cb(void *opaque)
   }
   }
 
 -typedef struct {
 -EventNotifier e;
 -int n;
 -int active;
 -bool auto_set;
 -} EventNotifierTestData;
 -
   static int event_active_cb(EventNotifier *e)
   {
   EventNotifierTestData *data = container_of(e, EventNotifierTestData, e);
 @@ -281,7 +289,7 @@ static void test_flush_event_notifier(void)
   g_assert_cmpint(data.active, ==, 9);
   g_assert(aio_poll(ctx, false));
 
 -wait_for_aio();
 +wait_until_inactive(data);
   g_assert_cmpint(data.n, ==, 10);
   g_assert_cmpint(data.active, ==, 0);
   g_assert(!aio_poll(ctx, false));
 @@ -325,7 +333,7 @@ static void test_wait_event_notifier_noflush(void)
   g_assert_cmpint(data.n, ==, 2);
 
   event_notifier_set(dummy.e);
 -wait_for_aio();
 +wait_until_inactive(dummy);
   g_assert_cmpint(data.n, ==, 2);
   g_assert_cmpint(dummy.n, ==, 1);
   g_assert_cmpint(dummy.active, ==, 0);
 


-- 
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH v6 05/18] tests: adjust test-thread-pool to new aio_poll() semantics

2013-07-29 Thread Wenchao Xia
I am confused for sometime about the reason of the change, I think
it can be concluded as: The meaning of aio_poll() will be changed, so
change the caller in this test case.

Reviewed-by: Wenchao Xia xiaw...@linux.vnet.ibm.com


 aio_poll(ctx, true) will soon block when fd handlers have been set.
 Previously aio_poll() would return early if all .io_flush() returned
 false.  This means we need to check the equivalent of the .io_flush()
 condition *before* calling aio_poll(ctx, true) to avoid deadlock.
 
 Reviewed-by: Paolo Bonzini pbonz...@redhat.com
 Signed-off-by: Stefan Hajnoczi stefa...@redhat.com
 ---
   tests/test-thread-pool.c | 24 
   1 file changed, 12 insertions(+), 12 deletions(-)
 
 diff --git a/tests/test-thread-pool.c b/tests/test-thread-pool.c
 index b62338f..8188d1a 100644
 --- a/tests/test-thread-pool.c
 +++ b/tests/test-thread-pool.c
 @@ -40,19 +40,13 @@ static void done_cb(void *opaque, int ret)
   active--;
   }
 
 -/* Wait until all aio and bh activity has finished */
 -static void qemu_aio_wait_all(void)
 -{
 -while (aio_poll(ctx, true)) {
 -/* Do nothing */
 -}
 -}
 -
   static void test_submit(void)
   {
   WorkerTestData data = { .n = 0 };
   thread_pool_submit(pool, worker_cb, data);
 -qemu_aio_wait_all();
 +while (data.n == 0) {
 +aio_poll(ctx, true);
 +}
   g_assert_cmpint(data.n, ==, 1);
   }
 
 @@ -65,7 +59,9 @@ static void test_submit_aio(void)
   /* The callbacks are not called until after the first wait.  */
   active = 1;
   g_assert_cmpint(data.ret, ==, -EINPROGRESS);
 -qemu_aio_wait_all();
 +while (data.ret == -EINPROGRESS) {
 +aio_poll(ctx, true);
 +}
   g_assert_cmpint(active, ==, 0);
   g_assert_cmpint(data.n, ==, 1);
   g_assert_cmpint(data.ret, ==, 0);
 @@ -103,7 +99,9 @@ static void test_submit_co(void)
 
   /* qemu_aio_wait_all will execute the rest of the coroutine.  */
 
 -qemu_aio_wait_all();
 +while (data.ret == -EINPROGRESS) {
 +aio_poll(ctx, true);
 +}
 
   /* Back here after the coroutine has finished.  */
 
 @@ -187,7 +185,9 @@ static void test_cancel(void)
   }
 
   /* Finish execution and execute any remaining callbacks.  */
 -qemu_aio_wait_all();
 +while (active  0) {
 +aio_poll(ctx, true);
 +}
   g_assert_cmpint(active, ==, 0);
   for (i = 0; i  100; i++) {
   if (data[i].n == 3) {
 


-- 
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH v6 06/18] aio: stop using .io_flush()

2013-07-29 Thread Wenchao Xia
 Now that aio_poll() users check their termination condition themselves,
 it is no longer necessary to call .io_flush() handlers.
 
 The behavior of aio_poll() changes as follows:
 
 1. .io_flush() is no longer invoked and file descriptors are *always*
 monitored.  Previously returning 0 from .io_flush() would skip this file
 descriptor.
 
 Due to this change it is essential to check that requests are pending
 before calling qemu_aio_wait().  Failure to do so means we block, for
 example, waiting for an idle iSCSI socket to become readable when there
 are no requests.  Currently all qemu_aio_wait()/aio_poll() callers check
 before calling.
 
 2. aio_poll() now returns true if progress was made (BH or fd handlers
 executed) and false otherwise.  Previously it would return true whenever
 'busy', which means that .io_flush() returned true.  The 'busy' concept
 no longer exists so just progress is returned.
 
 Due to this change we need to update tests/test-aio.c which asserts
 aio_poll() return values.  Note that QEMU doesn't actually rely on these
 return values so only tests/test-aio.c cares.
 
 Note that ctx-notifier, the EventNotifier fd used for aio_notify(), is
 now handled as a special case.  This is a little ugly but maintains
 aio_poll() semantics, i.e. aio_notify() does not count as 'progress' and
 aio_poll() avoids blocking when the user has not set any fd handlers yet.
 
  I guess the goal is, distinguish qemu's internal used fd, with the
real meaningful external fd such as socket? How about distinguish them
with different GSource?


 Patches after this remove .io_flush() handler code until we can finally
 drop the io_flush arguments to aio_set_fd_handler() and friends.
 
 Reviewed-by: Paolo Bonzini pbonz...@redhat.com
 Signed-off-by: Stefan Hajnoczi stefa...@redhat.com
 ---
   aio-posix.c  | 29 +
   aio-win32.c  | 34 ++
   tests/test-aio.c | 10 +-
   3 files changed, 28 insertions(+), 45 deletions(-)
 


-- 
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH v6 07/18] block/curl: drop curl_aio_flush()

2013-07-29 Thread Wenchao Xia
Reviewed-by: Wenchao Xia xiaw...@linux.vnet.ibm.com

 .io_flush() is no longer called so drop curl_aio_flush().  The acb[]
 array that the function checks is still used in other parts of
 block/curl.c.  Therefore we cannot remove acb[], it is needed.
 
 Signed-off-by: Stefan Hajnoczi stefa...@redhat.com
 ---
   block/curl.c | 22 +++---
   1 file changed, 3 insertions(+), 19 deletions(-)
 


-- 
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH v6 08/18] block/gluster: drop qemu_gluster_aio_flush_cb()

2013-07-29 Thread Wenchao Xia
Reviewed-by: Wenchao Xia xiaw...@linux.vnet.ibm.com

 Since .io_flush() is no longer called we do not need
 qemu_gluster_aio_flush_cb() anymore.  It turns out that qemu_aio_count
 is unused now and can be dropped.
 
 Signed-off-by: Stefan Hajnoczi stefa...@redhat.com
 ---
   block/gluster.c | 16 +---
   1 file changed, 1 insertion(+), 15 deletions(-)
 


-- 
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH v6 09/18] block/iscsi: drop iscsi_process_flush()

2013-07-29 Thread Wenchao Xia
Reviewed-by: Wenchao Xia xiaw...@linux.vnet.ibm.com

 .io_flush() is no longer called so drop iscsi_process_flush().
 
 Signed-off-by: Stefan Hajnoczi stefa...@redhat.com
 ---
   block/iscsi.c | 9 +
   1 file changed, 1 insertion(+), 8 deletions(-)
 
 diff --git a/block/iscsi.c b/block/iscsi.c
 index 5f28c6a..e2692d6 100644
 --- a/block/iscsi.c
 +++ b/block/iscsi.c
 @@ -146,13 +146,6 @@ static const AIOCBInfo iscsi_aiocb_info = {
   static void iscsi_process_read(void *arg);
   static void iscsi_process_write(void *arg);
 
 -static int iscsi_process_flush(void *arg)
 -{
 -IscsiLun *iscsilun = arg;
 -
 -return iscsi_queue_length(iscsilun-iscsi)  0;
 -}
 -
   static void
   iscsi_set_events(IscsiLun *iscsilun)
   {
 @@ -166,7 +159,7 @@ iscsi_set_events(IscsiLun *iscsilun)
   qemu_aio_set_fd_handler(iscsi_get_fd(iscsi),
 iscsi_process_read,
 (ev  POLLOUT) ? iscsi_process_write : NULL,
 -  iscsi_process_flush,
 +  NULL,
 iscsilun);
 
   }
 


-- 
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH v6 11/18] block/nbd: drop nbd_have_request()

2013-07-29 Thread Wenchao Xia
Reviewed-by: Wenchao Xia xiaw...@linux.vnet.ibm.com

 .io_flush() is no longer called so drop nbd_have_request().  We cannot
 drop in_flight since it is still used by other block/nbd.c code.
 
 Signed-off-by: Stefan Hajnoczi stefa...@redhat.com
 ---
   block/nbd.c | 13 +++--
   1 file changed, 3 insertions(+), 10 deletions(-)
 
 diff --git a/block/nbd.c b/block/nbd.c
 index 9c480b8..f1619f9 100644
 --- a/block/nbd.c
 +++ b/block/nbd.c
 @@ -279,13 +279,6 @@ static void nbd_coroutine_start(BDRVNBDState *s, struct 
 nbd_request *request)
   request-handle = INDEX_TO_HANDLE(s, i);
   }
 
 -static int nbd_have_request(void *opaque)
 -{
 -BDRVNBDState *s = opaque;
 -
 -return s-in_flight  0;
 -}
 -
   static void nbd_reply_ready(void *opaque)
   {
   BDRVNBDState *s = opaque;
 @@ -342,7 +335,7 @@ static int nbd_co_send_request(BDRVNBDState *s, struct 
 nbd_request *request,
   qemu_co_mutex_lock(s-send_mutex);
   s-send_coroutine = qemu_coroutine_self();
   qemu_aio_set_fd_handler(s-sock, nbd_reply_ready, nbd_restart_write,
 -nbd_have_request, s);
 +NULL, s);
   if (qiov) {
   if (!s-is_unix) {
   socket_set_cork(s-sock, 1);
 @@ -362,7 +355,7 @@ static int nbd_co_send_request(BDRVNBDState *s, struct 
 nbd_request *request,
   rc = nbd_send_request(s-sock, request);
   }
   qemu_aio_set_fd_handler(s-sock, nbd_reply_ready, NULL,
 -nbd_have_request, s);
 +NULL, s);
   s-send_coroutine = NULL;
   qemu_co_mutex_unlock(s-send_mutex);
   return rc;
 @@ -439,7 +432,7 @@ static int nbd_establish_connection(BlockDriverState *bs)
* kick the reply mechanism.  */
   qemu_set_nonblock(sock);
   qemu_aio_set_fd_handler(sock, nbd_reply_ready, NULL,
 -nbd_have_request, s);
 +NULL, s);
 
   s-sock = sock;
   s-size = size;
 


-- 
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH v6 10/18] block/linux-aio: drop qemu_laio_completion_cb()

2013-07-29 Thread Wenchao Xia
Reviewed-by: Wenchao Xia xiaw...@linux.vnet.ibm.com

 .io_flush() is no longer called so drop qemu_laio_completion_cb().  It
 turns out that count is now unused so drop that too.
 
 Signed-off-by: Stefan Hajnoczi stefa...@redhat.com
 ---
   block/linux-aio.c | 17 ++---
   1 file changed, 2 insertions(+), 15 deletions(-)
 
 diff --git a/block/linux-aio.c b/block/linux-aio.c
 index ee0f8d1..d9128f3 100644
 --- a/block/linux-aio.c
 +++ b/block/linux-aio.c
 @@ -39,7 +39,6 @@ struct qemu_laiocb {
   struct qemu_laio_state {
   io_context_t ctx;
   EventNotifier e;
 -int count;
   };
 
   static inline ssize_t io_event_ret(struct io_event *ev)
 @@ -55,8 +54,6 @@ static void qemu_laio_process_completion(struct 
 qemu_laio_state *s,
   {
   int ret;
 
 -s-count--;
 -
   ret = laiocb-ret;
   if (ret != -ECANCELED) {
   if (ret == laiocb-nbytes) {
 @@ -101,13 +98,6 @@ static void qemu_laio_completion_cb(EventNotifier *e)
   }
   }
 
 -static int qemu_laio_flush_cb(EventNotifier *e)
 -{
 -struct qemu_laio_state *s = container_of(e, struct qemu_laio_state, e);
 -
 -return (s-count  0) ? 1 : 0;
 -}
 -
   static void laio_cancel(BlockDriverAIOCB *blockacb)
   {
   struct qemu_laiocb *laiocb = (struct qemu_laiocb *)blockacb;
 @@ -177,14 +167,11 @@ BlockDriverAIOCB *laio_submit(BlockDriverState *bs, 
 void *aio_ctx, int fd,
   goto out_free_aiocb;
   }
   io_set_eventfd(laiocb-iocb, event_notifier_get_fd(s-e));
 -s-count++;
 
   if (io_submit(s-ctx, 1, iocbs)  0)
 -goto out_dec_count;
 +goto out_free_aiocb;
   return laiocb-common;
 
 -out_dec_count:
 -s-count--;
   out_free_aiocb:
   qemu_aio_release(laiocb);
   return NULL;
 @@ -204,7 +191,7 @@ void *laio_init(void)
   }
 
   qemu_aio_set_event_notifier(s-e, qemu_laio_completion_cb,
 -qemu_laio_flush_cb);
 +NULL);
 
   return s;
 


-- 
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH v6 12/18] block/rbd: drop qemu_rbd_aio_flush_cb()

2013-07-29 Thread Wenchao Xia
Reviewed-by: Wenchao Xia xiaw...@linux.vnet.ibm.com

 .io_flush() is no longer called so drop qemu_rbd_aio_flush_cb().
 qemu_aio_count is unused now so drop it too.
 
 Signed-off-by: Stefan Hajnoczi stefa...@redhat.com
 ---
   block/rbd.c | 14 +-
   1 file changed, 1 insertion(+), 13 deletions(-)
 
 diff --git a/block/rbd.c b/block/rbd.c
 index cb71751..71b4a0c 100644
 --- a/block/rbd.c
 +++ b/block/rbd.c
 @@ -100,7 +100,6 @@ typedef struct BDRVRBDState {
   rados_ioctx_t io_ctx;
   rbd_image_t image;
   char name[RBD_MAX_IMAGE_NAME_SIZE];
 -int qemu_aio_count;
   char *snap;
   int event_reader_pos;
   RADOSCB *event_rcb;
 @@ -428,19 +427,11 @@ static void qemu_rbd_aio_event_reader(void *opaque)
   if (s-event_reader_pos == sizeof(s-event_rcb)) {
   s-event_reader_pos = 0;
   qemu_rbd_complete_aio(s-event_rcb);
 -s-qemu_aio_count--;
   }
   }
   } while (ret  0  errno == EINTR);
   }
 
 -static int qemu_rbd_aio_flush_cb(void *opaque)
 -{
 -BDRVRBDState *s = opaque;
 -
 -return (s-qemu_aio_count  0);
 -}
 -
   /* TODO Convert to fine grained options */
   static QemuOptsList runtime_opts = {
   .name = rbd,
 @@ -554,7 +545,7 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict 
 *options, int flags)
   fcntl(s-fds[0], F_SETFL, O_NONBLOCK);
   fcntl(s-fds[1], F_SETFL, O_NONBLOCK);
   qemu_aio_set_fd_handler(s-fds[RBD_FD_READ], qemu_rbd_aio_event_reader,
 -NULL, qemu_rbd_aio_flush_cb, s);
 +NULL, NULL, s);
 
 
   qemu_opts_del(opts);
 @@ -741,8 +732,6 @@ static BlockDriverAIOCB *rbd_start_aio(BlockDriverState 
 *bs,
   off = sector_num * BDRV_SECTOR_SIZE;
   size = nb_sectors * BDRV_SECTOR_SIZE;
 
 -s-qemu_aio_count++; /* All the RADOSCB */
 -
   rcb = g_malloc(sizeof(RADOSCB));
   rcb-done = 0;
   rcb-acb = acb;
 @@ -779,7 +768,6 @@ static BlockDriverAIOCB *rbd_start_aio(BlockDriverState 
 *bs,
 
   failed:
   g_free(rcb);
 -s-qemu_aio_count--;
   qemu_aio_release(acb);
   return NULL;
   }
 


-- 
Best Regards

Wenchao Xia




Re: [Qemu-devel] [PATCH v6 04/18] tests: adjust test-aio to new aio_poll() semantics

2013-07-29 Thread Wenchao Xia
Reviewed-by: Wenchao Xia xiaw...@linux.vnet.ibm.com

 aio_poll(ctx, true) will soon block if any fd handlers have been set.
 Previously it would only block when .io_flush() returned true.
 
 This means that callers must check their wait condition *before*
 aio_poll() to avoid deadlock.
 
 Reviewed-by: Paolo Bonzini pbonz...@redhat.com
 Signed-off-by: Stefan Hajnoczi stefa...@redhat.com
 ---
   tests/test-aio.c | 26 +-
   1 file changed, 17 insertions(+), 9 deletions(-)
 
 diff --git a/tests/test-aio.c b/tests/test-aio.c
 index c173870..20bf5e6 100644
 --- a/tests/test-aio.c
 +++ b/tests/test-aio.c
 @@ -15,6 +15,13 @@
 
   AioContext *ctx;
 
 +typedef struct {
 +EventNotifier e;
 +int n;
 +int active;
 +bool auto_set;
 +} EventNotifierTestData;
 +
   /* Wait until there are no more BHs or AIO requests */
   static void wait_for_aio(void)
   {
 @@ -23,6 +30,14 @@ static void wait_for_aio(void)
   }
   }
 
 +/* Wait until event notifier becomes inactive */
 +static void wait_until_inactive(EventNotifierTestData *data)
 +{
 +while (data-active  0) {
 +aio_poll(ctx, true);
 +}
 +}
 +
   /* Simple callbacks for testing.  */
 
   typedef struct {
 @@ -50,13 +65,6 @@ static void bh_delete_cb(void *opaque)
   }
   }
 
 -typedef struct {
 -EventNotifier e;
 -int n;
 -int active;
 -bool auto_set;
 -} EventNotifierTestData;
 -
   static int event_active_cb(EventNotifier *e)
   {
   EventNotifierTestData *data = container_of(e, EventNotifierTestData, e);
 @@ -281,7 +289,7 @@ static void test_flush_event_notifier(void)
   g_assert_cmpint(data.active, ==, 9);
   g_assert(aio_poll(ctx, false));
 
 -wait_for_aio();
 +wait_until_inactive(data);
   g_assert_cmpint(data.n, ==, 10);
   g_assert_cmpint(data.active, ==, 0);
   g_assert(!aio_poll(ctx, false));
 @@ -325,7 +333,7 @@ static void test_wait_event_notifier_noflush(void)
   g_assert_cmpint(data.n, ==, 2);
 
   event_notifier_set(dummy.e);
 -wait_for_aio();
 +wait_until_inactive(dummy);
   g_assert_cmpint(data.n, ==, 2);
   g_assert_cmpint(dummy.n, ==, 1);
   g_assert_cmpint(dummy.active, ==, 0);
 


-- 
Best Regards

Wenchao Xia




<    2   3   4   5   6   7   8   9   10   11   >