Commit b2b6c39a authored by Anthony Liguori's avatar Anthony Liguori
Browse files

qom: optimize qdev_get_canonical_path using a parent link



The full tree search was a bit unreasonable.

Signed-off-by: default avatarAnthony Liguori <aliguori@us.ibm.com>
parent 18297050
Loading
Loading
Loading
Loading
+24 −32
Original line number Diff line number Diff line
@@ -1229,6 +1229,8 @@ void qdev_property_add_child(DeviceState *dev, const char *name,
                      NULL, NULL, child, errp);

    qdev_ref(child);
    g_assert(child->parent == NULL);
    child->parent = dev;

    g_free(type);
}
@@ -1307,47 +1309,37 @@ void qdev_property_add_link(DeviceState *dev, const char *name,
    g_free(full_type);
}

static gchar *qdev_get_path_in(DeviceState *parent, DeviceState *dev)
gchar *qdev_get_canonical_path(DeviceState *dev)
{
    DeviceProperty *prop;
    DeviceState *root = qdev_get_root();
    char *newpath = NULL, *path = NULL;

    if (parent == dev) {
        return g_strdup("");
    }
    while (dev != root) {
        DeviceProperty *prop = NULL;

    QTAILQ_FOREACH(prop, &parent->properties, node) {
        gchar *subpath;
        g_assert(dev->parent != NULL);

        QTAILQ_FOREACH(prop, &dev->parent->properties, node) {
            if (!strstart(prop->type, "child<", NULL)) {
                continue;
            }

        /* Check to see if the device is one of parent's children */
            if (prop->opaque == dev) {
            return g_strdup(prop->name);
        }

        /* Check to see if the device is a child of our child */
        subpath = qdev_get_path_in(prop->opaque, dev);
        if (subpath) {
            gchar *path;

            path = g_strdup_printf("%s/%s", prop->name, subpath);
            g_free(subpath);

            return path;
                if (path) {
                    newpath = g_strdup_printf("%s/%s", prop->name, path);
                    g_free(path);
                    path = newpath;
                } else {
                    path = g_strdup(prop->name);
                }
                break;
            }

    return NULL;
        }

gchar *qdev_get_canonical_path(DeviceState *dev)
{
    gchar *path, *newpath;
        g_assert(prop != NULL);

    path = qdev_get_path_in(qdev_get_root(), dev);
    g_assert(path != NULL);
        dev = dev->parent;
    }

    newpath = g_strdup_printf("/%s", path);
    g_free(path);
+4 −0
Original line number Diff line number Diff line
@@ -92,6 +92,10 @@ struct DeviceState {
    uint32_t ref;

    QTAILQ_HEAD(, DeviceProperty) properties;

    /* Do not, under any circumstance, use this parent link below anywhere
     * outside of qdev.c.  You have been warned. */
    DeviceState *parent;
};

typedef void (*bus_dev_printfn)(Monitor *mon, DeviceState *dev, int indent);