ia64/xen-unstable

changeset 6263:b0893b876c8c

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@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Thu Aug 18 19:15:22 2005 +0000 (2005-08-18)
parents b2f2c08e1222
children a028975ecc05
files linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c	Thu Aug 18 19:08:09 2005 +0000
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c	Thu Aug 18 19:15:22 2005 +0000
     1.3 @@ -257,6 +257,34 @@ struct xenbus_device *xenbus_device_find
     1.4  	return info.dev;
     1.5  }
     1.6  
     1.7 +static int cleanup_dev(struct device *dev, void *data)
     1.8 +{
     1.9 +	struct xenbus_device *xendev = to_xenbus_device(dev);
    1.10 +	struct xb_find_info *info = data;
    1.11 +	int len = strlen(info->nodename);
    1.12 +
    1.13 +	if (!strncmp(xendev->nodename, info->nodename, len)) {
    1.14 +		info->dev = xendev;
    1.15 +		get_device(dev);
    1.16 +		return 1;
    1.17 +	}
    1.18 +	return 0;
    1.19 +}
    1.20 +
    1.21 +static void xenbus_cleanup_devices(const char *path, struct bus_type *bus)
    1.22 +{
    1.23 +	struct xb_find_info info = { .nodename = path };
    1.24 +
    1.25 +	do {
    1.26 +		info.dev = NULL;
    1.27 +		bus_for_each_dev(bus, NULL, &info, cleanup_dev);
    1.28 +		if (info.dev) {
    1.29 +			device_unregister(&info.dev->dev);
    1.30 +			put_device(&info.dev->dev);
    1.31 +		}
    1.32 +	} while (info.dev);
    1.33 +}
    1.34 +
    1.35  static void xenbus_release_device(struct device *dev)
    1.36  {
    1.37  	if (dev) {
    1.38 @@ -443,33 +471,54 @@ static unsigned int char_count(const cha
    1.39  	return ret;
    1.40  }
    1.41  
    1.42 +static int strsep_len(const char *str, char c, unsigned int len)
    1.43 +{
    1.44 +	unsigned int i;
    1.45 +
    1.46 +	for (i = 0; str[i]; i++)
    1.47 +		if (str[i] == c) {
    1.48 +			if (len == 0)
    1.49 +				return i;
    1.50 +			len--;
    1.51 +		}
    1.52 +	return (len == 0) ? i : -ERANGE;
    1.53 +}
    1.54 +
    1.55  static void dev_changed(const char *node, struct xen_bus_type *bus)
    1.56  {
    1.57 -	int exists;
    1.58 +	int exists, rootlen;
    1.59  	struct xenbus_device *dev;
    1.60  	char type[BUS_ID_SIZE];
    1.61 -	const char *p;
    1.62 +	const char *p, *root;
    1.63 +
    1.64 +	if (char_count(node, '/') < 2)
    1.65 + 		return;
    1.66  
    1.67 -	/* FIXME: wouldn't need this if we could limit watch depth. */
    1.68 -	if (char_count(node, '/') != bus->levels)
    1.69 +	exists = xenbus_exists(node, "");
    1.70 +	if (!exists) {
    1.71 +		xenbus_cleanup_devices(node, &bus->bus);
    1.72  		return;
    1.73 +	}
    1.74  
    1.75  	/* backend/<type>/... or device/<type>/... */
    1.76  	p = strchr(node, '/') + 1;
    1.77  	snprintf(type, BUS_ID_SIZE, "%.*s", strcspn(p, "/"), p);
    1.78  	type[BUS_ID_SIZE-1] = '\0';
    1.79  
    1.80 -	/* Created or deleted? */
    1.81 -	exists = xenbus_exists(node, "");
    1.82 -	dev = xenbus_device_find(node, &bus->bus);
    1.83 +	rootlen = strsep_len(node, '/', bus->levels);
    1.84 +	if (rootlen < 0)
    1.85 +		return;
    1.86 +	root = kasprintf("%.*s", rootlen, node);
    1.87 +	if (!root)
    1.88 +		return;
    1.89  
    1.90 -	if (dev && !exists) {
    1.91 -		device_unregister(&dev->dev);
    1.92 -	} else if (!dev && exists) {
    1.93 -		xenbus_probe_node(bus, type, node);
    1.94 -	}
    1.95 -	if (dev)
    1.96 +	dev = xenbus_device_find(root, &bus->bus);
    1.97 +	if (!dev)
    1.98 +		xenbus_probe_node(bus, type, root);
    1.99 +	else
   1.100  		put_device(&dev->dev);
   1.101 +
   1.102 +	kfree(root);
   1.103  }
   1.104  
   1.105  static void frontend_changed(struct xenbus_watch *watch, const char *node)
   1.106 @@ -484,7 +533,6 @@ static void backend_changed(struct xenbu
   1.107  
   1.108  /* We watch for devices appearing and vanishing. */
   1.109  static struct xenbus_watch fe_watch = {
   1.110 -	/* FIXME: Ideally we'd only watch for changes 2 levels deep... */
   1.111  	.node = "device",
   1.112  	.callback = frontend_changed,
   1.113  };