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
prev parent 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).