Behavior changes:
authorbvassche <bvassche@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Fri, 25 Dec 2009 15:26:42 +0000 (15:26 +0000)
committerbvassche <bvassche@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Fri, 25 Dec 2009 15:26:42 +0000 (15:26 +0000)
- Fixed: the SCSOLNT and UCSOLNT bits were ignored in received SRP requests,
  and the SOLNT bit was not set in responses when required. This is required
  by the SRP protocol specification.
- Fixed: SRP_RSP messages must be limited to the MAXIMUM TARGET TO INITIATOR
  IU LENGTH  field indicated in the SRP_LOGIN_RSP response instead of the
  maximum message size supported by SRPT. This is also required by the SRP
  protocol specification.
- Fixed: the STATUS field of response messages with status GOOD and that
  contain sense data is no longer modified into CHECK CONDITION.
Internal changes (refactoring):
- Replaced the SCSI sense data handling data structures and code in SRPT by
  those of the SCST core.
- Moved the code for building an error response from srpt_handle_cmd() and
  srpt_handle_tsk_mgmt() to srpt_handle_new_iu().
- Removed the ioctx::data_len member.

git-svn-id: https://scst.svn.sourceforge.net/svnroot/scst/trunk@1416 d57e44dd-8a1f-0410-8b47-8ef2f437770f

srpt/src/ib_srpt.c
srpt/src/ib_srpt.h

index 298dbf5..794b978 100644 (file)
@@ -806,7 +806,22 @@ out:
        return ret;
 }
 
-static int srpt_get_desc_tbl(struct srpt_ioctx *ioctx, struct srp_cmd *srp_cmd)
+/**
+ * srpt_get_desc_tbl() - Parse the data descriptors of an SRP_CMD request.
+ * @ioctx: Pointer to the I/O context associated with the request.
+ * @srp_cmd: Pointer to the SRP_CMD request data.
+ * @dir: Pointer to the variable to which the transfer direction will be
+ *   written.
+ * @data_len: Pointer to the variable to which the total data length of all
+ *   descriptors in the SRP_CMD request will be written.
+ *
+ * This function initializes ioctx->nrbuf and ioctx->r_bufs.
+ *
+ * Returns -EINVAL when the SRP_CMD request contains inconsistent descriptors;
+ * -ENOMEM when memory allocation fails and zero upon success.
+ */
+static int srpt_get_desc_tbl(struct srpt_ioctx *ioctx, struct srp_cmd *srp_cmd,
+                            scst_data_direction *dir, u64 *data_len)
 {
        struct srp_indirect_buf *idb;
        struct srp_direct_buf *db;
@@ -815,7 +830,8 @@ static int srpt_get_desc_tbl(struct srpt_ioctx *ioctx, struct srp_cmd *srp_cmd)
 
        /*
         * The pointer computations below will only be compiled correctly
-        * if srp_cmd::add_data is declared as s8*, u8*, s8[] or u8[].
+        * if srp_cmd::add_data is declared as s8*, u8*, s8[] or u8[], so check
+        * whether srp_cmd::add_data has been declared as a byte pointer.
         */
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
        BUILD_BUG_ON(!__same_type(srp_cmd->add_data[0], (s8)0)
@@ -824,7 +840,25 @@ static int srpt_get_desc_tbl(struct srpt_ioctx *ioctx, struct srp_cmd *srp_cmd)
        /* Note: the __same_type() macro has been introduced in kernel 2.6.31.*/
 #endif
 
+       BUG_ON(!dir);
+       BUG_ON(!data_len);
+
        ret = 0;
+       *data_len = 0;
+
+       /*
+        * The lower four bits of the buffer format field contain the DATA-IN
+        * buffer descriptor format, and the highest four bits contain the
+        * DATA-OUT buffer descriptor format.
+        */
+       *dir = SCST_DATA_NONE;
+       if (srp_cmd->buf_fmt & 0xf)
+               /* DATA-IN: transfer data from target to initiator. */
+               *dir = SCST_DATA_READ;
+       else if (srp_cmd->buf_fmt >> 4)
+               /* DATA-OUT: transfer data from initiator to target. */
+               *dir = SCST_DATA_WRITE;
+
        /*
         * According to the SRP spec, the lower two bits of the 'ADDITIONAL
         * CDB LENGTH' field are reserved and the size in bytes of this field
@@ -839,8 +873,9 @@ static int srpt_get_desc_tbl(struct srpt_ioctx *ioctx, struct srp_cmd *srp_cmd)
                db = (struct srp_direct_buf *)(srp_cmd->add_data
                                               + add_cdb_offset);
                memcpy(ioctx->rbufs, db, sizeof *db);
-               ioctx->data_len = be32_to_cpu(db->len);
-       } else {
+               *data_len = be32_to_cpu(db->len);
+       } else if (((srp_cmd->buf_fmt & 0xf) == SRP_DATA_DESC_INDIRECT) ||
+                  ((srp_cmd->buf_fmt >> 4) == SRP_DATA_DESC_INDIRECT)) {
                idb = (struct srp_indirect_buf *)(srp_cmd->add_data
                                                  + add_cdb_offset);
 
@@ -873,7 +908,7 @@ static int srpt_get_desc_tbl(struct srpt_ioctx *ioctx, struct srp_cmd *srp_cmd)
 
                db = idb->desc_list;
                memcpy(ioctx->rbufs, db, ioctx->n_rbuf * sizeof *db);
-               ioctx->data_len = be32_to_cpu(idb->len);
+               *data_len = be32_to_cpu(idb->len);
        }
 out:
        return ret;
@@ -1106,12 +1141,15 @@ static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch,
 }
 
 /**
- * Build an SRP_RSP response.
+ * srpt_build_cmd_rsp() - Build an SRP_RSP response.
  * @ch: RDMA channel through which the request has been received.
- * @ioctx: I/O context in which the SRP_RSP response will be built.
- * @s_key: sense key that will be stored in the response.
- * @s_code: value that will be stored in the asc_ascq field of the sense data.
+ * @ioctx: I/O context associated with the SRP_CMD request. The response will
+ *   be built in the buffer ioctx->buf points at and hence this function will
+ *   overwrite the request data.
  * @tag: tag of the request for which this response is being generated.
+ * @status: value for the STATUS field of the SRP_RSP information unit.
+ * @sense_data: pointer to sense data to be included in the response.
+ * @sense_data_len: length in bytes of the sense data.
  *
  * Returns the size in bytes of the SRP_RSP response.
  *
@@ -1120,40 +1158,56 @@ static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch,
  * response. See also SPC-2 for more information about sense data.
  */
 static int srpt_build_cmd_rsp(struct srpt_rdma_ch *ch,
-                             struct srpt_ioctx *ioctx, u8 s_key, u8 s_code,
-                             u64 tag)
+                             struct srpt_ioctx *ioctx, u64 tag, int status,
+                             const u8 *sense_data, int sense_data_len)
 {
        struct srp_rsp *srp_rsp;
-       struct sense_data *sense;
        int limit_delta;
-       int sense_data_len;
-       int resp_len;
+       int max_sense_len;
 
-       sense_data_len = (s_key == NO_SENSE) ? 0 : sizeof(*sense);
-       resp_len = sizeof(*srp_rsp) + sense_data_len;
+       /*
+        * The lowest bit of all SAM-3 status codes is zero (see also
+        * paragraph 5.3 in SAM-3).
+        */
+       WARN_ON(status & 1);
 
        srp_rsp = ioctx->buf;
+       BUG_ON(!srp_rsp);
        memset(srp_rsp, 0, sizeof *srp_rsp);
 
        limit_delta = atomic_read(&ch->req_lim_delta);
        atomic_sub(limit_delta, &ch->req_lim_delta);
 
        srp_rsp->opcode = SRP_RSP;
+       /*
+        * Copy the SCSOLNT or UCSOLNT bit from the request to the SOLNT bit
+        * of the response.
+        */
+       srp_rsp->sol_not
+               = (ioctx->sol_not
+                  & (status == SAM_STAT_GOOD ? SRP_SCSOLNT : SRP_UCSOLNT))
+               ? SRP_SOLNT : 0;
        srp_rsp->req_lim_delta = cpu_to_be32(limit_delta);
        srp_rsp->tag = tag;
 
-       if (s_key != NO_SENSE) {
+       if (SCST_SENSE_VALID(sense_data)) {
+               BUILD_BUG_ON(MIN_MAX_MESSAGE_SIZE <= sizeof(*srp_rsp));
+               max_sense_len = ch->max_ti_iu_len - sizeof(*srp_rsp);
+               if (sense_data_len > max_sense_len) {
+                       PRINT_WARNING("truncated sense data from %d to %d"
+                               " bytes", sense_data_len,
+                               max_sense_len);
+                       sense_data_len = max_sense_len;
+               }
+
                srp_rsp->flags |= SRP_RSP_FLAG_SNSVALID;
-               srp_rsp->status = SAM_STAT_CHECK_CONDITION;
+               srp_rsp->status = status;
                srp_rsp->sense_data_len = cpu_to_be32(sense_data_len);
+               memcpy(srp_rsp + 1, sense_data, sense_data_len);
+       } else
+               sense_data_len = 0;
 
-               sense = (struct sense_data *)(srp_rsp + 1);
-               sense->err_code = 0x70;
-               sense->key = s_key;
-               sense->asc_ascq = s_code;
-       }
-
-       return resp_len;
+       return sizeof(*srp_rsp) + sense_data_len;
 }
 
 /**
@@ -1188,6 +1242,15 @@ static int srpt_build_tskmgmt_rsp(struct srpt_rdma_ch *ch,
        atomic_sub(limit_delta, &ch->req_lim_delta);
 
        srp_rsp->opcode = SRP_RSP;
+       /*
+        * Copy the SCSOLNT or UCSOLNT bit from the request to the SOLNT bit
+        * of the response.
+        */
+       srp_rsp->sol_not
+               = (ioctx->sol_not
+                  & (rsp_code == SRP_TSK_MGMT_SUCCESS
+                     ? SRP_SCSOLNT : SRP_UCSOLNT))
+               ? SRP_SOLNT : 0;
        srp_rsp->req_lim_delta = cpu_to_be32(limit_delta);
        srp_rsp->tag = tag;
 
@@ -1207,48 +1270,27 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, struct srpt_ioctx *ioctx)
 {
        struct scst_cmd *scmnd;
        struct srp_cmd *srp_cmd;
-       struct srp_rsp *srp_rsp;
        scst_data_direction dir;
+       u64 data_len;
        int ret;
 
        srp_cmd = ioctx->buf;
-       srp_rsp = ioctx->buf;
-
-       dir = SCST_DATA_NONE;
-       if (srp_cmd->buf_fmt) {
-               ret = srpt_get_desc_tbl(ioctx, srp_cmd);
-               if (ret) {
-                       srpt_build_cmd_rsp(ch, ioctx, NO_SENSE,
-                                          NO_ADD_SENSE, srp_cmd->tag);
-                       srp_rsp->status = SAM_STAT_TASK_SET_FULL;
-                       goto err;
-               }
-
-               /*
-                * The lower four bits of the buffer format field contain the
-                * DATA-IN buffer descriptor format, and the highest four bits
-                * contain the DATA-OUT buffer descriptor format.
-                */
-               if (srp_cmd->buf_fmt & 0xf)
-                       /* DATA-IN: transfer data from target to initiator. */
-                       dir = SCST_DATA_READ;
-               else if (srp_cmd->buf_fmt >> 4)
-                       /* DATA-OUT: transfer data from initiator to target. */
-                       dir = SCST_DATA_WRITE;
-       }
 
        scmnd = scst_rx_cmd(ch->scst_sess, (u8 *) &srp_cmd->lun,
                            sizeof srp_cmd->lun, srp_cmd->cdb, 16,
                            thread ? SCST_NON_ATOMIC : SCST_ATOMIC);
-       if (!scmnd) {
-               srpt_build_cmd_rsp(ch, ioctx, NO_SENSE,
-                                  NO_ADD_SENSE, srp_cmd->tag);
-               srp_rsp->status = SAM_STAT_TASK_SET_FULL;
+       if (!scmnd)
                goto err;
-       }
 
        ioctx->scmnd = scmnd;
 
+       ret = srpt_get_desc_tbl(ioctx, srp_cmd, &dir, &data_len);
+       if (ret) {
+               scst_set_cmd_error(scmnd,
+                       SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
+               goto err;
+       }
+
        switch (srp_cmd->task_attr) {
        case SRP_CMD_HEAD_OF_Q:
                scmnd->queue_type = SCST_CMD_QUEUE_HEAD_OF_QUEUE;
@@ -1269,21 +1311,19 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, struct srpt_ioctx *ioctx)
 
        scst_cmd_set_tag(scmnd, srp_cmd->tag);
        scst_cmd_set_tgt_priv(scmnd, ioctx);
-       scst_cmd_set_expected(scmnd, dir, ioctx->data_len);
+       scst_cmd_set_expected(scmnd, dir, data_len);
        scst_cmd_init_done(scmnd, scst_estimate_context());
 
        return 0;
 
 err:
-       WARN_ON(srp_rsp->opcode != SRP_RSP);
-
        return -1;
 }
 
 /*
- * Process an SRP_TSK_MGMT request.
+ * srpt_handle_tsk_mgmt() - Process an SRP_TSK_MGMT information unit.
  *
- * Returns 0 upon success and -1 upon failure.
+ * Returns SRP_TSK_MGMT_SUCCESS upon success.
  *
  * Each task management function is performed by calling one of the
  * scst_rx_mgmt_fn*() functions. These functions will either report failure
@@ -1296,12 +1336,13 @@ err:
  * For more information about SRP_TSK_MGMT information units, see also section
  * 6.7 in the T10 SRP r16a document.
  */
-static int srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
-                               struct srpt_ioctx *ioctx)
+static u8 srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
+                              struct srpt_ioctx *ioctx)
 {
        struct srp_tsk_mgmt *srp_tsk;
        struct srpt_mgmt_ioctx *mgmt_ioctx;
        int ret;
+       u8 srp_tsk_mgmt_status;
 
        srp_tsk = ioctx->buf;
 
@@ -1312,12 +1353,10 @@ static int srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
                  (unsigned long long) srp_tsk->tag,
                  ch->cm_id, ch->scst_sess);
 
+       srp_tsk_mgmt_status = SRP_TSK_MGMT_FAILED;
        mgmt_ioctx = kmalloc(sizeof *mgmt_ioctx, GFP_ATOMIC);
-       if (!mgmt_ioctx) {
-               srpt_build_tskmgmt_rsp(ch, ioctx, SRP_TSK_MGMT_FAILED,
-                                      srp_tsk->tag);
+       if (!mgmt_ioctx)
                goto err;
-       }
 
        mgmt_ioctx->ioctx = ioctx;
        mgmt_ioctx->ch = ch;
@@ -1375,28 +1414,42 @@ static int srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
                break;
        default:
                TRACE_DBG("%s", "Unsupported task management function.");
-               srpt_build_tskmgmt_rsp(ch, ioctx,
-                                      SRP_TSK_MGMT_FUNC_NOT_SUPP,
-                                      srp_tsk->tag);
+               srp_tsk_mgmt_status = SRP_TSK_MGMT_FUNC_NOT_SUPP;
                goto err;
        }
 
        if (ret) {
-               TRACE_DBG("%s", "Processing task management function failed.");
-               srpt_build_tskmgmt_rsp(ch, ioctx, SRP_TSK_MGMT_FAILED,
-                                      srp_tsk->tag);
+               TRACE_DBG("Processing task management function failed"
+                         " (ret = %d).", ret);
                goto err;
        }
+       return SRP_TSK_MGMT_SUCCESS;
 
-       WARN_ON(srp_tsk->opcode == SRP_RSP);
+err:
+       kfree(mgmt_ioctx);
+       return srp_tsk_mgmt_status;
+}
 
-       return 0;
+/**
+ * set_sense() - A copy of the function with the same name in
+ * scst/src/common.c.
+ */
+static int set_sense(uint8_t *buffer, int len, int key, int asc, int ascq)
+{
+       int res = 18;
 
-err:
-       WARN_ON(srp_tsk->opcode != SRP_RSP);
+       EXTRACHECKS_BUG_ON(len < res);
 
-       kfree(mgmt_ioctx);
-       return -1;
+       memset(buffer, 0, res);
+
+       buffer[0] = 0x70;       /* Error Code                   */
+       buffer[2] = key;        /* Sense Key                    */
+       buffer[7] = 0x0a;       /* Additional Sense Length      */
+       buffer[12] = asc;       /* ASC                          */
+       buffer[13] = ascq;      /* ASCQ                         */
+
+       TRACE_BUFFER("Sense set", buffer, res);
+       return res;
 }
 
 /**
@@ -1408,10 +1461,25 @@ static void srpt_handle_new_iu(struct srpt_rdma_ch *ch,
                               struct srpt_ioctx *ioctx)
 {
        struct srp_cmd *srp_cmd;
-       struct srp_rsp *srp_rsp;
        enum rdma_ch_state ch_state;
+       u8 srp_response_status;
+       u8 srp_tsk_mgmt_status;
        int len;
 
+       /*
+        * A quote from SAM-3, paragraph 4.9.6: "Any command that is not
+        * relayed to a dependent logical unit shall be terminated with a
+        * CHECK CONDITION status. The sense key shall be set to ILLEGAL
+        * REQUEST and the additional sense code shall be set to INVALID
+        * COMMAND OPERATION CODE. If a task management function cannot be
+        * relayed to a dependent logical unit, a service response of SERVICE
+        * DELIVERY OR TARGET FAILURE shall be returned."
+        */
+
+       srp_response_status = SAM_STAT_CHECK_CONDITION;
+       /* To keep the compiler happy. */
+       srp_tsk_mgmt_status = -1;
+
        ch_state = atomic_read(&ch->state);
        if (ch_state == RDMA_CHANNEL_CONNECTING) {
                list_add_tail(&ioctx->wait_list, &ch->cmd_wait_list);
@@ -1427,7 +1495,8 @@ static void srpt_handle_new_iu(struct srpt_rdma_ch *ch,
                                   ioctx->dma, srp_max_message_size,
                                   DMA_FROM_DEVICE);
 
-       ioctx->data_len = 0;
+       srp_cmd = ioctx->buf;
+
        ioctx->n_rbuf = 0;
        ioctx->rbufs = NULL;
        ioctx->n_rdma = 0;
@@ -1435,44 +1504,65 @@ static void srpt_handle_new_iu(struct srpt_rdma_ch *ch,
        ioctx->rdma_ius = NULL;
        ioctx->scmnd = NULL;
        ioctx->ch = ch;
+       ioctx->sol_not = srp_cmd->sol_not;
        atomic_set(&ioctx->state, SRPT_STATE_NEW);
 
-       srp_cmd = ioctx->buf;
-       srp_rsp = ioctx->buf;
-
        switch (srp_cmd->opcode) {
        case SRP_CMD:
-               if (srpt_handle_cmd(ch, ioctx) < 0)
+               if (srpt_handle_cmd(ch, ioctx) < 0) {
+                       if (ioctx->scmnd)
+                               srp_response_status =
+                                       scst_cmd_get_status(ioctx->scmnd);
                        goto err;
+               }
                break;
 
        case SRP_TSK_MGMT:
-               if (srpt_handle_tsk_mgmt(ch, ioctx) < 0)
+               srp_tsk_mgmt_status = srpt_handle_tsk_mgmt(ch, ioctx);
+               if (srp_tsk_mgmt_status != SRP_TSK_MGMT_SUCCESS)
                        goto err;
                break;
 
        case SRP_I_LOGOUT:
        case SRP_AER_REQ:
        default:
-               srpt_build_cmd_rsp(ch, ioctx, ILLEGAL_REQUEST, INVALID_CDB,
-                                  srp_cmd->tag);
                goto err;
        }
 
        return;
 
 err:
-       WARN_ON(srp_rsp->opcode != SRP_RSP);
-       len = (sizeof *srp_rsp) + be32_to_cpu(srp_rsp->sense_data_len);
-
        ch_state = atomic_read(&ch->state);
        if (ch_state != RDMA_CHANNEL_LIVE) {
                /* Give up if another thread modified the channel state. */
                PRINT_ERROR("%s: channel is in state %d", __func__, ch_state);
                srpt_reset_ioctx(ch, ioctx);
-       } else if (srpt_post_send(ch, ioctx, len)) {
-               PRINT_ERROR("%s: sending SRP_RSP response failed", __func__);
-               srpt_reset_ioctx(ch, ioctx);
+       } else {
+               if (srp_cmd->opcode == SRP_TSK_MGMT) {
+                       len = srpt_build_tskmgmt_rsp(ch, ioctx,
+                                    srp_tsk_mgmt_status,
+                                    ((struct srp_tsk_mgmt *)srp_cmd)->tag);
+               } else if (ioctx->scmnd)
+                       len = srpt_build_cmd_rsp(ch, ioctx, srp_cmd->tag,
+                               srp_response_status,
+                               scst_cmd_get_sense_buffer(ioctx->scmnd),
+                               scst_cmd_get_sense_buffer_len(ioctx->scmnd));
+               else {
+                       u8 sense_buf[18];
+                       int sense_len;
+
+                       sense_len = set_sense(sense_buf,
+                                             ARRAY_SIZE(sense_buf),
+                                             scst_sense_invalid_field_in_cdb);
+                       len = srpt_build_cmd_rsp(ch, ioctx, srp_cmd->tag,
+                                                srp_response_status,
+                                                sense_buf, sense_len);
+               }
+               if (srpt_post_send(ch, ioctx, len)) {
+                       PRINT_ERROR("%s: sending SRP_RSP response failed",
+                                   __func__);
+                       srpt_reset_ioctx(ch, ioctx);
+               }
        }
 }
 
@@ -1765,7 +1855,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
        it_iu_len = be32_to_cpu(req->req_it_iu_len);
 
        PRINT_INFO("Received SRP_LOGIN_REQ with"
-           " i_port_id 0x%llx:0x%llx, t_port_id 0x%llx:0x%llx and length %d"
+           " i_port_id 0x%llx:0x%llx, t_port_id 0x%llx:0x%llx and it_iu_len %d"
            " on port %d (guid=0x%llx:0x%llx)",
            (unsigned long long)be64_to_cpu(*(u64 *)&req->initiator_port_id[0]),
            (unsigned long long)be64_to_cpu(*(u64 *)&req->initiator_port_id[8]),
@@ -1945,6 +2035,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
        rsp->tag = req->tag;
        rsp->max_it_iu_len = req->req_it_iu_len;
        rsp->max_ti_iu_len = req->req_it_iu_len;
+       ch->max_ti_iu_len = req->req_it_iu_len;
        rsp->buf_fmt =
            cpu_to_be16(SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT);
        rsp->req_lim_delta = cpu_to_be32(SRPT_RQ_SIZE);
@@ -2463,19 +2554,19 @@ out:
        return ret;
 }
 
-/*
- * Called by the SCST core. Transmits the response buffer and status held in
- * 'scmnd'. Must not block.
+/**
+ * srpt_xmit_response() - SCST callback function that transmits the response
+ * to a SCSI command.
+ *
+ * Must not block.
  */
 static int srpt_xmit_response(struct scst_cmd *scmnd)
 {
        struct srpt_rdma_ch *ch;
        struct srpt_ioctx *ioctx;
-       struct srp_rsp *srp_rsp;
-       u64 tag;
        int ret = SCST_TGT_RES_SUCCESS;
        int dir;
-       int status;
+       int resp_len;
 
        ioctx = scst_cmd_get_tgt_priv(scmnd);
        BUG_ON(!ioctx);
@@ -2497,56 +2588,30 @@ static int srpt_xmit_response(struct scst_cmd *scmnd)
                goto out;
        }
 
-       tag = scst_cmd_get_tag(scmnd);
        dir = scst_cmd_get_data_direction(scmnd);
-       status = scst_cmd_get_status(scmnd) & 0xff;
-
-       srpt_build_cmd_rsp(ch, ioctx, NO_SENSE, NO_ADD_SENSE, tag);
-
-       srp_rsp = ioctx->buf;
-
-       if (SCST_SENSE_VALID(scst_cmd_get_sense_buffer(scmnd))) {
-               unsigned int max_sense_len;
-
-               srp_rsp->sense_data_len = scst_cmd_get_sense_buffer_len(scmnd);
-               BUILD_BUG_ON(MIN_MAX_MESSAGE_SIZE <= sizeof(*srp_rsp));
-               WARN_ON(srp_max_message_size <= sizeof(*srp_rsp));
-               max_sense_len = srp_max_message_size - sizeof(*srp_rsp);
-               if (srp_rsp->sense_data_len > max_sense_len) {
-                       PRINT_WARNING("truncated sense data from %d to %d"
-                               " bytes", srp_rsp->sense_data_len,
-                               max_sense_len);
-                       srp_rsp->sense_data_len = max_sense_len;
-               }
-
-               memcpy((u8 *) (srp_rsp + 1), scst_cmd_get_sense_buffer(scmnd),
-                      srp_rsp->sense_data_len);
-
-               srp_rsp->sense_data_len = cpu_to_be32(srp_rsp->sense_data_len);
-               srp_rsp->flags |= SRP_RSP_FLAG_SNSVALID;
-
-               if (!status)
-                       status = SAM_STAT_CHECK_CONDITION;
-       }
-
-       srp_rsp->status = status;
 
        /* For read commands, transfer the data to the initiator. */
        if (dir == SCST_DATA_READ && scst_cmd_get_resp_data_len(scmnd)) {
                ret = srpt_xfer_data(ch, ioctx, scmnd);
                if (ret != SCST_TGT_RES_SUCCESS) {
                        PRINT_ERROR("%s: tag= %lld xfer_data failed",
-                                   __func__, (unsigned long long)tag);
+                                   __func__,
+                                   (unsigned long long)
+                                   scst_cmd_get_tag(scmnd));
                        goto out;
                }
        }
 
-       if (srpt_post_send(ch, ioctx,
-                          sizeof *srp_rsp +
-                          be32_to_cpu(srp_rsp->sense_data_len))) {
+       resp_len = srpt_build_cmd_rsp(ch, ioctx,
+                                     scst_cmd_get_tag(scmnd),
+                                     scst_cmd_get_status(scmnd),
+                                     scst_cmd_get_sense_buffer(scmnd),
+                                     scst_cmd_get_sense_buffer_len(scmnd));
+
+       if (srpt_post_send(ch, ioctx, resp_len)) {
                PRINT_ERROR("%s[%d]: ch->state= %d tag= %lld",
                            __func__, __LINE__, atomic_read(&ch->state),
-                           (unsigned long long)tag);
+                           (unsigned long long)scst_cmd_get_tag(scmnd));
                ret = SCST_TGT_RES_FATAL_ERROR;
        }
 
@@ -2554,9 +2619,11 @@ out:
        return ret;
 }
 
-/*
- * Called by the SCST core to inform ib_srpt that a received task management
- * function has been completed. Must not block.
+/**
+ * srpt_tsk_mgmt_done() - SCST callback function that sends back the response
+ * for a task management request.
+ *
+ * Must not block.
  */
 static void srpt_tsk_mgmt_done(struct scst_mgmt_cmd *mcmnd)
 {
index ad290e6..f231b4c 100644 (file)
@@ -70,6 +70,19 @@ enum {
        SRP_RDMA_READ_FROM_IOC = 0x08,
        SRP_RDMA_WRITE_FROM_IOC = 0x20,
 
+       /*
+        * srp_cmd::sol_nt / srp_tsk_mgmt::sol_not bitmasks. See also tables
+        * 18 and 20 in the T10 r16a document.
+        */
+       SRP_SCSOLNT = 0x02, /* SCSOLNT = successful solicited notification */
+       SRP_UCSOLNT = 0x04, /* UCSOLNT = unsuccessful solicited notification */
+
+       /*
+        * srp_rsp::sol_not / srp_t_logout::sol_not bitmasks. See also tables
+        * 16 and 22 in the T10 r16a document.
+        */
+       SRP_SOLNT = 0x01, /* SOLNT = solicited notification */
+
        /* See also table 24 in the T10 r16a document. */
        SRP_TSK_MGMT_SUCCESS = 0x00,
        SRP_TSK_MGMT_FUNC_NOT_SUPP = 0x04,
@@ -138,13 +151,13 @@ struct srpt_ioctx {
        u16 n_rdma_ius;
        u8 n_rdma;
        u8 n_rbuf;
+       u8 sol_not;
 
        enum ib_wc_opcode op;
        /* Node for insertion in the srpt_thread::thread_ioctx_list. */
        struct list_head comp_list;
        struct srpt_rdma_ch *ch;
        struct scst_cmd *scmnd;
-       u64 data_len;
        atomic_t state; /*enum srpt_command_state*/
 };
 
@@ -174,6 +187,7 @@ struct srpt_rdma_ch {
        u8 i_port_id[16];
        /* 128-bit target port identifier copied from SRP_LOGIN_REQ. */
        u8 t_port_id[16];
+       int max_ti_iu_len;
        atomic_t req_lim_delta;
        atomic_t state; /*enum rdma_ch_state*/
        /* Node for insertion in the srpt_device::rch_list list. */
@@ -244,36 +258,4 @@ struct srpt_device {
        struct scst_tgt *scst_tgt;
 };
 
-/*
- * Sense code/qualifier pairs (sense_data::key) as defined in the SCSI Primary
- * Commands (SPC) standard. Bits 0 .. 3 contain the sense key, bit 4 is
- * reserved, bit 5 is the ILI (incorrect length indicator) bit, bit 6 is the
- * EOM (end-of-medium) bit and bit 7 is the
- * FILEMARK bit.
- */
-enum {
-       NO_ADD_SENSE            = 0x00,
-       LUN_NOT_READY           = 0x04, /* HARDWARE ERROR */
-       INVALID_CDB             = 0x24, /* ILI | HARDWARE ERROR */
-       INTERNAL_TARGET_FAILURE = 0x44  /* EOM | HARDWARE ERROR */
-};
-
-/*
- * Sense data structure containing three sense bytes. See also the SCSI Primary
- * Commands (SPC) standard.
- */
-struct sense_data {
-       u8 err_code;
-       u8 segment_number;
-       u8 key;
-       u8 info_bytes[4];
-       u8 addl_sense_len;
-       u8 cmd_info_bytes[4];
-       u8 addl_sense_code;
-       u8 addl_sense_code_qual;
-       u16 asc_ascq;
-       u8 fru_code;
-       u8 sense_bytes[3];
-};
-
 #endif                         /* IB_SRPT_H */