Commit 9f5de6b1 authored by FUJITA Tomonori's avatar FUJITA Tomonori Committed by James Bottomley

[SCSI] bsg: add large command support

This enables bsg to handle the request length larger than BLK_MAX_CDB
(mainly for the variable length CDB format).
Signed-off-by: default avatarFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Acked-by: default avatarJens Axboe <jens.axboe@oracle.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent 0462590e
...@@ -174,7 +174,11 @@ static int bsg_io_schedule(struct bsg_device *bd) ...@@ -174,7 +174,11 @@ static int bsg_io_schedule(struct bsg_device *bd)
static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq, static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq,
struct sg_io_v4 *hdr, int has_write_perm) struct sg_io_v4 *hdr, int has_write_perm)
{ {
memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */ if (hdr->request_len > BLK_MAX_CDB) {
rq->cmd = kzalloc(hdr->request_len, GFP_KERNEL);
if (!rq->cmd)
return -ENOMEM;
}
if (copy_from_user(rq->cmd, (void *)(unsigned long)hdr->request, if (copy_from_user(rq->cmd, (void *)(unsigned long)hdr->request,
hdr->request_len)) hdr->request_len))
...@@ -211,8 +215,6 @@ bsg_validate_sgv4_hdr(struct request_queue *q, struct sg_io_v4 *hdr, int *rw) ...@@ -211,8 +215,6 @@ bsg_validate_sgv4_hdr(struct request_queue *q, struct sg_io_v4 *hdr, int *rw)
if (hdr->guard != 'Q') if (hdr->guard != 'Q')
return -EINVAL; return -EINVAL;
if (hdr->request_len > BLK_MAX_CDB)
return -EINVAL;
if (hdr->dout_xfer_len > (q->max_sectors << 9) || if (hdr->dout_xfer_len > (q->max_sectors << 9) ||
hdr->din_xfer_len > (q->max_sectors << 9)) hdr->din_xfer_len > (q->max_sectors << 9))
return -EIO; return -EIO;
...@@ -302,6 +304,8 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr) ...@@ -302,6 +304,8 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr)
} }
return rq; return rq;
out: out:
if (rq->cmd != rq->__cmd)
kfree(rq->cmd);
blk_put_request(rq); blk_put_request(rq);
if (next_rq) { if (next_rq) {
blk_rq_unmap_user(next_rq->bio); blk_rq_unmap_user(next_rq->bio);
...@@ -455,6 +459,8 @@ static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr, ...@@ -455,6 +459,8 @@ static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr,
ret = rq->errors; ret = rq->errors;
blk_rq_unmap_user(bio); blk_rq_unmap_user(bio);
if (rq->cmd != rq->__cmd)
kfree(rq->cmd);
blk_put_request(rq); blk_put_request(rq);
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment