X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=block%2Fscsi_ioctl.c;h=65c6a3cba6d6e85d31d345dd75b322f7196889a5;hb=6ffa01d88c9dd45e2ed917b5eeeb494d07efb1ab;hp=ac63964b72421d591f933dafcdc51220f67f3c43;hpb=85e04e371b5a321b5df2bc3f8e0099a64fb087d7;p=powerpc.git diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index ac63964b72..65c6a3cba6 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -223,12 +223,12 @@ static int verify_command(struct file *file, unsigned char *cmd) static int sg_io(struct file *file, request_queue_t *q, struct gendisk *bd_disk, struct sg_io_hdr *hdr) { - unsigned long start_time; + unsigned long start_time, timeout; 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,26 @@ 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; + + timeout = msecs_to_jiffies(hdr->timeout); + rq->timeout = (timeout < INT_MAX) ? timeout : INT_MAX; + 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 +294,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 +303,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 = jiffies_to_msecs(hdr->timeout); - if (!rq->timeout) - rq->timeout = q->sg_timeout; - if (!rq->timeout) - rq->timeout = BLK_DEFAULT_TIMEOUT; - rq->retries = 0; start_time = jiffies; @@ -340,7 +334,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(bio)) ret = -EFAULT; /* may not have succeeded, but output values written to control