diff options
Diffstat (limited to 'block/blk-map.c')
-rw-r--r-- | block/blk-map.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/block/blk-map.c b/block/blk-map.c index 955d75c1a58f..09f7fd0bcb73 100644 --- a/block/blk-map.c +++ b/block/blk-map.c | |||
@@ -19,6 +19,7 @@ int blk_rq_append_bio(struct request_queue *q, struct request *rq, | |||
19 | rq->biotail->bi_next = bio; | 19 | rq->biotail->bi_next = bio; |
20 | rq->biotail = bio; | 20 | rq->biotail = bio; |
21 | 21 | ||
22 | rq->raw_data_len += bio->bi_size; | ||
22 | rq->data_len += bio->bi_size; | 23 | rq->data_len += bio->bi_size; |
23 | } | 24 | } |
24 | return 0; | 25 | return 0; |
@@ -139,10 +140,29 @@ int blk_rq_map_user(struct request_queue *q, struct request *rq, | |||
139 | ubuf += ret; | 140 | ubuf += ret; |
140 | } | 141 | } |
141 | 142 | ||
143 | /* | ||
144 | * __blk_rq_map_user() copies the buffers if starting address | ||
145 | * or length isn't aligned. As the copied buffer is always | ||
146 | * page aligned, we know that there's enough room for padding. | ||
147 | * Extend the last bio and update rq->data_len accordingly. | ||
148 | * | ||
149 | * On unmap, bio_uncopy_user() will use unmodified | ||
150 | * bio_map_data pointed to by bio->bi_private. | ||
151 | */ | ||
152 | if (len & queue_dma_alignment(q)) { | ||
153 | unsigned int pad_len = (queue_dma_alignment(q) & ~len) + 1; | ||
154 | struct bio *bio = rq->biotail; | ||
155 | |||
156 | bio->bi_io_vec[bio->bi_vcnt - 1].bv_len += pad_len; | ||
157 | bio->bi_size += pad_len; | ||
158 | rq->data_len += pad_len; | ||
159 | } | ||
160 | |||
142 | rq->buffer = rq->data = NULL; | 161 | rq->buffer = rq->data = NULL; |
143 | return 0; | 162 | return 0; |
144 | unmap_rq: | 163 | unmap_rq: |
145 | blk_rq_unmap_user(bio); | 164 | blk_rq_unmap_user(bio); |
165 | rq->bio = NULL; | ||
146 | return ret; | 166 | return ret; |
147 | } | 167 | } |
148 | EXPORT_SYMBOL(blk_rq_map_user); | 168 | EXPORT_SYMBOL(blk_rq_map_user); |