]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
xen-blkback: refactor backend_changed()
authorAnkur Arora <ankur.a.arora@oracle.com>
Thu, 30 Aug 2018 01:53:18 +0000 (18:53 -0700)
committerBrian Maly <brian.maly@oracle.com>
Mon, 8 Oct 2018 15:43:14 +0000 (11:43 -0400)
Add xenbus_scan_be_params() to handle vbd param parsing. This gets
called from backend_changed().

Also place all the parameters (major, minor, cdrom, readonly) in struct
blkif_params. The readonly param is an integer replacement of mode --
this allows us to avoid tracking an additional pointer.

Orabug: 28651655

Signed-off-by: Ankur Arora <ankur.a.arora@oracle.com>
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Bhavesh Davda <bhavesh.davda@oracle.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Signed-off-by: Brian Maly <brian.maly@oracle.com>
drivers/block/xen-blkback/xenbus.c

index 27a12f20acb26992e812dacd74ff48fd05bb058e..34f0f9f4ff5bf139fd64b55596789e01733c37a2 100644 (file)
 /* On the XenBus the max length of 'ring-ref%u'. */
 #define RINGREF_NAME_LEN (20)
 
+struct blkif_params {
+       unsigned int major;
+       unsigned int minor;
+       unsigned int readonly;
+       unsigned int cdrom;
+};
+
 struct backend_info {
        struct xenbus_device    *dev;
        struct xen_blkif        *blkif;
        struct xenbus_watch     backend_watch;
-       unsigned                major;
-       unsigned                minor;
-       char                    *mode;
+       struct blkif_params     params;
 };
 
 static struct kmem_cache *xen_blkif_cachep;
@@ -311,7 +316,6 @@ static void xen_blkif_free(struct xen_blkif *blkif)
 {
        WARN_ON(xen_blkif_disconnect(blkif));
        xen_vbd_free(&blkif->vbd);
-       kfree(blkif->be->mode);
        kfree(blkif->be);
 
        /* Make sure everything is drained before shutting down */
@@ -400,8 +404,8 @@ static const struct attribute_group xen_vbdstat_group = {
        }                                                               \
        static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
 
-VBD_SHOW(physical_device, "%x:%x\n", be->major, be->minor);
-VBD_SHOW(mode, "%s\n", be->mode);
+VBD_SHOW(physical_device, "%x:%x\n", be->params.major, be->params.minor);
+VBD_SHOW(mode, "%s\n", be->params.readonly ? "r":"w");
 
 static int xenvbd_sysfs_addif(struct xenbus_device *dev)
 {
@@ -443,8 +447,7 @@ static void xen_vbd_free(struct xen_vbd *vbd)
 }
 
 static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle,
-                         unsigned major, unsigned minor, int readonly,
-                         int cdrom)
+                         struct blkif_params *p)
 {
        struct xen_vbd *vbd;
        struct block_device *bdev;
@@ -452,10 +455,10 @@ static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle,
 
        vbd = &blkif->vbd;
        vbd->handle   = handle;
-       vbd->readonly = readonly;
+       vbd->readonly = p->readonly;
        vbd->type     = 0;
 
-       vbd->pdevice  = MKDEV(major, minor);
+       vbd->pdevice  = MKDEV(p->major, p->minor);
 
        bdev = blkdev_get_by_dev(vbd->pdevice, vbd->readonly ?
                                 FMODE_READ : FMODE_WRITE, NULL);
@@ -475,7 +478,7 @@ static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle,
        }
        vbd->size = vbd_sz(vbd);
 
-       if (vbd->bdev->bd_disk->flags & GENHD_FL_CD || cdrom)
+       if (vbd->bdev->bd_disk->flags & GENHD_FL_CD || p->cdrom)
                vbd->type |= VDISK_CDROM;
        if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE)
                vbd->type |= VDISK_REMOVABLE;
@@ -487,8 +490,8 @@ static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle,
        if (q && blk_queue_secdiscard(q))
                vbd->discard_secure = true;
 
-       pr_debug("Successful creation of handle=%04x (dom=%u)\n",
-               handle, blkif->domid);
+       pr_debug("Successful creation of handle=%04x (dom=%u), device %x:%x\n",
+               handle, blkif->domid, p->major, p->minor);
        return 0;
 }
 static int xen_blkbk_remove(struct xenbus_device *dev)
@@ -497,7 +500,7 @@ static int xen_blkbk_remove(struct xenbus_device *dev)
 
        pr_debug("%s %p %d\n", __func__, dev, dev->otherend_id);
 
-       if (be->major || be->minor)
+       if (be->params.major || be->params.minor)
                xenvbd_sysfs_delif(dev);
 
        if (be->backend_watch.node) {
@@ -658,98 +661,112 @@ fail:
        return err;
 }
 
-
-/*
- * Callback received when the hotplug scripts have placed the physical-device
- * node.  Read it and the mode node, and create a vbd.  If the frontend is
- * ready, connect.
- */
-static void backend_changed(struct xenbus_watch *watch,
-                           const char *path, const char *token)
+static int
+xenbus_scan_be_params(struct blkif_params *p, struct xenbus_device *dev,
+                       unsigned long *handle)
 {
        int err;
-       unsigned major;
-       unsigned minor;
-       struct backend_info *be
-               = container_of(watch, struct backend_info, backend_watch);
-       struct xenbus_device *dev = be->dev;
-       int cdrom = 0;
-       unsigned long handle;
        char *device_type;
-
-       pr_debug("%s %p %d\n", __func__, dev, dev->otherend_id);
+       char *mode;
 
        err = xenbus_scanf(XBT_NIL, dev->nodename, "physical-device", "%x:%x",
-                          &major, &minor);
+                          &p->major, &p->minor);
        if (XENBUS_EXIST_ERR(err)) {
                /*
                 * Since this watch will fire once immediately after it is
                 * registered, we expect this.  Ignore it, and wait for the
                 * hotplug scripts.
                 */
-               return;
+               return err;
        }
        if (err != 2) {
                xenbus_dev_fatal(dev, err, "reading physical-device");
-               return;
-       }
-
-       if (be->major | be->minor) {
-               if (be->major != major || be->minor != minor)
-                       pr_warn("changing physical device (from %x:%x to %x:%x) not supported.\n",
-                               be->major, be->minor, major, minor);
-               return;
+               return err;
        }
 
-       be->mode = xenbus_read(XBT_NIL, dev->nodename, "mode", NULL);
-       if (IS_ERR(be->mode)) {
-               err = PTR_ERR(be->mode);
-               be->mode = NULL;
+       mode = xenbus_read(XBT_NIL, dev->nodename, "mode", NULL);
+       if (IS_ERR(mode)) {
+               err = PTR_ERR(mode);
                xenbus_dev_fatal(dev, err, "reading mode");
-               return;
+               return err;
        }
 
+       p->readonly = strchr(mode, 'w') == NULL ? 1 : 0;
+       kfree(mode);
+
+       p->cdrom = 0;
+
        device_type = xenbus_read(XBT_NIL, dev->otherend, "device-type", NULL);
        if (!IS_ERR(device_type)) {
-               cdrom = strcmp(device_type, "cdrom") == 0;
+               p->cdrom = strcmp(device_type, "cdrom") == 0;
                kfree(device_type);
        }
 
        /* Front end dir is a number, which is used as the handle. */
-       err = kstrtoul(strrchr(dev->otherend, '/') + 1, 0, &handle);
-       if (err) {
-               kfree(be->mode);
-               be->mode = NULL;
-               return;
-       }
+       err = kstrtoul(strrchr(dev->otherend, '/') + 1, 0, handle);
+       if (err)
+               return err;
 
-       be->major = major;
-       be->minor = minor;
+       return 0;
+}
 
-       err = xen_vbd_create(be->blkif, handle, major, minor,
-                            !strchr(be->mode, 'w'), cdrom);
+/*
+ * Callback received when the hotplug scripts have placed the physical-device
+ * node.  Read it and the mode node, and create a vbd.  If the frontend is
+ * ready, connect.
+ */
+static void backend_changed(struct xenbus_watch *watch,
+                           const char *path, const char *token)
+{
+       int err;
+       struct backend_info *be
+               = container_of(watch, struct backend_info, backend_watch);
+       struct xenbus_device *dev = be->dev;
+       unsigned long handle;
+       struct blkif_params p;
+
+       pr_debug("%s %p %d\n", __func__, dev, dev->otherend_id);
 
+       err = xenbus_scan_be_params(&p, dev, &handle);
        if (err)
+               return;
+
+       if (be->params.major | be->params.minor) {
+               err = -EINVAL;
+               if (be->params.major != p.major || be->params.minor != p.minor)
+                       pr_warn("changing physical device (from %x:%x to %x:%x) not supported.\n",
+                               be->params.major, be->params.minor,
+                               p.major, p.minor);
+               goto out;
+       }
+
+       err = xen_vbd_create(be->blkif, handle, &p);
+       if (err) {
                xenbus_dev_fatal(dev, err, "creating vbd structure");
-       else {
-               err = xenvbd_sysfs_addif(dev);
-               if (err) {
-                       xen_vbd_free(&be->blkif->vbd);
-                       xenbus_dev_fatal(dev, err, "creating sysfs entries");
-               }
+               goto out;
        }
 
+       be->params = p;
+
+       err = xenvbd_sysfs_addif(dev);
        if (err) {
-               kfree(be->mode);
-               be->mode = NULL;
-               be->major = 0;
-               be->minor = 0;
-       } else {
-               /* We're potentially connected now */
-               xen_update_blkif_status(be->blkif);
+               xen_vbd_free(&be->blkif->vbd);
+               xenbus_dev_fatal(dev, err, "creating sysfs entries");
+               goto sysfs_out;
        }
-}
 
+       /* We're potentially connected now */
+       xen_update_blkif_status(be->blkif);
+
+sysfs_out:
+       /*
+        * In case of failure reset the params.
+        */
+       if (err)
+               memset(&be->params, 0, sizeof(be->params));
+out:
+       return;
+}
 
 /*
  * Callback received when the frontend's state changes.