diff options
author | Christoph Hellwig <hch@lst.de> | 2014-08-21 21:39:53 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2014-08-21 21:42:01 -0400 |
commit | a57821cac6bb6e46abea118e34d0e86444ec1410 (patch) | |
tree | 87bacd0df173a80439af323372035f69932cc8d8 /block/scsi_ioctl.c | |
parent | 2cada584b20007470931080c49310d85908449b0 (diff) |
block: support > 16 byte CDBs for SG_IO
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Boaz Harrosh <boaz@plexistor.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'block/scsi_ioctl.c')
-rw-r--r-- | block/scsi_ioctl.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index ba8706f6cded..1d78e6cf9d61 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c | |||
@@ -296,8 +296,6 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk, | |||
296 | 296 | ||
297 | if (hdr->interface_id != 'S') | 297 | if (hdr->interface_id != 'S') |
298 | return -EINVAL; | 298 | return -EINVAL; |
299 | if (hdr->cmd_len > BLK_MAX_CDB) | ||
300 | return -EINVAL; | ||
301 | 299 | ||
302 | if (hdr->dxfer_len > (queue_max_hw_sectors(q) << 9)) | 300 | if (hdr->dxfer_len > (queue_max_hw_sectors(q) << 9)) |
303 | return -EIO; | 301 | return -EIO; |
@@ -316,14 +314,21 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk, | |||
316 | if (hdr->flags & SG_FLAG_Q_AT_HEAD) | 314 | if (hdr->flags & SG_FLAG_Q_AT_HEAD) |
317 | at_head = 1; | 315 | at_head = 1; |
318 | 316 | ||
317 | ret = -ENOMEM; | ||
319 | rq = blk_get_request(q, writing ? WRITE : READ, GFP_KERNEL); | 318 | rq = blk_get_request(q, writing ? WRITE : READ, GFP_KERNEL); |
320 | if (!rq) | 319 | if (!rq) |
321 | return -ENOMEM; | 320 | goto out; |
322 | blk_rq_set_block_pc(rq); | 321 | blk_rq_set_block_pc(rq); |
323 | 322 | ||
323 | if (hdr->cmd_len > BLK_MAX_CDB) { | ||
324 | rq->cmd = kzalloc(hdr->cmd_len, GFP_KERNEL); | ||
325 | if (!rq->cmd) | ||
326 | goto out_put_request; | ||
327 | } | ||
328 | |||
324 | ret = -EFAULT; | 329 | ret = -EFAULT; |
325 | if (blk_fill_sghdr_rq(q, rq, hdr, mode)) | 330 | if (blk_fill_sghdr_rq(q, rq, hdr, mode)) |
326 | goto out; | 331 | goto out_free_cdb; |
327 | 332 | ||
328 | if (hdr->iovec_count) { | 333 | if (hdr->iovec_count) { |
329 | size_t iov_data_len; | 334 | size_t iov_data_len; |
@@ -333,7 +338,7 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk, | |||
333 | 0, NULL, &iov); | 338 | 0, NULL, &iov); |
334 | if (ret < 0) { | 339 | if (ret < 0) { |
335 | kfree(iov); | 340 | kfree(iov); |
336 | goto out; | 341 | goto out_free_cdb; |
337 | } | 342 | } |
338 | 343 | ||
339 | iov_data_len = ret; | 344 | iov_data_len = ret; |
@@ -356,7 +361,7 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk, | |||
356 | GFP_KERNEL); | 361 | GFP_KERNEL); |
357 | 362 | ||
358 | if (ret) | 363 | if (ret) |
359 | goto out; | 364 | goto out_free_cdb; |
360 | 365 | ||
361 | bio = rq->bio; | 366 | bio = rq->bio; |
362 | memset(sense, 0, sizeof(sense)); | 367 | memset(sense, 0, sizeof(sense)); |
@@ -375,8 +380,13 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk, | |||
375 | hdr->duration = jiffies_to_msecs(jiffies - start_time); | 380 | hdr->duration = jiffies_to_msecs(jiffies - start_time); |
376 | 381 | ||
377 | ret = blk_complete_sghdr_rq(rq, hdr, bio); | 382 | ret = blk_complete_sghdr_rq(rq, hdr, bio); |
378 | out: | 383 | |
384 | out_free_cdb: | ||
385 | if (rq->cmd != rq->__cmd) | ||
386 | kfree(rq->cmd); | ||
387 | out_put_request: | ||
379 | blk_put_request(rq); | 388 | blk_put_request(rq); |
389 | out: | ||
380 | return ret; | 390 | return ret; |
381 | } | 391 | } |
382 | 392 | ||