aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo2008-02-19 04:35:38 -0600
committerJens Axboe2008-02-19 04:35:38 -0600
commit40b01b9bbdf51ae543a04744283bf2d56c4a6afa (patch)
tree0f81015c01834b97fdb5646a63c3fe1a24936d81 /block/blk-map.c
parent56c819df77f96c3fc0c2a979e12b478403728790 (diff)
downloadkernel-common-40b01b9bbdf51ae543a04744283bf2d56c4a6afa.tar.gz
kernel-common-40b01b9bbdf51ae543a04744283bf2d56c4a6afa.tar.xz
kernel-common-40b01b9bbdf51ae543a04744283bf2d56c4a6afa.zip
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.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/block/blk-map.c b/block/blk-map.c
index bc5ce60691c..a7cf63ccb5c 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;
144unmap_rq: 161unmap_rq: