From patchwork Tue Oct 8 06:23:09 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Wu X-Patchwork-Id: 281331 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 3F4EA2C00AB for ; Tue, 8 Oct 2013 17:24:08 +1100 (EST) Received: from localhost ([::1]:34849 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VTQiC-0001QW-P7 for incoming@patchwork.ozlabs.org; Tue, 08 Oct 2013 02:24:04 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46256) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VTQhi-0001N2-PS for qemu-devel@nongnu.org; Tue, 08 Oct 2013 02:23:43 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VTQhZ-00051g-Qs for qemu-devel@nongnu.org; Tue, 08 Oct 2013 02:23:34 -0400 Received: from e28smtp09.in.ibm.com ([122.248.162.9]:39649) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VTQhZ-00050h-3W for qemu-devel@nongnu.org; Tue, 08 Oct 2013 02:23:25 -0400 Received: from /spool/local by e28smtp09.in.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 8 Oct 2013 11:53:17 +0530 Received: from d28dlp01.in.ibm.com (9.184.220.126) by e28smtp09.in.ibm.com (192.168.1.139) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 8 Oct 2013 11:53:15 +0530 Received: from d28relay03.in.ibm.com (d28relay03.in.ibm.com [9.184.220.60]) by d28dlp01.in.ibm.com (Postfix) with ESMTP id 9949FE004A for ; Tue, 8 Oct 2013 11:54:31 +0530 (IST) Received: from d28av03.in.ibm.com (d28av03.in.ibm.com [9.184.220.65]) by d28relay03.in.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id r986PjU946071982 for ; Tue, 8 Oct 2013 11:55:46 +0530 Received: from d28av03.in.ibm.com (localhost [127.0.0.1]) by d28av03.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id r986NDm4027938 for ; Tue, 8 Oct 2013 11:53:13 +0530 Received: from localhost.cn.ibm.com ([9.115.126.172]) by d28av03.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id r986NBn0027737; Tue, 8 Oct 2013 11:53:11 +0530 From: Mark Wu To: Qemu-devel@nongnu.org Date: Tue, 8 Oct 2013 14:23:09 +0800 Message-Id: <1381213389-11440-1-git-send-email-wudxw@linux.vnet.ibm.com> X-Mailer: git-send-email 1.8.3.1 X-TM-AS-MML: No X-Content-Scanned: Fidelis XPS MAILER x-cbid: 13100806-2674-0000-0000-00000AF3A7A3 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4.x-2.6.x [generic] X-Received-From: 122.248.162.9 Cc: Mark Wu , Michael Roth , Luiz Capitulino Subject: [Qemu-devel] [PATCH v2] Add interface to traverse the qmp command list by QmpCommand X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org In the original code, qmp_get_command_list is used to construct a list of all commands' name. To get the information of all qga commands, it traverses the name list and search the command info with its name. So it can cause O(n^2) in the number of commands. This patch adds an interface to traverse the qmp command list by QmpCommand to replace qmp_get_command_list. It can decrease the complexity from O(n^2) to O(n). Signed-off-by: Mark Wu Reviewed-by: Eric Blake --- Changes: v2: 1. Keep the signature of qmp_command_is_enabled (per Eric and Michael) 2. Remove the unnecessary pointer castings (per Eric) include/qapi/qmp/dispatch.h | 5 ++-- qapi/qmp-registry.c | 27 +++--------------- qga/commands.c | 38 ++++++++++--------------- qga/main.c | 68 +++++++++++++++++---------------------------- 4 files changed, 48 insertions(+), 90 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index 1ce11f5..b6eb49e 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -47,9 +47,10 @@ QmpCommand *qmp_find_command(const char *name); QObject *qmp_dispatch(QObject *request); void qmp_disable_command(const char *name); void qmp_enable_command(const char *name); -bool qmp_command_is_enabled(const char *name); -char **qmp_get_command_list(void); +bool qmp_command_is_enabled(const QmpCommand *cmd); QObject *qmp_build_error_object(Error *errp); +typedef void (*qmp_cmd_callback_fn)(QmpCommand *cmd, void *opaque); +void qmp_for_each_command(qmp_cmd_callback_fn fn, void *opaque); #endif diff --git a/qapi/qmp-registry.c b/qapi/qmp-registry.c index 28bbbe8..3fcf10e 100644 --- a/qapi/qmp-registry.c +++ b/qapi/qmp-registry.c @@ -66,35 +66,16 @@ void qmp_enable_command(const char *name) qmp_toggle_command(name, true); } -bool qmp_command_is_enabled(const char *name) +bool qmp_command_is_enabled(const QmpCommand *cmd) { - QmpCommand *cmd; - - QTAILQ_FOREACH(cmd, &qmp_commands, node) { - if (strcmp(cmd->name, name) == 0) { - return cmd->enabled; - } - } - - return false; + return cmd->enabled; } -char **qmp_get_command_list(void) +void qmp_for_each_command(qmp_cmd_callback_fn fn, void *opaque) { QmpCommand *cmd; - int count = 1; - char **list_head, **list; - - QTAILQ_FOREACH(cmd, &qmp_commands, node) { - count++; - } - - list_head = list = g_malloc0(count * sizeof(char *)); QTAILQ_FOREACH(cmd, &qmp_commands, node) { - *list = g_strdup(cmd->name); - list++; + fn(cmd, opaque); } - - return list_head; } diff --git a/qga/commands.c b/qga/commands.c index 528b082..063b22b 100644 --- a/qga/commands.c +++ b/qga/commands.c @@ -45,35 +45,27 @@ void qmp_guest_ping(Error **err) slog("guest-ping called"); } -struct GuestAgentInfo *qmp_guest_info(Error **err) +static void qmp_command_info(QmpCommand *cmd, void *opaque) { - GuestAgentInfo *info = g_malloc0(sizeof(GuestAgentInfo)); + GuestAgentInfo *info = opaque; GuestAgentCommandInfo *cmd_info; GuestAgentCommandInfoList *cmd_info_list; - char **cmd_list_head, **cmd_list; - - info->version = g_strdup(QEMU_VERSION); - - cmd_list_head = cmd_list = qmp_get_command_list(); - if (*cmd_list_head == NULL) { - goto out; - } - while (*cmd_list) { - cmd_info = g_malloc0(sizeof(GuestAgentCommandInfo)); - cmd_info->name = g_strdup(*cmd_list); - cmd_info->enabled = qmp_command_is_enabled(cmd_info->name); + cmd_info = g_malloc0(sizeof(GuestAgentCommandInfo)); + cmd_info->name = g_strdup(cmd->name); + cmd_info->enabled = qmp_command_is_enabled(cmd); - cmd_info_list = g_malloc0(sizeof(GuestAgentCommandInfoList)); - cmd_info_list->value = cmd_info; - cmd_info_list->next = info->supported_commands; - info->supported_commands = cmd_info_list; + cmd_info_list = g_malloc0(sizeof(GuestAgentCommandInfoList)); + cmd_info_list->value = cmd_info; + cmd_info_list->next = info->supported_commands; + info->supported_commands = cmd_info_list; +} - g_free(*cmd_list); - cmd_list++; - } +struct GuestAgentInfo *qmp_guest_info(Error **err) +{ + GuestAgentInfo *info = g_malloc0(sizeof(GuestAgentInfo)); -out: - g_free(cmd_list_head); + info->version = g_strdup(QEMU_VERSION); + qmp_for_each_command(qmp_command_info, info); return info; } diff --git a/qga/main.c b/qga/main.c index 6c746c8..ff2ee03 100644 --- a/qga/main.c +++ b/qga/main.c @@ -347,48 +347,34 @@ static gint ga_strcmp(gconstpointer str1, gconstpointer str2) } /* disable commands that aren't safe for fsfreeze */ -static void ga_disable_non_whitelisted(void) +static void ga_disable_non_whitelisted(QmpCommand *cmd, void *opaque) { - char **list_head, **list; bool whitelisted; int i; - list_head = list = qmp_get_command_list(); - while (*list != NULL) { - whitelisted = false; - i = 0; - while (ga_freeze_whitelist[i] != NULL) { - if (strcmp(*list, ga_freeze_whitelist[i]) == 0) { - whitelisted = true; - } - i++; - } - if (!whitelisted) { - g_debug("disabling command: %s", *list); - qmp_disable_command(*list); + whitelisted = false; + i = 0; + while (ga_freeze_whitelist[i] != NULL) { + if (strcmp(cmd->name, ga_freeze_whitelist[i]) == 0) { + whitelisted = true; } - g_free(*list); - list++; + i++; + } + if (!whitelisted) { + g_debug("disabling command: %s", cmd->name); + qmp_disable_command(cmd->name); } - g_free(list_head); } /* [re-]enable all commands, except those explicitly blacklisted by user */ -static void ga_enable_non_blacklisted(GList *blacklist) +static void ga_enable_non_blacklisted(QmpCommand *cmd, void *opaque) { - char **list_head, **list; - - list_head = list = qmp_get_command_list(); - while (*list != NULL) { - if (g_list_find_custom(blacklist, *list, ga_strcmp) == NULL && - !qmp_command_is_enabled(*list)) { - g_debug("enabling command: %s", *list); - qmp_enable_command(*list); - } - g_free(*list); - list++; + GList *blacklist = opaque; + if (g_list_find_custom(blacklist, cmd->name, ga_strcmp) == NULL && + !cmd->enabled) { + g_debug("enabling command: %s", cmd->name); + qmp_enable_command(cmd->name); } - g_free(list_head); } static bool ga_create_file(const char *path) @@ -424,7 +410,7 @@ void ga_set_frozen(GAState *s) return; } /* disable all non-whitelisted (for frozen state) commands */ - ga_disable_non_whitelisted(); + qmp_for_each_command(ga_disable_non_whitelisted, NULL); g_warning("disabling logging due to filesystem freeze"); ga_disable_logging(s); s->frozen = true; @@ -460,7 +446,7 @@ void ga_unset_frozen(GAState *s) } /* enable all disabled, non-blacklisted commands */ - ga_enable_non_blacklisted(s->blacklist); + qmp_for_each_command(ga_enable_non_blacklisted, s->blacklist); s->frozen = false; if (!ga_delete_file(s->state_filepath_isfrozen)) { g_warning("unable to delete %s, fsfreeze may not function properly", @@ -920,6 +906,11 @@ int64_t ga_get_fd_handle(GAState *s, Error **errp) return handle; } +static void ga_print_cmd(QmpCommand *cmd, void *opaque) +{ + printf("%s\n", cmd->name); +} + int main(int argc, char **argv) { const char *sopt = "hVvdm:p:l:f:F::b:s:t:"; @@ -996,15 +987,8 @@ int main(int argc, char **argv) daemonize = 1; break; case 'b': { - char **list_head, **list; if (is_help_option(optarg)) { - list_head = list = qmp_get_command_list(); - while (*list != NULL) { - printf("%s\n", *list); - g_free(*list); - list++; - } - g_free(list_head); + qmp_for_each_command(ga_print_cmd, NULL); return 0; } for (j = 0, i = 0, len = strlen(optarg); i < len; i++) { @@ -1126,7 +1110,7 @@ int main(int argc, char **argv) s->deferred_options.log_filepath = log_filepath; } ga_disable_logging(s); - ga_disable_non_whitelisted(); + qmp_for_each_command(ga_disable_non_whitelisted, NULL); } else { if (daemonize) { become_daemon(pid_filepath);