[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-devel] [UNIKRAFT PATCH v6] lib/ukblkdev: Stop and release a Unikraft block device
We introduce 3 main function for cleaning up the device: -> stop: further requests are not allowed -> queue release: release every data used for each queue -> unconfigure: sets the device state to UNCONFIGURED. Unregister the device is also introduced, which is responsible for cleaning up any memory used by uk_blkdev. Signed-off-by: Roxana Nicolescu <nicolescu.roxana1996@xxxxxxxxx> --- lib/ukblkdev/blkdev.c | 99 +++++++++++++++++++++++++ lib/ukblkdev/exportsyms.uk | 4 + lib/ukblkdev/include/uk/blkdev.h | 44 +++++++++++ lib/ukblkdev/include/uk/blkdev_core.h | 13 ++++ lib/ukblkdev/include/uk/blkdev_driver.h | 9 +++ 5 files changed, 169 insertions(+) diff --git a/lib/ukblkdev/blkdev.c b/lib/ukblkdev/blkdev.c index 8679e074..06b47438 100644 --- a/lib/ukblkdev/blkdev.c +++ b/lib/ukblkdev/blkdev.c @@ -466,3 +466,102 @@ int uk_blkdev_sync_io(struct uk_blkdev *dev, return req->result; } #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); + + uk_pr_info("Trying to stop blkdev%"PRIu16" device\n", + dev->_data->id); + 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; +} + +int 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); + UK_ASSERT(!PTRISERR(dev->_queue[queue_id])); + +#if CONFIG_LIBUKBLKDEV_DISPATCHERTHREADS + if (dev->_data->queue_handler[queue_id].callback) + _destroy_event_handler(&dev->_data->queue_handler[queue_id]); +#endif + + rc = dev->dev_ops->queue_release(dev, dev->_queue[queue_id]); + 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; + } + + return rc; +} + +void uk_blkdev_drv_unregister(struct uk_blkdev *dev) +{ + uint16_t id; + + UK_ASSERT(dev != NULL); + UK_ASSERT(dev->_data); + UK_ASSERT(dev->_data->state == UK_BLKDEV_UNCONFIGURED); + + id = dev->_data->id; + + uk_free(dev->_data->a, dev->_data); + UK_TAILQ_REMOVE(&uk_blkdev_list, dev, _list); + blkdev_count--; + + uk_pr_info("Unregistered blkdev%"PRIu16": %p\n", + id, dev); +} + +int uk_blkdev_unconfigure(struct uk_blkdev *dev) +{ + uint16_t q_id; + int rc; + + UK_ASSERT(dev); + UK_ASSERT(dev->_data); + UK_ASSERT(dev->dev_ops); + UK_ASSERT(dev->dev_ops->dev_unconfigure); + UK_ASSERT(dev->_data->state == UK_BLKDEV_CONFIGURED); + for (q_id = 0; q_id < CONFIG_LIBUKBLKDEV_MAXNBQUEUES; ++q_id) + UK_ASSERT(PTRISERR(dev->_queue[q_id])); + + rc = dev->dev_ops->dev_unconfigure(dev); + if (rc) + uk_pr_err("Failed to unconfigure blkdev%"PRIu16": %d\n", + dev->_data->id, rc); + else { + uk_pr_info("Unconfigured blkdev%"PRIu16"\n", dev->_data->id); + dev->_data->state = UK_BLKDEV_UNCONFIGURED; + } + + return rc; +} diff --git a/lib/ukblkdev/exportsyms.uk b/lib/ukblkdev/exportsyms.uk index 5c05994a..f3be6c51 100644 --- a/lib/ukblkdev/exportsyms.uk +++ b/lib/ukblkdev/exportsyms.uk @@ -12,3 +12,7 @@ uk_blkdev_start uk_blkdev_queue_submit_one uk_blkdev_queue_finish_reqs uk_blkdev_sync_io +uk_blkdev_stop +uk_blkdev_queue_release +uk_blkdev_drv_unregister +uk_blkdev_unconfigure diff --git a/lib/ukblkdev/include/uk/blkdev.h b/lib/ukblkdev/include/uk/blkdev.h index ad0f2629..ad60cbec 100644 --- a/lib/ukblkdev/include/uk/blkdev.h +++ b/lib/ukblkdev/include/uk/blkdev.h @@ -471,6 +471,50 @@ int uk_blkdev_sync_io(struct uk_blkdev *dev, #endif +/** + * Stop a Unikraft block device, and set its state to UK_BLKDEV_CONFIGURED + * state. From now on, users cannot send any requests. + * If there are pending requests, this function will return -EBUSY because + * the queues are not empty. If polling is used instead of interrupts, + * make sure to clean the queue and process all the responses before this + * operation is called. + * The device can be restarted with a call to uk_blkdev_start(). + * + * @param dev + * The Unikraft Block Device. + * @return + * - 0: Success + * - (<0): on error returned by driver + */ +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() + * @return + * - 0: Success + * - (<0): on error returned by driver + */ +int uk_blkdev_queue_release(struct uk_blkdev *dev, uint16_t queue_id); + +/** + * Close a stopped Unikraft block device. + * The function frees all resources except for + * the ones needed by the UK_BLKDEV_UNCONFIGURED state. + * The device can be reconfigured with a call to uk_blkdev_configure(). + * @param dev + * The Unikraft Block Device. + * @return + * - 0: Success + * - (<0): on error returned by driver + */ +int uk_blkdev_unconfigure(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 b12e3eb1..ba9bf575 100644 --- a/lib/ukblkdev/include/uk/blkdev_core.h +++ b/lib/ukblkdev/include/uk/blkdev_core.h @@ -203,14 +203,27 @@ typedef int (*uk_blkdev_queue_submit_one_t)(struct uk_blkdev *dev, typedef int (*uk_blkdev_queue_finish_reqs_t)(struct uk_blkdev *dev, struct uk_blkdev_queue *queue); +/** 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, + struct uk_blkdev_queue *queue); + +/** Driver callback type to close an Unikraft block device. */ +typedef int (*uk_blkdev_unconfigure_t)(struct uk_blkdev *dev); + struct uk_blkdev_ops { uk_blkdev_get_info_t get_info; uk_blkdev_configure_t dev_configure; uk_blkdev_queue_get_info_t queue_get_info; uk_blkdev_queue_configure_t queue_setup; uk_blkdev_start_t dev_start; + uk_blkdev_stop_t dev_stop; uk_blkdev_queue_intr_enable_t queue_intr_enable; uk_blkdev_queue_intr_disable_t queue_intr_disable; + uk_blkdev_queue_release_t queue_release; + uk_blkdev_unconfigure_t dev_unconfigure; }; /** diff --git a/lib/ukblkdev/include/uk/blkdev_driver.h b/lib/ukblkdev/include/uk/blkdev_driver.h index a3c41da3..be807069 100644 --- a/lib/ukblkdev/include/uk/blkdev_driver.h +++ b/lib/ukblkdev/include/uk/blkdev_driver.h @@ -106,6 +106,15 @@ static inline void uk_blkdev_drv_queue_event(struct uk_blkdev *dev, #define uk_blkreq_finished(req) \ (ukarch_store_n(&(req)->state.counter, UK_BLKDEV_REQ_FINISHED)) +/** + * Frees the data allocated for the Unikraft Block Device. + * Removes the block device from the list. + * + * @param dev + * Unikraft block device + */ +void uk_blkdev_drv_unregister(struct uk_blkdev *dev); + #ifdef __cplusplus } #endif -- 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 |