From patchwork Mon Dec 12 20:18:02 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony Liguori X-Patchwork-Id: 130870 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id B42F8B6F70 for ; Tue, 13 Dec 2011 08:42:29 +1100 (EST) Received: from localhost ([::1]:52876 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RaCON-00020b-TU for incoming@patchwork.ozlabs.org; Mon, 12 Dec 2011 15:22:31 -0500 Received: from eggs.gnu.org ([140.186.70.92]:41749) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RaCNp-0000sv-Qv for qemu-devel@nongnu.org; Mon, 12 Dec 2011 15:21:59 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RaCNo-0000W2-GB for qemu-devel@nongnu.org; Mon, 12 Dec 2011 15:21:57 -0500 Received: from cpe-70-123-132-139.austin.res.rr.com ([70.123.132.139]:44413 helo=localhost6.localdomain6) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RaCNo-0000Vv-7b for qemu-devel@nongnu.org; Mon, 12 Dec 2011 15:21:56 -0500 Received: from localhost6.localdomain6 (localhost.localdomain [127.0.0.1]) by localhost6.localdomain6 (8.14.4/8.14.4/Debian-2ubuntu1) with ESMTP id pBCKLicj032484; Mon, 12 Dec 2011 14:21:45 -0600 Received: (from anthony@localhost) by localhost6.localdomain6 (8.14.4/8.14.4/Submit) id pBCKLha0032480; Mon, 12 Dec 2011 14:21:43 -0600 From: Anthony Liguori To: qemu-devel@nongnu.org Date: Mon, 12 Dec 2011 14:18:02 -0600 Message-Id: <1323721273-32404-7-git-send-email-aliguori@us.ibm.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1323721273-32404-1-git-send-email-aliguori@us.ibm.com> References: <1323721273-32404-1-git-send-email-aliguori@us.ibm.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 70.123.132.139 Cc: Kevin Wolf , Peter Maydell , Anthony Liguori , Stefan Hajnoczi , Jan Kiszka , Markus Armbruster , Luiz Capitulino Subject: [Qemu-devel] [PATCH v3 006/197] qdev: provide a path resolution (v2) 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 There are two types of supported paths--absolute paths and partial paths. Absolute paths are derived from the root device and can follow child<> or link<> properties. Since they can follow link<> properties, they can be arbitrarily long. Absolute paths look like absolute filenames and are prefixed with a leading slash. Partial paths are look like relative filenames. They do not begin with a prefix. The matching rules for partial paths are subtle but designed to make specifying devices easy. At each level of the composition tree, the partial path is matched as an absolute path. The first match is not returned. At least two matches are searched for. A successful result is only returned if only one match is founded. If more than one match is found, a flag is returned to indicate that the match was ambiguous. At the end of the day, partial path support means that if you create a device called 'ide0', you can just say 'ide0' as the path name and it will Just Work. If we internally create a device called 'i440fx', you can just say 'i440fx' and it will Just Work and long as you don't do anything silly. A management tool should probably always use absolute paths since then they don't have to deal with the possibility of ambiguity. Signed-off-by: Anthony Liguori --- v1 -> v2 - fix comments (Stefan) - always initialize ambiguous to false (Stefan) - change from gslist to qemu-queue (Kevin/Gerd) --- hw/qdev.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/qdev.h | 28 ++++++++++++++++ 2 files changed, 131 insertions(+), 0 deletions(-) diff --git a/hw/qdev.c b/hw/qdev.c index 79849c9..2519f00 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -1221,3 +1221,106 @@ gchar *qdev_get_canonical_path(DeviceState *dev) return newpath; } + +static DeviceState *qdev_resolve_abs_path(DeviceState *parent, + gchar **parts, + int index) +{ + DeviceProperty *prop; + DeviceState *child; + + if (parts[index] == NULL) { + return parent; + } + + if (strcmp(parts[index], "") == 0) { + return qdev_resolve_abs_path(parent, parts, index + 1); + } + + prop = qdev_property_find(parent, parts[index]); + if (prop == NULL) { + return NULL; + } + + child = NULL; + if (strstart(prop->type, "link<", NULL)) { + DeviceState **pchild = prop->opaque; + if (*pchild) { + child = *pchild; + } + } else if (strstart(prop->type, "child<", NULL)) { + child = prop->opaque; + } + + if (!child) { + return NULL; + } + + return qdev_resolve_abs_path(child, parts, index + 1); +} + +static DeviceState *qdev_resolve_partial_path(DeviceState *parent, + gchar **parts, + bool *ambiguous) +{ + DeviceState *dev; + DeviceProperty *prop; + + dev = qdev_resolve_abs_path(parent, parts, 0); + + QTAILQ_FOREACH(prop, &parent->properties, node) { + DeviceState *found; + + if (!strstart(prop->type, "child<", NULL)) { + continue; + } + + found = qdev_resolve_partial_path(prop->opaque, parts, ambiguous); + if (found) { + if (dev) { + if (ambiguous) { + *ambiguous = true; + } + return NULL; + } + dev = found; + } + + if (ambiguous && *ambiguous) { + return NULL; + } + } + + return dev; +} + +DeviceState *qdev_resolve_path(const char *path, bool *ambiguous) +{ + bool partial_path = true; + DeviceState *dev; + gchar **parts; + + parts = g_strsplit(path, "/", 0); + if (parts == NULL || parts[0] == NULL) { + g_strfreev(parts); + return qdev_get_root(); + } + + if (strcmp(parts[0], "") == 0) { + partial_path = false; + } + + if (partial_path) { + if (ambiguous) { + *ambiguous = false; + } + dev = qdev_resolve_partial_path(qdev_get_root(), parts, ambiguous); + } else { + dev = qdev_resolve_abs_path(qdev_get_root(), parts, 1); + } + + g_strfreev(parts); + + return dev; +} + diff --git a/hw/qdev.h b/hw/qdev.h index 0f00497..641d134 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -499,4 +499,32 @@ DeviceState *qdev_get_root(void); */ gchar *qdev_get_canonical_path(DeviceState *dev); +/** + * @qdev_resolve_path - resolves a path returning a device + * + * There are two types of supported paths--absolute paths and partial paths. + * + * Absolute paths are derived from the root device and can follow child<> or + * link<> properties. Since they can follow link<> properties, they can be + * arbitrarily long. Absolute paths look like absolute filenames and are + * prefixed with a leading slash. + * + * Partial paths look like relative filenames. They do not begin with a + * prefix. The matching rules for partial paths are subtle but designed to make + * specifying devices easy. At each level of the composition tree, the partial + * path is matched as an absolute path. The first match is not returned. At + * least two matches are searched for. A successful result is only returned if + * only one match is founded. If more than one match is found, a flag is + * return to indicate that the match was ambiguous. + * + * @path - the path to resolve + * + * @ambiguous - returns true if the path resolution failed because of an + * ambiguous match + * + * Returns: + * The matched device or NULL on path lookup failure. + */ +DeviceState *qdev_resolve_path(const char *path, bool *ambiguous); + #endif