Commit c15fe55d authored by Juergen Gross's avatar Juergen Gross Committed by Eric Van Hensbergen

9p/xen: fix connection sequence

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: 868eb122 ("xen/9pfs: introduce Xen 9pfs transport driver")
Signed-off-by: default avatarJuergen Gross <jgross@suse.com>
Reviewed-by: default avatarSimon Horman <simon.horman@corigine.com>
Signed-off-by: default avatarDominique Martinet <asmadeus@codewreck.org>
Signed-off-by: default avatarEric Van Hensbergen <ericvh@kernel.org>
parent f1956f4e
...@@ -373,12 +373,11 @@ static int xen_9pfs_front_alloc_dataring(struct xenbus_device *dev, ...@@ -373,12 +373,11 @@ static int xen_9pfs_front_alloc_dataring(struct xenbus_device *dev,
return ret; return ret;
} }
static int xen_9pfs_front_probe(struct xenbus_device *dev, static int xen_9pfs_front_init(struct xenbus_device *dev)
const struct xenbus_device_id *id)
{ {
int ret, i; int ret, i;
struct xenbus_transaction xbt; 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; char *versions, *v;
unsigned int max_rings, max_ring_order, len = 0; unsigned int max_rings, max_ring_order, len = 0;
...@@ -406,11 +405,6 @@ static int xen_9pfs_front_probe(struct xenbus_device *dev, ...@@ -406,11 +405,6 @@ static int xen_9pfs_front_probe(struct xenbus_device *dev,
if (p9_xen_trans.maxsize > XEN_FLEX_RING_SIZE(max_ring_order)) if (p9_xen_trans.maxsize > XEN_FLEX_RING_SIZE(max_ring_order))
p9_xen_trans.maxsize = XEN_FLEX_RING_SIZE(max_ring_order) / 2; 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->num_rings = XEN_9PFS_NUM_RINGS;
priv->rings = kcalloc(priv->num_rings, sizeof(*priv->rings), priv->rings = kcalloc(priv->num_rings, sizeof(*priv->rings),
GFP_KERNEL); GFP_KERNEL);
...@@ -469,23 +463,35 @@ static int xen_9pfs_front_probe(struct xenbus_device *dev, ...@@ -469,23 +463,35 @@ static int xen_9pfs_front_probe(struct xenbus_device *dev,
goto error; 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; return 0;
error_xenbus: error_xenbus:
xenbus_transaction_end(xbt, 1); xenbus_transaction_end(xbt, 1);
xenbus_dev_fatal(dev, ret, "writing xenstore"); xenbus_dev_fatal(dev, ret, "writing xenstore");
error: error:
dev_set_drvdata(&dev->dev, NULL);
xen_9pfs_front_free(priv); xen_9pfs_front_free(priv);
return ret; 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) static int xen_9pfs_front_resume(struct xenbus_device *dev)
{ {
dev_warn(&dev->dev, "suspend/resume unsupported\n"); dev_warn(&dev->dev, "suspend/resume unsupported\n");
...@@ -504,6 +510,8 @@ static void xen_9pfs_front_changed(struct xenbus_device *dev, ...@@ -504,6 +510,8 @@ static void xen_9pfs_front_changed(struct xenbus_device *dev,
break; break;
case XenbusStateInitWait: case XenbusStateInitWait:
if (!xen_9pfs_front_init(dev))
xenbus_switch_state(dev, XenbusStateInitialised);
break; break;
case XenbusStateConnected: case XenbusStateConnected:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment