mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-21 14:21:48 +00:00
[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 <bharrosh@panasas.com> Signed-off-by: Olaf Kirch <olaf.kirch@oracle.com> Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
This commit is contained in:
parent
7207fea452
commit
004d6530f8
5 changed files with 94 additions and 19 deletions
|
@ -37,6 +37,9 @@
|
|||
#include <scsi/scsi_transport_iscsi.h>
|
||||
#include <scsi/libiscsi.h>
|
||||
|
||||
static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
|
||||
int err);
|
||||
|
||||
struct iscsi_session *
|
||||
class_to_transport_session(struct iscsi_cls_session *cls_session)
|
||||
{
|
||||
|
@ -122,6 +125,20 @@ void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *ctask,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(iscsi_prep_unsolicit_data_pdu);
|
||||
|
||||
static int iscsi_add_hdr(struct iscsi_cmd_task *ctask, unsigned len)
|
||||
{
|
||||
unsigned exp_len = ctask->hdr_len + len;
|
||||
|
||||
if (exp_len > ctask->hdr_max) {
|
||||
WARN_ON(1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
WARN_ON(len & (ISCSI_PAD_LEN - 1)); /* caller must pad the AHS */
|
||||
ctask->hdr_len = exp_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu
|
||||
* @ctask: iscsi cmd task
|
||||
|
@ -129,13 +146,19 @@ EXPORT_SYMBOL_GPL(iscsi_prep_unsolicit_data_pdu);
|
|||
* Prep basic iSCSI PDU fields for a scsi cmd pdu. The LLD should set
|
||||
* fields like dlength or final based on how much data it sends
|
||||
*/
|
||||
static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
|
||||
static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
|
||||
{
|
||||
struct iscsi_conn *conn = ctask->conn;
|
||||
struct iscsi_session *session = conn->session;
|
||||
struct iscsi_cmd *hdr = ctask->hdr;
|
||||
struct scsi_cmnd *sc = ctask->sc;
|
||||
unsigned hdrlength;
|
||||
int rc;
|
||||
|
||||
ctask->hdr_len = 0;
|
||||
rc = iscsi_add_hdr(ctask, sizeof(*hdr));
|
||||
if (rc)
|
||||
return rc;
|
||||
hdr->opcode = ISCSI_OP_SCSI_CMD;
|
||||
hdr->flags = ISCSI_ATTR_SIMPLE;
|
||||
int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
|
||||
|
@ -199,6 +222,15 @@ static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
|
|||
hdr->flags |= ISCSI_FLAG_CMD_READ;
|
||||
}
|
||||
|
||||
/* calculate size of additional header segments (AHSs) */
|
||||
hdrlength = ctask->hdr_len - sizeof(*hdr);
|
||||
|
||||
WARN_ON(hdrlength & (ISCSI_PAD_LEN-1));
|
||||
hdrlength /= ISCSI_PAD_LEN;
|
||||
|
||||
WARN_ON(hdrlength >= 256);
|
||||
hdr->hlength = hdrlength & 0xFF;
|
||||
|
||||
conn->scsicmd_pdus_cnt++;
|
||||
|
||||
debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d "
|
||||
|
@ -206,6 +238,7 @@ static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
|
|||
sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
|
||||
conn->id, sc, sc->cmnd[0], ctask->itt, scsi_bufflen(sc),
|
||||
session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -744,7 +777,10 @@ check_mgmt:
|
|||
|
||||
conn->ctask = list_entry(conn->xmitqueue.next,
|
||||
struct iscsi_cmd_task, running);
|
||||
iscsi_prep_scsi_cmd_pdu(conn->ctask);
|
||||
if (iscsi_prep_scsi_cmd_pdu(conn->ctask)) {
|
||||
fail_command(conn, conn->ctask, DID_ABORT << 16);
|
||||
continue;
|
||||
}
|
||||
conn->session->tt->init_cmd_task(conn->ctask);
|
||||
conn->ctask->state = ISCSI_TASK_RUNNING;
|
||||
list_move_tail(conn->xmitqueue.next, &conn->run_list);
|
||||
|
@ -1534,6 +1570,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
|
|||
if (cmd_task_size)
|
||||
ctask->dd_data = &ctask[1];
|
||||
ctask->itt = cmd_i;
|
||||
ctask->hdr_max = sizeof(struct iscsi_cmd);
|
||||
INIT_LIST_HEAD(&ctask->running);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue