All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paulina Szubarczyk <paulinaszubarczyk@gmail.com>
To: xen-devel@lists.xenproject.org, roger.pau@citrix.com
Cc: anthony.perard@citrix.com, sstabellini@kernel.org,
	Paulina Szubarczyk <paulinaszubarczyk@gmail.com>,
	P.Gawkowski@ii.pw.edu.pl
Subject: [PATCH 1/1] qemu-qdisk: indirect descriptors
Date: Wed, 15 Jun 2016 19:01:02 +0200	[thread overview]
Message-ID: <1466010062-16270-2-git-send-email-paulinaszubarczyk@gmail.com> (raw)
In-Reply-To: <1466010062-16270-1-git-send-email-paulinaszubarczyk@gmail.com>

Introduction of indirect descriptors for qdisk.

Changes in the xen_blkif.h file:
 - struct blkif_x86_**_request contains union of
   'struct blkif_x86_**_request_direct' (previous struct blkif_x86_**_request)
   and 'struct blkif_x86_**_request_indirect'
 - new helper functions to rewrite 'struct blkif_x86_**_request_**'
   to struct 'blkif_request_local' named like that to not interfer with
   'blkif_request' from "tools/include/xen/io/blkif.h"
 - a set of macros to maintain the indirect descriptors

Changes in the xen_disk.c file:
 - a new boolean feature_indirect member
 - a new helper function ioreq_get_operation_and_nr_segments
 - a new ioreq_parse_indirect function called when 'BLKIF_OP_INDIRECT'
   occurs. The function grant maps the pages with indirect descriptors and copy
   the segments to a local seg[MAX_INDIRECT_SEGMENTS] tabel placed in ioreq.

   After that the ioreq_parse function proceedes withoth changes. For
   direct request segments are mem-copied to the ioreq page.

Signed-off-by: Paulina Szubarczyk <paulinaszubarczyk@gmail.com>
---
 hw/block/xen_blkif.h         | 151 ++++++++++++++++++++++++++++++----
 hw/block/xen_disk.c          | 187 ++++++++++++++++++++++++++++++++++---------
 include/hw/xen/xen_backend.h |   2 +
 3 files changed, 285 insertions(+), 55 deletions(-)

diff --git a/hw/block/xen_blkif.h b/hw/block/xen_blkif.h
index c68487cb..04dce2f 100644
--- a/hw/block/xen_blkif.h
+++ b/hw/block/xen_blkif.h
@@ -18,40 +18,97 @@ struct blkif_common_response {
 
 /* i386 protocol version */
 #pragma pack(push, 4)
-struct blkif_x86_32_request {
-	uint8_t        operation;    /* BLKIF_OP_???                         */
+struct blkif_x86_32_request_direct {
 	uint8_t        nr_segments;  /* number of segments                   */
 	blkif_vdev_t   handle;       /* only for read/write requests         */
 	uint64_t       id;           /* private guest value, echoed in resp  */
 	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
 	struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
-};
+} __attribute__((__packed__));
+
+struct blkif_x86_32_request_indirect {
+	uint8_t        operation;
+	uint16_t       nr_segments;
+	uint64_t       id;
+	blkif_sector_t sector_number;
+	blkif_vdev_t   handle;
+	uint16_t       _pad2;
+	grant_ref_t    indirect_grefs[BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST];
+	uint64_t       _pad3;         /* make it 64 byte aligned */
+} __attribute__((__packed__));
+
+struct blkif_x86_32_request {
+	uint8_t 	   operation;
+	union  {
+		struct blkif_x86_32_request_direct direct;
+		struct blkif_x86_32_request_indirect indirect;
+	} u;
+} __attribute__((__packed__));
+
 struct blkif_x86_32_response {
 	uint64_t        id;              /* copied from request */
 	uint8_t         operation;       /* copied from request */
 	int16_t         status;          /* BLKIF_RSP_???       */
-};
+} __attribute__((__packed__));
+
 typedef struct blkif_x86_32_request blkif_x86_32_request_t;
+typedef struct blkif_x86_32_request_direct blkif_x86_32_request_direct_t;
+typedef struct blkif_x86_32_request_indirect blkif_x86_32_request_indirect_t;
 typedef struct blkif_x86_32_response blkif_x86_32_response_t;
 #pragma pack(pop)
 
 /* x86_64 protocol version */
-struct blkif_x86_64_request {
-	uint8_t        operation;    /* BLKIF_OP_???                         */
+struct blkif_x86_64_request_direct {
 	uint8_t        nr_segments;  /* number of segments                   */
 	blkif_vdev_t   handle;       /* only for read/write requests         */
-	uint64_t       __attribute__((__aligned__(8))) id;
+	uint32_t       _pad1;	     /* offsetof(blkif_request,u.rw.id) == 8 */
+	uint64_t       id;           /* private guest value, echoed in resp  */
 	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
 	struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
-};
+} __attribute__((__packed__));
+
+struct blkif_x86_64_request_indirect {
+	uint8_t        operation;
+	uint16_t       nr_segments;
+	uint32_t       _pad1;  
+	uint64_t       id;
+	blkif_sector_t sector_number;
+	blkif_vdev_t   handle;
+	uint16_t       _pad2;
+	grant_ref_t    indirect_grefs[BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST];
+	uint32_t      _pad3;         /* make it 64 byte aligned */
+} __attribute__((__packed__));
+
+struct blkif_x86_64_request {
+	uint8_t        operation;    /* BLKIF_OP_???                         */
+	union {
+		struct blkif_x86_64_request_direct direct;
+		struct blkif_x86_64_request_indirect indirect;
+	} u;
+} __attribute__((__packed__));
+
 struct blkif_x86_64_response {
-	uint64_t       __attribute__((__aligned__(8))) id;
+	uint64_t        id;              /* copied from request */
 	uint8_t         operation;       /* copied from request */
 	int16_t         status;          /* BLKIF_RSP_???       */
 };
+
 typedef struct blkif_x86_64_request blkif_x86_64_request_t;
+typedef struct blkif_x86_64_request_direct blkif_x86_64_request_direct_t;
+typedef struct blkif_x86_64_request_indirect blkif_x86_64_request_indirect_t;
 typedef struct blkif_x86_64_response blkif_x86_64_response_t;
 
+struct blkif_request_local {
+	uint8_t 	   operation;
+ 	union {
+		struct blkif_request direct;
+		struct blkif_request_indirect indirect;
+	} u;
+} __attribute__((__packed__));
+typedef struct blkif_request blkif_request_direct_t;
+typedef struct blkif_request_indirect blkif_request_indirect_t;
+typedef struct blkif_request_local blkif_request_local_t;
+
 DEFINE_RING_TYPES(blkif_common, struct blkif_common_request, struct blkif_common_response);
 DEFINE_RING_TYPES(blkif_x86_32, struct blkif_x86_32_request, struct blkif_x86_32_response);
 DEFINE_RING_TYPES(blkif_x86_64, struct blkif_x86_64_request, struct blkif_x86_64_response);
@@ -70,16 +127,27 @@ enum blkif_protocol {
 	BLKIF_PROTOCOL_X86_64 = 3,
 };
 
-static inline void blkif_get_x86_32_req(blkif_request_t *dst, blkif_x86_32_request_t *src)
+#define XEN_PAGE_SIZE 4096
+#define XEN_PAGES_PER_SEGMENT 1
+#define XEN_PAGES_PER_INDIRECT_FRAME \
+      (XEN_PAGE_SIZE/sizeof(struct blkif_request_segment))
+#define SEGS_PER_INDIRECT_FRAME \
+      (XEN_PAGES_PER_INDIRECT_FRAME / XEN_PAGES_PER_SEGMENT)
+#define MAX_INDIRECT_PAGES \
+      ((MAX_INDIRECT_SEGMENTS + SEGS_PER_INDIRECT_FRAME - 1)/SEGS_PER_INDIRECT_FRAME)
+#define INDIRECT_PAGES(_segs) DIV_ROUND_UP(_segs, XEN_PAGES_PER_INDIRECT_FRAME)
+
+static inline void blkif_get_x86_32_req_direct(blkif_request_direct_t *dst, 
+										       blkif_x86_32_request_direct_t *src,
+										       uint8_t operation)
 {
 	int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST;
 
-	dst->operation = src->operation;
 	dst->nr_segments = src->nr_segments;
 	dst->handle = src->handle;
 	dst->id = src->id;
 	dst->sector_number = src->sector_number;
-	if (src->operation == BLKIF_OP_DISCARD) {
+	if (operation == BLKIF_OP_DISCARD) {
 		struct blkif_request_discard *s = (void *)src;
 		struct blkif_request_discard *d = (void *)dst;
 		d->nr_sectors = s->nr_sectors;
@@ -93,16 +161,43 @@ static inline void blkif_get_x86_32_req(blkif_request_t *dst, blkif_x86_32_reque
 		dst->seg[i] = src->seg[i];
 }
 
-static inline void blkif_get_x86_64_req(blkif_request_t *dst, blkif_x86_64_request_t *src)
+static inline void blkif_get_x86_32_req_indirect(blkif_request_indirect_t *dst, 
+									             blkif_x86_32_request_indirect_t *src)
 {
-	int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST;
+	int i, n;
+
+	dst->operation = src->operation;
+	dst->nr_segments = src->nr_segments;
+	dst->handle = src->handle;
+	dst->id = src->id;
+	dst->sector_number = src->sector_number;
+	n = INDIRECT_PAGES(dst->nr_segments);
+	for (i = 0; i < n; i++)
+		dst->indirect_grefs[i] = src->indirect_grefs[i];
+}
 
+static inline void blkif_get_x86_32_req_local(blkif_request_local_t *dst, 
+											  blkif_x86_32_request_t *src) 
+{
 	dst->operation = src->operation;
+	if (dst->operation == BLKIF_OP_INDIRECT) {
+		blkif_get_x86_32_req_indirect(&dst->u.indirect, &src->u.indirect);
+	} else {
+		blkif_get_x86_32_req_direct(&dst->u.direct, &src->u.direct, dst->operation);
+	}
+}
+
+static inline void blkif_get_x86_64_req_direct(blkif_request_direct_t *dst, 
+											   blkif_x86_64_request_direct_t *src,
+										       uint8_t operation)
+{
+	int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST;
+
 	dst->nr_segments = src->nr_segments;
 	dst->handle = src->handle;
 	dst->id = src->id;
 	dst->sector_number = src->sector_number;
-	if (src->operation == BLKIF_OP_DISCARD) {
+	if (operation == BLKIF_OP_DISCARD) {
 		struct blkif_request_discard *s = (void *)src;
 		struct blkif_request_discard *d = (void *)dst;
 		d->nr_sectors = s->nr_sectors;
@@ -116,4 +211,30 @@ static inline void blkif_get_x86_64_req(blkif_request_t *dst, blkif_x86_64_reque
 		dst->seg[i] = src->seg[i];
 }
 
+static inline void blkif_get_x86_64_req_indirect(blkif_request_indirect_t *dst, 
+									             blkif_x86_64_request_indirect_t *src)
+{
+	int i, n;
+
+	dst->operation = src->operation;
+	dst->nr_segments = src->nr_segments;
+	dst->handle = src->handle;
+	dst->id = src->id;
+	dst->sector_number = src->sector_number;
+	n = INDIRECT_PAGES(dst->nr_segments);
+	for (i = 0; i < n; i++)
+		dst->indirect_grefs[i] = src->indirect_grefs[i];
+}
+
+static inline void blkif_get_x86_64_req_local(blkif_request_local_t *dst, 
+											  blkif_x86_64_request_t *src) 
+{
+	dst->operation = src->operation;
+	if (dst->operation == BLKIF_OP_INDIRECT) {
+		blkif_get_x86_64_req_indirect(&dst->u.indirect, &src->u.indirect);
+	} else {
+		blkif_get_x86_64_req_direct(&dst->u.direct, &src->u.direct, dst->operation);
+	}
+}
+
 #endif /* __XEN_BLKIF_H__ */
diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
index 37e14d1..e497cde 100644
--- a/hw/block/xen_disk.c
+++ b/hw/block/xen_disk.c
@@ -52,7 +52,6 @@ static int max_requests = 32;
 /* ------------------------------------------------------------- */
 
 #define BLOCK_SIZE  512
-#define IOCB_COUNT  (BLKIF_MAX_SEGMENTS_PER_REQUEST + 2)
 
 struct PersistentGrant {
     void *page;
@@ -69,8 +68,8 @@ struct PersistentRegion {
 typedef struct PersistentRegion PersistentRegion;
 
 struct ioreq {
-    blkif_request_t     req;
-    int16_t             status;
+    blkif_request_local_t   req;
+    int16_t                 status;
 
     /* parsed request */
     off_t               start;
@@ -80,19 +79,22 @@ struct ioreq {
     uint8_t             mapped;
 
     /* grant mapping */
-    uint32_t            domids[BLKIF_MAX_SEGMENTS_PER_REQUEST];
-    uint32_t            refs[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+    uint32_t            domids[MAX_INDIRECT_SEGMENTS];
+    uint32_t            refs[MAX_INDIRECT_SEGMENTS];
     int                 prot;
-    void                *page[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+    void                *page[MAX_INDIRECT_SEGMENTS];
     void                *pages;
     int                 num_unmap;
 
+    /* indirect request */
+    struct blkif_request_segment seg[MAX_INDIRECT_SEGMENTS];
+
     /* aio status */
     int                 aio_inflight;
     int                 aio_errors;
 
     struct XenBlkDev    *blkdev;
-    QLIST_ENTRY(ioreq)   list;
+    QLIST_ENTRY(ioreq)  list;
     BlockAcctCookie     acct;
 };
 
@@ -131,6 +133,9 @@ struct XenBlkDev {
     unsigned int        persistent_gnt_count;
     unsigned int        max_grants;
 
+    /* Indirect descriptors */
+    gboolean            feature_indirect;
+
     /* qemu block driver */
     DriveInfo           *dinfo;
     BlockBackend        *blk;
@@ -216,7 +221,11 @@ static struct ioreq *ioreq_start(struct XenBlkDev *blkdev)
         ioreq = g_malloc0(sizeof(*ioreq));
         ioreq->blkdev = blkdev;
         blkdev->requests_total++;
-        qemu_iovec_init(&ioreq->v, BLKIF_MAX_SEGMENTS_PER_REQUEST);
+        if (blkdev->feature_indirect) {
+            qemu_iovec_init(&ioreq->v, MAX_INDIRECT_SEGMENTS);
+        } else {
+            qemu_iovec_init(&ioreq->v, BLKIF_MAX_SEGMENTS_PER_REQUEST);
+        }
     } else {
         /* get one from freelist */
         ioreq = QLIST_FIRST(&blkdev->freelist);
@@ -254,6 +263,57 @@ static void ioreq_release(struct ioreq *ioreq, bool finish)
     }
 }
 
+static void ioreq_get_operation_and_nr_segments(struct ioreq *ioreq, 
+                                                uint8_t *operation, 
+                                                uint16_t *nseg)
+{
+    if (ioreq->req.operation == BLKIF_OP_INDIRECT) {
+        *operation = ioreq->req.u.indirect.operation;
+        *nseg = ioreq->req.u.indirect.nr_segments;
+    } else {
+        *operation = ioreq->req.operation;
+        *nseg = ioreq->req.u.direct.nr_segments;
+    }
+}
+
+static int ioreq_parse_indirect(struct XenBlkDev *blkdev,
+                                blkif_request_indirect_t *req, uint32_t domid,
+                                struct blkif_request_segment *seg) 
+{
+    void *pages;
+    struct blkif_request_segment *segments = NULL;
+    int i, j, nr_indirect_grefs;
+
+    nr_indirect_grefs = INDIRECT_PAGES(req->nr_segments);
+
+    pages = xc_gnttab_map_domain_grant_refs(blkdev->xendev.gnttabdev, 
+                                            nr_indirect_grefs, domid, 
+                                            req->indirect_grefs,
+                                            PROT_READ);
+    
+    if (pages == NULL) {
+        xen_be_printf(&blkdev->xendev, 0, "can't map indirect grant refs %s\n", 
+                      strerror(errno));
+        return -1;
+    }
+
+    for (i = 0, j = 0; j < req->nr_segments; j++) {
+        i = j % SEGS_PER_INDIRECT_FRAME;
+        if (i == 0) {
+            segments = pages + i/SEGS_PER_INDIRECT_FRAME * XC_PAGE_SIZE;
+        }
+        seg[j].gref = segments[i].gref;
+        seg[j].first_sect = segments[i].first_sect;
+        seg[j].last_sect = segments[i].last_sect;
+    }
+
+    if (xc_gnttab_munmap(blkdev->xendev.gnttabdev, pages, nr_indirect_grefs)) {
+        xen_be_printf(&blkdev->xendev, 0, "xc_gnttab_munmap failed: %s\n",
+                      strerror(errno));
+    }
+
+    return 0;
+}
 /*
  * translate request into iovec + start offset
  * do sanity checks along the way
@@ -261,21 +321,21 @@ static void ioreq_release(struct ioreq *ioreq, bool finish)
 static int ioreq_parse(struct ioreq *ioreq)
 {
     struct XenBlkDev *blkdev = ioreq->blkdev;
+    uint8_t operation;
+    uint16_t nseg;
     uintptr_t mem;
     size_t len;
-    int i;
+    int i, r;
 
-    xen_be_printf(&blkdev->xendev, 3,
-                  "op %d, nr %d, handle %d, id %" PRId64 ", sector %" PRId64 "\n",
-                  ioreq->req.operation, ioreq->req.nr_segments,
-                  ioreq->req.handle, ioreq->req.id, ioreq->req.sector_number);
-    switch (ioreq->req.operation) {
+    ioreq_get_operation_and_nr_segments(ioreq, &operation, &nseg);
+
+    switch (operation) {
     case BLKIF_OP_READ:
         ioreq->prot = PROT_WRITE; /* to memory */
         break;
     case BLKIF_OP_FLUSH_DISKCACHE:
         ioreq->presync = 1;
-        if (!ioreq->req.nr_segments) {
+        if (!nseg) {
             return 0;
         }
         /* fall through */
@@ -286,35 +346,53 @@ static int ioreq_parse(struct ioreq *ioreq)
         return 0;
     default:
         xen_be_printf(&blkdev->xendev, 0, "error: unknown operation (%d)\n",
-                      ioreq->req.operation);
+                      operation);
         goto err;
     };
 
-    if (ioreq->req.operation != BLKIF_OP_READ && blkdev->mode[0] != 'w') {
+    if (operation != BLKIF_OP_READ && blkdev->mode[0] != 'w') {
         xen_be_printf(&blkdev->xendev, 0, "error: write req for ro device\n");
         goto err;
     }
 
-    ioreq->start = ioreq->req.sector_number * blkdev->file_blk;
-    for (i = 0; i < ioreq->req.nr_segments; i++) {
-        if (i == BLKIF_MAX_SEGMENTS_PER_REQUEST) {
+    if (ioreq->req.operation == BLKIF_OP_INDIRECT) {
+        if (nseg > MAX_INDIRECT_SEGMENTS) {
             xen_be_printf(&blkdev->xendev, 0, "error: nr_segments too big\n");
             goto err;
         }
-        if (ioreq->req.seg[i].first_sect > ioreq->req.seg[i].last_sect) {
+        r = ioreq_parse_indirect(ioreq->blkdev, &ioreq->req.u.indirect, 
+                                 blkdev->xendev.dom, ioreq->seg);
+        if (r != 0) {
+            xen_be_printf(&blkdev->xendev, 0, 
+                                  "error: failed to map indirect segments\n");
+            goto err;
+        }
+        ioreq->start = ioreq->req.u.indirect.sector_number * blkdev->file_blk;
+    } else {
+        if (nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST) {
+            xen_be_printf(&blkdev->xendev, 0, "error: nr_segments too big\n");
+            goto err;
+        }
+        memcpy(ioreq->seg, ioreq->req.u.direct.seg, sizeof(struct blkif_request_segment)*nseg);
+        ioreq->start = ioreq->req.u.direct.sector_number * blkdev->file_blk;
+    }
+
+    for (i = 0; i < nseg; i++) {
+
+        if (ioreq->seg[i].first_sect > ioreq->seg[i].last_sect) {
             xen_be_printf(&blkdev->xendev, 0, "error: first > last sector\n");
             goto err;
         }
-        if (ioreq->req.seg[i].last_sect * BLOCK_SIZE >= XC_PAGE_SIZE) {
+        if (ioreq->seg[i].last_sect * BLOCK_SIZE >= XC_PAGE_SIZE) {
             xen_be_printf(&blkdev->xendev, 0, "error: page crossing\n");
             goto err;
         }
 
         ioreq->domids[i] = blkdev->xendev.dom;
-        ioreq->refs[i]   = ioreq->req.seg[i].gref;
+        ioreq->refs[i]   = ioreq->seg[i].gref;
 
-        mem = ioreq->req.seg[i].first_sect * blkdev->file_blk;
-        len = (ioreq->req.seg[i].last_sect - ioreq->req.seg[i].first_sect + 1) * blkdev->file_blk;
+        mem = ioreq->seg[i].first_sect * blkdev->file_blk;
+        len = (ioreq->seg[i].last_sect - ioreq->seg[i].first_sect + 1) * blkdev->file_blk;
         qemu_iovec_add(&ioreq->v, (void*)mem, len);
     }
     if (ioreq->start + ioreq->v.size > blkdev->file_size) {
@@ -365,9 +443,9 @@ static void ioreq_unmap(struct ioreq *ioreq)
 static int ioreq_map(struct ioreq *ioreq)
 {
     XenGnttab gnt = ioreq->blkdev->xendev.gnttabdev;
-    uint32_t domids[BLKIF_MAX_SEGMENTS_PER_REQUEST];
-    uint32_t refs[BLKIF_MAX_SEGMENTS_PER_REQUEST];
-    void *page[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+    uint32_t domids[MAX_INDIRECT_SEGMENTS];
+    uint32_t refs[MAX_INDIRECT_SEGMENTS];
+    void *page[MAX_INDIRECT_SEGMENTS];
     int i, j, new_maps = 0;
     PersistentGrant *grant;
     PersistentRegion *region;
@@ -505,10 +583,14 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq);
 static void qemu_aio_complete(void *opaque, int ret)
 {
     struct ioreq *ioreq = opaque;
+    uint8_t operation;    
+    uint16_t nseg;
+
+    ioreq_get_operation_and_nr_segments(ioreq, &operation, &nseg);
 
     if (ret != 0) {
         xen_be_printf(&ioreq->blkdev->xendev, 0, "%s I/O error\n",
-                      ioreq->req.operation == BLKIF_OP_READ ? "read" : "write");
+                      operation ? "read" : "write");
         ioreq->aio_errors++;
     }
 
@@ -531,10 +613,10 @@ static void qemu_aio_complete(void *opaque, int ret)
     ioreq->status = ioreq->aio_errors ? BLKIF_RSP_ERROR : BLKIF_RSP_OKAY;
     ioreq_unmap(ioreq);
     ioreq_finish(ioreq);
-    switch (ioreq->req.operation) {
+    switch (operation) {
     case BLKIF_OP_WRITE:
     case BLKIF_OP_FLUSH_DISKCACHE:
-        if (!ioreq->req.nr_segments) {
+        if (!nseg) {
             break;
         }
     case BLKIF_OP_READ:
@@ -550,8 +632,12 @@ static void qemu_aio_complete(void *opaque, int ret)
 static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
 {
     struct XenBlkDev *blkdev = ioreq->blkdev;
+    uint8_t operation;    
+    uint16_t nseg;
 
-    if (ioreq->req.nr_segments && ioreq_map(ioreq) == -1) {
+    ioreq_get_operation_and_nr_segments(ioreq, &operation, &nseg);
+
+    if (nseg && ioreq_map(ioreq) == -1) {
         goto err_no_map;
     }
 
@@ -561,7 +647,7 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
         return 0;
     }
 
-    switch (ioreq->req.operation) {
+    switch (operation) {
     case BLKIF_OP_READ:
         block_acct_start(blk_get_stats(blkdev->blk), &ioreq->acct,
                          ioreq->v.size, BLOCK_ACCT_READ);
@@ -572,7 +658,7 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
         break;
     case BLKIF_OP_WRITE:
     case BLKIF_OP_FLUSH_DISKCACHE:
-        if (!ioreq->req.nr_segments) {
+        if (!nseg) {
             break;
         }
 
@@ -617,8 +703,13 @@ static int blk_send_response_one(struct ioreq *ioreq)
     blkif_response_t  resp;
     void              *dst;
 
-    resp.id        = ioreq->req.id;
-    resp.operation = ioreq->req.operation;
+    if (ioreq->req.operation == BLKIF_OP_INDIRECT) {
+        resp.id        = ioreq->req.u.indirect.id;
+        resp.operation = ioreq->req.u.indirect.operation;
+    } else {        
+        resp.id        = ioreq->req.u.direct.id;
+        resp.operation = ioreq->req.operation;
+    }   
     resp.status    = ioreq->status;
 
     /* Place on the response ring for the relevant domain. */
@@ -683,11 +774,11 @@ static int blk_get_request(struct XenBlkDev *blkdev, struct ioreq *ioreq, RING_I
                sizeof(ioreq->req));
         break;
     case BLKIF_PROTOCOL_X86_32:
-        blkif_get_x86_32_req(&ioreq->req,
+        blkif_get_x86_32_req_local(&ioreq->req,
                              RING_GET_REQUEST(&blkdev->rings.x86_32_part, rc));
         break;
     case BLKIF_PROTOCOL_X86_64:
-        blkif_get_x86_64_req(&ioreq->req,
+        blkif_get_x86_64_req_local(&ioreq->req,
                              RING_GET_REQUEST(&blkdev->rings.x86_64_part, rc));
         break;
     }
@@ -756,6 +847,7 @@ static void blk_bh(void *opaque)
 static void blk_alloc(struct XenDevice *xendev)
 {
     struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
+    int max_segments = BLKIF_MAX_SEGMENTS_PER_REQUEST;
 
     QLIST_INIT(&blkdev->inflight);
     QLIST_INIT(&blkdev->finished);
@@ -764,8 +856,15 @@ static void blk_alloc(struct XenDevice *xendev)
     if (xen_mode != XEN_EMULATE) {
         batch_maps = 1;
     }
+    blkdev->feature_indirect = true;
+
+    if (blkdev->feature_indirect) {
+        max_segments = MAX_INDIRECT_SEGMENTS;
+    }
+
+    if (blkdev->feature_indirect)
     if (xc_gnttab_set_max_grants(xendev->gnttabdev,
-            MAX_GRANTS(max_requests, BLKIF_MAX_SEGMENTS_PER_REQUEST)) < 0) {
+            MAX_GRANTS(max_requests, max_segments)) < 0) {
         xen_be_printf(xendev, 0, "xc_gnttab_set_max_grants failed: %s\n",
                       strerror(errno));
     }
@@ -855,6 +954,10 @@ static int blk_init(struct XenDevice *xendev)
     xenstore_write_be_int(&blkdev->xendev, "feature-flush-cache", 1);
     xenstore_write_be_int(&blkdev->xendev, "feature-persistent", 1);
     xenstore_write_be_int(&blkdev->xendev, "info", info);
+    if (blkdev->feature_indirect) {
+        xenstore_write_be_int(&blkdev->xendev, "feature-max-indirect-segments", 
+                              MAX_INDIRECT_SEGMENTS);
+    }
 
     blk_parse_discard(blkdev);
 
@@ -1008,7 +1111,11 @@ static int blk_connect(struct XenDevice *xendev)
 
     if (blkdev->feature_persistent) {
         /* Init persistent grants */
-        blkdev->max_grants = max_requests * BLKIF_MAX_SEGMENTS_PER_REQUEST;
+        if (blkdev->feature_indirect) {
+            blkdev->max_grants = max_requests * MAX_INDIRECT_SEGMENTS;
+        } else {
+            blkdev->max_grants = max_requests * BLKIF_MAX_SEGMENTS_PER_REQUEST;
+        }
         blkdev->persistent_gnts = g_tree_new_full((GCompareDataFunc)int_cmp,
                                              NULL, NULL,
                                              batch_maps ?
diff --git a/include/hw/xen/xen_backend.h b/include/hw/xen/xen_backend.h
index 3b4125e..6836f98 100644
--- a/include/hw/xen/xen_backend.h
+++ b/include/hw/xen/xen_backend.h
@@ -15,6 +15,8 @@ struct XenDevice;
 #define DEVOPS_FLAG_NEED_GNTDEV   1
 /* don't expect frontend doing correct state transitions (aka console quirk) */
 #define DEVOPS_FLAG_IGNORE_STATE  2
+/* */
+#define MAX_INDIRECT_SEGMENTS 32
 
 struct XenDevOps {
     size_t    size;
-- 
1.9.1


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

      reply	other threads:[~2016-06-15 17:02 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-06-15 17:01 [PATCH 0/1] qemu-qdisk: indirect descriptors Paulina Szubarczyk
2016-06-15 17:01 ` Paulina Szubarczyk [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1466010062-16270-2-git-send-email-paulinaszubarczyk@gmail.com \
    --to=paulinaszubarczyk@gmail.com \
    --cc=P.Gawkowski@ii.pw.edu.pl \
    --cc=anthony.perard@citrix.com \
    --cc=roger.pau@citrix.com \
    --cc=sstabellini@kernel.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.