diff options
| author | Roger Pau Monné <royger@FreeBSD.org> | 2016-06-03 11:38:52 +0000 |
|---|---|---|
| committer | Roger Pau Monné <royger@FreeBSD.org> | 2016-06-03 11:38:52 +0000 |
| commit | de0bad00010c9e7e68c4ede0f415535abf8e7da3 (patch) | |
| tree | d878dd28683c16f245fd937e1eef85252f59c6ac /sys/dev/xen/blkback | |
| parent | 477ef5caf67c59863298b927122a6d5bee09d7fc (diff) | |
Notes
Diffstat (limited to 'sys/dev/xen/blkback')
| -rw-r--r-- | sys/dev/xen/blkback/blkback.c | 160 |
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); |
