From mboxrd@z Thu Jan 1 00:00:00 1970 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 From: Jan Kiszka Date: Wed, 16 Jun 2010 00:38:31 +0200 Message-Id: <4ce8e9efe689eed00bccad228ccaea2210c69821.1276641524.git.jan.kiszka@web.de> In-Reply-To: References: In-Reply-To: References: Sender: jan.kiszka@web.de Subject: [Qemu-devel] [PATCH v4 07/23] qdev: Allow device specification by qtree path for device_del List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org, Anthony Liguori Cc: Juan Quintela , Jan Kiszka , Markus Armbruster , Luiz Capitulino , Blue Swirl , Avi Kivity 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 -- 1.6.0.2