diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2008-08-28 03:17:06 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2008-10-09 02:56:10 -0400 |
commit | 152e283fdfea0cd11e297d982378b55937842dde (patch) | |
tree | a97a57108353f167a1e2911e8ee09c527ef42d3e /block | |
parent | a3bce90edd8f6cafe3f63b1a943800792e830178 (diff) |
block: introduce struct rq_map_data to use reserved pages
This patch introduces struct rq_map_data to enable bio_copy_use_iov()
use reserved pages.
Currently, bio_copy_user_iov allocates bounce pages but
drivers/scsi/sg.c wants to allocate pages by itself and use
them. struct rq_map_data can be used to pass allocated pages to
bio_copy_user_iov.
The current users of bio_copy_user_iov simply passes NULL (they don't
want to use pre-allocated pages).
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Cc: Jens Axboe <jens.axboe@oracle.com>
Cc: Douglas Gilbert <dougg@torque.net>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block')
-rw-r--r-- | block/blk-map.c | 26 | ||||
-rw-r--r-- | block/bsg.c | 7 | ||||
-rw-r--r-- | block/scsi_ioctl.c | 4 |
3 files changed, 22 insertions, 15 deletions
diff --git a/block/blk-map.c b/block/blk-map.c index ac21b7397e15..dad6a2907835 100644 --- a/block/blk-map.c +++ b/block/blk-map.c | |||
@@ -41,8 +41,8 @@ static int __blk_rq_unmap_user(struct bio *bio) | |||
41 | } | 41 | } |
42 | 42 | ||
43 | static int __blk_rq_map_user(struct request_queue *q, struct request *rq, | 43 | static int __blk_rq_map_user(struct request_queue *q, struct request *rq, |
44 | void __user *ubuf, unsigned int len, | 44 | struct rq_map_data *map_data, void __user *ubuf, |
45 | gfp_t gfp_mask) | 45 | unsigned int len, gfp_t gfp_mask) |
46 | { | 46 | { |
47 | unsigned long uaddr; | 47 | unsigned long uaddr; |
48 | unsigned int alignment; | 48 | unsigned int alignment; |
@@ -57,10 +57,10 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq, | |||
57 | */ | 57 | */ |
58 | uaddr = (unsigned long) ubuf; | 58 | uaddr = (unsigned long) ubuf; |
59 | alignment = queue_dma_alignment(q) | q->dma_pad_mask; | 59 | alignment = queue_dma_alignment(q) | q->dma_pad_mask; |
60 | if (!(uaddr & alignment) && !(len & alignment)) | 60 | if (!(uaddr & alignment) && !(len & alignment) && !map_data) |
61 | bio = bio_map_user(q, NULL, uaddr, len, reading, gfp_mask); | 61 | bio = bio_map_user(q, NULL, uaddr, len, reading, gfp_mask); |
62 | else | 62 | else |
63 | bio = bio_copy_user(q, uaddr, len, reading, gfp_mask); | 63 | bio = bio_copy_user(q, map_data, uaddr, len, reading, gfp_mask); |
64 | 64 | ||
65 | if (IS_ERR(bio)) | 65 | if (IS_ERR(bio)) |
66 | return PTR_ERR(bio); | 66 | return PTR_ERR(bio); |
@@ -89,6 +89,7 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq, | |||
89 | * blk_rq_map_user - map user data to a request, for REQ_TYPE_BLOCK_PC usage | 89 | * blk_rq_map_user - map user data to a request, for REQ_TYPE_BLOCK_PC usage |
90 | * @q: request queue where request should be inserted | 90 | * @q: request queue where request should be inserted |
91 | * @rq: request structure to fill | 91 | * @rq: request structure to fill |
92 | * @map_data: pointer to the rq_map_data holding pages (if necessary) | ||
92 | * @ubuf: the user buffer | 93 | * @ubuf: the user buffer |
93 | * @len: length of user data | 94 | * @len: length of user data |
94 | * @gfp_mask: memory allocation flags | 95 | * @gfp_mask: memory allocation flags |
@@ -107,7 +108,8 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq, | |||
107 | * unmapping. | 108 | * unmapping. |
108 | */ | 109 | */ |
109 | int blk_rq_map_user(struct request_queue *q, struct request *rq, | 110 | int blk_rq_map_user(struct request_queue *q, struct request *rq, |
110 | void __user *ubuf, unsigned long len, gfp_t gfp_mask) | 111 | struct rq_map_data *map_data, void __user *ubuf, |
112 | unsigned long len, gfp_t gfp_mask) | ||
111 | { | 113 | { |
112 | unsigned long bytes_read = 0; | 114 | unsigned long bytes_read = 0; |
113 | struct bio *bio = NULL; | 115 | struct bio *bio = NULL; |
@@ -134,7 +136,8 @@ int blk_rq_map_user(struct request_queue *q, struct request *rq, | |||
134 | if (end - start > BIO_MAX_PAGES) | 136 | if (end - start > BIO_MAX_PAGES) |
135 | map_len -= PAGE_SIZE; | 137 | map_len -= PAGE_SIZE; |
136 | 138 | ||
137 | ret = __blk_rq_map_user(q, rq, ubuf, map_len, gfp_mask); | 139 | ret = __blk_rq_map_user(q, rq, map_data, ubuf, map_len, |
140 | gfp_mask); | ||
138 | if (ret < 0) | 141 | if (ret < 0) |
139 | goto unmap_rq; | 142 | goto unmap_rq; |
140 | if (!bio) | 143 | if (!bio) |
@@ -159,6 +162,7 @@ EXPORT_SYMBOL(blk_rq_map_user); | |||
159 | * blk_rq_map_user_iov - map user data to a request, for REQ_TYPE_BLOCK_PC usage | 162 | * blk_rq_map_user_iov - map user data to a request, for REQ_TYPE_BLOCK_PC usage |
160 | * @q: request queue where request should be inserted | 163 | * @q: request queue where request should be inserted |
161 | * @rq: request to map data to | 164 | * @rq: request to map data to |
165 | * @map_data: pointer to the rq_map_data holding pages (if necessary) | ||
162 | * @iov: pointer to the iovec | 166 | * @iov: pointer to the iovec |
163 | * @iov_count: number of elements in the iovec | 167 | * @iov_count: number of elements in the iovec |
164 | * @len: I/O byte count | 168 | * @len: I/O byte count |
@@ -178,8 +182,8 @@ EXPORT_SYMBOL(blk_rq_map_user); | |||
178 | * unmapping. | 182 | * unmapping. |
179 | */ | 183 | */ |
180 | int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, | 184 | int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, |
181 | struct sg_iovec *iov, int iov_count, unsigned int len, | 185 | struct rq_map_data *map_data, struct sg_iovec *iov, |
182 | gfp_t gfp_mask) | 186 | int iov_count, unsigned int len, gfp_t gfp_mask) |
183 | { | 187 | { |
184 | struct bio *bio; | 188 | struct bio *bio; |
185 | int i, read = rq_data_dir(rq) == READ; | 189 | int i, read = rq_data_dir(rq) == READ; |
@@ -197,8 +201,9 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, | |||
197 | } | 201 | } |
198 | } | 202 | } |
199 | 203 | ||
200 | if (unaligned || (q->dma_pad_mask & len)) | 204 | if (unaligned || (q->dma_pad_mask & len) || map_data) |
201 | bio = bio_copy_user_iov(q, iov, iov_count, read, gfp_mask); | 205 | bio = bio_copy_user_iov(q, map_data, iov, iov_count, read, |
206 | gfp_mask); | ||
202 | else | 207 | else |
203 | bio = bio_map_user_iov(q, NULL, iov, iov_count, read, gfp_mask); | 208 | bio = bio_map_user_iov(q, NULL, iov, iov_count, read, gfp_mask); |
204 | 209 | ||
@@ -220,6 +225,7 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, | |||
220 | rq->buffer = rq->data = NULL; | 225 | rq->buffer = rq->data = NULL; |
221 | return 0; | 226 | return 0; |
222 | } | 227 | } |
228 | EXPORT_SYMBOL(blk_rq_map_user_iov); | ||
223 | 229 | ||
224 | /** | 230 | /** |
225 | * blk_rq_unmap_user - unmap a request with user data | 231 | * blk_rq_unmap_user - unmap a request with user data |
diff --git a/block/bsg.c b/block/bsg.c index e7a142e9916c..56cb343c76d8 100644 --- a/block/bsg.c +++ b/block/bsg.c | |||
@@ -283,8 +283,8 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, int has_write_perm) | |||
283 | next_rq->cmd_type = rq->cmd_type; | 283 | next_rq->cmd_type = rq->cmd_type; |
284 | 284 | ||
285 | dxferp = (void*)(unsigned long)hdr->din_xferp; | 285 | dxferp = (void*)(unsigned long)hdr->din_xferp; |
286 | ret = blk_rq_map_user(q, next_rq, dxferp, hdr->din_xfer_len, | 286 | ret = blk_rq_map_user(q, next_rq, NULL, dxferp, |
287 | GFP_KERNEL); | 287 | hdr->din_xfer_len, GFP_KERNEL); |
288 | if (ret) | 288 | if (ret) |
289 | goto out; | 289 | goto out; |
290 | } | 290 | } |
@@ -299,7 +299,8 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, int has_write_perm) | |||
299 | dxfer_len = 0; | 299 | dxfer_len = 0; |
300 | 300 | ||
301 | if (dxfer_len) { | 301 | if (dxfer_len) { |
302 | ret = blk_rq_map_user(q, rq, dxferp, dxfer_len, GFP_KERNEL); | 302 | ret = blk_rq_map_user(q, rq, NULL, dxferp, dxfer_len, |
303 | GFP_KERNEL); | ||
303 | if (ret) | 304 | if (ret) |
304 | goto out; | 305 | goto out; |
305 | } | 306 | } |
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index f49d6a11a69e..c34272a348fe 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c | |||
@@ -314,11 +314,11 @@ static int sg_io(struct file *file, struct request_queue *q, | |||
314 | goto out; | 314 | goto out; |
315 | } | 315 | } |
316 | 316 | ||
317 | ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count, | 317 | ret = blk_rq_map_user_iov(q, rq, NULL, iov, hdr->iovec_count, |
318 | hdr->dxfer_len, GFP_KERNEL); | 318 | hdr->dxfer_len, GFP_KERNEL); |
319 | kfree(iov); | 319 | kfree(iov); |
320 | } else if (hdr->dxfer_len) | 320 | } else if (hdr->dxfer_len) |
321 | ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len, | 321 | ret = blk_rq_map_user(q, rq, NULL, hdr->dxferp, hdr->dxfer_len, |
322 | GFP_KERNEL); | 322 | GFP_KERNEL); |
323 | 323 | ||
324 | if (ret) | 324 | if (ret) |