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

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

To: Xen devel list <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [patch 5/6] frontend device shutdown
From: Gerd Hoffmann <kraxel@xxxxxxx>
Date: Thu, 17 Aug 2006 16:03:48 +0200
Delivery-date: Thu, 17 Aug 2006 07:04:14 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
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>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Thunderbird 1.5.0.5 (X11/20060725)
  Hi,

This patch makes xenbus and net/blkfront drivers correctly handle
device_shutdown().  Changes:

  * new xenbus_strstate() helper function for fancy debug output.
  * add xenbus_dev_shutdown() function which switches the devices
    into Closing state and waits for them to finish shutdown.
  * new helper function xenbus_closing_done(), which handles the
    final state transition and informs xenbus_dev_shutdown().

xenbus_closing_done() behaves differently depending on how the closing
was triggered.  If it was triggered by the backend the frontend acks the
removal by going to CLosed.  If it was triggered via device_shutdown()
the state is set back to "Initializing", to allow a possible new kernel
instance to reuse the devices (for domU kexec again ;)

cheers,

  Gerd

-- 
Gerd Hoffmann <kraxel@xxxxxxx>
http://www.suse.de/~kraxel/julika-dora.jpeg
Signed-off-by: Gerd Hoffmann <kraxel@xxxxxxx>
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 <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,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 */
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel