summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2011-04-15 11:35:13 -0400
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2011-04-15 11:35:13 -0400
commit1a95fe6e42cefc52c62c471ad87d7fe8643231df (patch)
treec291f0877992d08f8129e56a8e58dfbfbb00c072
parentb0aef17924a06646403cae8eecf6c73219a63c19 (diff)
downloadop-kernel-dev-1a95fe6e42cefc52c62c471ad87d7fe8643231df.zip
op-kernel-dev-1a95fe6e42cefc52c62c471ad87d7fe8643231df.tar.gz
xen/blkback: Shuffle code around (vbd_translate moved higher).
We take out the chunk of code dealing with mapping to the guest of pages into the xen_blk_map_buf code. And we also move the vbd_translate to be done much earlier. Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
-rw-r--r--drivers/xen/blkback/blkback.c129
1 files changed, 70 insertions, 59 deletions
diff --git a/drivers/xen/blkback/blkback.c b/drivers/xen/blkback/blkback.c
index f282463..211b200 100644
--- a/drivers/xen/blkback/blkback.c
+++ b/drivers/xen/blkback/blkback.c
@@ -241,6 +241,10 @@ int blkif_schedule(void *arg)
return 0;
}
+struct seg_buf {
+ unsigned long buf;
+ unsigned int nsec;
+};
/*
* Unmap the grant references, and also remove the M2P over-rides
* used in the 'pending_req'.
@@ -278,6 +282,62 @@ static void fast_flush_area(struct pending_req *req)
}
}
}
+static int xen_blk_map_buf(struct blkif_request *req, struct pending_req *pending_req,
+ struct seg_buf seg[])
+{
+ struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+ int i;
+ int nseg = req->nr_segments;
+ int ret = 0;
+ /* Fill out preq.nr_sects with proper amount of sectors, and setup
+ * assign map[..] with the PFN of the page in our domain with the
+ * corresponding grant reference for each page.
+ */
+ for (i = 0; i < nseg; i++) {
+ uint32_t flags;
+
+ flags = GNTMAP_host_map;
+ if (pending_req->operation != BLKIF_OP_READ)
+ flags |= GNTMAP_readonly;
+ gnttab_set_map_op(&map[i], vaddr(pending_req, i), flags,
+ req->u.rw.seg[i].gref, pending_req->blkif->domid);
+ }
+
+ ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, nseg);
+ BUG_ON(ret);
+
+ /* Now swizzel the MFN in our domain with the MFN from the other domain
+ * so that when we access vaddr(pending_req,i) it has the contents of
+ * the page from the other domain.
+ */
+ for (i = 0; i < nseg; i++) {
+ if (unlikely(map[i].status != 0)) {
+ DPRINTK("invalid buffer -- could not remap it\n");
+ map[i].handle = BLKBACK_INVALID_HANDLE;
+ ret |= 1;
+ }
+
+ pending_handle(pending_req, i) = map[i].handle;
+
+ if (ret)
+ continue;
+
+ ret = m2p_add_override(PFN_DOWN(map[i].dev_bus_addr),
+ blkbk->pending_page(pending_req, i), false);
+ if (ret) {
+ printk(KERN_ALERT "Failed to install M2P override for"\
+ " %lx (ret: %d)\n", (unsigned long)
+ map[i].dev_bus_addr, ret);
+ /* We could switch over to GNTTABOP_copy */
+ continue;
+ }
+
+ seg[i].buf = map[i].dev_bus_addr |
+ (req->u.rw.seg[i].first_sect << 9);
+ }
+ return ret;
+}
+
/*
* Completion callback on the bio's. Called as bh->b_end_io()
*/
@@ -411,15 +471,12 @@ static void dispatch_rw_block_io(struct blkif_st *blkif,
struct blkif_request *req,
struct pending_req *pending_req)
{
- struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST];
struct phys_req preq;
- struct {
- unsigned long buf; unsigned int nsec;
- } seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+ struct seg_buf seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
unsigned int nseg;
struct bio *bio = NULL;
struct bio *biolist[BLKIF_MAX_SEGMENTS_PER_REQUEST];
- int ret, i, nbio = 0;
+ int i, nbio = 0;
int operation;
struct blk_plug plug;
struct request_queue *q;
@@ -444,6 +501,7 @@ static void dispatch_rw_block_io(struct blkif_st *blkif,
if (unlikely(nseg == 0 && operation != WRITE_BARRIER) ||
unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) {
DPRINTK("Bad number of segments in request (%d)\n", nseg);
+ /* Haven't submitted any bio's yet. */
goto fail_response;
}
@@ -456,77 +514,30 @@ static void dispatch_rw_block_io(struct blkif_st *blkif,
pending_req->operation = req->operation;
pending_req->status = BLKIF_RSP_OKAY;
pending_req->nr_pages = nseg;
-
- /* Fill out preq.nr_sects with proper amount of sectors, and setup
- * assign map[..] with the PFN of the page in our domain with the
- * corresponding grant reference for each page.
- */
for (i = 0; i < nseg; i++) {
- uint32_t flags;
-
seg[i].nsec = req->u.rw.seg[i].last_sect -
req->u.rw.seg[i].first_sect + 1;
if ((req->u.rw.seg[i].last_sect >= (PAGE_SIZE >> 9)) ||
(req->u.rw.seg[i].last_sect < req->u.rw.seg[i].first_sect))
goto fail_response;
preq.nr_sects += seg[i].nsec;
-
- flags = GNTMAP_host_map;
- if (operation != READ)
- flags |= GNTMAP_readonly;
- gnttab_set_map_op(&map[i], vaddr(pending_req, i), flags,
- req->u.rw.seg[i].gref, blkif->domid);
}
- ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, nseg);
- BUG_ON(ret);
-
- /* Now swizzel the MFN in our domain with the MFN from the other domain
- * so that when we access vaddr(pending_req,i) it has the contents of
- * the page from the other domain.
- */
- for (i = 0; i < nseg; i++) {
- if (unlikely(map[i].status != 0)) {
- DPRINTK("invalid buffer -- could not remap it\n");
- map[i].handle = BLKBACK_INVALID_HANDLE;
- ret |= 1;
- }
-
- pending_handle(pending_req, i) = map[i].handle;
-
- if (ret)
- continue;
-
- ret = m2p_add_override(PFN_DOWN(map[i].dev_bus_addr),
- blkbk->pending_page(pending_req, i), false);
- if (ret) {
- printk(KERN_ALERT "Failed to install M2P override for"\
- " %lx (ret: %d)\n", (unsigned long)
- map[i].dev_bus_addr, ret);
- /* We could switch over to GNTTABOP_copy */
- continue;
- }
-
- seg[i].buf = map[i].dev_bus_addr |
- (req->u.rw.seg[i].first_sect << 9);
+ if (vbd_translate(&preq, blkif, operation) != 0) {
+ DPRINTK("access denied: %s of [%llu,%llu] on dev=%04x\n",
+ operation == READ ? "read" : "write",
+ preq.sector_number,
+ preq.sector_number + preq.nr_sects, preq.dev);
+ goto fail_response;
}
-
/* If we have failed at this point, we need to undo the M2P override,
* set gnttab_set_unmap_op on all of the grant references and perform
* the hypercall to unmap the grants - that is all done in
* fast_flush_area.
*/
- if (ret)
+ if (xen_blk_map_buf(req, pending_req, seg))
goto fail_flush;
- if (vbd_translate(&preq, blkif, operation) != 0) {
- DPRINTK("access denied: %s of [%llu,%llu] on dev=%04x\n",
- operation == READ ? "read" : "write",
- preq.sector_number,
- preq.sector_number + preq.nr_sects, preq.dev);
- goto fail_flush;
- }
-
/* This corresponding blkif_put is done in __end_block_io_op */
blkif_get(blkif);
OpenPOWER on IntegriCloud