|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Minios-devel] [UNIKRAFT PATCH v3 13/17] plat/xen/drivers/blk: Send requests to backend
Reviewed-by: Costin Lupu <costin.lupu@xxxxxxxxx>
On 10/30/19 5:54 PM, Roxana Nicolescu wrote:
> This patch introduces the request interface.
> The following steps are:
> -> find a free spot in the queue
> -> set the ring request
> -> notify Backend
> Supported operations are: read and write.
>
> Signed-off-by: Roxana Nicolescu <nicolescu.roxana1996@xxxxxxxxx>
> ---
> plat/xen/drivers/blk/blkfront.c | 171 +++++++++++++++++++++++++++++
> plat/xen/drivers/blk/blkfront.h | 13 +++
> plat/xen/drivers/blk/blkfront_xs.c | 4 +
> 3 files changed, 188 insertions(+)
>
> diff --git a/plat/xen/drivers/blk/blkfront.c b/plat/xen/drivers/blk/blkfront.c
> index 00343525..2129f191 100644
> --- a/plat/xen/drivers/blk/blkfront.c
> +++ b/plat/xen/drivers/blk/blkfront.c
> @@ -40,6 +40,7 @@
> #include <uk/alloc.h>
> #include <uk/essentials.h>
> #include <uk/arch/limits.h>
> +#include <uk/page.h>
> #include <uk/blkdev_driver.h>
> #include <xen-x86/mm.h>
> #include <xen-x86/mm_pv.h>
> @@ -49,6 +50,8 @@
>
> #define DRIVER_NAME "xen-blkfront"
>
> +#define SECTOR_INDEX_IN_PAGE(a, sector_size) \
> + (((a) & ~PAGE_MASK) / (sector_size))
>
> /* TODO Same interrupt macros we use in virtio-blk */
> #define BLKFRONT_INTR_EN (1 << 0)
> @@ -63,6 +66,173 @@
> static struct uk_alloc *drv_allocator;
>
>
> +static void blkif_request_init(struct blkif_request *ring_req,
> + __sector sector_size)
> +{
> + uintptr_t start_sector, end_sector;
> + uint16_t nb_segments;
> + struct blkfront_request *blkfront_req;
> + struct uk_blkreq *req;
> + uintptr_t start_data, end_data;
> + uint16_t seg;
> +
> + UK_ASSERT(ring_req);
> + blkfront_req = (struct blkfront_request *)ring_req->id;
> + req = blkfront_req->req;
> + start_data = (uintptr_t)req->aio_buf;
> + end_data = (uintptr_t)req->aio_buf + req->nb_sectors * sector_size;
> +
> + /* Can't io non-sector-aligned buffer */
> + UK_ASSERT(!(start_data & (sector_size - 1)));
> +
> + /*
> + * Find number of segments (pages)
> + * Being sector-size aligned buffer, it may not be aligned
> + * to page_size. If so, it is necessary to find the start and end
> + * of the pages the buffer is allocated, in order to calculate the
> + * number of pages the request has.
> + **/
> + start_sector = round_pgdown(start_data);
> + end_sector = round_pgup(end_data);
> + nb_segments = (end_sector - start_sector) / PAGE_SIZE;
> + UK_ASSERT(nb_segments <= BLKIF_MAX_SEGMENTS_PER_REQUEST);
> +
> + /* Set ring request */
> + ring_req->operation = (req->operation == UK_BLKDEV_WRITE) ?
> + BLKIF_OP_WRITE : BLKIF_OP_READ;
> + ring_req->nr_segments = nb_segments;
> + ring_req->sector_number = req->start_sector;
> +
> + /* Set for each page the offset of sectors used for request */
> + for (seg = 0; seg < nb_segments; ++seg) {
> + ring_req->seg[seg].first_sect = 0;
> + ring_req->seg[seg].last_sect = PAGE_SIZE / sector_size - 1;
> + }
> +
> + ring_req->seg[0].first_sect =
> + SECTOR_INDEX_IN_PAGE(start_data, sector_size);
> + ring_req->seg[nb_segments - 1].last_sect =
> + SECTOR_INDEX_IN_PAGE(end_data - 1, sector_size);
> +}
> +
> +static int blkfront_request_write(struct blkfront_request *blkfront_req,
> + struct blkif_request *ring_req)
> +{
> + struct blkfront_dev *dev;
> + struct uk_blkreq *req;
> + struct uk_blkdev_cap *cap;
> + __sector sector_size;
> + int rc = 0;
> +
> + UK_ASSERT(blkfront_req);
> + req = blkfront_req->req;
> + dev = blkfront_req->queue->dev;
> + cap = &dev->blkdev.capabilities;
> + sector_size = cap->ssize;
> + if (req->operation == UK_BLKDEV_WRITE && cap->mode == O_RDONLY)
> + return -EPERM;
> +
> + if (req->aio_buf == NULL)
> + return -EINVAL;
> +
> + if (req->nb_sectors == 0)
> + return -EINVAL;
> +
> + if (req->start_sector + req->nb_sectors > cap->sectors)
> + return -EINVAL;
> +
> + if (req->nb_sectors > cap->max_sectors_per_req)
> + return -EINVAL;
> +
> + blkif_request_init(ring_req, sector_size);
> + blkfront_req->nb_segments = ring_req->nr_segments;
> +
> + return rc;
> +}
> +
> +static int blkfront_queue_enqueue(struct uk_blkdev_queue *queue,
> + struct uk_blkreq *req)
> +{
> + struct blkfront_request *blkfront_req;
> + struct blkfront_dev *dev;
> + RING_IDX ring_idx;
> + struct blkif_request *ring_req;
> + struct blkif_front_ring *ring;
> + int rc = 0;
> +
> + UK_ASSERT(queue);
> + UK_ASSERT(req);
> +
> + blkfront_req = uk_malloc(drv_allocator, sizeof(*blkfront_req));
> + if (!blkfront_req)
> + return -ENOMEM;
> +
> + blkfront_req->req = req;
> + blkfront_req->queue = queue;
> + dev = queue->dev;
> + ring = &queue->ring;
> + ring_idx = ring->req_prod_pvt;
> + ring_req = RING_GET_REQUEST(ring, ring_idx);
> + ring_req->id = (uintptr_t) blkfront_req;
> + ring_req->handle = dev->handle;
> +
> + if (req->operation == UK_BLKDEV_READ ||
> + req->operation == UK_BLKDEV_WRITE)
> + rc = blkfront_request_write(blkfront_req, ring_req);
> + else
> + rc = -EINVAL;
> +
> + if (rc)
> + goto err_out;
> +
> + ring->req_prod_pvt = ring_idx + 1;
> +
> + /* Memory barrier */
> + wmb();
> +out:
> + return rc;
> +
> +err_out:
> + uk_free(drv_allocator, blkfront_req);
> + goto out;
> +}
> +
> +static int blkfront_submit_request(struct uk_blkdev *blkdev,
> + struct uk_blkdev_queue *queue,
> + struct uk_blkreq *req)
> +{
> + int err = 0;
> + int notify;
> + int status = 0x0;
> +
> + UK_ASSERT(blkdev != NULL);
> + UK_ASSERT(req != NULL);
> + UK_ASSERT(queue != NULL);
> +
> + if (RING_FULL(&queue->ring)) {
> + uk_pr_err("Queue %p is full\n", queue);
> + return -EBUSY;
> + }
> +
> + err = blkfront_queue_enqueue(queue, req);
> + if (err) {
> + uk_pr_err("Failed to set ring req for %d op: %d\n",
> + req->operation, err);
> + return err;
> + }
> +
> + status |= UK_BLKDEV_STATUS_SUCCESS;
> + RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&queue->ring, notify);
> + if (notify) {
> + err = notify_remote_via_evtchn(queue->evtchn);
> + if (err)
> + return err;
> + }
> +
> + status |= (!RING_FULL(&queue->ring)) ? UK_BLKDEV_STATUS_MORE : 0x0;
> + return status;
> +}
> +
> /* Returns 1 if more responses available */
> static int blkfront_xen_ring_intr_enable(struct uk_blkdev_queue *queue)
> {
> @@ -369,6 +539,7 @@ static int blkfront_add_dev(struct xenbus_device *dev)
> return -ENOMEM;
>
> d->xendev = dev;
> + d->blkdev.submit_one = blkfront_submit_request;
> d->blkdev.dev_ops = &blkfront_ops;
>
> /* Xenbus initialization */
> diff --git a/plat/xen/drivers/blk/blkfront.h b/plat/xen/drivers/blk/blkfront.h
> index 037c627a..ec727fc8 100644
> --- a/plat/xen/drivers/blk/blkfront.h
> +++ b/plat/xen/drivers/blk/blkfront.h
> @@ -46,6 +46,19 @@
> #include <common/gnttab.h>
> #include <common/events.h>
>
> +
> +/**
> + * Structure used to describe a front device request.
> + */
> +struct blkfront_request {
> + /* Request from the API. */
> + struct uk_blkreq *req;
> + /* Number of segments. */
> + uint16_t nb_segments;
> + /* Queue in which the request will be stored */
> + struct uk_blkdev_queue *queue;
> +};
> +
> /*
> * Structure used to describe a queue used for both requests and responses
> */
> diff --git a/plat/xen/drivers/blk/blkfront_xs.c
> b/plat/xen/drivers/blk/blkfront_xs.c
> index 732e92f0..69a2df9d 100644
> --- a/plat/xen/drivers/blk/blkfront_xs.c
> +++ b/plat/xen/drivers/blk/blkfront_xs.c
> @@ -198,6 +198,10 @@ static int blkfront_xb_get_capabilities(struct
> blkfront_dev *blkdev)
> }
>
> blkdev->blkdev.capabilities.mode = (*mode == 'r') ? O_RDONLY : O_RDWR;
> + blkdev->blkdev.capabilities.max_sectors_per_req =
> + (BLKIF_MAX_SEGMENTS_PER_REQUEST - 1) *
> + (PAGE_SIZE / blkdev->blkdev.capabilities.ssize) + 1;
> + blkdev->blkdev.capabilities.ioalign = blkdev->blkdev.capabilities.ssize;
>
> free(mode);
> return 0;
>
_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |