[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [RFC v1 3/5] VBD: enlarge max segment per request in blkfront



 

refactoring balback

Signed-off-by: Ronghui Duan <ronghui.duan@xxxxxxxxx>

 

diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c

index 73f196c..b4767f5 100644

--- a/drivers/block/xen-blkback/blkback.c

+++ b/drivers/block/xen-blkback/blkback.c

@@ -64,6 +64,11 @@ MODULE_PARM_DESC(reqs, "Number of blkback requests to allocate");

static unsigned int log_stats;

module_param(log_stats, int, 0644);

+struct seg_buf {

+        unsigned long buf;

+        unsigned int nsec;

+};

+

/*

  * Each outstanding request that we've passed to the lower device layers has a

  * 'pending_req' allocated to it. Each buffer_head that completes decrements

@@ -78,6 +83,11 @@ struct pending_req {

    unsigned short       operation;

    int             status;

    struct list_head     free_list;

+    struct gnttab_map_grant_ref     *map;

+    struct gnttab_unmap_grant_ref   *unmap;

+    struct seg_buf             *seg;

+    struct bio           **biolist;

+    struct page                **pages;

};

 #define BLKBACK_INVALID_HANDLE (~0)

@@ -123,28 +133,9 @@ static inline unsigned long vaddr(struct pending_req *req, int seg)

 static int do_block_io_op(struct xen_blkif *blkif);

static int dispatch_rw_block_io(struct xen_blkif *blkif,

-                    struct blkif_request *req,

                    struct pending_req *pending_req);

static void make_response(struct xen_blkif *blkif, u64 id,

-                 unsigned short op, int st);

-

-/*

- * Retrieve from the 'pending_reqs' a free pending_req structure to be used.

- */

-static struct pending_req *alloc_req(void)

-{

-    struct pending_req *req = NULL;

-    unsigned long flags;

-

-    spin_lock_irqsave(&blkbk->pending_free_lock, flags);

-    if (!list_empty(&blkbk->pending_free)) {

-          req = list_entry(blkbk->pending_free.next, struct pending_req,

-                    free_list);

-          list_del(&req->free_list);

-    }

-    spin_unlock_irqrestore(&blkbk->pending_free_lock, flags);

-    return req;

-}

+                 unsigned short op, int nr_page, int st);

 /*

  * Return the 'pending_req' structure back to the freepool. We also

@@ -155,6 +146,12 @@ static void free_req(struct pending_req *req)

    unsigned long flags;

    int was_empty;

+    kfree(req->map);

+    kfree(req->unmap);

+    kfree(req->biolist);

+    kfree(req->seg);

+    kfree(req->pages);

+

    spin_lock_irqsave(&blkbk->pending_free_lock, flags);

    was_empty = list_empty(&blkbk->pending_free);

    list_add(&req->free_list, &blkbk->pending_free);

@@ -162,7 +159,42 @@ static void free_req(struct pending_req *req)

    if (was_empty)

          wake_up(&blkbk->pending_free_wq);

}

-

+/*

+ * Retrieve from the 'pending_reqs' a free pending_req structure to be used.

+ */

+static struct pending_req *alloc_req(void)

+{

+    struct pending_req *req = NULL;

+    unsigned long flags;

+    unsigned int max_seg = BLKIF_MAX_SEGMENTS_PER_REQUEST;

+   

+    spin_lock_irqsave(&blkbk->pending_free_lock, flags);

+    if (!list_empty(&blkbk->pending_free)) {

+          req = list_entry(blkbk->pending_free.next, struct pending_req,

+                    free_list);

+          list_del(&req->free_list);

+    }

+    spin_unlock_irqrestore(&blkbk->pending_free_lock, flags);

+   

+    if (req != NULL) {

+          req->map = kzalloc(sizeof(struct gnttab_map_grant_ref) *

+                       max_seg, GFP_KERNEL);

+          req->unmap = kzalloc(sizeof(struct gnttab_unmap_grant_ref) *

+                       max_seg, GFP_KERNEL);

+          req->biolist = kzalloc(sizeof(struct bio *) * max_seg,

+                           GFP_KERNEL);

+          req->seg = kzalloc(sizeof(struct seg_buf) * max_seg,

+                       GFP_KERNEL);

+          req->pages = kzalloc(sizeof(struct page *) * max_seg,

+                       GFP_KERNEL);

+          if (!req->map || !req->unmap || !req->biolist ||

+              !req->seg || !req->pages) {

+               free_req(req);

+               req = NULL;

+          }

+    }

+    return req;

+}

/*

  * Routines for managing virtual block devices (vbds).

  */

@@ -308,11 +340,6 @@ int xen_blkif_schedule(void *arg)

    xen_blkif_put(blkif);

     return 0;

-}

-

-struct seg_buf {

-    unsigned long buf;

-    unsigned int nsec;

};

/*

  * Unmap the grant references, and also remove the M2P over-rides

@@ -320,8 +347,8 @@ struct seg_buf {

  */

static void xen_blkbk_unmap(struct pending_req *req)

{

-    struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];

-    struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];

+    struct gnttab_unmap_grant_ref *unmap = req->unmap;

+    struct page **pages = req->pages;

    unsigned int i, invcount = 0;

    grant_handle_t handle;

    int ret;

@@ -341,11 +368,13 @@ static void xen_blkbk_unmap(struct pending_req *req)

    BUG_ON(ret);

}

+

static int xen_blkbk_map(struct blkif_request *req,

+               struct blkif_request_segment *seg_req,

                struct pending_req *pending_req,

                struct seg_buf seg[])

{

-    struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST];

+    struct gnttab_map_grant_ref *map = pending_req->map;

    int i;

    int nseg = req->u.rw.nr_segments;

    int ret = 0;

@@ -362,7 +391,7 @@ static int xen_blkbk_map(struct blkif_request *req,

          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,

+                      seg_req[i].gref,

                      pending_req->blkif->domid);

    }

@@ -387,14 +416,15 @@ static int xen_blkbk_map(struct blkif_request *req,

               continue;

           seg[i].buf  = map[i].dev_bus_addr |

-               (req->u.rw.seg[i].first_sect << 9);

+               (seg_req[i].first_sect << 9);

    }

    return ret;

}

-static int dispatch_discard_io(struct xen_blkif *blkif,

-                    struct blkif_request *req)

+static int dispatch_discard_io(struct xen_blkif *blkif)

{

+    struct blkif_request *blkif_req = (struct blkif_request *)blkif->req;

+    struct blkif_request_discard *req = &blkif_req->u.discard;

    int err = 0;

    int status = BLKIF_RSP_OKAY;

    struct block_device *bdev = blkif->vbd.bdev;

@@ -404,11 +434,11 @@ static int dispatch_discard_io(struct xen_blkif *blkif,

     xen_blkif_get(blkif);

    secure = (blkif->vbd.discard_secure &&

-          (req->u.discard.flag & BLKIF_DISCARD_SECURE)) ?

+          (req->flag & BLKIF_DISCARD_SECURE)) ?

           BLKDEV_DISCARD_SECURE : 0;

-    err = blkdev_issue_discard(bdev, req->u.discard.sector_number,

-                       req->u.discard.nr_sectors,

+    err = blkdev_issue_discard(bdev, req->sector_number,

+                       req->nr_sectors,

                       GFP_KERNEL, secure);

     if (err == -EOPNOTSUPP) {

@@ -417,7 +447,7 @@ static int dispatch_discard_io(struct xen_blkif *blkif,

    } else if (err)

          status = BLKIF_RSP_ERROR;

-    make_response(blkif, req->u.discard.id, req->operation, status);

+    make_response(blkif, req->id, BLKIF_OP_DISCARD, 0, status);

    xen_blkif_put(blkif);

    return err;

}

@@ -470,7 +500,8 @@ static void __end_block_io_op(struct pending_req *pending_req, int error)

    if (atomic_dec_and_test(&pending_req->pendcnt)) {

          xen_blkbk_unmap(pending_req);

          make_response(pending_req->blkif, pending_req->id,

-                     pending_req->operation, pending_req->status);

+                     pending_req->operation, pending_req->nr_pages,

+                     pending_req->status);

          xen_blkif_put(pending_req->blkif);

          if (atomic_read(&pending_req->blkif->refcnt) <= 2) {

               if (atomic_read(&pending_req->blkif->drain))

@@ -489,8 +520,37 @@ static void end_block_io_op(struct bio *bio, int error)

    bio_put(bio);

}

+void *get_back_ring(struct xen_blkif *blkif)

+{

+    return (void *)&blkif->blk_rings;

+}

+void copy_blkif_req(struct xen_blkif *blkif, RING_IDX rc)

+{

+    struct blkif_request *req = (struct blkif_request *)blkif->req;

+    union blkif_back_rings *blk_rings = &blkif->blk_rings;

+    switch (blkif->blk_protocol) {

+    case BLKIF_PROTOCOL_NATIVE:

+          memcpy(req, RING_GET_REQUEST(&blk_rings->native, rc),

+               sizeof(struct blkif_request));

+          break;

+    case BLKIF_PROTOCOL_X86_32:

+          blkif_get_x86_32_req(req, RING_GET_REQUEST(&blk_rings->x86_32, rc));

+          break;

+    case BLKIF_PROTOCOL_X86_64:

+          blkif_get_x86_64_req(req, RING_GET_REQUEST(&blk_rings->x86_64, rc));

+          break;

+    default:

+          BUG();

+    }

+}

+

+void copy_blkif_seg_req(struct xen_blkif *blkif)

+{

+    struct blkif_request *req = (struct blkif_request *)blkif->req;

+    blkif->seg_req = req->u.rw.seg;

+}

/*

  * Function to copy the from the ring buffer the 'struct blkif_request'

  * (which has the sectors we want, number of them, grant references, etc),

@@ -499,8 +559,9 @@ static void end_block_io_op(struct bio *bio, int error)

static int

__do_block_io_op(struct xen_blkif *blkif)

{

-    union blkif_back_rings *blk_rings = &blkif->blk_rings;

-    struct blkif_request req;

+    union blkif_back_rings *blk_rings =

+          (union blkif_back_rings *)blkif->ops->get_back_ring(blkif);

+    struct blkif_request *req = (struct blkif_request *)blkif->req;

    struct pending_req *pending_req;

    RING_IDX rc, rp;

    int more_to_do = 0;

@@ -526,28 +587,19 @@ __do_block_io_op(struct xen_blkif *blkif)

               break;

          }

-          switch (blkif->blk_protocol) {

-          case BLKIF_PROTOCOL_NATIVE:

-              memcpy(&req, RING_GET_REQUEST(&blk_rings->native, rc), sizeof(req));

-               break;

-          case BLKIF_PROTOCOL_X86_32:

-               blkif_get_x86_32_req(&req, RING_GET_REQUEST(&blk_rings->x86_32, rc));

-               break;

-          case BLKIF_PROTOCOL_X86_64:

-               blkif_get_x86_64_req(&req, RING_GET_REQUEST(&blk_rings->x86_64, rc));

-               break;

-          default:

-               BUG();

-          }

+          blkif->ops->copy_blkif_req(blkif, rc);

+

+          blkif->ops->copy_blkif_seg_req(blkif);

+

          blk_rings->common.req_cons = ++rc; /* before make_response() */

           /* Apply all sanity checks to /private copy/ of request. */

          barrier();

-          if (unlikely(req.operation == BLKIF_OP_DISCARD)) {

+          if (unlikely(req->operation == BLKIF_OP_DISCARD)) {

               free_req(pending_req);

-               if (dispatch_discard_io(blkif, &req))

+               if (dispatch_discard_io(blkif))

                    break;

-          } else if (dispatch_rw_block_io(blkif, &req, pending_req))

+          } else if (dispatch_rw_block_io(blkif, pending_req))

               break;

           /* Yield point for this unbounded loop. */

@@ -560,7 +612,8 @@ __do_block_io_op(struct xen_blkif *blkif)

static int

do_block_io_op(struct xen_blkif *blkif)

{

-    union blkif_back_rings *blk_rings = &blkif->blk_rings;

+    union blkif_back_rings *blk_rings =

+          (union blkif_back_rings *)blkif->ops->get_back_ring(blkif);

    int more_to_do;

     do {

@@ -578,14 +631,15 @@ do_block_io_op(struct xen_blkif *blkif)

  * and call the 'submit_bio' to pass it to the underlying storage.

  */

static int dispatch_rw_block_io(struct xen_blkif *blkif,

-                    struct blkif_request *req,

                    struct pending_req *pending_req)

{

+    struct blkif_request *req = (struct blkif_request *)blkif->req;

+    struct blkif_request_segment *seg_req = blkif->seg_req;

    struct phys_req preq;

-    struct seg_buf seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];

+    struct seg_buf *seg = pending_req->seg;

    unsigned int nseg;

    struct bio *bio = NULL;

-    struct bio *biolist[BLKIF_MAX_SEGMENTS_PER_REQUEST];

+    struct bio **biolist = pending_req->biolist;

    int i, nbio = 0;

    int operation;

    struct blk_plug plug;

@@ -616,7 +670,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,

    nseg = req->u.rw.nr_segments;

     if (unlikely(nseg == 0 && operation != WRITE_FLUSH) ||

-        unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) {

+        unlikely(nseg > blkif->ops->max_seg)) {

          pr_debug(DRV_PFX "Bad number of segments in request (%d)\n",

                nseg);

          /* Haven't submitted any bio's yet. */

@@ -634,10 +688,10 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,

    pending_req->nr_pages  = nseg;

     for (i = 0; i < nseg; i++) {

-          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))

+          seg[i].nsec = seg_req[i].last_sect -

+               seg_req[i].first_sect + 1;

+          if ((seg_req[i].last_sect >= (PAGE_SIZE >> 9)) ||

+              (seg_req[i].last_sect < seg_req[i].first_sect))

               goto fail_response;

          preq.nr_sects += seg[i].nsec;

@@ -676,7 +730,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,

     * the hypercall to unmap the grants - that is all done in

     * xen_blkbk_unmap.

     */

-    if (xen_blkbk_map(req, pending_req, seg))

+    if (xen_blkbk_map(req, seg_req, pending_req, seg))

          goto fail_flush;

     /*

@@ -746,7 +800,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,

    xen_blkbk_unmap(pending_req);

  fail_response:

    /* Haven't submitted any bio's yet. */

-    make_response(blkif, req->u.rw.id, req->operation, BLKIF_RSP_ERROR);

+    make_response(blkif, req->u.rw.id, req->operation, 0, BLKIF_RSP_ERROR);

    free_req(pending_req);

    msleep(1); /* back off a bit */

    return -EIO;

@@ -759,17 +813,28 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,

    return -EIO;

}

+struct blkif_segment_back_ring *

+    get_seg_back_ring(struct xen_blkif *blkif)

+{

+    return NULL;

+}

+void push_back_ring_rsp(union blkif_back_rings *blk_rings, int nr_page, int *notify)

+{

+    blk_rings->common.rsp_prod_pvt++;

+    RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blk_rings->common, *notify);

+}

 /*

  * Put a response on the ring on how the operation fared.

  */

static void make_response(struct xen_blkif *blkif, u64 id,

-                 unsigned short op, int st)

+                 unsigned short op, int nr_page, int st)

{

    struct blkif_response  resp;

    unsigned long     flags;

-    union blkif_back_rings *blk_rings = &blkif->blk_rings;

+    union blkif_back_rings *blk_rings =

+          (union blkif_back_rings *)blkif->ops->get_back_ring(blkif);

    int notify;

     resp.id        = id;

@@ -794,8 +859,9 @@ static void make_response(struct xen_blkif *blkif, u64 id,

    default:

          BUG();

    }

-    blk_rings->common.rsp_prod_pvt++;

-    RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blk_rings->common, notify);

+

+    blkif->ops->push_back_ring_rsp(blk_rings, nr_page, &notify);

+

    spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);

    if (notify)

          notify_remote_via_irq(blkif->irq);

@@ -873,6 +939,14 @@ static int __init xen_blkif_init(void)

    return rc;

}

+struct blkback_ring_operation blkback_ring_ops = {

+    .get_back_ring = get_back_ring,

+    .copy_blkif_req = copy_blkif_req,

+    .copy_blkif_seg_req = copy_blkif_seg_req,

+    .push_back_ring_rsp = push_back_ring_rsp,

+    .max_seg = BLKIF_MAX_SEGMENTS_PER_REQUEST,

+};

+

module_init(xen_blkif_init);

 MODULE_LICENSE("Dual BSD/GPL");

diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h

index 9ad3b5e..ce5556a 100644

--- a/drivers/block/xen-blkback/common.h

+++ b/drivers/block/xen-blkback/common.h

@@ -146,6 +146,11 @@ enum blkif_protocol {

    BLKIF_PROTOCOL_X86_64 = 3,

};

+enum blkif_backring_type {

+    BACKRING_TYPE_1 = 1,

+    BACKRING_TYPE_2 = 2,

+};

+

struct xen_vbd {

    /* What the domain refers to this vbd as. */

    blkif_vdev_t         handle;

@@ -163,6 +168,15 @@ struct xen_vbd {

};

 struct backend_info;

+struct xen_blkif;

+

+struct blkback_ring_operation {

+    void *(*get_back_ring) (struct xen_blkif *blkif);

+    void (*copy_blkif_req) (struct xen_blkif *blkif, RING_IDX rc);

+    void (*copy_blkif_seg_req) (struct xen_blkif *blkif);

+    void (*push_back_ring_rsp) (union blkif_back_rings *blk_rings, int nr_page, int *notify);

+    unsigned int max_seg;

+};

 struct xen_blkif {

    /* Unique identifier for this interface. */

@@ -171,7 +185,9 @@ struct xen_blkif {

    /* Physical parameters of the comms window. */

    unsigned int         irq;

    /* Comms information. */

+    struct blkback_ring_operation   *ops;

    enum blkif_protocol  blk_protocol;

+    enum blkif_backring_type blk_backring_type;

    union blkif_back_rings     blk_rings;

    void            *blk_ring;

    /* The VBD attached to this interface. */

@@ -179,6 +195,8 @@ struct xen_blkif {

    /* Back pointer to the backend_info. */

    struct backend_info  *be;

    /* Private fields. */

+    void *               req;

+    struct blkif_request_segment *seg_req;

    spinlock_t      blk_ring_lock;

    atomic_t        refcnt;

diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c

index 4f66171..850ecad 100644

--- a/drivers/block/xen-blkback/xenbus.c

+++ b/drivers/block/xen-blkback/xenbus.c

@@ -36,6 +36,8 @@ static int connect_ring(struct backend_info *);

static void backend_changed(struct xenbus_watch *, const char **,

                   unsigned int);

+extern struct blkback_ring_operation blkback_ring_ops;

+

struct xenbus_device *xen_blkbk_xenbus(struct backend_info *be)

{

    return be->dev;

@@ -725,6 +727,12 @@ static int connect_ring(struct backend_info *be)

    int err;

     DPRINTK("%s", dev->otherend);

+    be->blkif->ops = &blkback_ring_ops;

+    be->blkif->req = kmalloc(sizeof(struct blkif_request),

+                    GFP_KERNEL);

+    be->blkif->seg_req = kmalloc(sizeof(struct blkif_request_segment)*

+                         be->blkif->ops->max_seg,  GFP_KERNEL);

+    be->blkif->blk_backring_type = BACKRING_TYPE_1;

     err = xenbus_gather(XBT_NIL, dev->otherend, "ring-ref", "%lu",

                   &ring_ref, "event-channel", "%u", &evtchn, NULL);

 

 

-ronghui

 

Attachment: vbd_enlarge_segments_03.patch
Description: vbd_enlarge_segments_03.patch

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

 


Rackspace

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