From 004d6530f83bee43a55b51bb5960db96e7ae0ffa Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Thu, 13 Dec 2007 12:43:23 -0600 Subject: [SCSI] iscsi_tcp, libiscsi: initial AHS Support at libiscsi generic code - currently code assumes a storage space of pdu header is allocated at llds ctask and is pointed to by iscsi_cmd_task->hdr. Here I add a hdr_max field pertaining to that storage, and an hdr_len that accumulates the current use of the pdu-header. - Add an iscsi_next_hdr() inline which returns the next free space to write new Header at. Also iscsi_next_hdr() is used to retrieve the address at which to write the header-digest. - Add iscsi_add_hdr(length). What the user do is calls iscsi_next_hdr() for address of the new header, than calls iscsi_add_hdr(length) with the size of the new header. iscsi_add_hdr() will check if space is available and update to the new size. length must be padded according to standard. - Add 2 padding inline helpers thanks to Olaf. Current patch does not use them but Following patches will. Also moved definition of ISCSI_PAD_LEN to iscsi_proto.h which had PAD_WORD_LEN that was never used anywhere. - Let iscsi_prep_scsi_cmd_pdu() signal an Error return since now it is possible that it will fail. - I was tired of yet again writing a "this is a digest" comment next to sizeof(__u32) so I defined a new ISCSI_DIGEST_SIZE. Now I don't need any comments. Changed all places that used sizeof(__u32) or "4" in connection to a digest. iscsi_tcp specific code - At struct iscsi_tcp_cmd_task allocate maximum space allowed in standard for all headers following the iscsi_cmd header. and mark it so in iscsi_tcp_session_create() - At iscsi_send_cmd_hdr() retrieve the correct headers size and write header digest at iscsi_next_hdr(). Signed-off-by: Boaz Harrosh Signed-off-by: Olaf Kirch Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- include/scsi/iscsi_proto.h | 10 +++++++++- include/scsi/libiscsi.h | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h index 751c81eaa7f3..6947082eee6d 100644 --- a/include/scsi/iscsi_proto.h +++ b/include/scsi/iscsi_proto.h @@ -27,7 +27,7 @@ #define ISCSI_LISTEN_PORT 3260 /* Padding word length */ -#define PAD_WORD_LEN 4 +#define ISCSI_PAD_LEN 4 /* * useful common(control and data pathes) macro @@ -147,6 +147,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; diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index e1fb3d0927b0..a9a9e869188d 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -78,6 +78,9 @@ enum { #define ISCSI_ADDRESS_BUF_LEN 64 enum { + /* this is the maximum possible storage for AHSs */ + ISCSI_MAX_AHS_SIZE = sizeof(struct iscsi_ecdb_ahdr) + + sizeof(struct iscsi_rlength_ahdr), ISCSI_DIGEST_SIZE = sizeof(__u32), }; @@ -102,10 +105,13 @@ enum { struct iscsi_cmd_task { /* - * Becuae LLDs allocate their hdr differently, this is a pointer to - * that storage. It must be setup at session creation time. + * Because LLDs allocate their hdr differently, this is a pointer + * and length to that storage. It must be setup at session + * creation time. */ struct iscsi_cmd *hdr; + unsigned short hdr_max; + unsigned short hdr_len; /* accumulated size of hdr used */ int itt; /* this ITT */ uint32_t unsol_datasn; @@ -124,6 +130,11 @@ struct iscsi_cmd_task { void *dd_data; /* driver/transport data */ }; +static inline void* iscsi_next_hdr(struct iscsi_cmd_task *ctask) +{ + return (void*)ctask->hdr + ctask->hdr_len; +} + struct iscsi_conn { struct iscsi_cls_conn *cls_conn; /* ptr to class connection */ void *dd_data; /* iscsi_transport data */ @@ -342,4 +353,22 @@ extern void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask); extern void iscsi_pool_free(struct iscsi_queue *, void **); extern int iscsi_pool_init(struct iscsi_queue *, int, void ***, int); +/* + * inline functions to deal with padding. + */ +static inline unsigned int +iscsi_padded(unsigned int len) +{ + return (len + ISCSI_PAD_LEN - 1) & ~(ISCSI_PAD_LEN - 1); +} + +static inline unsigned int +iscsi_padding(unsigned int len) +{ + len &= (ISCSI_PAD_LEN - 1); + if (len) + len = ISCSI_PAD_LEN - len; + return len; +} + #endif -- cgit v1.2.2