From patchwork Tue Feb 5 20:39:23 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laszlo Ersek X-Patchwork-Id: 218360 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 33EF72C02C1 for ; Wed, 6 Feb 2013 08:37:43 +1100 (EST) Received: from localhost ([::1]:59885 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U2qCz-0008IJ-8P for incoming@patchwork.ozlabs.org; Tue, 05 Feb 2013 16:37:41 -0500 Received: from eggs.gnu.org ([208.118.235.92]:56416) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U2pHg-0003T1-Kx for qemu-devel@nongnu.org; Tue, 05 Feb 2013 15:38:32 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1U2pHd-0001D9-Q4 for qemu-devel@nongnu.org; Tue, 05 Feb 2013 15:38:28 -0500 Received: from mx1.redhat.com ([209.132.183.28]:45257) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1U2pHd-0001D0-IG for qemu-devel@nongnu.org; Tue, 05 Feb 2013 15:38:25 -0500 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r15KbvgX030368 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 5 Feb 2013 15:37:57 -0500 Received: from lacos-laptop.usersys.redhat.com (vpn1-5-180.ams2.redhat.com [10.36.5.180]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r15KbRvh020516; Tue, 5 Feb 2013 15:37:55 -0500 From: Laszlo Ersek To: aliguori@us.ibm.com, pbonzini@redhat.com, afaerber@suse.de, lcapitulino@redhat.com, stefanha@linux.vnet.ibm.com, xiawenc@linux.vnet.ibm.com, kwolf@redhat.com, ehabkost@redhat.com, jasowang@redhat.com, qemu-devel@nongnu.org Date: Tue, 5 Feb 2013 21:39:23 +0100 Message-Id: <1360096768-8863-11-git-send-email-lersek@redhat.com> In-Reply-To: <1360096768-8863-1-git-send-email-lersek@redhat.com> References: <1360096768-8863-1-git-send-email-lersek@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v2 10/15] qbus_find_recursive(): push Error and make it terminate a recursive search 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 Push error handling to callers. When a bus is found by name and it has no free slots, that's a fatal error for the recursive search. Clarify the interface contract, and use error propagation to unwind the recursion quickly. Conversion status (call chains covered or substituted by error propagation marked with square brackets): do_device_add -> [qemu_find_opts -> error_report] do_device_add -> qdev_device_add -> qerror_report do_device_add -> qdev_device_add -> qbus_find -> [qbus_find_recursive -> qerror_report] do_device_add -> qdev_device_add -> qbus_find -> qerror_report do_device_add -> qdev_device_add -> [set_property -> qdev_prop_parse -> qerror_report_err] Signed-off-by: Laszlo Ersek --- hw/qdev-monitor.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 48 insertions(+), 7 deletions(-) diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c index 0a0bced..4fa64c9 100644 --- a/hw/qdev-monitor.c +++ b/hw/qdev-monitor.c @@ -288,6 +288,40 @@ static DeviceState *qbus_find_dev(BusState *bus, char *elem) return NULL; } +/* + * qbus_find_recursive() -- locate a bus by name and/or type in a subtree + * + * Search the bus subtree rooted in @bus for a bus matching the optionally + * specified @name and the optionally specified @type attributes. Matching + * candidates are examined for a free bus slot. + * + * The following return configurations are possible: + * + * - @retval != NULL Matching bus with a free slot found. + * + * - @retval == NULL No matching bus with a free slot was found. + * For (@name != NULL) calls, a further distinction is + * made for this case: + * + * - *@errp == NULL Bus not found by requested name. For recursive calls, + * the search should continue with siblings of @bus. + * + * - *@errp != NULL Bus found by name, but it has no free slot. For + * recursive calls, this is an abort condition; names are + * unique. + * + * Parameters: + * + * - @bus root of subtree to search + * + * - @name if non-NULL, restrict search by this bus name + * + * - @type if non-NULL, restrict search by this bus type + * + * - @errp Returns the error if bus is found by name but it has no free slot. + * (@errp != NULL && *@errp == NULL) must hold on input for all + * calls. + */ static BusState *qbus_find_recursive(BusState *bus, const char *name, const char *type, Error **errp) { @@ -304,8 +338,7 @@ static BusState *qbus_find_recursive(BusState *bus, const char *name, /* bus is full -- fatal error for search by name */ if (name != NULL) { - qerror_report(ERROR_CLASS_GENERIC_ERROR, "Bus '%s' is full", - bus->name); + error_setg(errp, "Bus '%s' is full", bus->name); return NULL; } } @@ -317,8 +350,8 @@ static BusState *qbus_find_recursive(BusState *bus, const char *name, QLIST_FOREACH(child, &dev->child_bus, sibling) { BusState *ret; - ret = qbus_find_recursive(child, name, type, NULL); - if (ret) { + ret = qbus_find_recursive(child, name, type, errp); + if (ret || error_is_set(errp)) { return ret; } } @@ -338,13 +371,20 @@ static BusState *qbus_find(const char *path) bus = sysbus_get_default(); pos = 0; } else { + Error *err = NULL; + if (sscanf(path, "%127[^/]%n", elem, &len) != 1) { assert(!path[0]); elem[0] = len = 0; } - bus = qbus_find_recursive(sysbus_get_default(), elem, NULL, NULL); + bus = qbus_find_recursive(sysbus_get_default(), elem, NULL, &err); if (!bus) { - qerror_report(QERR_BUS_NOT_FOUND, elem); + if (error_is_set(&err)) { + qerror_report_err(err); + error_free(err); + } else { + qerror_report(QERR_BUS_NOT_FOUND, elem); + } return NULL; } pos = len; @@ -460,8 +500,9 @@ DeviceState *qdev_device_add(QemuOpts *opts) } } else { bus = qbus_find_recursive(sysbus_get_default(), NULL, k->bus_type, - NULL); + &local_err); if (!bus) { + assert(!error_is_set(&local_err)); qerror_report(QERR_NO_BUS_FOR_DEVICE, k->bus_type, driver); return NULL;