]> err.no Git - linux-2.6/commitdiff
block: add request->raw_data_len
authorTejun Heo <htejun@gmail.com>
Tue, 19 Feb 2008 10:36:35 +0000 (11:36 +0100)
committerJens Axboe <jens.axboe@oracle.com>
Tue, 19 Feb 2008 10:36:35 +0000 (11:36 +0100)
With padding and draining moved into it, block layer now may extend
requests as directed by queue parameters, so now a request has two
sizes - the original request size and the extended size which matches
the size of area pointed to by bios and later by sgs.  The latter size
is what lower layers are primarily interested in when allocating,
filling up DMA tables and setting up the controller.

Both padding and draining extend the data area to accomodate
controller characteristics.  As any controller which speaks SCSI can
handle underflows, feeding larger data area is safe.

So, this patch makes the primary data length field, request->data_len,
indicate the size of full data area and add a separate length field,
request->raw_data_len, for the unmodified request size.  The latter is
used to report to higher layer (userland) and where the original
request size should be fed to the controller or device.

Signed-off-by: Tejun Heo <htejun@gmail.com>
Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
block/blk-core.c
block/blk-map.c
block/blk-merge.c
block/bsg.c
block/scsi_ioctl.c
drivers/scsi/scsi_lib.c
include/linux/blkdev.h

index c013ca22eb67359748aefc61910871ddecc68147..775c8516abf5fe5b083416e3be5f07e969ec6f93 100644 (file)
@@ -127,6 +127,7 @@ void rq_init(struct request_queue *q, struct request *rq)
        rq->nr_hw_segments = 0;
        rq->ioprio = 0;
        rq->special = NULL;
+       rq->raw_data_len = 0;
        rq->buffer = NULL;
        rq->tag = -1;
        rq->errors = 0;
@@ -2015,6 +2016,7 @@ void blk_rq_bio_prep(struct request_queue *q, struct request *rq,
        rq->hard_cur_sectors = rq->current_nr_sectors;
        rq->hard_nr_sectors = rq->nr_sectors = bio_sectors(bio);
        rq->buffer = bio_data(bio);
+       rq->raw_data_len = bio->bi_size;
        rq->data_len = bio->bi_size;
 
        rq->bio = rq->biotail = bio;
index a7cf63ccb5cfd19191e822c768a395567a77892a..09f7fd0bcb73000d4899f2b96dc088d852d41aab 100644 (file)
@@ -19,6 +19,7 @@ int blk_rq_append_bio(struct request_queue *q, struct request *rq,
                rq->biotail->bi_next = bio;
                rq->biotail = bio;
 
+               rq->raw_data_len += bio->bi_size;
                rq->data_len += bio->bi_size;
        }
        return 0;
@@ -154,6 +155,7 @@ int blk_rq_map_user(struct request_queue *q, struct request *rq,
 
                bio->bi_io_vec[bio->bi_vcnt - 1].bv_len += pad_len;
                bio->bi_size += pad_len;
+               rq->data_len += pad_len;
        }
 
        rq->buffer = rq->data = NULL;
index d3b84bbb776a5fd0b3ba3238c7de20e7df93eaeb..39f2e077a01469fe3f9c04443b285777964224b5 100644 (file)
@@ -228,6 +228,7 @@ new_segment:
                            ((unsigned long)q->dma_drain_buffer) &
                            (PAGE_SIZE - 1));
                nsegs++;
+               rq->data_len += q->dma_drain_size;
        }
 
        if (sg)
index 8917c5174dc2646c5ad8d4d67eb67529a98783f5..7f3c09549e4be7364be012d834450215bcd7096f 100644 (file)
@@ -437,14 +437,14 @@ static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr,
        }
 
        if (rq->next_rq) {
-               hdr->dout_resid = rq->data_len;
-               hdr->din_resid = rq->next_rq->data_len;
+               hdr->dout_resid = rq->raw_data_len;
+               hdr->din_resid = rq->next_rq->raw_data_len;
                blk_rq_unmap_user(bidi_bio);
                blk_put_request(rq->next_rq);
        } else if (rq_data_dir(rq) == READ)
-               hdr->din_resid = rq->data_len;
+               hdr->din_resid = rq->raw_data_len;
        else
-               hdr->dout_resid = rq->data_len;
+               hdr->dout_resid = rq->raw_data_len;
 
        /*
         * If the request generated a negative error number, return it
index 9675b34638d4824b566e9df643042239bbf04e05..e993cac4911dbc9f3d3c0249f3912285ea61e581 100644 (file)
@@ -266,7 +266,7 @@ static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
        hdr->info = 0;
        if (hdr->masked_status || hdr->host_status || hdr->driver_status)
                hdr->info |= SG_INFO_CHECK;
-       hdr->resid = rq->data_len;
+       hdr->resid = rq->raw_data_len;
        hdr->sb_len_wr = 0;
 
        if (rq->sense_len && hdr->sbp) {
@@ -528,6 +528,7 @@ static int __blk_send_generic(struct request_queue *q, struct gendisk *bd_disk,
        rq = blk_get_request(q, WRITE, __GFP_WAIT);
        rq->cmd_type = REQ_TYPE_BLOCK_PC;
        rq->data = NULL;
+       rq->raw_data_len = 0;
        rq->data_len = 0;
        rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
        memset(rq->cmd, 0, sizeof(rq->cmd));
index 135c1d0547015e3ce54edcf634f24d3f7247cefb..ba21d97d185577ac6fdd0a59bec760cb24cb5880 100644 (file)
@@ -1014,10 +1014,6 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb,
        }
 
        req->buffer = NULL;
-       if (blk_pc_request(req))
-               sdb->length = req->data_len;
-       else
-               sdb->length = req->nr_sectors << 9;
 
        /* 
         * Next, walk the list, and fill in the addresses and sizes of
@@ -1026,6 +1022,10 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb,
        count = blk_rq_map_sg(req->q, req, sdb->table.sgl);
        BUG_ON(count > sdb->table.nents);
        sdb->table.nents = count;
+       if (blk_pc_request(req))
+               sdb->length = req->data_len;
+       else
+               sdb->length = req->nr_sectors << 9;
        return BLKPREP_OK;
 }
 
index e1888cc5b8ae5d2aabfc806a9100489802422eb3..f1fe9fbf1c0e35b41377c947f015b48234152761 100644 (file)
@@ -216,6 +216,7 @@ struct request {
        unsigned int cmd_len;
        unsigned char cmd[BLK_MAX_CDB];
 
+       unsigned int raw_data_len;
        unsigned int data_len;
        unsigned int sense_len;
        void *data;