summary refs log tree commit diff
path: root/block/scsi_ioctl.c
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2006-12-01 10:40:55 +0100
committerJens Axboe <jens.axboe@oracle.com>2006-12-01 10:40:55 +0100
commit0e75f9063f5c55fb0b0b546a7c356f8ec186825e (patch)
treedb138f641175403546c2147def4b405f3ff453a8 /block/scsi_ioctl.c
parentad2d7225709b11da47e092634cbdf0591829ae9c (diff)
downloadlinux-0e75f9063f5c55fb0b0b546a7c356f8ec186825e.tar.gz
[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.c53
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,
 	unsigned long start_time;
 	int writing = 0, ret = 0;
 	struct request *rq;
-	struct bio *bio;
 	char sense[SCSI_SENSE_BUFFERSIZE];
 	unsigned char cmd[BLK_MAX_CDB];
 
@@ -258,30 +257,6 @@ static int sg_io(struct file *file, request_queue_t *q,
 	if (!rq)
 		return -ENOMEM;
 
-	if (hdr->iovec_count) {
-		const int size = sizeof(struct sg_iovec) * hdr->iovec_count;
-		struct sg_iovec *iov;
-
-		iov = kmalloc(size, GFP_KERNEL);
-		if (!iov) {
-			ret = -ENOMEM;
-			goto out;
-		}
-
-		if (copy_from_user(iov, hdr->dxferp, size)) {
-			kfree(iov);
-			ret = -EFAULT;
-			goto out;
-		}
-
-		ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count);
-		kfree(iov);
-	} else if (hdr->dxfer_len)
-		ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len);
-
-	if (ret)
-		goto out;
-
 	/*
 	 * fill in request structure
 	 */
@@ -294,7 +269,6 @@ static int sg_io(struct file *file, request_queue_t *q,
 	rq->sense_len = 0;
 
 	rq->cmd_type = REQ_TYPE_BLOCK_PC;
-	bio = rq->bio;
 
 	/*
 	 * 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,
 	if (!rq->timeout)
 		rq->timeout = BLK_DEFAULT_TIMEOUT;
 
+	if (hdr->iovec_count) {
+		const int size = sizeof(struct sg_iovec) * hdr->iovec_count;
+		struct sg_iovec *iov;
+
+		iov = kmalloc(size, GFP_KERNEL);
+		if (!iov) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		if (copy_from_user(iov, hdr->dxferp, size)) {
+			kfree(iov);
+			ret = -EFAULT;
+			goto out;
+		}
+
+		ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count,
+					  hdr->dxfer_len);
+		kfree(iov);
+	} else if (hdr->dxfer_len)
+		ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len);
+
+	if (ret)
+		goto out;
+
 	rq->retries = 0;
 
 	start_time = jiffies;
@@ -339,7 +338,7 @@ static int sg_io(struct file *file, request_queue_t *q,
 			hdr->sb_len_wr = len;
 	}
 
-	if (blk_rq_unmap_user(bio, hdr->dxfer_len))
+	if (blk_rq_unmap_user(rq))
 		ret = -EFAULT;
 
 	/* may not have succeeded, but output values written to control