aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/xen/blkback
diff options
context:
space:
mode:
authorRoger Pau Monné <royger@FreeBSD.org>2016-06-03 11:38:52 +0000
committerRoger Pau Monné <royger@FreeBSD.org>2016-06-03 11:38:52 +0000
commitde0bad00010c9e7e68c4ede0f415535abf8e7da3 (patch)
treed878dd28683c16f245fd937e1eef85252f59c6ac /sys/dev/xen/blkback
parent477ef5caf67c59863298b927122a6d5bee09d7fc (diff)
Notes
Diffstat (limited to 'sys/dev/xen/blkback')
-rw-r--r--sys/dev/xen/blkback/blkback.c160
1 files changed, 104 insertions, 56 deletions
diff --git a/sys/dev/xen/blkback/blkback.c b/sys/dev/xen/blkback/blkback.c
index 8729b456b7de..6ca8c007614f 100644
--- a/sys/dev/xen/blkback/blkback.c
+++ b/sys/dev/xen/blkback/blkback.c
@@ -802,6 +802,9 @@ struct xbb_softc {
/** How many times we have run out of request structures */
uint64_t request_shortages;
+
+ /** Watch to wait for hotplug script execution */
+ struct xs_watch hotplug_watch;
};
/*---------------------------- Request Processing ----------------------------*/
@@ -3306,7 +3309,7 @@ xbb_connect(struct xbb_softc *xbb)
{
int error;
- if (xenbus_get_state(xbb->dev) == XenbusStateConnected)
+ if (xenbus_get_state(xbb->dev) != XenbusStateInitialised)
return;
if (xbb_collect_frontend_info(xbb) != 0)
@@ -3403,6 +3406,12 @@ xbb_shutdown(struct xbb_softc *xbb)
xbb->flags |= XBBF_IN_SHUTDOWN;
mtx_unlock(&xbb->lock);
+ if (xbb->hotplug_watch.node != NULL) {
+ xs_unregister_watch(&xbb->hotplug_watch);
+ free(xbb->hotplug_watch.node, M_XENBLOCKBACK);
+ xbb->hotplug_watch.node = NULL;
+ }
+
if (xenbus_get_state(xbb->dev) < XenbusStateClosing)
xenbus_set_state(xbb->dev, XenbusStateClosing);
@@ -3583,61 +3592,24 @@ xbb_setup_sysctl(struct xbb_softc *xbb)
"communication channel pages (negotiated)");
}
-/**
- * Attach to a XenBus device that has been claimed by our probe routine.
- *
- * \param dev NewBus device object representing this Xen Block Back instance.
- *
- * \return 0 for success, errno codes for failure.
- */
-static int
-xbb_attach(device_t dev)
+static void
+xbb_attach_disk(struct xs_watch *watch, const char **vec, unsigned int len)
{
+ device_t dev;
struct xbb_softc *xbb;
int error;
- u_int max_ring_page_order;
-
- DPRINTF("Attaching to %s\n", xenbus_get_node(dev));
- /*
- * Basic initialization.
- * After this block it is safe to call xbb_detach()
- * to clean up any allocated data for this instance.
- */
+ dev = (device_t) watch->callback_data;
xbb = device_get_softc(dev);
- xbb->dev = dev;
- xbb->otherend_id = xenbus_get_otherend_id(dev);
- TASK_INIT(&xbb->io_task, /*priority*/0, xbb_run_queue, xbb);
- mtx_init(&xbb->lock, device_get_nameunit(dev), NULL, MTX_DEF);
- /*
- * Publish protocol capabilities for consumption by the
- * front-end.
- */
- error = xs_printf(XST_NIL, xenbus_get_node(xbb->dev),
- "feature-barrier", "1");
- if (error) {
- xbb_attach_failed(xbb, error, "writing %s/feature-barrier",
- xenbus_get_node(xbb->dev));
- return (error);
- }
+ error = xs_gather(XST_NIL, xenbus_get_node(dev), "physical-device-path",
+ NULL, &xbb->dev_name, NULL);
+ if (error != 0)
+ return;
- error = xs_printf(XST_NIL, xenbus_get_node(xbb->dev),
- "feature-flush-cache", "1");
- if (error) {
- xbb_attach_failed(xbb, error, "writing %s/feature-flush-cache",
- xenbus_get_node(xbb->dev));
- return (error);
- }
-
- max_ring_page_order = flsl(XBB_MAX_RING_PAGES) - 1;
- error = xs_printf(XST_NIL, xenbus_get_node(xbb->dev),
- "max-ring-page-order", "%u", max_ring_page_order);
- if (error) {
- xbb_attach_failed(xbb, error, "writing %s/max-ring-page-order",
- xenbus_get_node(xbb->dev));
- return (error);
- }
+ 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),
@@ -3648,12 +3620,11 @@ xbb_attach(device_t dev)
error = xs_gather(XST_NIL, xenbus_get_node(dev),
"mode", NULL, &xbb->dev_mode,
- "params", NULL, &xbb->dev_name,
NULL);
if (error != 0) {
xbb_attach_failed(xbb, error, "reading backend fields at %s",
xenbus_get_node(dev));
- return (ENXIO);
+ return;
}
/* Parse fopen style mode flags. */
@@ -3664,13 +3635,11 @@ xbb_attach(device_t dev)
* Verify the physical device is present and can support
* the desired I/O mode.
*/
- DROP_GIANT();
error = xbb_open_backend(xbb);
- PICKUP_GIANT();
if (error != 0) {
xbb_attach_failed(xbb, error, "Unable to open %s",
xbb->dev_name);
- return (ENXIO);
+ return;
}
/* Use devstat(9) for recording statistics. */
@@ -3702,7 +3671,7 @@ xbb_attach(device_t dev)
/*contxt*/&xbb->io_taskqueue);
if (xbb->io_taskqueue == NULL) {
xbb_attach_failed(xbb, error, "Unable to create taskqueue");
- return (ENOMEM);
+ return;
}
taskqueue_start_threads(&xbb->io_taskqueue,
@@ -3717,10 +3686,89 @@ xbb_attach(device_t dev)
if (error) {
xbb_attach_failed(xbb, error, "writing %s/hotplug-status",
xenbus_get_node(xbb->dev));
- return (error);
+ return;
}
/* Tell the front end that we are ready to connect. */
+ xenbus_set_state(dev, XenbusStateInitialised);
+}
+
+/**
+ * Attach to a XenBus device that has been claimed by our probe routine.
+ *
+ * \param dev NewBus device object representing this Xen Block Back instance.
+ *
+ * \return 0 for success, errno codes for failure.
+ */
+static int
+xbb_attach(device_t dev)
+{
+ struct xbb_softc *xbb;
+ int error;
+ u_int max_ring_page_order;
+ struct sbuf *watch_path;
+
+ DPRINTF("Attaching to %s\n", xenbus_get_node(dev));
+
+ /*
+ * Basic initialization.
+ * After this block it is safe to call xbb_detach()
+ * to clean up any allocated data for this instance.
+ */
+ xbb = device_get_softc(dev);
+ xbb->dev = dev;
+ xbb->otherend_id = xenbus_get_otherend_id(dev);
+ TASK_INIT(&xbb->io_task, /*priority*/0, xbb_run_queue, xbb);
+ mtx_init(&xbb->lock, device_get_nameunit(dev), NULL, MTX_DEF);
+
+ /*
+ * Publish protocol capabilities for consumption by the
+ * front-end.
+ */
+ error = xs_printf(XST_NIL, xenbus_get_node(xbb->dev),
+ "feature-barrier", "1");
+ if (error) {
+ xbb_attach_failed(xbb, error, "writing %s/feature-barrier",
+ xenbus_get_node(xbb->dev));
+ return (error);
+ }
+
+ error = xs_printf(XST_NIL, xenbus_get_node(xbb->dev),
+ "feature-flush-cache", "1");
+ if (error) {
+ xbb_attach_failed(xbb, error, "writing %s/feature-flush-cache",
+ xenbus_get_node(xbb->dev));
+ return (error);
+ }
+
+ max_ring_page_order = flsl(XBB_MAX_RING_PAGES) - 1;
+ error = xs_printf(XST_NIL, xenbus_get_node(xbb->dev),
+ "max-ring-page-order", "%u", max_ring_page_order);
+ if (error) {
+ xbb_attach_failed(xbb, error, "writing %s/max-ring-page-order",
+ xenbus_get_node(xbb->dev));
+ return (error);
+ }
+
+ /*
+ * We need to wait for hotplug script execution before
+ * moving forward.
+ */
+ 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;
+ KASSERT(xbb->hotplug_watch.node == NULL, ("watch node already setup"));
+ xbb->hotplug_watch.node = strdup(sbuf_data(watch_path), M_XENBLOCKBACK);
+ sbuf_delete(watch_path);
+ error = xs_register_watch(&xbb->hotplug_watch);
+ if (error != 0) {
+ xbb_attach_failed(xbb, error, "failed to create watch on %s",
+ xbb->hotplug_watch.node);
+ free(xbb->hotplug_watch.node, M_XENBLOCKBACK);
+ return (error);
+ }
+
+ /* Tell the toolstack blkback has attached. */
xenbus_set_state(dev, XenbusStateInitWait);
return (0);