From patchwork Tue Jun 15 22:38:31 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 55812 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id BD0E6B7D85 for ; Wed, 16 Jun 2010 08:51:33 +1000 (EST) Received: from localhost ([127.0.0.1]:46122 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OOeyU-00065q-LD for incoming@patchwork.ozlabs.org; Tue, 15 Jun 2010 18:51:18 -0400 Received: from [140.186.70.92] (port=33375 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OOeml-0007va-HN for qemu-devel@nongnu.org; Tue, 15 Jun 2010 18:39:18 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OOemi-0005Wl-1G for qemu-devel@nongnu.org; Tue, 15 Jun 2010 18:39:11 -0400 Received: from fmmailgate03.web.de ([217.72.192.234]:51459) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OOemh-0005W7-Dx for qemu-devel@nongnu.org; Tue, 15 Jun 2010 18:39:08 -0400 Received: from smtp04.web.de ( [172.20.0.225]) by fmmailgate03.web.de (Postfix) with ESMTP id CBC35156935CC; Wed, 16 Jun 2010 00:39:06 +0200 (CEST) Received: from [92.74.52.35] (helo=localhost.localdomain) by smtp04.web.de with asmtp (TLSv1:AES256-SHA:256) (WEB.DE 4.110 #4) id 1OOemg-0003C9-01; Wed, 16 Jun 2010 00:39:06 +0200 From: Jan Kiszka To: qemu-devel@nongnu.org, Anthony Liguori Date: Wed, 16 Jun 2010 00:38:31 +0200 Message-Id: <4ce8e9efe689eed00bccad228ccaea2210c69821.1276641524.git.jan.kiszka@web.de> X-Mailer: git-send-email 1.6.0.2 In-Reply-To: References: In-Reply-To: References: X-Sender: jan.kiszka@web.de X-Provags-ID: V01U2FsdGVkX1/MyQsDaJpcMlG9HLbEOvJpcd3JcA/aSMLyslr8 PUZMhe36hO5DjGL6oqzfF/r6mRPvGcVPHm00JnkEKUtxsst3O2 KJbRf6X2c= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4-2.6 Cc: Juan Quintela , Jan Kiszka , Markus Armbruster , Luiz Capitulino , Blue Swirl , Avi Kivity Subject: [Qemu-devel] [PATCH v4 07/23] qdev: Allow device specification by qtree path for device_del X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Jan Kiszka Allow to specify the device to be removed via device_del not only by ID but also by its full or abbreviated qtree path. For this purpose, qdev_find is introduced which combines walking the qtree with searching for device IDs if required. Signed-off-by: Jan Kiszka --- hw/qdev.c | 75 ++++++++++++++++++++++++++++++++++++++++++++----------- qemu-monitor.hx | 10 +++--- 2 files changed, 65 insertions(+), 20 deletions(-) diff --git a/hw/qdev.c b/hw/qdev.c index ac450cf..2d1d171 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -39,7 +39,7 @@ DeviceInfo *device_info_list; static BusState *qbus_find_recursive(BusState *bus, const char *name, const BusInfo *info); -static BusState *qbus_find(const char *path); +static BusState *qbus_find(const char *path, bool report_errors); /* Register a new device type. */ void qdev_register(DeviceInfo *info) @@ -217,7 +217,7 @@ DeviceState *qdev_device_add(QemuOpts *opts) /* find bus */ path = qemu_opt_get(opts, "bus"); if (path != NULL) { - bus = qbus_find(path); + bus = qbus_find(path, true); if (!bus) { return NULL; } @@ -475,7 +475,7 @@ static BusState *qbus_find_recursive(BusState *bus, const char *name, return NULL; } -static DeviceState *qdev_find_recursive(BusState *bus, const char *id) +static DeviceState *qdev_find_id_recursive(BusState *bus, const char *id) { DeviceState *dev, *ret; BusState *child; @@ -484,7 +484,7 @@ static DeviceState *qdev_find_recursive(BusState *bus, const char *id) if (dev->id && strcmp(dev->id, id) == 0) return dev; QTAILQ_FOREACH(child, &dev->child_bus, sibling) { - ret = qdev_find_recursive(child, id); + ret = qdev_find_id_recursive(child, id); if (ret) { return ret; } @@ -590,7 +590,7 @@ static DeviceState *qbus_find_dev(BusState *bus, const char *elem) return NULL; } -static BusState *qbus_find(const char *path) +static BusState *qbus_find(const char *path, bool report_errors) { DeviceState *dev; BusState *bus = main_system_bus; @@ -600,7 +600,7 @@ static BusState *qbus_find(const char *path) /* search for bus name recursively if path is not absolute */ if (path[0] != '/') { bus = qbus_find_recursive(bus, path, NULL); - if (!bus) { + if (!bus && report_errors) { qerror_report(QERR_BUS_NOT_FOUND, path); } return bus; @@ -623,12 +623,16 @@ static BusState *qbus_find(const char *path) pos += len; dev = qbus_find_dev(bus, elem); if (!dev) { - qerror_report(QERR_DEVICE_NOT_FOUND, elem); - qbus_list_dev(bus); + if (report_errors) { + qerror_report(QERR_DEVICE_NOT_FOUND, elem); + qbus_list_dev(bus); + } return NULL; } if (dev->num_child_bus == 0) { - qerror_report(QERR_DEVICE_NO_BUS, elem); + if (report_errors) { + qerror_report(QERR_DEVICE_NO_BUS, elem); + } return NULL; } @@ -644,13 +648,55 @@ static BusState *qbus_find(const char *path) pos += len; bus = qbus_find_bus(dev, elem); if (!bus) { - qerror_report(QERR_BUS_NOT_FOUND, elem); - qbus_list_bus(dev); + if (report_errors) { + qerror_report(QERR_BUS_NOT_FOUND, elem); + qbus_list_bus(dev); + } return NULL; } } } +static DeviceState *qdev_find(const char *path) +{ + const char *dev_name; + DeviceState *dev; + char *bus_path; + BusState *bus; + + /* search for unique ID recursively if path is not absolute */ + if (path[0] != '/') { + dev = qdev_find_id_recursive(main_system_bus, path); + if (!dev) { + qerror_report(QERR_DEVICE_NOT_FOUND, path); + } + return dev; + } + + dev_name = strrchr(path, '/') + 1; + + bus_path = qemu_strdup(path); + bus_path[dev_name - path] = 0; + + bus = qbus_find(bus_path, false); + qemu_free(bus_path); + if (!bus) { + /* retry with full path to generate correct error message */ + bus = qbus_find(path, true); + if (!bus) { + return NULL; + } + dev_name = ""; + } + + dev = qbus_find_dev(bus, dev_name); + if (!dev) { + qerror_report(QERR_DEVICE_NOT_FOUND, dev_name); + qbus_list_dev(bus); + } + return dev; +} + void qbus_create_inplace(BusState *bus, BusInfo *info, DeviceState *parent, const char *name) { @@ -810,12 +856,11 @@ int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data) int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data) { - const char *id = qdict_get_str(qdict, "id"); + const char *path = qdict_get_str(qdict, "device"); DeviceState *dev; - dev = qdev_find_recursive(main_system_bus, id); - if (NULL == dev) { - qerror_report(QERR_DEVICE_NOT_FOUND, id); + dev = qdev_find(path); + if (!dev) { return -1; } return qdev_unplug(dev); diff --git a/qemu-monitor.hx b/qemu-monitor.hx index 9f62b94..0ea0555 100644 --- a/qemu-monitor.hx +++ b/qemu-monitor.hx @@ -703,7 +703,7 @@ EQMP { .name = "device_del", - .args_type = "id:s", + .args_type = "device:s", .params = "device", .help = "remove device", .user_print = monitor_user_noop, @@ -711,10 +711,10 @@ EQMP }, STEXI -@item device_del @var{id} +@item device_del @var{device} @findex device_del -Remove device @var{id}. +Remove @var{device}, specified via its qtree path or unique ID. ETEXI SQMP device_del @@ -724,11 +724,11 @@ Remove a device. Arguments: -- "id": the device's ID (json-string) +- "device": the device's qtree path or unique ID (json-string) Example: --> { "execute": "device_del", "arguments": { "id": "net1" } } +-> { "execute": "device_del", "arguments": { "device": "net1" } } <- { "return": {} } EQMP