diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2007-07-16 08:52:16 +0200 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2007-07-16 08:52:47 +0200 |
commit | 15d10b611fa94b52f004a08a1d4cf7b39de3cba3 (patch) | |
tree | 39b1e114689b71d37677e9733428b355d52d4e44 | |
parent | 2c9ecdf40af0554ee9a2b1cbbbbdbc77f90a40e1 (diff) | |
download | linux-3.10-15d10b611fa94b52f004a08a1d4cf7b39de3cba3.tar.gz linux-3.10-15d10b611fa94b52f004a08a1d4cf7b39de3cba3.tar.bz2 linux-3.10-15d10b611fa94b52f004a08a1d4cf7b39de3cba3.zip |
bsg: add SCSI transport-level request support
This enables bsg to handle SCSI transport-level request like SAS
management protocol (SMP).
- add BSG_SUB_PROTOCOL_{SCSI_CMD, SCSI_TMF, SCSI_TRANSPORT} definitions.
- SCSI transport-level requests skip blk_verify_command().
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
-rw-r--r-- | block/bsg.c | 27 | ||||
-rw-r--r-- | include/linux/bsg.h | 6 |
2 files changed, 27 insertions, 6 deletions
diff --git a/block/bsg.c b/block/bsg.c index 13ecc951a4c..461c9f56f3e 100644 --- a/block/bsg.c +++ b/block/bsg.c @@ -208,7 +208,11 @@ static int blk_fill_sgv4_hdr_rq(request_queue_t *q, struct request *rq, if (copy_from_user(rq->cmd, (void *)(unsigned long)hdr->request, hdr->request_len)) return -EFAULT; - if (blk_verify_command(rq->cmd, has_write_perm)) + + if (hdr->subprotocol == BSG_SUB_PROTOCOL_SCSI_CMD) { + if (blk_verify_command(rq->cmd, has_write_perm)) + return -EPERM; + } else if (!capable(CAP_SYS_RAWIO)) return -EPERM; /* @@ -232,6 +236,8 @@ static int blk_fill_sgv4_hdr_rq(request_queue_t *q, struct request *rq, static int bsg_validate_sgv4_hdr(request_queue_t *q, struct sg_io_v4 *hdr, int *rw) { + int ret = 0; + if (hdr->guard != 'Q') return -EINVAL; if (hdr->request_len > BLK_MAX_CDB) @@ -240,13 +246,22 @@ bsg_validate_sgv4_hdr(request_queue_t *q, struct sg_io_v4 *hdr, int *rw) hdr->din_xfer_len > (q->max_sectors << 9)) return -EIO; - /* not supported currently */ - if (hdr->protocol || hdr->subprotocol) - return -EINVAL; + switch (hdr->protocol) { + case BSG_PROTOCOL_SCSI: + switch (hdr->subprotocol) { + case BSG_SUB_PROTOCOL_SCSI_CMD: + case BSG_SUB_PROTOCOL_SCSI_TRANSPORT: + break; + default: + ret = -EINVAL; + } + break; + default: + ret = -EINVAL; + } *rw = hdr->dout_xfer_len ? WRITE : READ; - - return 0; + return ret; } /* diff --git a/include/linux/bsg.h b/include/linux/bsg.h index 0dd01f90ba5..bd998ca6cb2 100644 --- a/include/linux/bsg.h +++ b/include/linux/bsg.h @@ -1,6 +1,12 @@ #ifndef BSG_H #define BSG_H +#define BSG_PROTOCOL_SCSI 0 + +#define BSG_SUB_PROTOCOL_SCSI_CMD 0 +#define BSG_SUB_PROTOCOL_SCSI_TMF 1 +#define BSG_SUB_PROTOCOL_SCSI_TRANSPORT 2 + struct sg_io_v4 { __s32 guard; /* [i] 'Q' to differentiate from v3 */ __u32 protocol; /* [i] 0 -> SCSI , .... */ |