[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [linux-2.6.18-xen] Fixes to block backend to handle -EAGAIN grant table errors properly.
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1261031870 0 # Node ID df70d482d0f43fbd6f5e55a006350e93e26ed9a5 # Parent 981db8d78913016a0dbfa041e106b3404b5f5791 Fixes to block backend to handle -EAGAIN grant table errors properly. Signed-off-by: Grzegorz Milos <Grzegorz.Milos@xxxxxxxxxx> --- drivers/xen/blkback/blkback.c | 53 ++++++++++++++++++++++++++++++++-------- drivers/xen/blkback/common.h | 2 + drivers/xen/blkback/interface.c | 8 ++++-- 3 files changed, 51 insertions(+), 12 deletions(-) diff -r 981db8d78913 -r df70d482d0f4 drivers/xen/blkback/blkback.c --- a/drivers/xen/blkback/blkback.c Thu Dec 17 06:37:49 2009 +0000 +++ b/drivers/xen/blkback/blkback.c Thu Dec 17 06:37:50 2009 +0000 @@ -107,7 +107,7 @@ static inline unsigned long vaddr(pendin static int do_block_io_op(blkif_t *blkif); -static void dispatch_rw_block_io(blkif_t *blkif, +static int dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req, pending_req_t *pending_req); static void make_response(blkif_t *blkif, u64 id, @@ -309,13 +309,13 @@ static int do_block_io_op(blkif_t *blkif blkif_request_t req; pending_req_t *pending_req; RING_IDX rc, rp; - int more_to_do = 0; + int more_to_do = 0, ret; rc = blk_rings->common.req_cons; rp = blk_rings->common.sring->req_prod; rmb(); /* Ensure we see queued requests up to 'rp'. */ - while (rc != rp) { + while ((rc != rp) || (blkif->is_suspended_req)) { if (RING_REQUEST_CONS_OVERFLOW(&blk_rings->common, rc)) break; @@ -332,6 +332,14 @@ static int do_block_io_op(blkif_t *blkif break; } + /* Handle the suspended request first, if one exists */ + if(blkif->is_suspended_req) + { + memcpy(&req, &blkif->suspended_req, sizeof(req)); + blkif->is_suspended_req = 0; + goto handle_request; + } + switch (blkif->blk_protocol) { case BLKIF_PROTOCOL_NATIVE: memcpy(&req, RING_GET_REQUEST(&blk_rings->native, rc), sizeof(req)); @@ -350,17 +358,19 @@ static int do_block_io_op(blkif_t *blkif /* Apply all sanity checks to /private copy/ of request. */ barrier(); +handle_request: + ret = 0; switch (req.operation) { case BLKIF_OP_READ: blkif->st_rd_req++; - dispatch_rw_block_io(blkif, &req, pending_req); + ret = dispatch_rw_block_io(blkif, &req, pending_req); break; case BLKIF_OP_WRITE_BARRIER: blkif->st_br_req++; /* fall through */ case BLKIF_OP_WRITE: blkif->st_wr_req++; - dispatch_rw_block_io(blkif, &req, pending_req); + ret = dispatch_rw_block_io(blkif, &req, pending_req); break; default: /* A good sign something is wrong: sleep for a while to @@ -373,6 +383,17 @@ static int do_block_io_op(blkif_t *blkif free_req(pending_req); break; } + BUG_ON(ret != 0 && ret != -EAGAIN); + /* If we can't handle the request at the moment, save it, and break the + * loop */ + if(ret == -EAGAIN) + { + memcpy(&blkif->suspended_req, &req, sizeof(req)); + blkif->is_suspended_req = 1; + /* Return "no more work pending", restart will be handled 'out of + * band' */ + return 0; + } /* Yield point for this unbounded loop. */ cond_resched(); @@ -381,7 +402,7 @@ static int do_block_io_op(blkif_t *blkif return more_to_do; } -static void dispatch_rw_block_io(blkif_t *blkif, +static int dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req, pending_req_t *pending_req) { @@ -450,11 +471,15 @@ static void dispatch_rw_block_io(blkif_t ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, nseg); BUG_ON(ret); +#define GENERAL_ERR (1<<0) +#define EAGAIN_ERR (1<<1) 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; + ret |= GENERAL_ERR; + if(map[i].status == GNTST_eagain) + ret |= EAGAIN_ERR; } else { blkback_pagemap_set(vaddr_pagenr(pending_req, i), pending_page(pending_req, i), @@ -473,6 +498,14 @@ static void dispatch_rw_block_io(blkif_t seg[i].buf = map[i].dev_bus_addr | (req->seg[i].first_sect << 9); } + + /* If any of grant maps failed with GNTST_eagain, suspend and retry later */ + if(ret & EAGAIN_ERR) + { + fast_flush_area(pending_req); + free_req(pending_req); + return -EAGAIN; + } if (ret) goto fail_flush; @@ -539,7 +572,7 @@ static void dispatch_rw_block_io(blkif_t else if (operation == WRITE || operation == WRITE_BARRIER) blkif->st_wr_sect += preq.nr_sects; - return; + return 0; fail_flush: fast_flush_area(pending_req); @@ -547,7 +580,7 @@ static void dispatch_rw_block_io(blkif_t make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR); free_req(pending_req); msleep(1); /* back off a bit */ - return; + return 0; fail_put_bio: __end_block_io_op(pending_req, -EINVAL); @@ -555,7 +588,7 @@ static void dispatch_rw_block_io(blkif_t bio_put(bio); unplug_queue(blkif); msleep(1); /* back off a bit */ - return; + return 0; } diff -r 981db8d78913 -r df70d482d0f4 drivers/xen/blkback/common.h --- a/drivers/xen/blkback/common.h Thu Dec 17 06:37:49 2009 +0000 +++ b/drivers/xen/blkback/common.h Thu Dec 17 06:37:50 2009 +0000 @@ -82,6 +82,8 @@ typedef struct blkif_st { struct task_struct *xenblkd; unsigned int waiting_reqs; request_queue_t *plug; + int is_suspended_req; + blkif_request_t suspended_req; /* statistics */ unsigned long st_print; diff -r 981db8d78913 -r df70d482d0f4 drivers/xen/blkback/interface.c --- a/drivers/xen/blkback/interface.c Thu Dec 17 06:37:49 2009 +0000 +++ b/drivers/xen/blkback/interface.c Thu Dec 17 06:37:50 2009 +0000 @@ -33,6 +33,7 @@ #include "common.h" #include <xen/evtchn.h> #include <linux/kthread.h> +#include <linux/delay.h> static kmem_cache_t *blkif_cachep; @@ -62,8 +63,11 @@ static int map_frontend_page(blkif_t *bl gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr, GNTMAP_host_map, shared_page, blkif->domid); - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) - BUG(); + do { + if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) + BUG(); + msleep(100); + } while(op.status == GNTST_eagain); if (op.status) { DPRINTK(" Grant table operation failure !\n"); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |