Avoid calling device_unregister from device_register callback.
authorcl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Wed, 24 Aug 2005 20:11:07 +0000 (20:11 +0000)
committercl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Wed, 24 Aug 2005 20:11:07 +0000 (20:11 +0000)
Also simplify code.
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c

index 2f2fdfc3cd8223f6e9143ebe55283e6da3cd50d1..2a445a39838faffe3762ecda84f66bef119891e8 100644 (file)
@@ -64,7 +64,7 @@ static void frontend_changed(struct xenbus_watch *watch, const char *node)
                = container_of(watch, struct backend_info, watch);
 
        /* If other end is gone, delete ourself. */
-       if (!xenbus_exists(be->frontpath, "")) {
+       if (node && !xenbus_exists(be->frontpath, "")) {
                xenbus_rm(be->dev->nodename, "");
                device_unregister(&be->dev->dev);
                return;
@@ -139,62 +139,22 @@ static void backend_changed(struct xenbus_watch *watch, const char *node)
 {
        int err;
        char *p;
-       char *frontend;
        long int handle, pdev;
        struct backend_info *be
                = container_of(watch, struct backend_info, backend_watch);
        struct xenbus_device *dev = be->dev;
 
-       frontend = NULL;
-       err = xenbus_gather(dev->nodename,
-                           "frontend-id", "%li", &be->frontend_id,
-                           "frontend", NULL, &frontend,
-                           NULL);
-       if (XENBUS_EXIST_ERR(err) ||
-           strlen(frontend) == 0 || !xenbus_exists(frontend, "")) {
-               /* If we can't get a frontend path and a frontend-id,
-                * then our bus-id is no longer valid and we need to
-                * destroy the backend device.
-                */
-               goto device_fail;
-       }
-       if (err < 0) {
-               xenbus_dev_error(dev, err,
-                                "reading %s/frontend or frontend-id",
-                                dev->nodename);
-               goto device_fail;
-       }
-
-       if (!be->frontpath || strcmp(frontend, be->frontpath)) {
-               if (be->watch.node)
-                       unregister_xenbus_watch(&be->watch);
-               if (be->frontpath)
-                       kfree(be->frontpath);
-               be->frontpath = frontend;
-               frontend = NULL;
-               be->watch.node = be->frontpath;
-               be->watch.callback = frontend_changed;
-               err = register_xenbus_watch(&be->watch);
-               if (err) {
-                       be->watch.node = NULL;
-                       xenbus_dev_error(dev, err,
-                                        "adding frontend watch on %s",
-                                        be->frontpath);
-                       goto device_fail;
-               }
-       }
-
        err = xenbus_scanf(dev->nodename, "physical-device", "%li", &pdev);
        if (XENBUS_EXIST_ERR(err))
-               goto out;
+               return;
        if (err < 0) {
                xenbus_dev_error(dev, err, "reading physical-device");
-               goto device_fail;
+               return;
        }
        if (be->pdev && be->pdev != pdev) {
                printk(KERN_WARNING
                       "changing physical-device not supported\n");
-               goto device_fail;
+               return;
        }
        be->pdev = pdev;
 
@@ -215,32 +175,25 @@ static void backend_changed(struct xenbus_watch *watch, const char *node)
                        err = PTR_ERR(be->blkif);
                        be->blkif = NULL;
                        xenbus_dev_error(dev, err, "creating block interface");
-                       goto device_fail;
+                       return;
                }
 
                err = vbd_create(be->blkif, handle, be->pdev, be->readonly);
                if (err) {
                        xenbus_dev_error(dev, err, "creating vbd structure");
-                       goto device_fail;
+                       return;
                }
 
-               frontend_changed(&be->watch, be->frontpath);
+               /* Pass in NULL node to skip exist test. */
+               frontend_changed(&be->watch, NULL);
        }
-
- out:
-       if (frontend)
-               kfree(frontend);
-       return;
-
- device_fail:
-       device_unregister(&be->dev->dev);
-       goto out;
 }
 
 static int blkback_probe(struct xenbus_device *dev,
                         const struct xenbus_device_id *id)
 {
        struct backend_info *be;
+       char *frontend;
        int err;
 
        be = kmalloc(sizeof(*be), GFP_KERNEL);
@@ -263,9 +216,46 @@ static int blkback_probe(struct xenbus_device *dev,
 
        dev->data = be;
 
+       frontend = NULL;
+       err = xenbus_gather(dev->nodename,
+                           "frontend-id", "%li", &be->frontend_id,
+                           "frontend", NULL, &frontend,
+                           NULL);
+       if (XENBUS_EXIST_ERR(err))
+               goto free_be;
+       if (frontend &&
+           (strlen(frontend) == 0 || !xenbus_exists(frontend, ""))) {
+               /* If we can't get a frontend path and a frontend-id,
+                * then our bus-id is no longer valid and we need to
+                * destroy the backend device.
+                */
+               goto free_be;
+       }
+       if (err < 0) {
+               xenbus_dev_error(dev, err,
+                                "reading %s/frontend or frontend-id",
+                                dev->nodename);
+               goto free_be;
+       }
+
+       be->frontpath = frontend;
+       be->watch.node = be->frontpath;
+       be->watch.callback = frontend_changed;
+       err = register_xenbus_watch(&be->watch);
+       if (err) {
+               be->watch.node = NULL;
+               xenbus_dev_error(dev, err,
+                                "adding frontend watch on %s",
+                                be->frontpath);
+               goto free_be;
+       }
+
        backend_changed(&be->backend_watch, dev->nodename);
        return err;
+
  free_be:
+       if (frontend)
+               kfree(frontend);
        kfree(be);
        return err;
 }