summaryrefslogtreecommitdiffstats
path: root/block/scsi_ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/scsi_ioctl.c')
-rw-r--r--block/scsi_ioctl.c56
1 files changed, 25 insertions, 31 deletions
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index 2dc326421a2..f322b6a441d 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -226,9 +226,9 @@ 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];
+ struct bio *bio;
if (hdr->interface_id != 'S')
return -EINVAL;
@@ -246,10 +246,10 @@ static int sg_io(struct file *file, request_queue_t *q,
switch (hdr->dxfer_direction) {
default:
return -EINVAL;
- case SG_DXFER_TO_FROM_DEV:
case SG_DXFER_TO_DEV:
writing = 1;
break;
+ case SG_DXFER_TO_FROM_DEV:
case SG_DXFER_FROM_DEV:
break;
}
@@ -258,6 +258,25 @@ static int sg_io(struct file *file, request_queue_t *q,
if (!rq)
return -ENOMEM;
+ /*
+ * 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);
+
+ memset(sense, 0, sizeof(sense));
+ rq->sense = sense;
+ rq->sense_len = 0;
+
+ rq->cmd_type = REQ_TYPE_BLOCK_PC;
+
+ rq->timeout = jiffies_to_msecs(hdr->timeout);
+ if (!rq->timeout)
+ rq->timeout = q->sg_timeout;
+ 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;
@@ -274,7 +293,8 @@ static int sg_io(struct file *file, request_queue_t *q,
goto out;
}
- ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count);
+ 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);
@@ -282,34 +302,7 @@ static int sg_io(struct file *file, request_queue_t *q,
if (ret)
goto out;
- /*
- * fill in request structure
- */
- rq->cmd_len = hdr->cmd_len;
- 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
- * needed for proper unmapping
- */
- if (rq->bio)
- blk_queue_bounce(q, &rq->bio);
-
- rq->timeout = (hdr->timeout * HZ) / 1000;
- if (!rq->timeout)
- rq->timeout = q->sg_timeout;
- if (!rq->timeout)
- rq->timeout = BLK_DEFAULT_TIMEOUT;
-
rq->retries = 0;
start_time = jiffies;
@@ -340,7 +333,8 @@ 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))
+ rq->bio = bio;
+ if (blk_rq_unmap_user(rq))
ret = -EFAULT;
/* may not have succeeded, but output values written to control