iscsi-target: Fix iscsit_add_reject* usage for iser
authorNicholas Bellinger <nab@linux-iscsi.org>
Wed, 3 Jul 2013 10:48:24 +0000 (03:48 -0700)
committerNicholas Bellinger <nab@linux-iscsi.org>
Sun, 7 Jul 2013 04:59:53 +0000 (21:59 -0700)
This patch changes iscsit_add_reject() + iscsit_add_reject_from_cmd()
usage to not sleep on iscsi_cmd->reject_comp to address a free-after-use
usage bug in v3.10 with iser-target code.

It saves ->reject_reason for use within iscsit_build_reject() so the
correct value for both transport cases.  It also drops the legacy
fail_conn parameter usage throughput iscsi-target code and adds
two iscsit_add_reject_cmd() and iscsit_reject_cmd helper functions,
along with various small cleanups.

(v2: Re-enable target_put_sess_cmd() to be called from
     iscsit_add_reject_from_cmd() for rejects invoked after
     target_get_sess_cmd() has been called)

Cc: Or Gerlitz <ogerlitz@mellanox.com>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: stable@vger.kernel.org # 3.10+
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
drivers/infiniband/ulp/isert/ib_isert.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target.h
drivers/target/iscsi/iscsi_target_core.h
drivers/target/iscsi/iscsi_target_erl0.c
drivers/target/iscsi/iscsi_target_erl1.c
drivers/target/iscsi/iscsi_target_util.c
include/target/iscsi/iscsi_transport.h

index 1b38eff..134ff58 100644 (file)
@@ -939,11 +939,6 @@ sequence_cmd:
        if (!rc && dump_payload == false && unsol_data)
                iscsit_set_unsoliticed_dataout(cmd);
 
-       if (rc == CMDSN_ERROR_CANNOT_RECOVER)
-               return iscsit_add_reject_from_cmd(
-                          ISCSI_REASON_PROTOCOL_ERROR,
-                          1, 0, (unsigned char *)hdr, cmd);
-
        return 0;
 }
 
index 19a31f9..2a25bd3 100644 (file)
@@ -628,25 +628,18 @@ static void __exit iscsi_target_cleanup_module(void)
 }
 
 static int iscsit_add_reject(
+       struct iscsi_conn *conn,
        u8 reason,
-       int fail_conn,
-       unsigned char *buf,
-       struct iscsi_conn *conn)
+       unsigned char *buf)
 {
        struct iscsi_cmd *cmd;
-       struct iscsi_reject *hdr;
-       int ret;
 
        cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
        if (!cmd)
                return -1;
 
        cmd->iscsi_opcode = ISCSI_OP_REJECT;
-       if (fail_conn)
-               cmd->cmd_flags |= ICF_REJECT_FAIL_CONN;
-
-       hdr     = (struct iscsi_reject *) cmd->pdu;
-       hdr->reason = reason;
+       cmd->reject_reason = reason;
 
        cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL);
        if (!cmd->buf_ptr) {
@@ -662,23 +655,16 @@ static int iscsit_add_reject(
        cmd->i_state = ISTATE_SEND_REJECT;
        iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
 
-       ret = wait_for_completion_interruptible(&cmd->reject_comp);
-       if (ret != 0)
-               return -1;
-
-       return (!fail_conn) ? 0 : -1;
+       return -1;
 }
 
-int iscsit_add_reject_from_cmd(
+static int iscsit_add_reject_from_cmd(
+       struct iscsi_cmd *cmd,
        u8 reason,
-       int fail_conn,
-       int add_to_conn,
-       unsigned char *buf,
-       struct iscsi_cmd *cmd)
+       bool add_to_conn,
+       unsigned char *buf)
 {
        struct iscsi_conn *conn;
-       struct iscsi_reject *hdr;
-       int ret;
 
        if (!cmd->conn) {
                pr_err("cmd->conn is NULL for ITT: 0x%08x\n",
@@ -688,11 +674,7 @@ int iscsit_add_reject_from_cmd(
        conn = cmd->conn;
 
        cmd->iscsi_opcode = ISCSI_OP_REJECT;
-       if (fail_conn)
-               cmd->cmd_flags |= ICF_REJECT_FAIL_CONN;
-
-       hdr     = (struct iscsi_reject *) cmd->pdu;
-       hdr->reason = reason;
+       cmd->reject_reason = reason;
 
        cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL);
        if (!cmd->buf_ptr) {
@@ -709,8 +691,6 @@ int iscsit_add_reject_from_cmd(
 
        cmd->i_state = ISTATE_SEND_REJECT;
        iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
-
-       ret = wait_for_completion_interruptible(&cmd->reject_comp);
        /*
         * Perform the kref_put now if se_cmd has already been setup by
         * scsit_setup_scsi_cmd()
@@ -719,12 +699,19 @@ int iscsit_add_reject_from_cmd(
                pr_debug("iscsi reject: calling target_put_sess_cmd >>>>>>\n");
                target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
        }
-       if (ret != 0)
-               return -1;
+       return -1;
+}
 
-       return (!fail_conn) ? 0 : -1;
+static int iscsit_add_reject_cmd(struct iscsi_cmd *cmd, u8 reason,
+                                unsigned char *buf)
+{
+       return iscsit_add_reject_from_cmd(cmd, reason, true, buf);
+}
+
+int iscsit_reject_cmd(struct iscsi_cmd *cmd, u8 reason, unsigned char *buf)
+{
+       return iscsit_add_reject_from_cmd(cmd, reason, false, buf);
 }
-EXPORT_SYMBOL(iscsit_add_reject_from_cmd);
 
 /*
  * Map some portion of the allocated scatterlist to an iovec, suitable for
@@ -844,8 +831,8 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
            !(hdr->flags & ISCSI_FLAG_CMD_FINAL)) {
                pr_err("ISCSI_FLAG_CMD_WRITE & ISCSI_FLAG_CMD_FINAL"
                                " not set. Bad iSCSI Initiator.\n");
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
-                               1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                                            ISCSI_REASON_BOOKMARK_INVALID, buf);
        }
 
        if (((hdr->flags & ISCSI_FLAG_CMD_READ) ||
@@ -865,8 +852,8 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                pr_err("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE"
                        " set when Expected Data Transfer Length is 0 for"
                        " CDB: 0x%02x. Bad iSCSI Initiator.\n", hdr->cdb[0]);
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
-                               1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                                            ISCSI_REASON_BOOKMARK_INVALID, buf);
        }
 done:
 
@@ -875,62 +862,62 @@ done:
                pr_err("ISCSI_FLAG_CMD_READ and/or ISCSI_FLAG_CMD_WRITE"
                        " MUST be set if Expected Data Transfer Length is not 0."
                        " Bad iSCSI Initiator\n");
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
-                               1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                                            ISCSI_REASON_BOOKMARK_INVALID, buf);
        }
 
        if ((hdr->flags & ISCSI_FLAG_CMD_READ) &&
            (hdr->flags & ISCSI_FLAG_CMD_WRITE)) {
                pr_err("Bidirectional operations not supported!\n");
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
-                               1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                                            ISCSI_REASON_BOOKMARK_INVALID, buf);
        }
 
        if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
                pr_err("Illegally set Immediate Bit in iSCSI Initiator"
                                " Scsi Command PDU.\n");
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
-                               1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                                            ISCSI_REASON_BOOKMARK_INVALID, buf);
        }
 
        if (payload_length && !conn->sess->sess_ops->ImmediateData) {
                pr_err("ImmediateData=No but DataSegmentLength=%u,"
                        " protocol error.\n", payload_length);
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
-                               1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                                            ISCSI_REASON_PROTOCOL_ERROR, buf);
        }
 
-       if ((be32_to_cpu(hdr->data_length )== payload_length) &&
+       if ((be32_to_cpu(hdr->data_length== payload_length) &&
            (!(hdr->flags & ISCSI_FLAG_CMD_FINAL))) {
                pr_err("Expected Data Transfer Length and Length of"
                        " Immediate Data are the same, but ISCSI_FLAG_CMD_FINAL"
                        " bit is not set protocol error\n");
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
-                               1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                                            ISCSI_REASON_PROTOCOL_ERROR, buf);
        }
 
        if (payload_length > be32_to_cpu(hdr->data_length)) {
                pr_err("DataSegmentLength: %u is greater than"
                        " EDTL: %u, protocol error.\n", payload_length,
                                hdr->data_length);
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
-                               1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                                            ISCSI_REASON_PROTOCOL_ERROR, buf);
        }
 
        if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
                pr_err("DataSegmentLength: %u is greater than"
                        " MaxXmitDataSegmentLength: %u, protocol error.\n",
                        payload_length, conn->conn_ops->MaxXmitDataSegmentLength);
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
-                               1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                                            ISCSI_REASON_PROTOCOL_ERROR, buf);
        }
 
        if (payload_length > conn->sess->sess_ops->FirstBurstLength) {
                pr_err("DataSegmentLength: %u is greater than"
                        " FirstBurstLength: %u, protocol error.\n",
                        payload_length, conn->sess->sess_ops->FirstBurstLength);
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
-                               1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                                            ISCSI_REASON_BOOKMARK_INVALID, buf);
        }
 
        data_direction = (hdr->flags & ISCSI_FLAG_CMD_WRITE) ? DMA_TO_DEVICE :
@@ -985,9 +972,8 @@ done:
 
                dr = iscsit_allocate_datain_req();
                if (!dr)
-                       return iscsit_add_reject_from_cmd(
-                                       ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                                       1, 1, buf, cmd);
+                       return iscsit_add_reject_cmd(cmd,
+                                       ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
 
                iscsit_attach_datain_req(cmd, dr);
        }
@@ -1015,18 +1001,16 @@ done:
        cmd->sense_reason = target_setup_cmd_from_cdb(&cmd->se_cmd, hdr->cdb);
        if (cmd->sense_reason) {
                if (cmd->sense_reason == TCM_OUT_OF_RESOURCES) {
-                       return iscsit_add_reject_from_cmd(
-                                       ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                                       1, 1, buf, cmd);
+                       return iscsit_add_reject_cmd(cmd,
+                                       ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
                }
 
                goto attach_cmd;
        }
 
        if (iscsit_build_pdu_and_seq_lists(cmd, payload_length) < 0) {
-               return iscsit_add_reject_from_cmd(
-                       ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                       1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                               ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
        }
 
 attach_cmd:
@@ -1075,10 +1059,6 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
 
                        target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
                        return 0;
-               } else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) {
-                       return iscsit_add_reject_from_cmd(
-                               ISCSI_REASON_PROTOCOL_ERROR,
-                               1, 0, (unsigned char *)hdr, cmd);
                }
        }
 
@@ -1149,11 +1129,6 @@ after_immediate_data:
                } else if (cmd->unsolicited_data)
                        iscsit_set_unsoliticed_dataout(cmd);
 
-               if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
-                       return iscsit_add_reject_from_cmd(
-                               ISCSI_REASON_PROTOCOL_ERROR,
-                               1, 0, (unsigned char *)hdr, cmd);
-
        } else if (immed_ret == IMMEDIATE_DATA_ERL1_CRC_FAILURE) {
                /*
                 * Immediate Data failed DataCRC and ERL>=1,
@@ -1190,9 +1165,8 @@ iscsit_handle_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
         * traditional iSCSI block I/O.
         */
        if (iscsit_allocate_iovecs(cmd) < 0) {
-               return iscsit_add_reject_from_cmd(
-                               ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                               1, 0, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                               ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
        }
        immed_data = cmd->immediate_data;
 
@@ -1282,8 +1256,8 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf,
 
        if (!payload_length) {
                pr_err("DataOUT payload is ZERO, protocol error.\n");
-               return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
-                                       buf, conn);
+               return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
+                                        buf);
        }
 
        /* iSCSI write */
@@ -1300,8 +1274,8 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf,
                pr_err("DataSegmentLength: %u is greater than"
                        " MaxXmitDataSegmentLength: %u\n", payload_length,
                        conn->conn_ops->MaxXmitDataSegmentLength);
-               return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
-                                       buf, conn);
+               return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
+                                        buf);
        }
 
        cmd = iscsit_find_cmd_from_itt_or_dump(conn, hdr->itt,
@@ -1324,8 +1298,7 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf,
        if (cmd->data_direction != DMA_TO_DEVICE) {
                pr_err("Command ITT: 0x%08x received DataOUT for a"
                        " NON-WRITE command.\n", cmd->init_task_tag);
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
-                               1, 0, buf, cmd);
+               return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, buf);
        }
        se_cmd = &cmd->se_cmd;
        iscsit_mod_dataout_timer(cmd);
@@ -1334,8 +1307,7 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf,
                pr_err("DataOut Offset: %u, Length %u greater than"
                        " iSCSI Command EDTL %u, protocol error.\n",
                        hdr->offset, payload_length, cmd->se_cmd.data_length);
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
-                               1, 0, buf, cmd);
+               return iscsit_reject_cmd(cmd, ISCSI_REASON_BOOKMARK_INVALID, buf);
        }
 
        if (cmd->unsolicited_data) {
@@ -1543,8 +1515,8 @@ int iscsit_setup_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
        if (hdr->itt == RESERVED_ITT && !(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
                pr_err("NOPOUT ITT is reserved, but Immediate Bit is"
                        " not set, protocol error.\n");
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
-                                       1, 0, (unsigned char *)hdr, cmd);
+               return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
+                                        (unsigned char *)hdr);
        }
 
        if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
@@ -1552,8 +1524,8 @@ int iscsit_setup_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                        " greater than MaxXmitDataSegmentLength: %u, protocol"
                        " error.\n", payload_length,
                        conn->conn_ops->MaxXmitDataSegmentLength);
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
-                                       1, 0, (unsigned char *)hdr, cmd);
+               return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
+                                        (unsigned char *)hdr);
        }
 
        pr_debug("Got NOPOUT Ping %s ITT: 0x%08x, TTT: 0x%08x,"
@@ -1612,9 +1584,7 @@ int iscsit_process_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                        return 0;
 
                if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
-                       return iscsit_add_reject_from_cmd(
-                                       ISCSI_REASON_PROTOCOL_ERROR,
-                                       1, 0, (unsigned char *)hdr, cmd);
+                       return -1;
 
                return 0;
        }
@@ -1780,8 +1750,8 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                pr_err("Task Management Request TASK_REASSIGN not"
                        " issued as immediate command, bad iSCSI Initiator"
                                "implementation\n");
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
-                                       1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                                            ISCSI_REASON_PROTOCOL_ERROR, buf);
        }
        if ((function != ISCSI_TM_FUNC_ABORT_TASK) &&
            be32_to_cpu(hdr->refcmdsn) != ISCSI_RESERVED_TAG)
@@ -1793,9 +1763,9 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
        if (!cmd->tmr_req) {
                pr_err("Unable to allocate memory for"
                        " Task Management command!\n");
-               return iscsit_add_reject_from_cmd(
-                       ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                       1, 1, buf, cmd);
+               return iscsit_add_reject_cmd(cmd,
+                                            ISCSI_REASON_BOOKMARK_NO_RESOURCES,
+                                            buf);
        }
 
        /*
@@ -1837,17 +1807,15 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                default:
                        pr_err("Unknown iSCSI TMR Function:"
                               " 0x%02x\n", function);
-                       return iscsit_add_reject_from_cmd(
-                               ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                               1, 1, buf, cmd);
+                       return iscsit_add_reject_cmd(cmd,
+                               ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
                }
 
                ret = core_tmr_alloc_req(&cmd->se_cmd, cmd->tmr_req,
                                         tcm_function, GFP_KERNEL);
                if (ret < 0)
-                       return iscsit_add_reject_from_cmd(
-                               ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                               1, 1, buf, cmd);
+                       return iscsit_add_reject_cmd(cmd,
+                               ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
 
                cmd->tmr_req->se_tmr_req = cmd->se_cmd.se_tmr_req;
        }
@@ -1906,9 +1874,8 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                        break;
 
                if (iscsit_check_task_reassign_expdatasn(tmr_req, conn) < 0)
-                       return iscsit_add_reject_from_cmd(
-                                       ISCSI_REASON_BOOKMARK_INVALID, 1, 1,
-                                       buf, cmd);
+                       return iscsit_add_reject_cmd(cmd,
+                                       ISCSI_REASON_BOOKMARK_INVALID, buf);
                break;
        default:
                pr_err("Unknown TMR function: 0x%02x, protocol"
@@ -1932,9 +1899,7 @@ attach:
                else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP)
                        return 0;
                else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
-                       return iscsit_add_reject_from_cmd(
-                                       ISCSI_REASON_PROTOCOL_ERROR,
-                                       1, 0, buf, cmd);
+                       return -1;
        }
        iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
 
@@ -1970,8 +1935,8 @@ iscsit_setup_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                pr_err("Unable to accept text parameter length: %u"
                        "greater than MaxXmitDataSegmentLength %u.\n",
                       payload_length, conn->conn_ops->MaxXmitDataSegmentLength);
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
-                                       1, 0, (unsigned char *)hdr, cmd);
+               return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
+                                        (unsigned char *)hdr);
        }
 
        pr_debug("Got Text Request: ITT: 0x%08x, CmdSN: 0x%08x,"
@@ -2033,17 +1998,16 @@ iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
        if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
                cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
                if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
-                       return iscsit_add_reject_from_cmd(
-                                       ISCSI_REASON_PROTOCOL_ERROR,
-                                       1, 0, (unsigned char *)hdr, cmd);
+                       return -1;
+
                return 0;
        }
 
        return iscsit_execute_cmd(cmd, 0);
 
 reject:
-       return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
-                                         0, 0, (unsigned char *)hdr, cmd);
+       return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
+                                (unsigned char *)hdr);
 }
 EXPORT_SYMBOL(iscsit_process_text_cmd);
 
@@ -2139,8 +2103,7 @@ iscsit_handle_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
 reject:
        kfree(cmd->text_in_ptr);
        cmd->text_in_ptr = NULL;
-       return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
-                                         0, 0, buf, cmd);
+       return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, buf);
 }
 EXPORT_SYMBOL(iscsit_handle_text_cmd);
 
@@ -2322,13 +2285,10 @@ iscsit_handle_logout_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                        return ret;
        } else {
                cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
-               if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
+               if (cmdsn_ret == CMDSN_LOWER_THAN_EXP)
                        logout_remove = 0;
-               } else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) {
-                       return iscsit_add_reject_from_cmd(
-                               ISCSI_REASON_PROTOCOL_ERROR,
-                               1, 0, buf, cmd);
-               }
+               else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
+                       return -1;
        }
 
        return logout_remove;
@@ -2352,8 +2312,8 @@ static int iscsit_handle_snack(
        if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
                pr_err("Initiator sent SNACK request while in"
                        " ErrorRecoveryLevel=0.\n");
-               return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
-                                       buf, conn);
+               return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
+                                        buf);
        }
        /*
         * SNACK_DATA and SNACK_R2T are both 0,  so check which function to
@@ -2377,13 +2337,13 @@ static int iscsit_handle_snack(
        case ISCSI_FLAG_SNACK_TYPE_RDATA:
                /* FIXME: Support R-Data SNACK */
                pr_err("R-Data SNACK Not Supported.\n");
-               return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
-                                       buf, conn);
+               return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
+                                        buf);
        default:
                pr_err("Unknown SNACK type 0x%02x, protocol"
                        " error.\n", hdr->flags & 0x0f);
-               return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
-                                       buf, conn);
+               return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
+                                        buf);
        }
 
        return 0;
@@ -2455,14 +2415,14 @@ static int iscsit_handle_immediate_data(
                                pr_err("Unable to recover from"
                                        " Immediate Data digest failure while"
                                        " in ERL=0.\n");
-                               iscsit_add_reject_from_cmd(
+                               iscsit_reject_cmd(cmd,
                                                ISCSI_REASON_DATA_DIGEST_ERROR,
-                                               1, 0, (unsigned char *)hdr, cmd);
+                                               (unsigned char *)hdr);
                                return IMMEDIATE_DATA_CANNOT_RECOVER;
                        } else {
-                               iscsit_add_reject_from_cmd(
+                               iscsit_reject_cmd(cmd,
                                                ISCSI_REASON_DATA_DIGEST_ERROR,
-                                               0, 0, (unsigned char *)hdr, cmd);
+                                               (unsigned char *)hdr);
                                return IMMEDIATE_DATA_ERL1_CRC_FAILURE;
                        }
                } else {
@@ -3595,6 +3555,7 @@ iscsit_build_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
                    struct iscsi_reject *hdr)
 {
        hdr->opcode             = ISCSI_OP_REJECT;
+       hdr->reason             = cmd->reject_reason;
        hdr->flags              |= ISCSI_FLAG_CMD_FINAL;
        hton24(hdr->dlength, ISCSI_HDR_LEN);
        hdr->ffffffff           = cpu_to_be32(0xffffffff);
@@ -3868,18 +3829,11 @@ check_rsp_state:
        case ISTATE_SEND_STATUS_RECOVERY:
        case ISTATE_SEND_TEXTRSP:
        case ISTATE_SEND_TASKMGTRSP:
+       case ISTATE_SEND_REJECT:
                spin_lock_bh(&cmd->istate_lock);
                cmd->i_state = ISTATE_SENT_STATUS;
                spin_unlock_bh(&cmd->istate_lock);
                break;
-       case ISTATE_SEND_REJECT:
-               if (cmd->cmd_flags & ICF_REJECT_FAIL_CONN) {
-                       cmd->cmd_flags &= ~ICF_REJECT_FAIL_CONN;
-                       complete(&cmd->reject_comp);
-                       goto err;
-               }
-               complete(&cmd->reject_comp);
-               break;
        default:
                pr_err("Unknown Opcode: 0x%02x ITT:"
                       " 0x%08x, i_state: %d on CID: %hu\n",
@@ -3984,8 +3938,7 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)
        case ISCSI_OP_SCSI_CMD:
                cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
                if (!cmd)
-                       return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                                               1, buf, conn);
+                       goto reject;
 
                ret = iscsit_handle_scsi_cmd(conn, cmd, buf);
                break;
@@ -3997,32 +3950,28 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)
                if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
                        cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
                        if (!cmd)
-                               return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                                               1, buf, conn);
+                               goto reject;
                }
                ret = iscsit_handle_nop_out(conn, cmd, buf);
                break;
        case ISCSI_OP_SCSI_TMFUNC:
                cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
                if (!cmd)
-                       return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                                               1, buf, conn);
+                       goto reject;
 
                ret = iscsit_handle_task_mgt_cmd(conn, cmd, buf);
                break;
        case ISCSI_OP_TEXT:
                cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
                if (!cmd)
-                       return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                                               1, buf, conn);
+                       goto reject;
 
                ret = iscsit_handle_text_cmd(conn, cmd, buf);
                break;
        case ISCSI_OP_LOGOUT:
                cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
                if (!cmd)
-                       return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                                               1, buf, conn);
+                       goto reject;
 
                ret = iscsit_handle_logout_cmd(conn, cmd, buf);
                if (ret > 0)
@@ -4054,6 +4003,8 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)
        }
 
        return ret;
+reject:
+       return iscsit_add_reject(conn, ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
 }
 
 int iscsi_target_rx_thread(void *arg)
@@ -4148,8 +4099,8 @@ restart:
                    (!(opcode & ISCSI_OP_LOGOUT)))) {
                        pr_err("Received illegal iSCSI Opcode: 0x%02x"
                        " while in Discovery Session, rejecting.\n", opcode);
-                       iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
-                                       buffer, conn);
+                       iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
+                                         buffer);
                        goto transport_err;
                }
 
index a0050b2..2c437cb 100644 (file)
@@ -15,7 +15,7 @@ extern struct iscsi_np *iscsit_add_np(struct __kernel_sockaddr_storage *,
 extern int iscsit_reset_np_thread(struct iscsi_np *, struct iscsi_tpg_np *,
                                struct iscsi_portal_group *);
 extern int iscsit_del_np(struct iscsi_np *);
-extern int iscsit_add_reject_from_cmd(u8, int, int, unsigned char *, struct iscsi_cmd *);
+extern int iscsit_reject_cmd(struct iscsi_cmd *cmd, u8, unsigned char *);
 extern void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *);
 extern int iscsit_logout_closesession(struct iscsi_cmd *, struct iscsi_conn *);
 extern int iscsit_logout_closeconnection(struct iscsi_cmd *, struct iscsi_conn *);
index caa0ad9..4f77a78 100644 (file)
@@ -132,9 +132,8 @@ enum cmd_flags_table {
        ICF_CONTIG_MEMORY                       = 0x00000020,
        ICF_ATTACHED_TO_RQUEUE                  = 0x00000040,
        ICF_OOO_CMDSN                           = 0x00000080,
-       ICF_REJECT_FAIL_CONN                    = 0x00000100,
-       IFC_SENDTARGETS_ALL                     = 0x00000200,
-       IFC_SENDTARGETS_SINGLE                  = 0x00000400,
+       IFC_SENDTARGETS_ALL                     = 0x00000100,
+       IFC_SENDTARGETS_SINGLE                  = 0x00000200,
 };
 
 /* struct iscsi_cmd->i_state */
@@ -368,6 +367,8 @@ struct iscsi_cmd {
        u8                      maxcmdsn_inc;
        /* Immediate Unsolicited Dataout */
        u8                      unsolicited_data;
+       /* Reject reason code */
+       u8                      reject_reason;
        /* CID contained in logout PDU when opcode == ISCSI_INIT_LOGOUT_CMND */
        u16                     logout_cid;
        /* Command flags */
@@ -450,7 +451,6 @@ struct iscsi_cmd {
        struct list_head        datain_list;
        /* R2T List */
        struct list_head        cmd_r2t_list;
-       struct completion       reject_comp;
        /* Timer for DataOUT */
        struct timer_list       dataout_timer;
        /* Iovecs for SCSI data payload RX/TX w/ kernel level sockets */
index 8e6298c..8f074e0 100644 (file)
@@ -746,13 +746,12 @@ int iscsit_check_post_dataout(
                if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
                        pr_err("Unable to recover from DataOUT CRC"
                                " failure while ERL=0, closing session.\n");
-                       iscsit_add_reject_from_cmd(ISCSI_REASON_DATA_DIGEST_ERROR,
-                                       1, 0, buf, cmd);
+                       iscsit_reject_cmd(cmd, ISCSI_REASON_DATA_DIGEST_ERROR,
+                                         buf);
                        return DATAOUT_CANNOT_RECOVER;
                }
 
-               iscsit_add_reject_from_cmd(ISCSI_REASON_DATA_DIGEST_ERROR,
-                               0, 0, buf, cmd);
+               iscsit_reject_cmd(cmd, ISCSI_REASON_DATA_DIGEST_ERROR, buf);
                return iscsit_dataout_post_crc_failed(cmd, buf);
        }
 }
index 40d9dbc..d00f132 100644 (file)
@@ -162,9 +162,8 @@ static int iscsit_handle_r2t_snack(
                        " protocol error.\n", cmd->init_task_tag, begrun,
                        (begrun + runlength), cmd->acked_data_sn);
 
-                       return iscsit_add_reject_from_cmd(
-                                       ISCSI_REASON_PROTOCOL_ERROR,
-                                       1, 0, buf, cmd);
+                       return iscsit_reject_cmd(cmd,
+                                       ISCSI_REASON_PROTOCOL_ERROR, buf);
        }
 
        if (runlength) {
@@ -173,8 +172,8 @@ static int iscsit_handle_r2t_snack(
                        " with BegRun: 0x%08x, RunLength: 0x%08x, exceeds"
                        " current R2TSN: 0x%08x, protocol error.\n",
                        cmd->init_task_tag, begrun, runlength, cmd->r2t_sn);
-                       return iscsit_add_reject_from_cmd(
-                               ISCSI_REASON_BOOKMARK_INVALID, 1, 0, buf, cmd);
+                       return iscsit_reject_cmd(cmd,
+                                       ISCSI_REASON_BOOKMARK_INVALID, buf);
                }
                last_r2tsn = (begrun + runlength);
        } else
@@ -433,8 +432,7 @@ static int iscsit_handle_recovery_datain(
                        " protocol error.\n", cmd->init_task_tag, begrun,
                        (begrun + runlength), cmd->acked_data_sn);
 
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
-                               1, 0, buf, cmd);
+               return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, buf);
        }
 
        /*
@@ -445,14 +443,14 @@ static int iscsit_handle_recovery_datain(
                pr_err("Initiator requesting BegRun: 0x%08x, RunLength"
                        ": 0x%08x greater than maximum DataSN: 0x%08x.\n",
                                begrun, runlength, (cmd->data_sn - 1));
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
-                               1, 0, buf, cmd);
+               return iscsit_reject_cmd(cmd, ISCSI_REASON_BOOKMARK_INVALID,
+                                        buf);
        }
 
        dr = iscsit_allocate_datain_req();
        if (!dr)
-               return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
-                               1, 0, buf, cmd);
+               return iscsit_reject_cmd(cmd, ISCSI_REASON_BOOKMARK_NO_RESOURCES,
+                                        buf);
 
        dr->data_sn = dr->begrun = begrun;
        dr->runlength = runlength;
index fe712d6..96ce6f2 100644 (file)
@@ -178,7 +178,6 @@ struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, gfp_t gfp_mask)
        INIT_LIST_HEAD(&cmd->i_conn_node);
        INIT_LIST_HEAD(&cmd->datain_list);
        INIT_LIST_HEAD(&cmd->cmd_r2t_list);
-       init_completion(&cmd->reject_comp);
        spin_lock_init(&cmd->datain_lock);
        spin_lock_init(&cmd->dataout_timeout_lock);
        spin_lock_init(&cmd->istate_lock);
index ce991ba..19a43ad 100644 (file)
@@ -34,8 +34,6 @@ extern void iscsit_put_transport(struct iscsit_transport *);
 /*
  * From iscsi_target.c
  */
-extern int iscsit_add_reject_from_cmd(u8, int, int, unsigned char *,
-                               struct iscsi_cmd *);
 extern int iscsit_setup_scsi_cmd(struct iscsi_conn *, struct iscsi_cmd *,
                                unsigned char *);
 extern void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *);