[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [patch 5/6] frontend device shutdown
Hi, >> 1. Always enter Closed state, and then run a cleanup phase in the kexec >> code which iterates over xenstore device directories, switching >> Closed->Initialising. > I'll try (1). I don't expect it being that hard, I expect doing that in > the old kernel _after_ unregistering the watches should work just fine. Here we go, changes: * new helper function xenbus_strstate() for more readable debug output. * some of the DPRINK()'s got some more info to print added (device node, state on state changes). * Both sides will happily enter "Closed" state without deleting the device. * There is a new helper function xenbus_reinit_frontend_devices() for kexec: It unregisteres the watch (to prevent the device from being reinitialized in the old kernel) and moves devices from Closed back to Initialising state. cheers, Gerd -- Gerd Hoffmann <kraxel@xxxxxxx> http://www.suse.de/~kraxel/julika-dora.jpeg Signed-off-by: Gerd Hoffmann <kraxel@xxxxxxx> diff -r f681ffc9b01a linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Mon Aug 21 12:05:11 2006 -0400 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Tue Aug 22 11:34:33 2006 +0200 @@ -301,11 +301,11 @@ static void frontend_changed(struct xenb struct backend_info *be = dev->dev.driver_data; int err; - DPRINTK(""); + DPRINTK("%s", xenbus_strstate(frontend_state)); switch (frontend_state) { case XenbusStateInitialising: - if (dev->state == XenbusStateClosing) { + if (dev->state == XenbusStateClosed) { printk("%s: %s: prepare for reconnect\n", __FUNCTION__, dev->nodename); xenbus_switch_state(dev, XenbusStateInitWait); @@ -331,8 +331,11 @@ static void frontend_changed(struct xenb xenbus_switch_state(dev, XenbusStateClosing); break; + case XenbusStateClosed: + xenbus_switch_state(dev, XenbusStateClosed); + break; + case XenbusStateUnknown: - case XenbusStateClosed: device_unregister(&dev->dev); break; diff -r f681ffc9b01a linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Mon Aug 21 12:05:11 2006 -0400 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Tue Aug 22 11:51:22 2006 +0200 @@ -273,7 +273,7 @@ static void backend_changed(struct xenbu xenbus_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 xenb xlvbd_del(info); - xenbus_switch_state(dev, XenbusStateClosed); + xenbus_closing_done(dev); } diff -r f681ffc9b01a linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Mon Aug 21 12:05:11 2006 -0400 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Tue Aug 22 11:34:33 2006 +0200 @@ -228,13 +228,13 @@ static void frontend_changed(struct xenb { struct backend_info *be = dev->dev.driver_data; - DPRINTK(""); + DPRINTK("%s", xenbus_strstate(frontend_state)); be->frontend_state = frontend_state; switch (frontend_state) { case XenbusStateInitialising: - if (dev->state == XenbusStateClosing) { + if (dev->state == XenbusStateClosed) { printk("%s: %s: prepare for reconnect\n", __FUNCTION__, dev->nodename); if (be->netif) { @@ -260,8 +260,11 @@ static void frontend_changed(struct xenb xenbus_switch_state(dev, XenbusStateClosing); break; + case XenbusStateClosed: + xenbus_switch_state(dev, XenbusStateClosed); + break; + case XenbusStateUnknown: - case XenbusStateClosed: if (be->netif != NULL) kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); device_unregister(&dev->dev); diff -r f681ffc9b01a linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Mon Aug 21 12:05:11 2006 -0400 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Tue Aug 22 11:52:13 2006 +0200 @@ -478,7 +478,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: @@ -1946,11 +1946,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); } diff -r f681ffc9b01a linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c Mon Aug 21 12:05:11 2006 -0400 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c Tue Aug 22 11:53:16 2006 +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,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. diff -r f681ffc9b01a linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Mon Aug 21 12:05:11 2006 -0400 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Tue Aug 22 11:56:32 2006 +0200 @@ -73,6 +73,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 * @@ -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 = { @@ -316,8 +319,8 @@ static void otherend_changed(struct xenb state = xenbus_read_driver_state(dev->otherend); - DPRINTK("state is %d, %s, %s", - state, dev->otherend_watch.node, vec[XS_WATCH_PATH]); + DPRINTK("state is %s, %s, %s", xenbus_strstate(state), + dev->otherend_watch.node, vec[XS_WATCH_PATH]); if (drv->otherend_changed) drv->otherend_changed(dev, state); } @@ -348,7 +351,7 @@ static int xenbus_dev_probe(struct devic const 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 devi struct 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); @@ -403,6 +406,27 @@ static int xenbus_dev_remove(struct devi xenbus_switch_state(dev, XenbusStateClosed); return 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, @@ -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; @@ -1168,3 +1193,23 @@ static int __init boot_wait_for_devices( late_initcall(boot_wait_for_devices); #endif + +#ifdef CONFIG_KEXEC +static int xenbus_reinit_device(struct device *dev, void *data) +{ + struct xenbus_device *xendev = to_xenbus_device(dev); + + if (xendev->state != XenbusStateClosed) + return 0; + free_otherend_watch(xendev); + xenbus_switch_state(xendev, XenbusStateInitialising); + return 0; +} + +int xenbus_reinit_frontend_devices(void) +{ + DPRINTK(""); + return bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, + xenbus_reinit_device); +} +#endif diff -r f681ffc9b01a linux-2.6-xen-sparse/include/xen/xenbus.h --- a/linux-2.6-xen-sparse/include/xen/xenbus.h Mon Aug 21 12:05:11 2006 -0400 +++ b/linux-2.6-xen-sparse/include/xen/xenbus.h Tue Aug 22 11:34:33 2006 +0200 @@ -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) @@ -297,4 +299,8 @@ void xenbus_dev_fatal(struct xenbus_devi int __init xenbus_dev_init(void); +int xenbus_closing_done(struct xenbus_device *dev); +char *xenbus_strstate(enum xenbus_state state); +int xenbus_reinit_frontend_devices(void); + #endif /* _XEN_XENBUS_H */ _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |