diff options
author | Tejun Heo <htejun@gmail.com> | 2008-02-19 05:35:38 -0500 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2008-02-19 05:35:38 -0500 |
commit | 40b01b9bbdf51ae543a04744283bf2d56c4a6afa (patch) | |
tree | 0f81015c01834b97fdb5646a63c3fe1a24936d81 /block/blk-map.c | |
parent | 56c819df77f96c3fc0c2a979e12b478403728790 (diff) |
block: update bio according to DMA alignment padding
DMA start address and transfer size alignment for PC requests are
achieved using bio_copy_user() instead of bio_map_user(). This works
because bio_copy_user() always uses full pages and block DMA alignment
isn't allowed to go over PAGE_SIZE.
However, the implementation didn't update the last bio of the request
to make this padding visible to lower layers. This patch makes
blk_rq_map_user() extend the last bio such that it includes the
padding area and the size of area pointed to by the request is
properly aligned.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block/blk-map.c')
-rw-r--r-- | block/blk-map.c | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/block/blk-map.c b/block/blk-map.c index bc5ce60691c3..a7cf63ccb5cf 100644 --- a/block/blk-map.c +++ b/block/blk-map.c | |||
@@ -139,6 +139,23 @@ int blk_rq_map_user(struct request_queue *q, struct request *rq, | |||
139 | ubuf += ret; | 139 | ubuf += ret; |
140 | } | 140 | } |
141 | 141 | ||
142 | /* | ||
143 | * __blk_rq_map_user() copies the buffers if starting address | ||
144 | * or length isn't aligned. As the copied buffer is always | ||
145 | * page aligned, we know that there's enough room for padding. | ||
146 | * Extend the last bio and update rq->data_len accordingly. | ||
147 | * | ||
148 | * On unmap, bio_uncopy_user() will use unmodified | ||
149 | * bio_map_data pointed to by bio->bi_private. | ||
150 | */ | ||
151 | if (len & queue_dma_alignment(q)) { | ||
152 | unsigned int pad_len = (queue_dma_alignment(q) & ~len) + 1; | ||
153 | struct bio *bio = rq->biotail; | ||
154 | |||
155 | bio->bi_io_vec[bio->bi_vcnt - 1].bv_len += pad_len; | ||
156 | bio->bi_size += pad_len; | ||
157 | } | ||
158 | |||
142 | rq->buffer = rq->data = NULL; | 159 | rq->buffer = rq->data = NULL; |
143 | return 0; | 160 | return 0; |
144 | unmap_rq: | 161 | unmap_rq: |