From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx> This patch updates usr/bs_sg.c:bs_sg_cmd_submit() to process incoming scsi-generic IO of type SG_DXFER_TO_DEV and SG_DXFER_FROM_DEV using a single new struct scsi_cmnd->sg_iovec set using existing scsi_cmd.h scsi_get_[out,in]_[buffer,length]() macros. It also makes set_cmd_failed() properly return SAM_STAT_CHECK_CONDITION, which is expected by the bs_sg_cmd_submit() caller in usr/scsi.c:scsi_cmd_perform() Finally, this patch adds struct backingstore_template->bs_passthrough=1 that is used by bs_sg.c here and the next patch to hand off struct scsi_cmd for CDB passthrough. Signed-off-by: Nicholas A. Bellinger <nab@xxxxxxxxxxxxxxx> --- usr/bs_sg.c | 31 ++++++++++++++++++++++++------- usr/scsi_cmnd.h | 4 ++++ usr/tgtd.h | 1 + 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/usr/bs_sg.c b/usr/bs_sg.c index 8baa480..9696392 100644 --- a/usr/bs_sg.c +++ b/usr/bs_sg.c @@ -82,7 +82,7 @@ static int graceful_write(int fd, void *p_write, int to_write) return 0; } -static void set_cmd_failed(struct scsi_cmd *cmd) +static int set_cmd_failed(struct scsi_cmd *cmd) { int result = SAM_STAT_CHECK_CONDITION; uint16_t asc = ASC_READ_ERROR; @@ -90,11 +90,14 @@ static void set_cmd_failed(struct scsi_cmd *cmd) scsi_set_result(cmd, result); sense_data_build(cmd, key, asc); + + return result; } static int bs_sg_cmd_submit(struct scsi_cmd *cmd) { struct scsi_lu *dev = cmd->dev; + struct sg_iovec *iov = &cmd->sg_iovec; int fd = dev->fd; struct sg_io_hdr io_hdr; int err = 0; @@ -104,14 +107,27 @@ static int bs_sg_cmd_submit(struct scsi_cmd *cmd) io_hdr.cmd_len = cmd->scb_len; io_hdr.cmdp = cmd->scb; + if (scsi_get_data_dir(cmd) == DATA_BIDIRECTIONAL) { + eprintf("Unable to process DATA_BIDIRECTIONAL to" + " SG_IO backstore\n"); + return set_cmd_failed(cmd); + } + if (scsi_get_data_dir(cmd) == DATA_WRITE) { io_hdr.dxfer_direction = SG_DXFER_TO_DEV; - io_hdr.dxfer_len = scsi_get_out_length(cmd); - io_hdr.dxferp = (void *)scsi_get_out_buffer(cmd); - } else { + io_hdr.dxfer_len = iov->iov_len = scsi_get_out_length(cmd); + iov->iov_base = (void *)scsi_get_out_buffer(cmd); + io_hdr.dxferp = &cmd->sg_iovec; + io_hdr.iovec_count = 1; + } else if (scsi_get_data_dir(cmd) == DATA_READ) { io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; - io_hdr.dxfer_len = scsi_get_in_length(cmd); - io_hdr.dxferp = (void *)scsi_get_in_buffer(cmd); + io_hdr.dxfer_len = iov->iov_len = scsi_get_in_length(cmd); + iov->iov_base = (void *)scsi_get_in_buffer(cmd); + io_hdr.dxferp = &cmd->sg_iovec; + io_hdr.iovec_count = 1; + } else { + io_hdr.dxfer_direction = SG_DXFER_NONE; + io_hdr.dxfer_len = 0; } io_hdr.mx_sb_len = sizeof(cmd->sense_buffer); io_hdr.sbp = cmd->sense_buffer; @@ -125,7 +141,7 @@ static int bs_sg_cmd_submit(struct scsi_cmd *cmd) set_cmd_async(cmd); else { eprintf("failed to start cmd 0x%p\n", cmd); - set_cmd_failed(cmd); + return set_cmd_failed(cmd); } return 0; } @@ -238,6 +254,7 @@ static int bs_sg_cmd_done(struct scsi_cmd *cmd) static struct backingstore_template sg_bst = { .bs_name = "sg", .bs_datasize = 0, + .bs_passthrough = 1, .bs_open = bs_sg_open, .bs_close = bs_sg_close, .bs_cmd_submit = bs_sg_cmd_submit, diff --git a/usr/scsi_cmnd.h b/usr/scsi_cmnd.h index 011f3e6..776ffb3 100644 --- a/usr/scsi_cmnd.h +++ b/usr/scsi_cmnd.h @@ -17,6 +17,8 @@ struct scsi_data_buffer { uint64_t buffer; }; +#include <scsi/sg.h> + struct scsi_cmd { struct target *c_target; /* linked it_nexus->cmd_hash_list */ @@ -31,6 +33,8 @@ struct scsi_cmd { enum data_direction data_dir; struct scsi_data_buffer in_sdb; struct scsi_data_buffer out_sdb; + /* used for bs_sg.c:bs_sg_cmd_submit() */ + struct sg_iovec sg_iovec; uint64_t cmd_itn_id; uint64_t offset; diff --git a/usr/tgtd.h b/usr/tgtd.h index 3323a9b..4f26a29 100644 --- a/usr/tgtd.h +++ b/usr/tgtd.h @@ -117,6 +117,7 @@ struct device_type_template { struct backingstore_template { const char *bs_name; int bs_datasize; + int bs_passthrough; int (*bs_open)(struct scsi_lu *dev, char *path, int *fd, uint64_t *size); void (*bs_close)(struct scsi_lu *dev); int (*bs_init)(struct scsi_lu *dev); -- 1.5.6.5 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html