lkml.org 
[lkml]   [2009]   [Mar]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch 073/114] xen/blkfront: use blk_rq_map_sg to generate ring entries
    2.6.28-stable review patch.  If anyone has any objections, please let us know.

    ------------------

    From: Jens Axboe <jens.axboe@oracle.com>

    commit 9e973e64ac6dc504e6447d52193d4fff1a670156 upstream.

    On occasion, the request will apparently have more segments than we
    fit into the ring. Jens says:

    > The second problem is that the block layer then appears to create one
    > too many segments, but from the dump it has rq->nr_phys_segments ==
    > BLKIF_MAX_SEGMENTS_PER_REQUEST. I suspect the latter is due to
    > xen-blkfront not handling the merging on its own. It should check that
    > the new page doesn't form part of the previous page. The
    > rq_for_each_segment() iterates all single bits in the request, not dma
    > segments. The "easiest" way to do this is to call blk_rq_map_sg() and
    > then iterate the mapped sg list. That will give you what you are
    > looking for.

    > Here's a test patch, compiles but otherwise untested. I spent more
    > time figuring out how to enable XEN than to code it up, so YMMV!
    > Probably the sg list wants to be put inside the ring and only
    > initialized on allocation, then you can get rid of the sg on stack and
    > sg_init_table() loop call in the function. I'll leave that, and the
    > testing, to you.

    [Moved sg array into info structure, and initialize once. -J]

    Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
    Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
    Cc: Sven Köhler <sven.koehler@gmail.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

    ---
    drivers/block/xen-blkfront.c | 30 +++++++++++++++---------------
    1 file changed, 15 insertions(+), 15 deletions(-)

    --- a/drivers/block/xen-blkfront.c
    +++ b/drivers/block/xen-blkfront.c
    @@ -40,6 +40,7 @@
    #include <linux/hdreg.h>
    #include <linux/cdrom.h>
    #include <linux/module.h>
    +#include <linux/scatterlist.h>

    #include <xen/xenbus.h>
    #include <xen/grant_table.h>
    @@ -82,6 +83,7 @@ struct blkfront_info
    enum blkif_state connected;
    int ring_ref;
    struct blkif_front_ring ring;
    + struct scatterlist sg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
    unsigned int evtchn, irq;
    struct request_queue *rq;
    struct work_struct work;
    @@ -204,12 +206,11 @@ static int blkif_queue_request(struct re
    struct blkfront_info *info = req->rq_disk->private_data;
    unsigned long buffer_mfn;
    struct blkif_request *ring_req;
    - struct req_iterator iter;
    - struct bio_vec *bvec;
    unsigned long id;
    unsigned int fsect, lsect;
    - int ref;
    + int i, ref;
    grant_ref_t gref_head;
    + struct scatterlist *sg;

    if (unlikely(info->connected != BLKIF_STATE_CONNECTED))
    return 1;
    @@ -238,12 +239,13 @@ static int blkif_queue_request(struct re
    if (blk_barrier_rq(req))
    ring_req->operation = BLKIF_OP_WRITE_BARRIER;

    - ring_req->nr_segments = 0;
    - rq_for_each_segment(bvec, req, iter) {
    - BUG_ON(ring_req->nr_segments == BLKIF_MAX_SEGMENTS_PER_REQUEST);
    - buffer_mfn = pfn_to_mfn(page_to_pfn(bvec->bv_page));
    - fsect = bvec->bv_offset >> 9;
    - lsect = fsect + (bvec->bv_len >> 9) - 1;
    + ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg);
    + BUG_ON(ring_req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST);
    +
    + for_each_sg(info->sg, sg, ring_req->nr_segments, i) {
    + buffer_mfn = pfn_to_mfn(page_to_pfn(sg_page(sg)));
    + fsect = sg->offset >> 9;
    + lsect = fsect + (sg->length >> 9) - 1;
    /* install a grant reference. */
    ref = gnttab_claim_grant_reference(&gref_head);
    BUG_ON(ref == -ENOSPC);
    @@ -254,16 +256,12 @@ static int blkif_queue_request(struct re
    buffer_mfn,
    rq_data_dir(req) );

    - info->shadow[id].frame[ring_req->nr_segments] =
    - mfn_to_pfn(buffer_mfn);
    -
    - ring_req->seg[ring_req->nr_segments] =
    + info->shadow[id].frame[i] = mfn_to_pfn(buffer_mfn);
    + ring_req->seg[i] =
    (struct blkif_request_segment) {
    .gref = ref,
    .first_sect = fsect,
    .last_sect = lsect };
    -
    - ring_req->nr_segments++;
    }

    info->ring.req_prod_pvt++;
    @@ -628,6 +626,8 @@ static int setup_blkring(struct xenbus_d
    SHARED_RING_INIT(sring);
    FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE);

    + sg_init_table(info->sg, BLKIF_MAX_SEGMENTS_PER_REQUEST);
    +
    err = xenbus_grant_ring(dev, virt_to_mfn(info->ring.sring));
    if (err < 0) {
    free_page((unsigned long)sring);

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2009-03-14 02:51    [W:4.365 / U:0.252 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site