aboutsummaryrefslogtreecommitdiffstats
path: root/block/scsi_ioctl.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2014-08-21 21:39:53 -0400
committerJens Axboe <axboe@fb.com>2014-08-21 21:42:01 -0400
commita57821cac6bb6e46abea118e34d0e86444ec1410 (patch)
tree87bacd0df173a80439af323372035f69932cc8d8 /block/scsi_ioctl.c
parent2cada584b20007470931080c49310d85908449b0 (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.c24
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);
378out: 383
384out_free_cdb:
385 if (rq->cmd != rq->__cmd)
386 kfree(rq->cmd);
387out_put_request:
379 blk_put_request(rq); 388 blk_put_request(rq);
389out:
380 return ret; 390 return ret;
381} 391}
382 392