[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Let dev_changed detect devices when a watch fires with a longer node name.
# HG changeset patch # User cl349@xxxxxxxxxxxxxxxxxxxx # Node ID b0893b876c8c4c4eb507d48fc1c4af4268ddecde # Parent b2f2c08e1222dce282b9483546e49fdff08b59c9 Let dev_changed detect devices when a watch fires with a longer node name. Also improve device cleanup when the dir for a while frontend domain is removed. Signed-off-by: Christian Limpach <Christian.Limpach@xxxxxxxxxxxx> diff -r b2f2c08e1222 -r b0893b876c8c linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Thu Aug 18 19:08:09 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Thu Aug 18 19:15:22 2005 @@ -257,6 +257,34 @@ return info.dev; } +static int cleanup_dev(struct device *dev, void *data) +{ + struct xenbus_device *xendev = to_xenbus_device(dev); + struct xb_find_info *info = data; + int len = strlen(info->nodename); + + if (!strncmp(xendev->nodename, info->nodename, len)) { + info->dev = xendev; + get_device(dev); + return 1; + } + return 0; +} + +static void xenbus_cleanup_devices(const char *path, struct bus_type *bus) +{ + struct xb_find_info info = { .nodename = path }; + + do { + info.dev = NULL; + bus_for_each_dev(bus, NULL, &info, cleanup_dev); + if (info.dev) { + device_unregister(&info.dev->dev); + put_device(&info.dev->dev); + } + } while (info.dev); +} + static void xenbus_release_device(struct device *dev) { if (dev) { @@ -443,33 +471,54 @@ return ret; } +static int strsep_len(const char *str, char c, unsigned int len) +{ + unsigned int i; + + for (i = 0; str[i]; i++) + if (str[i] == c) { + if (len == 0) + return i; + len--; + } + return (len == 0) ? i : -ERANGE; +} + static void dev_changed(const char *node, struct xen_bus_type *bus) { - int exists; + int exists, rootlen; struct xenbus_device *dev; char type[BUS_ID_SIZE]; - const char *p; - - /* FIXME: wouldn't need this if we could limit watch depth. */ - if (char_count(node, '/') != bus->levels) + const char *p, *root; + + if (char_count(node, '/') < 2) + return; + + exists = xenbus_exists(node, ""); + if (!exists) { + xenbus_cleanup_devices(node, &bus->bus); return; + } /* backend/<type>/... or device/<type>/... */ p = strchr(node, '/') + 1; snprintf(type, BUS_ID_SIZE, "%.*s", strcspn(p, "/"), p); type[BUS_ID_SIZE-1] = '\0'; - /* Created or deleted? */ - exists = xenbus_exists(node, ""); - dev = xenbus_device_find(node, &bus->bus); - - if (dev && !exists) { - device_unregister(&dev->dev); - } else if (!dev && exists) { - xenbus_probe_node(bus, type, node); - } - if (dev) + rootlen = strsep_len(node, '/', bus->levels); + if (rootlen < 0) + return; + root = kasprintf("%.*s", rootlen, node); + if (!root) + return; + + dev = xenbus_device_find(root, &bus->bus); + if (!dev) + xenbus_probe_node(bus, type, root); + else put_device(&dev->dev); + + kfree(root); } static void frontend_changed(struct xenbus_watch *watch, const char *node) @@ -484,7 +533,6 @@ /* We watch for devices appearing and vanishing. */ static struct xenbus_watch fe_watch = { - /* FIXME: Ideally we'd only watch for changes 2 levels deep... */ .node = "device", .callback = frontend_changed, }; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |