[PATCH] block: support larger block pc requests
[safe/jmp/linux-2.6] / block / scsi_ioctl.c
index a19338e..5493c2f 100644 (file)
@@ -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,44 +257,18 @@ 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
         */
        rq->cmd_len = hdr->cmd_len;
+       memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
        memcpy(rq->cmd, cmd, hdr->cmd_len);
-       if (sizeof(rq->cmd) != hdr->cmd_len)
-               memset(rq->cmd + hdr->cmd_len, 0, sizeof(rq->cmd) - hdr->cmd_len);
 
        memset(sense, 0, sizeof(sense));
        rq->sense = sense;
        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
@@ -310,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;
@@ -340,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