[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Minios-devel] [UNIKRAFT PATCH 10/17] plat/xen/drivers/blk: Start blkfront device



This patch introduces start/stop operations to blkfront device.
This implies connection to backend by communication through Xenstore.

Signed-off-by: Roxana Nicolescu <nicolescu.roxana1996@xxxxxxxxx>
---
 plat/xen/drivers/blk/blkfront.c    |  39 +++++++++++
 plat/xen/drivers/blk/blkfront_xb.h |  17 +++++
 plat/xen/drivers/blk/blkfront_xs.c | 128 +++++++++++++++++++++++++++++++++++++
 3 files changed, 184 insertions(+)

diff --git a/plat/xen/drivers/blk/blkfront.c b/plat/xen/drivers/blk/blkfront.c
index c65267f0..c2f8e62d 100644
--- a/plat/xen/drivers/blk/blkfront.c
+++ b/plat/xen/drivers/blk/blkfront.c
@@ -299,6 +299,43 @@ out_err:
        uk_free(drv_allocator, dev->queues);
        goto out;
 }
+
+static int blkfront_start(struct uk_blkdev *blkdev)
+{
+       struct blkfront_dev *dev;
+       int err = 0;
+
+       UK_ASSERT(blkdev != NULL);
+       dev = to_blkfront(blkdev);
+       err = blkfront_xb_connect(dev);
+       if (err) {
+               uk_pr_err("Failed to connect to backend: %d.\n", err);
+               return err;
+       }
+
+       uk_pr_info(DRIVER_NAME": %"PRIu16" started\n", dev->uid);
+
+       return err;
+}
+
+static int blkfront_stop(struct uk_blkdev *blkdev)
+{
+       struct blkfront_dev *dev;
+       int err;
+
+       UK_ASSERT(blkdev != NULL);
+
+       dev = to_blkfront(blkdev);
+       err = blkfront_xb_disconnect(dev);
+       if (err) {
+               uk_pr_err(
+                       "Failed to disconnect: %d.\n", err);
+               return err;
+       }
+
+       uk_pr_info(DRIVER_NAME": %"PRIu16" stopped\n", dev->uid);
+
+       return err;
 }
 
 static void blkfront_close(struct uk_blkdev *blkdev)
@@ -335,6 +372,8 @@ static const struct uk_blkdev_ops blkfront_ops = {
        .queue_get_info = blkfront_queue_get_info,
        .queue_setup = blkfront_queue_setup,
        .queue_release = blkfront_queue_release,
+       .dev_start = blkfront_start,
+       .dev_stop = blkfront_stop,
        .dev_close = blkfront_close,
        .queue_intr_enable = blkfront_queue_intr_enable,
        .queue_intr_disable = blkfront_queue_intr_disable,
diff --git a/plat/xen/drivers/blk/blkfront_xb.h 
b/plat/xen/drivers/blk/blkfront_xb.h
index a846fda7..60070d9c 100644
--- a/plat/xen/drivers/blk/blkfront_xb.h
+++ b/plat/xen/drivers/blk/blkfront_xb.h
@@ -64,4 +64,21 @@ void blkfront_xb_fini(struct blkfront_dev *dev);
  */
 int blkfront_xb_write_nb_queues(struct blkfront_dev *dev);
 
+/**
+ * Device changes its state to Connected.
+ * It waits until the backend is connected.
+ *
+ * Return 0 on success, a negative errno value on error.
+ */
+int blkfront_xb_connect(struct blkfront_dev *dev);
+
+/**
+ * Reinitialize the connection with the backend.
+ * The following states are:
+ *     Connected -> Closing -> Closed -> Initializing.
+ *
+ * Return 0 on success, a negative errno value on error.
+ */
+int blkfront_xb_disconnect(struct blkfront_dev *dev);
+
 #endif /* __BLKFRONT_XB_H__ */
diff --git a/plat/xen/drivers/blk/blkfront_xs.c 
b/plat/xen/drivers/blk/blkfront_xs.c
index 13c25969..6e3263da 100644
--- a/plat/xen/drivers/blk/blkfront_xs.c
+++ b/plat/xen/drivers/blk/blkfront_xs.c
@@ -163,3 +163,131 @@ int blkfront_xb_write_nb_queues(struct blkfront_dev *dev)
 out:
        return err;
 }
+
+#define WAIT_BE_STATE_CHANGE_WHILE_COND(state_cond) \
+       do { \
+               err = xs_read_integer(XBT_NIL, back_state_path,\
+                       (int *) &back_state); \
+               if (err) \
+                       goto out; \
+               while (!err && (state_cond)) \
+                       err = xenbus_wait_for_state_change(back_state_path, \
+                               &back_state, \
+                               xendev->otherend_watch); \
+               if (err) \
+                       goto out; \
+       } while (0)
+
+
+static int blkfront_xb_wait_be_connect(struct blkfront_dev *blkdev)
+{
+       struct xenbus_device *xendev;
+       char *back_state_path = NULL;
+       XenbusState back_state;
+       int err = 0;
+
+       UK_ASSERT(blkdev != NULL);
+       xendev = blkdev->xendev;
+       err = asprintf(&back_state_path, "%s/state", xendev->otherend);
+       if (err <= 0) {
+               uk_pr_err("Failed to format back_state_path: %d\n", err);
+               goto out;
+       }
+
+       WAIT_BE_STATE_CHANGE_WHILE_COND(back_state < XenbusStateConnected);
+       if (back_state != XenbusStateConnected) {
+               uk_pr_err("Backend not available, state=%s\n",
+                               xenbus_state_to_str(back_state));
+               err = -1;
+               goto out;
+       }
+
+out:
+       free(back_state_path);
+       return err;
+}
+
+static int blkfront_xb_wait_be_disconnect(struct blkfront_dev *blkdev)
+{
+       struct xenbus_device *xendev;
+       char *back_state_path = NULL;
+       XenbusState back_state;
+       int err = 0;
+
+       UK_ASSERT(blkdev != NULL);
+       xendev = blkdev->xendev;
+
+       err = asprintf(&back_state_path, "%s/state", xendev->otherend);
+       if (err <= 0) {
+               uk_pr_err("Failed to format back_state_path: %d\n", err);
+               goto out;
+       }
+
+       WAIT_BE_STATE_CHANGE_WHILE_COND(back_state < XenbusStateClosing);
+       err = xenbus_switch_state(XBT_NIL, xendev, XenbusStateClosed);
+       if (err) {
+               uk_pr_err("Failed to switch state to Closed: %d\n", err);
+               goto out;
+       }
+
+       WAIT_BE_STATE_CHANGE_WHILE_COND(back_state < XenbusStateClosed);
+       err = xenbus_switch_state(XBT_NIL, xendev, XenbusStateInitialising);
+       if (err) {
+               uk_pr_err("Failed to switch state to Initialising: %d\n", err);
+               goto out;
+       }
+
+       WAIT_BE_STATE_CHANGE_WHILE_COND(back_state < XenbusStateInitWait ||
+                       back_state >= XenbusStateClosed);
+
+out:
+       free(back_state_path);
+       return err;
+}
+
+int blkfront_xb_connect(struct blkfront_dev *blkdev)
+{
+       int err;
+       struct xenbus_device *xendev;
+
+       UK_ASSERT(blkdev != NULL);
+       xendev = blkdev->xendev;
+       err = xenbus_switch_state(XBT_NIL, xendev, XenbusStateConnected);
+       if (err)
+               goto err;
+
+       err = blkfront_xb_wait_be_connect(blkdev);
+       if (err)
+               goto err;
+
+err:
+       return err;
+}
+
+int blkfront_xb_disconnect(struct blkfront_dev *blkdev)
+{
+       struct xenbus_device *xendev;
+       int err;
+
+       UK_ASSERT(blkdev != NULL);
+
+       xendev = blkdev->xendev;
+
+       uk_pr_info("Disconnect blkfront: backend at %s\n",
+                       xendev->otherend);
+
+       err = xenbus_switch_state(XBT_NIL, xendev, XenbusStateClosing);
+       if (err) {
+               uk_pr_err("Failed to switch state to Closing: %d\n", err);
+               goto out;
+       }
+
+       err = blkfront_xb_wait_be_disconnect(blkdev);
+       if (err) {
+               uk_pr_err("Failed to disconnect: %d\n", err);
+               goto out;
+       }
+
+out:
+       return err;
+}
-- 
2.11.0


_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.