[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.