Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 3 Jun 2016 11:38:52 +0000 (UTC)
From:      =?UTF-8?Q?Roger_Pau_Monn=c3=a9?= <royger@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r301268 - head/sys/dev/xen/blkback
Message-ID:  <201606031138.u53Bcq9o085337@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: royger
Date: Fri Jun  3 11:38:52 2016
New Revision: 301268
URL: https://svnweb.freebsd.org/changeset/base/301268

Log:
  blkback: add support for hotplug scripts
  
  Hotplug scripts are needed in order to use fancy disk configurations in xl,
  like iSCSI disks. The job of hotplug scripts is to locally attach the disk
  and present it to blkback as a block device or a regular file.
  
  This change introduces a new xenstore node in the blkback hierarchy, called
  "physical-device-path". This is a straigh replacement for the "params" node,
  which was used before.
  
  Hotplug scripts will need to read the "params" node, perform whatever
  actions are necessary and then write the "physical-device-path" node. The
  hotplug script is also in charge of detaching the disk once the domain has
  been shutdown.
  
  Sponsored by: Citrix Systems R&D

Modified:
  head/sys/dev/xen/blkback/blkback.c

Modified: head/sys/dev/xen/blkback/blkback.c
==============================================================================
--- head/sys/dev/xen/blkback/blkback.c	Fri Jun  3 11:18:30 2016	(r301267)
+++ head/sys/dev/xen/blkback/blkback.c	Fri Jun  3 11:38:52 2016	(r301268)
@@ -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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201606031138.u53Bcq9o085337>