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

[Minios-devel] [UNIKRAFT PATCH 10/12] plat/drivers: Flush requests for virtio block



This patch introduces the flush requests.
This operation garantees that all previous write requests
are finished.

Signed-off-by: Roxana Nicolescu <nicolescu.roxana1996@xxxxxxxxx>
---
 plat/drivers/include/virtio/virtio_blk.h |  8 ++++
 plat/drivers/virtio/virtio_blk.c         | 72 +++++++++++++++++++++++++-------
 2 files changed, 66 insertions(+), 14 deletions(-)

diff --git a/plat/drivers/include/virtio/virtio_blk.h 
b/plat/drivers/include/virtio/virtio_blk.h
index fde1953c..e2d28928 100644
--- a/plat/drivers/include/virtio/virtio_blk.h
+++ b/plat/drivers/include/virtio/virtio_blk.h
@@ -32,6 +32,10 @@
 #define VIRTIO_BLK_F_RO                5
 /* Block size of disk is in blk_size. */
 #define VIRTIO_BLK_F_BLK_SIZE  6
+/* Cache flush command support. */
+#define VIRTIO_BLK_F_FLUSH     9
+/* Device can toggle its cache between writeback and writethrough modes. */
+#define VIRTIO_BLK_F_CONFIG_WCE 11
 /* Device supports multi-queues */
 #define VIRTIO_BLK_F_MQ                12
 
@@ -45,6 +49,10 @@ struct virtio_blk_config {
        __u32 seg_max;
        /* Block size */
        __u32 blk_size;
+       /* It is set if backend has writeback cache,
+        * otherwise it has writethrough cache.
+        **/
+       __u8 writeback;
        /* Number of vqs, only available when VIRTIO_BLK_F_MQ is set */
        __u16 num_queues;
 };
diff --git a/plat/drivers/virtio/virtio_blk.c b/plat/drivers/virtio/virtio_blk.c
index bc845d97..5b8972cf 100644
--- a/plat/drivers/virtio/virtio_blk.c
+++ b/plat/drivers/virtio/virtio_blk.c
@@ -25,6 +25,7 @@
 #include <uk/print.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <stdbool.h>
 #include <virtio/virtio_bus.h>
 #include <virtio/virtio_ids.h>
 #include <uk/blkdev.h>
@@ -49,11 +50,13 @@
  *     Multi-queue,
  *     Maximum size of a segment for requests,
  *     Maximum number of segments per request,
+ *     Flush
  **/
 #define VIRTIO_BLK_DRV_FEATURES(features) \
        (VIRTIO_FEATURES_UPDATE(features, VIRTIO_BLK_F_RO | \
        VIRTIO_BLK_F_BLK_SIZE | VIRTIO_BLK_F_MQ | \
-       VIRTIO_BLK_F_SEG_MAX | VIRTIO_BLK_F_SIZE_MAX))
+       VIRTIO_BLK_F_SEG_MAX | VIRTIO_BLK_F_SIZE_MAX | \
+       VIRTIO_BLK_F_CONFIG_WCE | VIRTIO_BLK_F_FLUSH))
 
 static struct uk_alloc *a;
 static const char *drv_name = DRIVER_NAME;
@@ -77,6 +80,8 @@ struct virtio_blk_device {
        __u32 max_segments;
        /* Maximum size of a segment */
        __u32 max_size_segment;
+       /* If it is set then flush request is permitted */
+       __u8 writeback;
 };
 
 struct uk_blkdev_queue {
@@ -102,7 +107,8 @@ struct uk_blkdev_queue {
 
 static int virtio_blkdev_request_set_sglist(struct uk_blkdev_queue *queue,
                struct uk_blkdev_request *req,
-               __sector sector_size)
+               __sector sector_size,
+               bool have_data)
 {
        struct virtio_blk_device *vbdev;
        size_t data_size = 0;
@@ -131,19 +137,20 @@ static int virtio_blkdev_request_set_sglist(struct 
uk_blkdev_queue *queue,
        /* Append to sglist chunks of `segment_max_size` size
         * Only for read / write operations
         **/
-       for (idx = 0; idx < data_size; idx += segment_max_size) {
-               segment_size = data_size - idx;
-               segment_size = (segment_size > segment_max_size) ?
-                               segment_max_size : segment_size;
-               rc = uk_sglist_append(&queue->sg,
-                               (void *)(start_data + idx),
-                               segment_size);
-               if (unlikely(rc != 0)) {
-                       uk_pr_err("Failed to append to sg list %d\n",
-                                       rc);
-                       goto out;
+       if (have_data)
+               for (idx = 0; idx < data_size; idx += segment_max_size) {
+                       segment_size = data_size - idx;
+                       segment_size = (segment_size > segment_max_size) ?
+                                       segment_max_size : segment_size;
+                       rc = uk_sglist_append(&queue->sg,
+                                       (void *)(start_data + idx),
+                                       segment_size);
+                       if (unlikely(rc != 0)) {
+                               uk_pr_err("Failed to append to sg list %d\n",
+                                               rc);
+                               goto out;
+                       }
                }
-       }
 
        rc = uk_sglist_append(&queue->sg, &req->result_status,
                        sizeof(req->result_status));
@@ -203,6 +210,38 @@ out:
        return rc;
 }
 
+static int virtio_blkdev_request_flush(struct uk_blkdev_queue *queue,
+               struct uk_blkdev_request *req, __u16 *read_segs,
+               __u16 *write_segs)
+{
+       struct virtio_blk_device *vbdev;
+       int rc = 0;
+
+       UK_ASSERT(queue);
+       UK_ASSERT(req);
+
+       vbdev = queue->vbd;
+       if (!vbdev->writeback)
+               return -ENOTSUP;
+
+       if (req->start_sector) {
+               uk_pr_warn("Start sector should be 0 at flush request\n");
+               req->start_sector = 0;
+       }
+
+       rc = virtio_blkdev_request_set_sglist(queue, req, 0, false);
+       if (rc) {
+               uk_pr_err("Failed to set sglist %d\n", rc);
+               goto out;
+       }
+
+       *read_segs = 1;
+       *write_segs = 1;
+
+out:
+       return rc;
+}
+
 static int virtio_blkdev_queue_enqueue(struct uk_blkdev_queue *queue,
                struct uk_blkdev_request *req)
 {
@@ -222,6 +261,9 @@ static int virtio_blkdev_queue_enqueue(struct 
uk_blkdev_queue *queue,
                        req->operation == UK_BLKDEV_READ)
                rc = virtio_blkdev_request_write(queue, req, &read_segs,
                                &write_segs);
+       else if (req->operation == UK_BLKDEV_FFLUSH)
+               rc = virtio_blkdev_request_flush(queue, req, &read_segs,
+                               &write_segs);
        else
                return -EINVAL;
 
@@ -726,6 +768,8 @@ static int virtio_blkdev_feature_negotiate(struct 
virtio_blk_device *vbdev)
        vbdev->max_vqueue_pairs = num_queues;
        vbdev->max_segments = max_segments;
        vbdev->max_size_segment = max_size_segment;
+       vbdev->writeback = virtio_has_features(host_features,
+                               VIRTIO_BLK_F_FLUSH);
 
        /**
         * Mask out features supported by both driver and device.
-- 
2.11.0


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