diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2006-12-01 04:40:55 -0500 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2006-12-01 04:40:55 -0500 |
commit | 0e75f9063f5c55fb0b0b546a7c356f8ec186825e (patch) | |
tree | db138f641175403546c2147def4b405f3ff453a8 /block/scsi_ioctl.c | |
parent | ad2d7225709b11da47e092634cbdf0591829ae9c (diff) |
[PATCH] block: support larger block pc requests
This patch modifies blk_rq_map/unmap_user() and the cdrom and scsi_ioctl.c
users so that it supports requests larger than bio by chaining them together.
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block/scsi_ioctl.c')
-rw-r--r-- | block/scsi_ioctl.c | 53 |
1 files changed, 26 insertions, 27 deletions
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index e55a75621437..5493c2fbbab1 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c | |||
@@ -226,7 +226,6 @@ static int sg_io(struct file *file, request_queue_t *q, | |||
226 | unsigned long start_time; | 226 | unsigned long start_time; |
227 | int writing = 0, ret = 0; | 227 | int writing = 0, ret = 0; |
228 | struct request *rq; | 228 | struct request *rq; |
229 | struct bio *bio; | ||
230 | char sense[SCSI_SENSE_BUFFERSIZE]; | 229 | char sense[SCSI_SENSE_BUFFERSIZE]; |
231 | unsigned char cmd[BLK_MAX_CDB]; | 230 | unsigned char cmd[BLK_MAX_CDB]; |
232 | 231 | ||
@@ -258,30 +257,6 @@ static int sg_io(struct file *file, request_queue_t *q, | |||
258 | if (!rq) | 257 | if (!rq) |
259 | return -ENOMEM; | 258 | return -ENOMEM; |
260 | 259 | ||
261 | if (hdr->iovec_count) { | ||
262 | const int size = sizeof(struct sg_iovec) * hdr->iovec_count; | ||
263 | struct sg_iovec *iov; | ||
264 | |||
265 | iov = kmalloc(size, GFP_KERNEL); | ||
266 | if (!iov) { | ||
267 | ret = -ENOMEM; | ||
268 | goto out; | ||
269 | } | ||
270 | |||
271 | if (copy_from_user(iov, hdr->dxferp, size)) { | ||
272 | kfree(iov); | ||
273 | ret = -EFAULT; | ||
274 | goto out; | ||
275 | } | ||
276 | |||
277 | ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count); | ||
278 | kfree(iov); | ||
279 | } else if (hdr->dxfer_len) | ||
280 | ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len); | ||
281 | |||
282 | if (ret) | ||
283 | goto out; | ||
284 | |||
285 | /* | 260 | /* |
286 | * fill in request structure | 261 | * fill in request structure |
287 | */ | 262 | */ |
@@ -294,7 +269,6 @@ static int sg_io(struct file *file, request_queue_t *q, | |||
294 | rq->sense_len = 0; | 269 | rq->sense_len = 0; |
295 | 270 | ||
296 | rq->cmd_type = REQ_TYPE_BLOCK_PC; | 271 | rq->cmd_type = REQ_TYPE_BLOCK_PC; |
297 | bio = rq->bio; | ||
298 | 272 | ||
299 | /* | 273 | /* |
300 | * bounce this after holding a reference to the original bio, it's | 274 | * bounce this after holding a reference to the original bio, it's |
@@ -309,6 +283,31 @@ static int sg_io(struct file *file, request_queue_t *q, | |||
309 | if (!rq->timeout) | 283 | if (!rq->timeout) |
310 | rq->timeout = BLK_DEFAULT_TIMEOUT; | 284 | rq->timeout = BLK_DEFAULT_TIMEOUT; |
311 | 285 | ||
286 | if (hdr->iovec_count) { | ||
287 | const int size = sizeof(struct sg_iovec) * hdr->iovec_count; | ||
288 | struct sg_iovec *iov; | ||
289 | |||
290 | iov = kmalloc(size, GFP_KERNEL); | ||
291 | if (!iov) { | ||
292 | ret = -ENOMEM; | ||
293 | goto out; | ||
294 | } | ||
295 | |||
296 | if (copy_from_user(iov, hdr->dxferp, size)) { | ||
297 | kfree(iov); | ||
298 | ret = -EFAULT; | ||
299 | goto out; | ||
300 | } | ||
301 | |||
302 | ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count, | ||
303 | hdr->dxfer_len); | ||
304 | kfree(iov); | ||
305 | } else if (hdr->dxfer_len) | ||
306 | ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len); | ||
307 | |||
308 | if (ret) | ||
309 | goto out; | ||
310 | |||
312 | rq->retries = 0; | 311 | rq->retries = 0; |
313 | 312 | ||
314 | start_time = jiffies; | 313 | start_time = jiffies; |
@@ -339,7 +338,7 @@ static int sg_io(struct file *file, request_queue_t *q, | |||
339 | hdr->sb_len_wr = len; | 338 | hdr->sb_len_wr = len; |
340 | } | 339 | } |
341 | 340 | ||
342 | if (blk_rq_unmap_user(bio, hdr->dxfer_len)) | 341 | if (blk_rq_unmap_user(rq)) |
343 | ret = -EFAULT; | 342 | ret = -EFAULT; |
344 | 343 | ||
345 | /* may not have succeeded, but output values written to control | 344 | /* may not have succeeded, but output values written to control |