Make frontend drivers shutdown cleanly.
PATCH 3/3 Make frontend drivers shutdown cleanly.
Hi,
This patch makes frontend drivers being shutdown when devices_shutdown() is called and walks down the device tree. Most of it is handled by the xenbus core, which got a new function for the bus->shutdown callback.
please apply,
Gerd
Signature · 2 lines
Gerd Hoffmann <[email protected]> http://www.suse.de/~kraxel/julika-dora.jpeg
Make frontend drivers shutdown cleanly.
This patch makes frontend drivers being shutdown when devices_shutdown() is called and walks down the device tree. Most of it is handled by the xenbus core, which got a new function for the bus->shutdown callback.
Signed-off-by Gerd Hoffmann <[email protected]>
--- linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c | 4 +- linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c | 7 +-- linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c | 7 +++ linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c | 29 ++++++++++++++-- linux-2.6-xen-sparse/include/xen/xenbus.h | 3 + 5 files changed, 42 insertions(+), 8 deletions(-)
linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c +2 -2
@@ -273,7 +273,7 @@ static void backend_changed(struct xenbuxenbus_dev_fatal (dev, -ENODEV ,"bdget failed" );down (&bd->bd_sem); -if (info->users >0 ) +if (info->users >0 && system_state ==SYSTEM_RUNNING )xenbus_dev_error (dev, -EBUSY ,"Device in use; refusing to close" );else
@@ -360,7 +360,7 @@ static void blkfront_closing(struct xenbxlvbd_del (info); -xenbus_switch_state (dev, XenbusStateClosed); +xenbus_closing_done (dev); }
linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +3 -4
@@ -486,7 +486,7 @@ static void backend_changed(struct xenbustruct 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:
@@ -1936,11 +1936,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); }
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c +7 -0
@@ -139,6 +139,13 @@ int xenbus_switch_state(struct xenbus_de }EXPORT_SYMBOL_GPL (xenbus_switch_state); +int xenbus_closing_done (struct xenbus_device *dev) +{ +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.
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c +27 -2
@@ -73,6 +73,7 @@ static int xenbus_probe_backend(const chstatic 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 *
@@ -192,6 +193,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",
@@ -246,6 +248,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 = {
@@ -348,7 +351,7 @@ static int xenbus_dev_probe(struct devicconst struct xenbus_device_id *id;int err; -DPRINTK ("" ); +DPRINTK ("%s" , dev->nodename);if (!drv->probe) { err = -ENODEV ;
@@ -393,7 +396,7 @@ static int xenbus_dev_remove(struct devistruct xenbus_device *dev =to_xenbus_device (_dev);struct xenbus_driver *drv =to_xenbus_driver (_dev->driver); -DPRINTK ("" ); +DPRINTK ("%s" , dev->nodename);free_otherend_watch (dev);free_otherend_details (dev);
@@ -405,6 +408,27 @@ static int xenbus_dev_remove(struct devireturn 0 ; } +static void xenbus_dev_shutdown (struct device *_dev) +{ +struct xenbus_device *dev =to_xenbus_device (_dev); +unsigned long timeout =5 *HZ ; + +DPRINTK ("%s" , dev->nodename); + +get_device (&dev->dev); +if (dev->state != XenbusStateConnected) { +printk ("%s: %s: %s != Connected, skipping\n" , __FUNCTION__, + dev->nodename,xenbus_strstate (dev->state)); + goto out; + } +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) {
@@ -587,6 +611,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;
linux-2.6-xen-sparse/include/xen/xenbus.h +3 -0
@@ -37,6 +37,7 @@#include <linux/device.h> #include <linux/notifier.h> #include <linux/mutex.h> +#include <linux/completion.h> #include <xen/interface/xen.h> #include <xen/interface/grant_table.h> #include <xen/interface/io/xenbus.h>
@@ -74,6 +75,7 @@ struct xenbus_device {struct xenbus_watch otherend_watch;struct device dev;enum xenbus_state state; +struct completion down; };static inline struct xenbus_device *to_xenbus_device (struct device *dev)
@@ -299,5 +301,6 @@ int __init xenbus_dev_init(void);char *xenbus_strstate (enum xenbus_state state);int xenbus_dev_is_online (struct xenbus_device *dev); +int xenbus_closing_done (struct xenbus_device *dev);#endif /* _XEN_XENBUS_H */
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel