]> xenbits.xen.org Git - xenclient/kernel.git/commitdiff
Watch the online node in the backend area, as well as the state node fake-GET_IDLUN-scsi-ioctl
authort_jeang <devnull@localhost>
Tue, 6 Jan 2009 12:06:02 +0000 (12:06 +0000)
committert_jeang <devnull@localhost>
Tue, 6 Jan 2009 12:06:02 +0000 (12:06 +0000)
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 45a1d55a6270a406d0e395cb2babe2db88b3e71a..78d9702a90786cea8750e373dbc114224b14b4ad 100644 (file)
@@ -132,6 +132,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;
        }
 }
 
@@ -215,23 +220,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),
@@ -257,6 +251,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)
 {
@@ -271,8 +292,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 753ebb5f87e97901d1ddba20b64cc539c376e4b6..c5bd548fd70b5d0bdb269b7eba08af992ada6155 100644 (file)
@@ -75,6 +75,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;