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

[Minios-devel] [UNIKRAFT PATCH v3 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    |  47 +++++++++++
 plat/xen/drivers/blk/blkfront_xb.h |  18 ++++
 plat/xen/drivers/blk/blkfront_xs.c | 129 +++++++++++++++++++++++++++++
 3 files changed, 194 insertions(+)

diff --git a/plat/xen/drivers/blk/blkfront.c b/plat/xen/drivers/blk/blkfront.c
index 63b1e778..00343525 100644
--- a/plat/xen/drivers/blk/blkfront.c
+++ b/plat/xen/drivers/blk/blkfront.c
@@ -270,6 +270,51 @@ 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;
+}
+
+/* If one queue has unconsumed responses it returns -EBUSY */
+static int blkfront_stop(struct uk_blkdev *blkdev)
+{
+       struct blkfront_dev *dev;
+       uint16_t q_id;
+       int err;
+
+       UK_ASSERT(blkdev != NULL);
+       dev = to_blkfront(blkdev);
+       for (q_id = 0; q_id < dev->nb_queues; ++q_id) {
+               if (RING_HAS_UNCONSUMED_RESPONSES(&dev->queues[q_id].ring)) {
+                       uk_pr_err("Queue:%"PRIu16" has unconsumed responses\n",
+                                       q_id);
+                       return -EBUSY;
+               }
+       }
+
+       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;
 }
 
@@ -302,6 +347,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_unconfigure = blkfront_unconfigure,
        .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 668206a0..90638e94 100644
--- a/plat/xen/drivers/blk/blkfront_xb.h
+++ b/plat/xen/drivers/blk/blkfront_xb.h
@@ -62,4 +62,22 @@ void blkfront_xb_fini(struct blkfront_dev *dev);
  * Return 0 on success, a negative errno value on error.
  */
 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 9f44246e..67320712 100644
--- a/plat/xen/drivers/blk/blkfront_xs.c
+++ b/plat/xen/drivers/blk/blkfront_xs.c
@@ -164,3 +164,132 @@ 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.17.1


_______________________________________________
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®.