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

Re: [Minios-devel] [UNIKRAFT PATCH 6/6] lib/ukblkdev: Stop and release an Unikraft block device



Hi Simon,

See my comments below.

Roxana

On Fri, Jun 14, 2019 at 3:17 PM Simon Kuenzer <simon.kuenzer@xxxxxxxxx> wrote:
On 29.05.19 10:34, Roxana Nicolescu wrote:
> A device can be stopped, which will not permit further requests.
> Also, for closing the device, the device must pe stopped,
> each queue must be release and all the data allocated must be freed.
>
> Signed-off-by: Roxana Nicolescu <nicolescu.roxana1996@xxxxxxxxx>
> ---
>   lib/ukblkdev/blkdev.c                   | 85 +++++++++++++++++++++++++++++++++
>   lib/ukblkdev/exportsyms.uk              |  4 ++
>   lib/ukblkdev/include/uk/blkdev.h        | 31 ++++++++++++
>   lib/ukblkdev/include/uk/blkdev_core.h   | 13 +++++
>   lib/ukblkdev/include/uk/blkdev_driver.h | 11 +++++
>   5 files changed, 144 insertions(+)
>
> diff --git a/lib/ukblkdev/blkdev.c b/lib/ukblkdev/blkdev.c
> index 534a9ae1..d06b5250 100644
> --- a/lib/ukblkdev/blkdev.c
> +++ b/lib/ukblkdev/blkdev.c
> @@ -467,3 +467,88 @@ int uk_blkdev_sync_io(struct uk_blkdev *dev,
>       return req->result_status;
>   }
>   #endif
> +
> +int uk_blkdev_stop(struct uk_blkdev *dev)
> +{
> +     int rc = 0;
> +
> +     UK_ASSERT(dev);
> +     UK_ASSERT(dev->_data);
> +     UK_ASSERT(dev->dev_ops);
> +     UK_ASSERT(dev->dev_ops->dev_stop);
> +     UK_ASSERT(dev->_data->state == UK_BLKDEV_RUNNING);
> +
> +     rc = dev->dev_ops->dev_stop(dev);
> +     if (rc)
> +             uk_pr_err("Failed to stop blkdev%"PRIu16" device %d\n",
> +                             dev->_data->id, rc);
> +     else {
> +             uk_pr_info("Stopped blkdev%"PRIu16" device\n",
> +                                             dev->_data->id);
> +             dev->_data->state = UK_BLKDEV_CONFIGURED;
> +     }
> +
> +     return rc;
> +}
> +
> +void uk_blkdev_queue_release(struct uk_blkdev *dev, uint16_t queue_id)
> +{
> +     int rc = 0;
> +
> +     UK_ASSERT(dev != NULL);
> +     UK_ASSERT(dev->_data);
> +     UK_ASSERT(dev->dev_ops);
> +     UK_ASSERT(dev->dev_ops->queue_release);
> +     UK_ASSERT(queue_id < CONFIG_LIBUKBLKDEV_MAXNBQUEUES);
> +     UK_ASSERT(dev->_data->state != UK_BLKDEV_RUNNING);
> +
> +#if CONFIG_LIBUKBLKDEV_DISPATCHERTHREADS
> +     if (dev->_data->queue_handler[queue_id].callback)
> +             _destroy_event_handler(&dev->_data->queue_handler[queue_id]);

Hum not sure if there is a condition where this could crash. Maybe you
should get the queue thread into an defined state and destroy it there.
I am just thinking what happens when it is getting destroyed while
executing the registered event callback. Maybe we need a condition
variable next to the event semaphore which is checked if the thread
should exit by itself.
At least we should put a /* TODO */ comment here because we may run into
problems especially with preemptive scheduling. It is okay to solve this
problem later.

I will provide a variable to stop the while loop in the dispatcher thread in v2.
> +#endif
> +
> +     rc = dev->dev_ops->queue_release(dev, queue_id);

Use `struct uk_blkdev_queue *` also here as commented in patch 4/6.

> +     if (rc)
> +             uk_pr_err("Failed to release blkdev%"PRIu16"-q%"PRIu16": %d\n",
> +                             dev->_data->id, queue_id, rc);
> +     else {
> +             uk_pr_info("Released blkdev%"PRIu16"-q%"PRIu16"\n",
> +                             dev->_data->id, queue_id);
> +
> +             dev->_queue[queue_id] = NULL;
> +     }
> +}
> +
> +void uk_blkdev_drv_unregister(struct uk_blkdev *dev, struct uk_alloc *a)
> +{
> +     uint16_t id;
> +
> +     UK_ASSERT(dev != NULL);
> +     UK_ASSERT(dev->_data);
> +     UK_ASSERT(dev->_data->state != UK_BLKDEV_RUNNING);
> +
> +     id = dev->_data->id;
> +
> +     uk_free(a, dev->_data);

Maybe it is better to store `uk_alloc *a` on `_data` while allocating.
Then we would not need the allocator function argument anymore.

For me, it is the same thing. But I will change it in v2. 
> +     UK_TAILQ_REMOVE(&uk_blkdev_list, dev, _list);
> +     blkdev_count--;
> +
> +     uk_pr_info("Unregistered blkdev%"PRIu16": %p\n",
> +                                id, dev);
> +}
> +
> +void uk_blkdev_close(struct uk_blkdev *dev)
> +{
> +     uint16_t id;
> +
> +     UK_ASSERT(dev);
> +     UK_ASSERT(dev->_data);
> +     UK_ASSERT(dev->dev_ops);
> +     UK_ASSERT(dev->dev_ops->dev_close);
> +     UK_ASSERT(dev->_data->state != UK_BLKDEV_RUNNING);
> +
> +     id = dev->_data->id;
> +     dev->dev_ops->dev_close(dev);
> +
> +     uk_pr_info("Closed blkdev%"PRIu16"\n", id);
> +}
> diff --git a/lib/ukblkdev/exportsyms.uk b/lib/ukblkdev/exportsyms.uk
> index 0274dae8..0abd8e10 100644
> --- a/lib/ukblkdev/exportsyms.uk
> +++ b/lib/ukblkdev/exportsyms.uk
> @@ -22,3 +22,7 @@ uk_blkdev_queue_finish_reqs
>   uk_blkdev_sync_io
>   uk_blkdev_read
>   uk_blkdev_write
> +uk_blkdev_stop
> +uk_blkdev_queue_release
> +uk_blkdev_drv_unregister
> +uk_blkdev_close
> diff --git a/lib/ukblkdev/include/uk/blkdev.h b/lib/ukblkdev/include/uk/blkdev.h
> index ba4c2784..00789198 100644
> --- a/lib/ukblkdev/include/uk/blkdev.h
> +++ b/lib/ukblkdev/include/uk/blkdev.h
> @@ -468,6 +468,37 @@ int uk_blkdev_sync_io(struct uk_blkdev *dev,
>   
>   #endif
>   
> +/**
> + * Stop an Unikraft block device, and set its state to UK_BLKDEV_CONFIGURED
> + * state.
> + * The device can be restarted with a call to uk_blkdev_start().
> + *
> + * @param dev
> + *   The Unikraft Block Device.
> + */
> +int uk_blkdev_stop(struct uk_blkdev *dev);
> +
> +/**
> + * Free a queue and its descriptors for an Unikraft block device.
> + * @param dev
> + *   The Unikraft Block Device.
> + * @param queue_id
> + *   The index of the queue to set up.
> + *   The value must be in range [0, nb_queue -1] previously supplied
> + *   to uk_blkdev_configure()
> + */
> +void uk_blkdev_queue_release(struct uk_blkdev *dev, uint16_t queue_id);

Use `struct uk_blkdev_queue *` also here.

Actually, I chose to use the queue_id in here, for debugging / error prints.
> +
> +/**
> + * Close a stopped Unikraft block device.
> + * The function frees all resources except for
> + * the ones needed by the UK_BLKDEV_UNCONFIGURED state.
> + *
> + * @param dev
> + *   The Unikraft Block Device.
> + */
> +void uk_blkdev_close(struct uk_blkdev *dev);
> +
>   #ifdef __cplusplus
>   }
>   #endif
> diff --git a/lib/ukblkdev/include/uk/blkdev_core.h b/lib/ukblkdev/include/uk/blkdev_core.h
> index 66831f90..71fdd34b 100644
> --- a/lib/ukblkdev/include/uk/blkdev_core.h
> +++ b/lib/ukblkdev/include/uk/blkdev_core.h
> @@ -204,6 +204,16 @@ typedef int (*uk_blkdev_queue_submit_one_t)(struct uk_blkdev *dev,
>   typedef int (*uk_blkdev_queue_finish_reqs_t)(struct uk_blkdev *dev,
>               uint16_t queue_id);
>   
> +/** Driver callback type to stop an Unikraft block device. */
> +typedef int (*uk_blkdev_stop_t)(struct uk_blkdev *dev);
> +
> +/** Driver callback type to release a queue of an Unikraft block device. */
> +typedef int (*uk_blkdev_queue_release_t)(struct uk_blkdev *dev,
> +             uint16_t queue_id);

Use `struct uk_blkdev_queue *` also here as commented in patch 4/6.

> +
> +/** Driver callback type to close an Unikraft block device. */
> +typedef void (*uk_blkdev_close_t)(struct uk_blkdev *dev);
> +
>   struct uk_blkdev_ops {
>       uk_blkdev_get_info_t                            get_info;
>       uk_blkdev_configure_t                           dev_configure;
> @@ -211,7 +221,10 @@ struct uk_blkdev_ops {
>       uk_blkdev_queue_configure_t                     queue_setup;
>       uk_blkdev_queue_intr_enable_t                   queue_intr_enable;
>       uk_blkdev_start_t                               dev_start;
> +     uk_blkdev_stop_t                                dev_stop;
>       uk_blkdev_queue_intr_disable_t                  queue_intr_disable;
> +     uk_blkdev_queue_release_t                       queue_release;
> +     uk_blkdev_close_t                               dev_close;
>   };
>   
>   /**
> diff --git a/lib/ukblkdev/include/uk/blkdev_driver.h b/lib/ukblkdev/include/uk/blkdev_driver.h
> index 37b5a3e8..f361e8fb 100644
> --- a/lib/ukblkdev/include/uk/blkdev_driver.h
> +++ b/lib/ukblkdev/include/uk/blkdev_driver.h
> @@ -98,6 +98,17 @@ static inline void uk_blkdev_drv_queue_event(struct uk_blkdev *dev,
>   #endif
>   }
>   
> +/**
> + * Frees the data allocated for the Unikraft Block Device.
> + * Removes the block device from the list.
> + *
> + * @param dev
> + *   Unikraft block device
> + * @param a
> + *   Allocator used for libukblkdev private data (dev->_data).
> + */
> +void uk_blkdev_drv_unregister(struct uk_blkdev *dev, struct uk_alloc *a);
> +
>   #ifdef __cplusplus
>   }
>   #endif
>
_______________________________________________
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®.