aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Pau Monné <royger@FreeBSD.org>2021-05-11 10:19:29 +0000
committerRoger Pau Monné <royger@FreeBSD.org>2022-04-12 08:05:47 +0000
commit590f093f74f2f60f7a49f0b8707970189d2faaef (patch)
tree10a0deb3309eb6fcab0e7ecc345d5c64bd2da0a5
parent499d685b02d4c3ff5de83f6dc1ea2b2aab7d6909 (diff)
downloadsrc-590f093f74f2f60f7a49f0b8707970189d2faaef.tar.gz
src-590f093f74f2f60f7a49f0b8707970189d2faaef.zip
xen/blkback: fix reconnection of backend
The hotplug script will be executed only once for each backend, regardless of the frontend triggering reconnections. Fix blkback to deal with the hotplug script being executed only once, so that reconnections don't stall waiting for a hotplug script execution that will never happen. As a result of the fix move the initialization of dev_mode, dev_type and dev_name to the watch callback, as they should be set only once the first time the backend connects. This fix is specially relevant for guests wanting to use UEFI OVMF firmware, because OVMF will use Xen PV block devices and disconnect afterwards, thus allowing them to be used by the guest OS. Without this change the guest OS will stall waiting for the block backed to attach. Fixes: de0bad00010c ('blkback: add support for hotplug scripts') Sponsored by: Citrix Systems R&D (cherry picked from commit 4772e86beb089ee08a3bff8ad359e83a4c623238)
-rw-r--r--sys/dev/xen/blkback/blkback.c83
1 files changed, 48 insertions, 35 deletions
diff --git a/sys/dev/xen/blkback/blkback.c b/sys/dev/xen/blkback/blkback.c
index 678472cc2ab8..010e737740b8 100644
--- a/sys/dev/xen/blkback/blkback.c
+++ b/sys/dev/xen/blkback/blkback.c
@@ -3412,7 +3412,6 @@ xbb_shutdown(struct xbb_softc *xbb)
free(xbb->hotplug_watch.node, M_XENBLOCKBACK);
xbb->hotplug_watch.node = NULL;
}
- xbb->hotplug_done = false;
if (xenbus_get_state(xbb->dev) < XenbusStateClosing)
xenbus_set_state(xbb->dev, XenbusStateClosing);
@@ -3597,39 +3596,14 @@ xbb_setup_sysctl(struct xbb_softc *xbb)
}
static void
-xbb_attach_disk(struct xs_watch *watch, const char **vec, unsigned int len)
+xbb_attach_disk(device_t dev)
{
- device_t dev;
struct xbb_softc *xbb;
int error;
- dev = (device_t) watch->callback_data;
xbb = device_get_softc(dev);
- error = xs_gather(XST_NIL, xenbus_get_node(dev), "physical-device-path",
- NULL, &xbb->dev_name, NULL);
- if (error != 0)
- return;
-
- xs_unregister_watch(watch);
- free(watch->node, M_XENBLOCKBACK);
- watch->node = NULL;
-
- /* Collect physical device information. */
- error = xs_gather(XST_NIL, xenbus_get_otherend_path(xbb->dev),
- "device-type", NULL, &xbb->dev_type,
- NULL);
- if (error != 0)
- xbb->dev_type = NULL;
-
- error = xs_gather(XST_NIL, xenbus_get_node(dev),
- "mode", NULL, &xbb->dev_mode,
- NULL);
- if (error != 0) {
- xbb_attach_failed(xbb, error, "reading backend fields at %s",
- xenbus_get_node(dev));
- return;
- }
+ KASSERT(xbb->hotplug_done, ("Missing hotplug execution"));
/* Parse fopen style mode flags. */
if (strchr(xbb->dev_mode, 'w') == NULL)
@@ -3693,13 +3667,48 @@ xbb_attach_disk(struct xs_watch *watch, const char **vec, unsigned int len)
return;
}
- xbb->hotplug_done = true;
-
/* The front end might be waiting for the backend, attach if so. */
if (xenbus_get_otherend_state(xbb->dev) == XenbusStateInitialised)
xbb_connect(xbb);
}
+static void
+xbb_attach_cb(struct xs_watch *watch, const char **vec, unsigned int len)
+{
+ device_t dev;
+ struct xbb_softc *xbb;
+ int error;
+
+ dev = (device_t)watch->callback_data;
+ xbb = device_get_softc(dev);
+
+ error = xs_gather(XST_NIL, xenbus_get_node(dev), "physical-device-path",
+ NULL, &xbb->dev_name, NULL);
+ if (error != 0)
+ return;
+
+ xs_unregister_watch(watch);
+ free(watch->node, M_XENBLOCKBACK);
+ watch->node = NULL;
+ xbb->hotplug_done = true;
+
+ /* Collect physical device information. */
+ error = xs_gather(XST_NIL, xenbus_get_otherend_path(dev), "device-type",
+ NULL, &xbb->dev_type, NULL);
+ if (error != 0)
+ xbb->dev_type = NULL;
+
+ error = xs_gather(XST_NIL, xenbus_get_node(dev), "mode", NULL,
+ &xbb->dev_mode, NULL);
+ if (error != 0) {
+ xbb_attach_failed(xbb, error, "reading backend fields at %s",
+ xenbus_get_node(dev));
+ return;
+ }
+
+ xbb_attach_disk(dev);
+}
+
/**
* Attach to a XenBus device that has been claimed by our probe routine.
*
@@ -3757,14 +3766,21 @@ xbb_attach(device_t dev)
return (error);
}
+ /* Tell the toolstack blkback has attached. */
+ xenbus_set_state(dev, XenbusStateInitWait);
+
+ if (xbb->hotplug_done) {
+ xbb_attach_disk(dev);
+ return (0);
+ }
+
/*
* We need to wait for hotplug script execution before
* moving forward.
*/
- KASSERT(!xbb->hotplug_done, ("Hotplug scripts already executed"));
watch_path = xs_join(xenbus_get_node(xbb->dev), "physical-device-path");
xbb->hotplug_watch.callback_data = (uintptr_t)dev;
- xbb->hotplug_watch.callback = xbb_attach_disk;
+ xbb->hotplug_watch.callback = xbb_attach_cb;
KASSERT(xbb->hotplug_watch.node == NULL, ("watch node already setup"));
xbb->hotplug_watch.node = strdup(sbuf_data(watch_path), M_XENBLOCKBACK);
/*
@@ -3782,9 +3798,6 @@ xbb_attach(device_t dev)
return (error);
}
- /* Tell the toolstack blkback has attached. */
- xenbus_set_state(dev, XenbusStateInitWait);
-
return (0);
}