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

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



Reviewed-by: Costin Lupu <costin.lupu@xxxxxxxxx>

On 10/30/19 5:54 PM, Roxana Nicolescu wrote:
> 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;
> +}
> 

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