bidi support: iSCSI bidi & varlen CDBs
Subsystems (4)
RFC 6/6 bidi support: iSCSI bidi & varlen CDBs
This patch is intended to provide a working example of a use case for bidi and varlen CDBs. The actual patches will be sent via the open-iscsi project.
- Use proposed SCSI implementation for iSCSI bidirectional commands.
- Use proposed block layer implementation for iSCSI extended CDBs.
- Dynamically build AHSs for extended cdbs and bidirectional requests.
- Follow iscsi rfc-3720 concerning datasn and r2tsn with bidirectional commands, these must be the same counter.
[- Remove check for first-burst bigger than max-burst so iSCSI regression tests can pass.
this is the wrong fix and will be removed in actual patches]
Signed-off-by Benny Halevy <[email protected]>
Signed-off-by Boaz Harrosh <[email protected]>
--- drivers/infiniband/ulp/iser/iscsi_iser.c | 4 +- drivers/scsi/iscsi_tcp.c | 190 +++++++++++++++++++++++------- drivers/scsi/iscsi_tcp.h | 10 +- drivers/scsi/libiscsi.c | 33 +++-- include/scsi/iscsi_proto.h | 8 ++ include/scsi/libiscsi.h | 18 +++- 6 files changed, 200 insertions(+), 63 deletions(-)
drivers/infiniband/ulp/iser/iscsi_iser.c +2 -2
@@ -140,10 +140,10 @@ iscsi_iser_cmd_init(struct iscsi_cmd_tas iser_ctask->iser_conn = iser_conn;if (sc->sc_data_direction ==DMA_TO_DEVICE ) { -BUG_ON (ctask->total_length ==0 ); +BUG_ON (iscsi_out_total_length (ctask) ==0 );debug_scsi ("cmd [itt %x total %d imm %d unsol_data %d\n" , - ctask->itt, ctask->total_length, ctask->imm_count, + ctask->itt,iscsi_out_total_length (ctask), ctask->imm_count, ctask->unsol_count); }
drivers/scsi/iscsi_tcp.c +149 -41
356 lines not on this page · raw message
drivers/scsi/iscsi_tcp.h +6 -4
@@ -47,7 +47,7 @@ #define XMSTATE_W_RESEND_DATA_DIGEST 0x8#define ISCSI_PAD_LEN 4#define ISCSI_SG_TABLESIZE SG_ALL -#define ISCSI_TCP_MAX_CMD_LEN 16 +#define ISCSI_TCP_MAX_CMD_LEN 260/* FIXME: SCSI_MAX_VARLEN_CDB_LEN */ struct crypto_hash ;struct socket ;
@@ -141,8 +141,10 @@ struct iscsi_r2t_info {struct iscsi_tcp_cmd_task {struct iscsi_cmd hdr; -char hdrext[4 *sizeof (__u16)+/* AHS */ -sizeof (__u32)];/* HeaderDigest */ +char hdrextbuf[sizeof (struct iscsi_ecdb_ahdr ) + +sizeof (struct iscsi_rlength_ahdr ) + +sizeof (__u32)];/* HeaderDigest */ +char *hdrext;char pad[ISCSI_PAD_LEN ];int pad_count;/* padded bytes */ struct iscsi_buf headbuf;/* header buf (xmit) */
@@ -152,7 +154,7 @@ struct iscsi_tcp_cmd_task {struct scatterlist *sg;/* per-cmd SG list */ struct scatterlist *bad_sg;/* assert statement */ int sg_count;/* SG's to process */ -uint32_t exp_r2tsn; +uint32_t exp_datasn;/* expected target's R2TSN/DataSN */ int data_offset;struct iscsi_r2t_info *r2t;/* in progress R2T */ struct iscsi_queue r2tpool;
drivers/scsi/libiscsi.c +20 -13
@@ -120,10 +120,16 @@ static void iscsi_prep_scsi_cmd_pdu(stru session->cmdsn++; hdr->exp_statsn =cpu_to_be32 (conn->exp_statsn);memcpy (hdr->cdb, sc->cmnd, sc->cmd_len); -memset (&hdr->cdb[sc->cmd_len],0 ,MAX_COMMAND_SIZE - sc->cmd_len); +if (sc->cmd_len <MAX_COMMAND_SIZE ) { +memset (&hdr->cdb[sc->cmd_len],0 ,MAX_COMMAND_SIZE - sc->cmd_len); + } ctask->data_count =0 ; -if (sc->sc_data_direction ==DMA_TO_DEVICE ) { +switch (sc->sc_data_direction) { +case DMA_BIDIRECTIONAL : + hdr->flags |=ISCSI_FLAG_CMD_READ ; +/* FALLTHROUGH */ +case DMA_TO_DEVICE : hdr->flags |=ISCSI_FLAG_CMD_WRITE ;/* * Write counters:
@@ -145,11 +151,11 @@ static void iscsi_prep_scsi_cmd_pdu(stru ctask->unsol_datasn =0 ;if (session->imm_data_en) { -if (ctask->total_length >= session->first_burst) +if (iscsi_out_total_length (ctask) >= session->first_burst) ctask->imm_count =min (session->first_burst, conn->max_xmit_dlength);else - ctask->imm_count =min (ctask->total_length, + ctask->imm_count =min (iscsi_out_total_length (ctask), conn->max_xmit_dlength);hton24 (ctask->hdr->dlength, ctask->imm_count); }else
@@ -157,20 +163,20 @@ static void iscsi_prep_scsi_cmd_pdu(struif (!session->initial_r2t_en) { ctask->unsol_count =min (session->first_burst, - ctask->total_length) - ctask->imm_count; +iscsi_out_total_length (ctask)) - ctask->imm_count; ctask->unsol_offset = ctask->imm_count; }if (!ctask->unsol_count)/* No unsolicit Data-Out's */ ctask->hdr->flags |=ISCSI_FLAG_CMD_FINAL ; - }else { - ctask->datasn =0 ; +break ; +case DMA_FROM_DEVICE : + hdr->flags |=ISCSI_FLAG_CMD_READ ; +/* FALLTHROUGH */ +default : hdr->flags |=ISCSI_FLAG_CMD_FINAL ;zero_data (hdr->dlength); - -if (sc->sc_data_direction ==DMA_FROM_DEVICE ) - hdr->flags |=ISCSI_FLAG_CMD_READ ; } conn->scsicmd_pdus_cnt++;
@@ -817,7 +823,6 @@ int iscsi_queuecommand(struct scsi_cmnd ctask->conn = conn; ctask->sc = sc;INIT_LIST_HEAD (&ctask->running); - ctask->total_length = sc->request_bufflen;iscsi_prep_scsi_cmd_pdu (ctask); session->tt->init_cmd_task (ctask);
@@ -826,7 +831,9 @@ int iscsi_queuecommand(struct scsi_cmnddebug_scsi ("ctask enq [%s cid %d sc %p cdb 0x%x itt 0x%x len %d cmdsn %d " "win %d]\n" , - sc->sc_data_direction ==DMA_TO_DEVICE ?"write" :"read" , + sc->sc_data_direction ==DMA_TO_DEVICE ?"write" : + sc->sc_data_direction ==DMA_BIDIRECTIONAL ?"bidirectional" : + sc->sc_data_direction ==DMA_FROM_DEVICE ?"read" :"none" , conn->id, sc, sc->cmnd[0 ], ctask->itt, sc->request_bufflen, session->cmdsn, session->max_cmdsn - session->exp_cmdsn +1 );spin_unlock (&session->lock);
@@ -1633,7 +1640,7 @@ int iscsi_conn_start(struct iscsi_cls_coprintk ("iscsi: invalid burst lengths: " "first_burst %d max_burst %d\n" , session->first_burst, session->max_burst); -return -EINVAL ; +// return -EINVAL; }spin_lock_bh (&session->lock);
include/scsi/iscsi_proto.h +8 -0
@@ -139,6 +139,14 @@ struct iscsi_rlength_ahdr {__be32 read_length; }; +/* Extended CDB AHS */ +struct iscsi_ecdb_ahdr { +__be16 ahslength;/* CDB length - 15, including reserved byte */ +uint8_t ahstype; +uint8_t reserved; +uint8_t ecdb[260 -16 ];/* 4-byte aligned extended CDB spillover */ +}; +/* SCSI Response Header */ struct iscsi_cmd_rsp {uint8_t opcode;
include/scsi/libiscsi.h +15 -3
@@ -25,6 +25,7 @@ #define LIBISCSI_H#include <linux/types.h> #include <linux/mutex.h> +#include <scsi/scsi_cmnd.h> #include <linux/timer.h> #include <linux/workqueue.h> #include <scsi/iscsi_proto.h>
@@ -33,7 +34,6 @@ #include <scsi/iscsi_if.h>struct scsi_transport_template ;struct scsi_device ;struct Scsi_Host ; -struct scsi_cmnd ;struct socket ;struct iscsi_transport ;struct iscsi_cls_session ;
@@ -99,7 +99,6 @@ struct iscsi_cmd_task {*/ struct iscsi_cmd *hdr;int itt;/* this ITT */ -int datasn;/* DataSN */ uint32_t unsol_datasn;int imm_count;/* imm-data (bytes) */
@@ -108,7 +107,6 @@ struct iscsi_cmd_task {int unsol_offset;int data_count;/* remaining Data-Out */ struct scsi_cmnd *sc;/* associated SCSI cmd*/ -int total_length;struct iscsi_conn *conn;/* used connection */ struct iscsi_mgmt_task *mtask;/* tmf mtask in progr */
@@ -119,6 +117,20 @@ struct iscsi_cmd_task {void *dd_data;/* driver/transport data */ }; +static inline int +iscsi_out_total_length (struct iscsi_cmd_task * ctask) +{ +return ctask->sc->request_bufflen; +} + +static inline int +iscsi_in_total_length (struct iscsi_cmd_task * ctask) +{ +return is_bidi_cmnd (ctask->sc) ? + ctask->sc->bidi_read_sdb.request_bufflen : + ctask->sc->request_bufflen; +} +struct iscsi_conn {struct iscsi_cls_conn *cls_conn;/* ptr to class connection */ void *dd_data;/* iscsi_transport data */