Signed-off-by: Gerd Hoffmann Index: source-lnx-stable-22813/drivers/xen/blkfront/blkfront.c =================================================================== --- source-lnx-stable-22813.orig/drivers/xen/blkfront/blkfront.c 2006-08-17 15:19:20.000000000 +0200 +++ source-lnx-stable-22813/drivers/xen/blkfront/blkfront.c 2006-08-17 15:20:17.000000000 +0200 @@ -272,10 +272,13 @@ static void backend_changed(struct xenbu xenbus_dev_fatal(dev, -ENODEV, "bdget failed"); down(&bd->bd_sem); - if (info->users > 0) + if (info->users) + printk("%-20s: %s: %d user(s) left\n", __FUNCTION__, + dev->nodename, info->users); + if (info->users > 0 && !dev->shutdown_in_progress) { xenbus_dev_error(dev, -EBUSY, "Device in use; refusing to close"); - else + } else blkfront_closing(dev); up(&bd->bd_sem); bdput(bd); @@ -359,7 +362,7 @@ static void blkfront_closing(struct xenb xlvbd_del(info); - xenbus_switch_state(dev, XenbusStateClosed); + xenbus_closing_done(dev); } Index: source-lnx-stable-22813/drivers/xen/netfront/netfront.c =================================================================== --- source-lnx-stable-22813.orig/drivers/xen/netfront/netfront.c 2006-08-17 15:19:20.000000000 +0200 +++ source-lnx-stable-22813/drivers/xen/netfront/netfront.c 2006-08-17 15:20:33.000000000 +0200 @@ -436,7 +436,7 @@ static void backend_changed(struct xenbu struct netfront_info *np = dev->dev.driver_data; struct net_device *netdev = np->netdev; - DPRINTK("\n"); + DPRINTK("%s\n", xenbus_strstate(backend_state)); switch (backend_state) { case XenbusStateInitialising: @@ -447,9 +447,11 @@ static void backend_changed(struct xenbu break; case XenbusStateInitWait: - network_connect(netdev); - xenbus_switch_state(dev, XenbusStateConnected); - (void)send_fake_arp(netdev); + if (!dev->shutdown_in_progress) { + network_connect(netdev); + xenbus_switch_state(dev, XenbusStateConnected); + (void)send_fake_arp(netdev); + } break; case XenbusStateClosing: @@ -1720,11 +1722,10 @@ static void netfront_closing(struct xenb { struct netfront_info *info = dev->dev.driver_data; - DPRINTK("netfront_closing: %s removed\n", dev->nodename); + DPRINTK("%s\n", dev->nodename); close_netdev(info); - - xenbus_switch_state(dev, XenbusStateClosed); + xenbus_closing_done(dev); } Index: source-lnx-stable-22813/drivers/xen/xenbus/xenbus_client.c =================================================================== --- source-lnx-stable-22813.orig/drivers/xen/xenbus/xenbus_client.c 2006-08-17 15:19:20.000000000 +0200 +++ source-lnx-stable-22813/drivers/xen/xenbus/xenbus_client.c 2006-08-17 15:20:17.000000000 +0200 @@ -41,6 +41,21 @@ extern char *kasprintf(const char *fmt, #define DPRINTK(fmt, args...) \ pr_debug("xenbus_client (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args) +char *xenbus_strstate(enum xenbus_state state) +{ + static char *name[] = { + [ XenbusStateUnknown ] = "Unknown", + [ XenbusStateInitialising ] = "Initialising", + [ XenbusStateInitWait ] = "InitWait", + [ XenbusStateInitialised ] = "Initialised", + [ XenbusStateConnected ] = "Connected", + [ XenbusStateClosing ] = "Closing", + [ XenbusStateClosed ] = "Closed", + }; + return state < sizeof(name)/sizeof(name[0]) + ? name[state] : "INVALID"; +} + int xenbus_watch_path(struct xenbus_device *dev, const char *path, struct xenbus_watch *watch, void (*callback)(struct xenbus_watch *, @@ -124,6 +139,23 @@ int xenbus_switch_state(struct xenbus_de } EXPORT_SYMBOL_GPL(xenbus_switch_state); +int xenbus_closing_done(struct xenbus_device *dev) +{ + if (dev->shutdown_in_progress) { + /* frontend (we) triggered closing, because of devices_shutdown(), + * prepare for possible re-connect */ + printk("%-20s: %s: => Initialising\n", __FUNCTION__, dev->nodename); + xenbus_switch_state(dev, XenbusStateInitialising); + } else { + /* backend triggered closing, probably the device went away, + * thus we are going to close down too. */ + printk("%-20s: %s: => Closed\n", __FUNCTION__, dev->nodename); + xenbus_switch_state(dev, XenbusStateClosed); + } + complete(&dev->down); + return 0; +} +EXPORT_SYMBOL_GPL(xenbus_closing_done); /** * Return the path to the error node for the given device, or NULL on failure. Index: source-lnx-stable-22813/drivers/xen/xenbus/xenbus_probe.c =================================================================== --- source-lnx-stable-22813.orig/drivers/xen/xenbus/xenbus_probe.c 2006-08-17 15:20:17.000000000 +0200 +++ source-lnx-stable-22813/drivers/xen/xenbus/xenbus_probe.c 2006-08-17 15:20:17.000000000 +0200 @@ -67,6 +67,7 @@ static int xenbus_probe_backend(const ch static int xenbus_dev_probe(struct device *_dev); static int xenbus_dev_remove(struct device *_dev); +static void xenbus_dev_shutdown(struct device *_dev); /* If something in array of ids matches this device, return it. */ static const struct xenbus_device_id * @@ -186,6 +187,7 @@ static struct xen_bus_type xenbus_fronte .match = xenbus_match, .probe = xenbus_dev_probe, .remove = xenbus_dev_remove, + .shutdown = xenbus_dev_shutdown, }, .dev = { .bus_id = "xen", @@ -240,6 +242,7 @@ static struct xen_bus_type xenbus_backen .match = xenbus_match, .probe = xenbus_dev_probe, .remove = xenbus_dev_remove, +// .shutdown = xenbus_dev_shutdown, .uevent = xenbus_uevent_backend, }, .dev = { @@ -399,6 +402,26 @@ static int xenbus_dev_remove(struct devi return 0; } +static void xenbus_dev_shutdown(struct device *_dev) +{ + struct xenbus_device *dev = to_xenbus_device(_dev); + unsigned long timeout = 5*HZ; + + get_device(&dev->dev); + if (dev->state != XenbusStateConnected) { + printk("%s: %s: %s != Connected, skipping\n", __FUNCTION__, + dev->nodename, xenbus_strstate(dev->state)); + goto out; + } + dev->shutdown_in_progress = 1; + xenbus_switch_state(dev, XenbusStateClosing); + timeout = wait_for_completion_timeout(&dev->down, timeout); + if (!timeout) + printk("%s: %s timeout closing device\n", __FUNCTION__, dev->nodename); + out: + put_device(&dev->dev); +} + static int xenbus_register_driver_common(struct xenbus_driver *drv, struct xen_bus_type *bus) { @@ -581,6 +604,7 @@ static int xenbus_probe_node(struct xen_ tmpstring += strlen(tmpstring) + 1; strcpy(tmpstring, type); xendev->devicetype = tmpstring; + init_completion(&xendev->down); xendev->dev.parent = &bus->dev; xendev->dev.bus = &bus->bus; Index: source-lnx-stable-22813/include/xen/xenbus.h =================================================================== --- source-lnx-stable-22813.orig/include/xen/xenbus.h 2006-08-17 15:19:20.000000000 +0200 +++ source-lnx-stable-22813/include/xen/xenbus.h 2006-08-17 15:20:17.000000000 +0200 @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -74,6 +75,9 @@ struct xenbus_device { struct xenbus_watch otherend_watch; struct device dev; enum xenbus_state state; + + struct completion down; + int shutdown_in_progress; }; static inline struct xenbus_device *to_xenbus_device(struct device *dev) @@ -296,4 +300,7 @@ void xenbus_dev_fatal(struct xenbus_devi ...); +int xenbus_closing_done(struct xenbus_device *dev); +char *xenbus_strstate(enum xenbus_state state); + #endif /* _XEN_XENBUS_H */