All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gerd Hoffmann <kraxel@suse.de>
To: Gerd Hoffmann <kraxel@suse.de>
Cc: Xen devel list <xen-devel@lists.xensource.com>,
	Ewan Mellor <ewan@xensource.com>
Subject: Re: [patch 5/6] frontend device shutdown
Date: Tue, 22 Aug 2006 12:22:06 +0200	[thread overview]
Message-ID: <44EADACE.5000107@suse.de> (raw)
In-Reply-To: <44EACA8B.5020901@suse.de>

[-- Attachment #1: Type: text/plain, Size: 939 bytes --]

  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@suse.de>
http://www.suse.de/~kraxel/julika-dora.jpeg

[-- Attachment #2: frontend-shutdown-2 --]
[-- Type: text/plain, Size: 9772 bytes --]

Signed-off-by: Gerd Hoffmann <kraxel@suse.de>
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 */


[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

  reply	other threads:[~2006-08-22 10:22 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-08-17 14:03 [patch 5/6] frontend device shutdown Gerd Hoffmann
2006-08-19 12:25 ` Keir Fraser
2006-08-19 12:29   ` Keir Fraser
2006-08-21 14:11   ` Gerd Hoffmann
2006-08-21 16:11     ` Keir Fraser
2006-08-22  8:04       ` Gerd Hoffmann
2006-08-22  8:30         ` Keir Fraser
2006-08-22  8:40           ` Keir Fraser
2006-08-22  9:12           ` Gerd Hoffmann
2006-08-22 10:22             ` Gerd Hoffmann [this message]
2006-08-19 12:52 ` Keir Fraser
2006-08-21  6:48   ` Gerd Hoffmann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=44EADACE.5000107@suse.de \
    --to=kraxel@suse.de \
    --cc=ewan@xensource.com \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.