Support for extended CDBs in iscsi.
  All we need is to check if command spills over 16 bytes then allocate
  an iscsi-extended-header for the leftovers.

Signed-off-by: Boaz Harrosh <[EMAIL PROTECTED]>
---
 drivers/scsi/iscsi_tcp.c   |    2 +-
 drivers/scsi/libiscsi.c    |   56 ++++++++++++++++++++++++++++++++++++++++----
 include/scsi/iscsi_proto.h |    6 +++-
 3 files changed, 56 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 8a17867..ee7acfa 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -1975,7 +1975,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
        .host_template          = &iscsi_sht,
        .conndata_size          = sizeof(struct iscsi_conn),
        .max_conn               = 1,
-       .max_cmd_len            = 16,
+       .max_cmd_len            = 260,
        /* session management */
        .create_session         = iscsi_tcp_session_create,
        .destroy_session        = iscsi_tcp_session_destroy,
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index cfffabd..498cea3 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -137,6 +137,45 @@ static int iscsi_add_hdr(struct iscsi_cmd_task *ctask, 
unsigned len)
        return 0;
 }
 
+/*
+ * make an extended cdb AHS
+ */
+static int iscsi_prep_ecdb_ahs(struct iscsi_cmd_task *ctask)
+{
+       struct scsi_cmnd *cmd = ctask->sc;
+       unsigned rlen, pad_len;
+       unsigned short ahslength;
+       struct iscsi_ecdb_ahdr *ecdb_ahdr;
+       int rc;
+
+       ecdb_ahdr = iscsi_next_hdr(ctask);
+       rlen = cmd->cmd_len - ISCSI_CDB_SIZE;
+
+       BUG_ON(rlen > sizeof(ecdb_ahdr->ecdb));
+       ahslength = rlen + sizeof(ecdb_ahdr->reserved);
+
+       pad_len = iscsi_padding(rlen);
+
+       rc = iscsi_add_hdr(ctask, sizeof(ecdb_ahdr->ahslength) +
+                     sizeof(ecdb_ahdr->ahstype) + ahslength + pad_len);
+       if (rc)
+               return rc;
+
+       if (pad_len)
+               memset(&ecdb_ahdr->ecdb[rlen], 0, pad_len);
+
+       ecdb_ahdr->ahslength = cpu_to_be16(ahslength);
+       ecdb_ahdr->ahstype = ISCSI_AHSTYPE_CDB;
+       ecdb_ahdr->reserved = 0;
+       memcpy(ecdb_ahdr->ecdb, cmd->cmnd + ISCSI_CDB_SIZE, rlen);
+
+       debug_scsi("iscsi_prep_ecdb_ahs: varlen_cdb_len %d "
+               "rlen %d pad_len %d ahs_length %d iscsi_headers_size %u\n",
+               cmd->cmd_len, rlen, pad_len, ahslength, ctask->hdr_len);
+
+       return 0;
+}
+
 /**
  * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu
  * @ctask: iscsi cmd task
@@ -150,7 +189,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task 
*ctask)
        struct iscsi_session *session = conn->session;
        struct iscsi_cmd *hdr = ctask->hdr;
        struct scsi_cmnd *sc = ctask->sc;
-       unsigned hdrlength;
+       unsigned hdrlength, cmd_len;
        int rc;
 
        ctask->hdr_len = 0;
@@ -165,10 +204,17 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task 
*ctask)
        hdr->cmdsn = cpu_to_be32(session->cmdsn);
        session->cmdsn++;
        hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
-       memcpy(hdr->cdb, sc->cmnd, sc->cmd_len);
-       if (sc->cmd_len < MAX_COMMAND_SIZE)
-               memset(&hdr->cdb[sc->cmd_len], 0,
-                       MAX_COMMAND_SIZE - sc->cmd_len);
+       cmd_len = sc->cmd_len;
+       if (cmd_len < ISCSI_CDB_SIZE)
+               memset(&hdr->cdb[cmd_len], 0,
+                       ISCSI_CDB_SIZE - cmd_len);
+       else if (cmd_len > ISCSI_CDB_SIZE) {
+               rc = iscsi_prep_ecdb_ahs(ctask);
+               if (rc)
+                       return rc;
+               cmd_len = ISCSI_CDB_SIZE;
+       }
+       memcpy(hdr->cdb, sc->cmnd, cmd_len);
 
        ctask->imm_count = 0;
        if (sc->sc_data_direction == DMA_TO_DEVICE) {
diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h
index 5ffec8a..e0593bf 100644
--- a/include/scsi/iscsi_proto.h
+++ b/include/scsi/iscsi_proto.h
@@ -112,6 +112,7 @@ struct iscsi_ahs_hdr {
 
 #define ISCSI_AHSTYPE_CDB              1
 #define ISCSI_AHSTYPE_RLENGTH          2
+#define ISCSI_CDB_SIZE                 16
 
 /* iSCSI PDU Header */
 struct iscsi_cmd {
@@ -125,7 +126,7 @@ struct iscsi_cmd {
        __be32 data_length;
        __be32 cmdsn;
        __be32 exp_statsn;
-       uint8_t cdb[16];        /* SCSI Command Block */
+       uint8_t cdb[ISCSI_CDB_SIZE];    /* SCSI Command Block */
        /* Additional Data (Command Dependent) */
 };
 
@@ -154,7 +155,8 @@ 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 */
+       /* 4-byte aligned extended CDB spillover */
+       uint8_t ecdb[260 - ISCSI_CDB_SIZE];
 };
 
 /* SCSI Response Header */
-- 
1.5.3.3


-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to