diff options
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: |