WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

Re: [Xen-devel] [patch 5/6] frontend device shutdown

To: Gerd Hoffmann <kraxel@xxxxxxx>
Subject: Re: [Xen-devel] [patch 5/6] frontend device shutdown
From: Gerd Hoffmann <kraxel@xxxxxxx>
Date: Tue, 22 Aug 2006 12:22:06 +0200
Cc: Xen devel list <xen-devel@xxxxxxxxxxxxxxxxxxx>, Ewan Mellor <ewan@xxxxxxxxxxxxx>
Delivery-date: Tue, 22 Aug 2006 03:22:44 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
In-reply-to: <44EACA8B.5020901@xxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <C1107F25.1331%Keir.Fraser@xxxxxxxxxxxx> <44EACA8B.5020901@xxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Thunderbird 1.5.0.5 (X11/20060725)
  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