[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |