]> xenbits.xensource.com Git - people/ssmith/nc2-2.6.27.git/commitdiff
Watch the online node in the backend area, as well as the state node
authorSteven Smith <ssmith@weybridge.uk.xensource.com>
Tue, 30 Jun 2009 11:55:48 +0000 (12:55 +0100)
committerSteven Smith <ssmith@weybridge.uk.xensource.com>
Tue, 30 Jun 2009 11:55:48 +0000 (12:55 +0100)
in the frontend area, and fire the frontend state changed watch
whenever it changes.  This allows us to catch the case where a device
shuts down in a domU and then gets xm detach'd from in dom0.

Otherwise, the backend doesn't shut down correctly, since online was
set when the frontend shut down and we don't get another kick when it
becomes unset.

drivers/xen/xenbus/xenbus_probe.c
include/xen/xenbus.h

index 3cfc5c64f958fe6f6817e309a6dfcbb3f8e645a9..3f7ea040e87c56d7e16dca4f01939a0506a1a240 100644 (file)
@@ -133,6 +133,11 @@ static void free_otherend_watch(struct xenbus_device *dev)
                unregister_xenbus_watch(&dev->otherend_watch);
                kfree(dev->otherend_watch.node);
                dev->otherend_watch.node = NULL;
+        }
+        if (dev->online_watch.node) {
+               unregister_xenbus_watch(&dev->online_watch);
+               kfree(dev->online_watch.node);
+               dev->online_watch.node = NULL;
        }
 }
 
@@ -211,23 +216,12 @@ static struct xen_bus_type xenbus_frontend = {
        },
 };
 
-static void otherend_changed(struct xenbus_watch *watch,
-                            const char **vec, unsigned int len)
+static void otherend_changed_common(struct xenbus_device *dev,
+                                    const char **vec, unsigned int len)
 {
-       struct xenbus_device *dev =
-               container_of(watch, struct xenbus_device, otherend_watch);
        struct xenbus_driver *drv = to_xenbus_driver(dev->dev.driver);
        enum xenbus_state state;
 
-       /* Protect us against watches firing on old details when the otherend
-          details change, say immediately after a resume. */
-       if (!dev->otherend ||
-           strncmp(dev->otherend, vec[XS_WATCH_PATH],
-                   strlen(dev->otherend))) {
-               DPRINTK("Ignoring watch at %s", vec[XS_WATCH_PATH]);
-               return;
-       }
-
        state = xenbus_read_driver_state(dev->otherend);
 
        DPRINTK("state is %d (%s), %s, %s", state, xenbus_strstate(state),
@@ -253,6 +247,33 @@ static void otherend_changed(struct xenbus_watch *watch,
                drv->otherend_changed(dev, state);
 }
 
+static void online_changed(struct xenbus_watch *watch,
+                           const char **vec, unsigned int len)
+{
+       struct xenbus_device *dev =
+               container_of(watch, struct xenbus_device, online_watch);
+
+        otherend_changed_common(dev, vec, len);
+}
+
+static void otherend_changed(struct xenbus_watch *watch,
+                            const char **vec, unsigned int len)
+{
+       struct xenbus_device *dev =
+               container_of(watch, struct xenbus_device, otherend_watch);
+
+       /* Protect us against watches firing on old details when the otherend
+          details change, say immediately after a resume. */
+       if (!dev->otherend ||
+           strncmp(dev->otherend, vec[XS_WATCH_PATH],
+                   strlen(dev->otherend))) {
+               DPRINTK("Ignoring watch at %s", vec[XS_WATCH_PATH]);
+               return;
+       }
+
+        otherend_changed_common(dev, vec, len);
+}
+
 
 static int talk_to_otherend(struct xenbus_device *dev)
 {
@@ -267,8 +288,14 @@ static int talk_to_otherend(struct xenbus_device *dev)
 
 static int watch_otherend(struct xenbus_device *dev)
 {
-       return xenbus_watch_path2(dev, dev->otherend, "state",
-                                 &dev->otherend_watch, otherend_changed);
+        int i;
+       i = xenbus_watch_path2(dev, dev->otherend, "state",
+                               &dev->otherend_watch, otherend_changed);
+        if (i >= 0) {
+                i = xenbus_watch_path2(dev, dev->nodename, "online",
+                                       &dev->online_watch, online_changed);
+        }
+        return i;
 }
 
 
index a0de4bad76a223ccb7be945a6afb8408bbc9b199..c062dd5b85b2bef48d47c78d7e87691764a3a082 100644 (file)
@@ -79,6 +79,7 @@ struct xenbus_device {
        const char *otherend;
        int otherend_id;
        struct xenbus_watch otherend_watch;
+       struct xenbus_watch online_watch;
        struct device dev;
        enum xenbus_state state;
        struct completion down;