]> git.baikalelectronics.ru Git - kernel.git/commitdiff
9p/xen: fix connection sequence
authorJuergen Gross <jgross@suse.com>
Mon, 30 Jan 2023 11:30:36 +0000 (12:30 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 11 Mar 2023 12:55:26 +0000 (13:55 +0100)
[ Upstream commit b1e56e88f84574d2b4ab8b6c6336b5eab0d59984 ]

Today the connection sequence of the Xen 9pfs frontend doesn't match
the documented sequence. It can work reliably only for a PV 9pfs device
having been added at boot time already, as the frontend is not waiting
for the backend to have set its state to "XenbusStateInitWait" before
reading the backend properties from Xenstore.

Fix that by following the documented sequence [1] (the documentation
has a bug, so the reference is for the patch fixing that).

[1]: https://lore.kernel.org/xen-devel/20230130090937.31623-1-jgross@suse.com/T/#u

Link: https://lkml.kernel.org/r/20230130113036.7087-3-jgross@suse.com
Fixes: 5860f278c7ab ("xen/9pfs: introduce Xen 9pfs transport driver")
Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
Signed-off-by: Eric Van Hensbergen <ericvh@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/9p/trans_xen.c

index 80cc0289dd0d69db4550e8b1d034f4f299100da2..75c03a82baf38d4073e8aec0eccf1a0e097bb17d 100644 (file)
@@ -371,12 +371,11 @@ out:
        return ret;
 }
 
-static int xen_9pfs_front_probe(struct xenbus_device *dev,
-                               const struct xenbus_device_id *id)
+static int xen_9pfs_front_init(struct xenbus_device *dev)
 {
        int ret, i;
        struct xenbus_transaction xbt;
-       struct xen_9pfs_front_priv *priv = NULL;
+       struct xen_9pfs_front_priv *priv = dev_get_drvdata(&dev->dev);
        char *versions, *v;
        unsigned int max_rings, max_ring_order, len = 0;
 
@@ -404,11 +403,6 @@ static int xen_9pfs_front_probe(struct xenbus_device *dev,
        if (p9_xen_trans.maxsize > XEN_FLEX_RING_SIZE(max_ring_order))
                p9_xen_trans.maxsize = XEN_FLEX_RING_SIZE(max_ring_order) / 2;
 
-       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-
-       priv->dev = dev;
        priv->num_rings = XEN_9PFS_NUM_RINGS;
        priv->rings = kcalloc(priv->num_rings, sizeof(*priv->rings),
                              GFP_KERNEL);
@@ -467,23 +461,35 @@ static int xen_9pfs_front_probe(struct xenbus_device *dev,
                goto error;
        }
 
-       write_lock(&xen_9pfs_lock);
-       list_add_tail(&priv->list, &xen_9pfs_devs);
-       write_unlock(&xen_9pfs_lock);
-       dev_set_drvdata(&dev->dev, priv);
-       xenbus_switch_state(dev, XenbusStateInitialised);
-
        return 0;
 
  error_xenbus:
        xenbus_transaction_end(xbt, 1);
        xenbus_dev_fatal(dev, ret, "writing xenstore");
  error:
-       dev_set_drvdata(&dev->dev, NULL);
        xen_9pfs_front_free(priv);
        return ret;
 }
 
+static int xen_9pfs_front_probe(struct xenbus_device *dev,
+                               const struct xenbus_device_id *id)
+{
+       struct xen_9pfs_front_priv *priv = NULL;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->dev = dev;
+       dev_set_drvdata(&dev->dev, priv);
+
+       write_lock(&xen_9pfs_lock);
+       list_add_tail(&priv->list, &xen_9pfs_devs);
+       write_unlock(&xen_9pfs_lock);
+
+       return 0;
+}
+
 static int xen_9pfs_front_resume(struct xenbus_device *dev)
 {
        dev_warn(&dev->dev, "suspend/resume unsupported\n");
@@ -502,6 +508,8 @@ static void xen_9pfs_front_changed(struct xenbus_device *dev,
                break;
 
        case XenbusStateInitWait:
+               if (!xen_9pfs_front_init(dev))
+                       xenbus_switch_state(dev, XenbusStateInitialised);
                break;
 
        case XenbusStateConnected: