diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index f73da43cdf9e..3a179302b904 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -1086,7 +1086,6 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, if (cmd->reject_reason) return 0; - target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); return 1; } /* @@ -1124,14 +1123,10 @@ iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr, */ cmdsn_ret = iscsit_sequence_cmd(cmd->conn, cmd, (unsigned char *)hdr, hdr->cmdsn); - if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) { + if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) return -1; - } else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) { - target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); - return 0; - } - if (cmd->sense_reason) { + if (cmd->sense_reason || cmdsn_ret == CMDSN_LOWER_THAN_EXP) { int rc; rc = iscsit_dump_data_payload(cmd->conn, @@ -1527,6 +1522,10 @@ 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"); + if (!cmd) + return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, + (unsigned char *)hdr); + return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, (unsigned char *)hdr); } @@ -1536,6 +1535,10 @@ 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); + if (!cmd) + return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, + (unsigned char *)hdr); + return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, (unsigned char *)hdr); } diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 3402241be87c..bc788c52b6cc 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -1163,12 +1163,11 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) if (np->np_thread_state == ISCSI_NP_THREAD_RESET) { spin_unlock_bh(&np->np_thread_lock); complete(&np->np_restart_comp); - if (ret == -ENODEV) { - iscsit_put_transport(conn->conn_transport); - kfree(conn); - conn = NULL; + iscsit_put_transport(conn->conn_transport); + kfree(conn); + conn = NULL; + if (ret == -ENODEV) goto out; - } /* Get another socket */ return 1; } diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 4cb667d720a7..9fabbf7214cd 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -97,9 +97,12 @@ spc_emulate_inquiry_std(struct se_cmd *cmd, unsigned char *buf) buf[7] = 0x2; /* CmdQue=1 */ - snprintf(&buf[8], 8, "LIO-ORG"); - snprintf(&buf[16], 16, "%s", dev->t10_wwn.model); - snprintf(&buf[32], 4, "%s", dev->t10_wwn.revision); + memcpy(&buf[8], "LIO-ORG ", 8); + memset(&buf[16], 0x20, 16); + memcpy(&buf[16], dev->t10_wwn.model, + min_t(size_t, strlen(dev->t10_wwn.model), 16)); + memcpy(&buf[32], dev->t10_wwn.revision, + min_t(size_t, strlen(dev->t10_wwn.revision), 4)); buf[4] = 31; /* Set additional length to 31 */ return 0; diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 7172d005d063..d8e49d79f8cc 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2134,6 +2134,7 @@ static void transport_write_pending_qf(struct se_cmd *cmd) int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks) { + unsigned long flags; int ret = 0; if (!(cmd->se_cmd_flags & SCF_SE_LUN_CMD)) { @@ -2144,6 +2145,16 @@ int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks) } else { if (wait_for_tasks) transport_wait_for_tasks(cmd); + /* + * Handle WRITE failure case where transport_generic_new_cmd() + * has already added se_cmd to state_list, but fabric has + * failed command before I/O submission. + */ + if (cmd->state_active) { + spin_lock_irqsave(&cmd->t_state_lock, flags); + target_remove_from_state_list(cmd); + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + } if (cmd->se_lun) transport_lun_remove_cmd(cmd);