From: Greg Kroah-Hartman Date: Thu, 1 Aug 2013 23:28:02 +0000 (+0800) Subject: 3.10-stable patches X-Git-Tag: v3.0.89~5 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=70e886b8c5f3e2754b2c4a911f2586a579601ce3;p=thirdparty%2Fkernel%2Fstable-queue.git 3.10-stable patches added patches: iscsi-target-fix-iscsit_add_reject-usage-for-iser.patch iscsi-target-fix-iscsit_sequence_cmd-reject-handling-for-iser.patch perf-tools-revert-regression-in-configuration-of-python-support.patch radeon-kms-do-not-flush-uninitialized-hotplug-work.patch xen-evtchn-avoid-a-deadlock-when-unbinding-an-event-channel.patch --- diff --git a/queue-3.10/iscsi-target-fix-iscsit_add_reject-usage-for-iser.patch b/queue-3.10/iscsi-target-fix-iscsit_add_reject-usage-for-iser.patch new file mode 100644 index 00000000000..594bc3c7ab8 --- /dev/null +++ b/queue-3.10/iscsi-target-fix-iscsit_add_reject-usage-for-iser.patch @@ -0,0 +1,806 @@ +From nab@linux-iscsi.org Fri Aug 2 06:54:09 2013 +From: "Nicholas A. Bellinger" +Date: Tue, 30 Jul 2013 04:04:01 +0000 +Subject: iscsi-target: Fix iscsit_add_reject* usage for iser +To: target-devel +Cc: Greg-KH , Stable , Nicholas Bellinger , Or Gerlitz , Mike Christie +Message-ID: <1375157042-25935-2-git-send-email-nab@linux-iscsi.org> + + +From: Nicholas Bellinger + +commit ba159914086f06532079fc15141f46ffe7e04a41 upstream + +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) + +Signed-off-by: Nicholas Bellinger +Cc: Or Gerlitz +Cc: Mike Christie +Signed-off-by: Greg Kroah-Hartman +--- + drivers/infiniband/ulp/isert/ib_isert.c | 5 + drivers/target/iscsi/iscsi_target.c | 251 ++++++++++++------------------- + drivers/target/iscsi/iscsi_target.h | 2 + drivers/target/iscsi/iscsi_target_core.h | 4 + drivers/target/iscsi/iscsi_target_erl0.c | 7 + drivers/target/iscsi/iscsi_target_erl1.c | 20 +- + drivers/target/iscsi/iscsi_target_util.c | 1 + include/target/iscsi/iscsi_transport.h | 2 + 8 files changed, 116 insertions(+), 176 deletions(-) + +--- a/drivers/infiniband/ulp/isert/ib_isert.c ++++ b/drivers/infiniband/ulp/isert/ib_isert.c +@@ -957,11 +957,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; + } + +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -628,25 +628,18 @@ static void __exit iscsi_target_cleanup_ + } + + 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; ++} ++ ++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); ++} + +- return (!fail_conn) ? 0 : -1; ++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_c + !(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_c + 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 + + 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 + * 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; + +@@ -1283,8 +1257,8 @@ iscsit_check_dataout_hdr(struct iscsi_co + + 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 */ +@@ -1301,8 +1275,8 @@ iscsit_check_dataout_hdr(struct iscsi_co + 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, +@@ -1325,8 +1299,7 @@ iscsit_check_dataout_hdr(struct iscsi_co + 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); +@@ -1335,8 +1308,7 @@ iscsit_check_dataout_hdr(struct iscsi_co + 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) { +@@ -1557,8 +1529,8 @@ int iscsit_handle_nop_out(struct iscsi_c + 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(ISCSI_REASON_PROTOCOL_ERROR, 1, +- buf, conn); ++ return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, ++ (unsigned char *)hdr); + } + + if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) { +@@ -1566,8 +1538,8 @@ int iscsit_handle_nop_out(struct iscsi_c + " greater than MaxXmitDataSegmentLength: %u, protocol" + " error.\n", payload_length, + conn->conn_ops->MaxXmitDataSegmentLength); +- return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, +- buf, conn); ++ return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, ++ (unsigned char *)hdr); + } + + pr_debug("Got NOPOUT Ping %s ITT: 0x%08x, TTT: 0x%08x," +@@ -1584,9 +1556,9 @@ int iscsit_handle_nop_out(struct iscsi_c + */ + if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) { + if (!cmd) +- return iscsit_add_reject( ++ return iscsit_reject_cmd(cmd, + ISCSI_REASON_BOOKMARK_NO_RESOURCES, +- 1, buf, conn); ++ (unsigned char *)hdr); + + cmd->iscsi_opcode = ISCSI_OP_NOOP_OUT; + cmd->i_state = ISTATE_SEND_NOPIN; +@@ -1706,9 +1678,7 @@ int iscsit_handle_nop_out(struct iscsi_c + goto ping_out; + } + if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) +- return iscsit_add_reject_from_cmd( +- ISCSI_REASON_PROTOCOL_ERROR, +- 1, 0, buf, cmd); ++ return -1; + + return 0; + } +@@ -1782,8 +1752,8 @@ iscsit_handle_task_mgt_cmd(struct iscsi_ + 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) +@@ -1795,9 +1765,9 @@ iscsit_handle_task_mgt_cmd(struct iscsi_ + 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); + } + + /* +@@ -1842,17 +1812,15 @@ iscsit_handle_task_mgt_cmd(struct iscsi_ + 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; + } +@@ -1911,9 +1879,8 @@ iscsit_handle_task_mgt_cmd(struct iscsi_ + 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" +@@ -1937,9 +1904,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)); + +@@ -1989,8 +1954,7 @@ static int iscsit_handle_text_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(ISCSI_REASON_PROTOCOL_ERROR, 1, +- buf, conn); ++ return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, buf); + } + + pr_debug("Got Text Request: ITT: 0x%08x, CmdSN: 0x%08x," +@@ -2092,8 +2056,8 @@ static int iscsit_handle_text_cmd( + + cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); + if (!cmd) +- return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, +- 1, buf, conn); ++ return iscsit_add_reject(conn, ++ ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); + + cmd->iscsi_opcode = ISCSI_OP_TEXT; + cmd->i_state = ISTATE_SEND_TEXTRSP; +@@ -2113,9 +2077,7 @@ static int iscsit_handle_text_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, buf, cmd); ++ return -1; + + return 0; + } +@@ -2301,13 +2263,10 @@ iscsit_handle_logout_cmd(struct iscsi_co + 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; +@@ -2331,8 +2290,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 +@@ -2356,13 +2315,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; +@@ -2434,14 +2393,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 { +@@ -3541,6 +3500,7 @@ iscsit_build_reject(struct iscsi_cmd *cm + 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); +@@ -3814,18 +3774,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", +@@ -3930,8 +3883,7 @@ static int iscsi_target_rx_opcode(struct + 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; +@@ -3943,16 +3895,14 @@ static int iscsi_target_rx_opcode(struct + 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; +@@ -3962,8 +3912,7 @@ static int iscsi_target_rx_opcode(struct + 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) +@@ -3995,6 +3944,8 @@ static int iscsi_target_rx_opcode(struct + } + + return ret; ++reject: ++ return iscsit_add_reject(conn, ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); + } + + int iscsi_target_rx_thread(void *arg) +@@ -4094,8 +4045,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; + } + +--- a/drivers/target/iscsi/iscsi_target.h ++++ b/drivers/target/iscsi/iscsi_target.h +@@ -15,7 +15,7 @@ extern struct iscsi_np *iscsit_add_np(st + 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 *); +--- a/drivers/target/iscsi/iscsi_target_core.h ++++ b/drivers/target/iscsi/iscsi_target_core.h +@@ -132,7 +132,6 @@ enum cmd_flags_table { + ICF_CONTIG_MEMORY = 0x00000020, + ICF_ATTACHED_TO_RQUEUE = 0x00000040, + ICF_OOO_CMDSN = 0x00000080, +- ICF_REJECT_FAIL_CONN = 0x00000100, + }; + + /* struct iscsi_cmd->i_state */ +@@ -366,6 +365,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 */ +@@ -446,7 +447,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 */ +--- a/drivers/target/iscsi/iscsi_target_erl0.c ++++ b/drivers/target/iscsi/iscsi_target_erl0.c +@@ -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); + } + } +--- a/drivers/target/iscsi/iscsi_target_erl1.c ++++ b/drivers/target/iscsi/iscsi_target_erl1.c +@@ -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; +--- a/drivers/target/iscsi/iscsi_target_util.c ++++ b/drivers/target/iscsi/iscsi_target_util.c +@@ -178,7 +178,6 @@ struct iscsi_cmd *iscsit_allocate_cmd(st + 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); +--- a/include/target/iscsi/iscsi_transport.h ++++ b/include/target/iscsi/iscsi_transport.h +@@ -34,8 +34,6 @@ extern void iscsit_put_transport(struct + /* + * 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 *); diff --git a/queue-3.10/iscsi-target-fix-iscsit_sequence_cmd-reject-handling-for-iser.patch b/queue-3.10/iscsi-target-fix-iscsit_sequence_cmd-reject-handling-for-iser.patch new file mode 100644 index 00000000000..349ffac632c --- /dev/null +++ b/queue-3.10/iscsi-target-fix-iscsit_sequence_cmd-reject-handling-for-iser.patch @@ -0,0 +1,283 @@ +From nab@linux-iscsi.org Fri Aug 2 06:54:36 2013 +From: "Nicholas A. Bellinger" +Date: Tue, 30 Jul 2013 04:04:02 +0000 +Subject: iscsi-target: Fix iscsit_sequence_cmd reject handling for iser +To: target-devel +Cc: Greg-KH , Stable , Nicholas Bellinger , Or Gerlitz , Mike Christie +Message-ID: <1375157042-25935-3-git-send-email-nab@linux-iscsi.org> + + +From: Nicholas Bellinger + +commit 561bf15892375597ee59d473a704a3e634c4f311 upstream + +This patch moves ISCSI_OP_REJECT failures into iscsit_sequence_cmd() +in order to avoid external iscsit_reject_cmd() reject usage for all +PDU types. + +It also updates PDU specific handlers for traditional iscsi-target +code to not reset the session after posting a ISCSI_OP_REJECT during +setup. + +(v2: Fix CMDSN_LOWER_THAN_EXP for ISCSI_OP_SCSI to call + target_put_sess_cmd() after iscsit_sequence_cmd() failure) + +Signed-off-by: Nicholas Bellinger +Cc: Or Gerlitz +Cc: Mike Christie +Signed-off-by: Greg Kroah-Hartman +--- + drivers/infiniband/ulp/isert/ib_isert.c | 2 - + drivers/target/iscsi/iscsi_target.c | 50 +++++++++++++++++++------------ + drivers/target/iscsi/iscsi_target_erl1.c | 6 +-- + drivers/target/iscsi/iscsi_target_util.c | 26 ++++++++++++---- + drivers/target/iscsi/iscsi_target_util.h | 3 + + include/target/iscsi/iscsi_transport.h | 3 + + 6 files changed, 60 insertions(+), 30 deletions(-) + +--- a/drivers/infiniband/ulp/isert/ib_isert.c ++++ b/drivers/infiniband/ulp/isert/ib_isert.c +@@ -952,7 +952,7 @@ isert_handle_scsi_cmd(struct isert_conn + } + + sequence_cmd: +- rc = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); ++ rc = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn); + + if (!rc && dump_payload == false && unsol_data) + iscsit_set_unsoliticed_dataout(cmd); +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -1052,11 +1052,11 @@ int iscsit_process_scsi_cmd(struct iscsi + * be acknowledged. (See below) + */ + if (!cmd->immediate_data) { +- cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); +- if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) { +- if (!cmd->sense_reason) +- return 0; +- ++ cmdsn_ret = iscsit_sequence_cmd(conn, cmd, ++ (unsigned char *)hdr, hdr->cmdsn); ++ 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; + } +@@ -1083,6 +1083,9 @@ int iscsit_process_scsi_cmd(struct iscsi + * iscsit_check_received_cmdsn() in iscsit_get_immediate_data() below. + */ + if (cmd->sense_reason) { ++ if (cmd->reject_reason) ++ return 0; ++ + target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); + return 1; + } +@@ -1091,10 +1094,8 @@ int iscsit_process_scsi_cmd(struct iscsi + * the backend memory allocation. + */ + cmd->sense_reason = transport_generic_new_cmd(&cmd->se_cmd); +- if (cmd->sense_reason) { +- target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); ++ if (cmd->sense_reason) + return 1; +- } + + return 0; + } +@@ -1104,6 +1105,7 @@ static int + iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr, + bool dump_payload) + { ++ struct iscsi_conn *conn = cmd->conn; + int cmdsn_ret = 0, immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION; + /* + * Special case for Unsupported SAM WRITE Opcodes and ImmediateData=Yes. +@@ -1120,12 +1122,22 @@ after_immediate_data: + * DataCRC, check against ExpCmdSN/MaxCmdSN if + * Immediate Bit is not set. + */ +- cmdsn_ret = iscsit_sequence_cmd(cmd->conn, cmd, hdr->cmdsn); ++ cmdsn_ret = iscsit_sequence_cmd(cmd->conn, cmd, ++ (unsigned char *)hdr, hdr->cmdsn); ++ 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 (iscsit_dump_data_payload(cmd->conn, +- cmd->first_burst_len, 1) < 0) +- return -1; ++ int rc; ++ ++ rc = iscsit_dump_data_payload(cmd->conn, ++ cmd->first_burst_len, 1); ++ target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); ++ return rc; + } else if (cmd->unsolicited_data) + iscsit_set_unsoliticed_dataout(cmd); + +@@ -1159,7 +1171,7 @@ iscsit_handle_scsi_cmd(struct iscsi_conn + + rc = iscsit_setup_scsi_cmd(conn, cmd, buf); + if (rc < 0) +- return rc; ++ return 0; + /* + * Allocation iovecs needed for struct socket operations for + * traditional iSCSI block I/O. +@@ -1500,7 +1512,7 @@ static int iscsit_handle_data_out(struct + + rc = iscsit_check_dataout_hdr(conn, buf, &cmd); + if (rc < 0) +- return rc; ++ return 0; + else if (!cmd) + return 0; + +@@ -1672,7 +1684,8 @@ int iscsit_handle_nop_out(struct iscsi_c + return 0; + } + +- cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); ++ cmdsn_ret = iscsit_sequence_cmd(conn, cmd, ++ (unsigned char *)hdr, hdr->cmdsn); + if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) { + ret = 0; + goto ping_out; +@@ -1898,7 +1911,7 @@ attach: + spin_unlock_bh(&conn->cmd_lock); + + if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) { +- int cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); ++ int cmdsn_ret = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn); + if (cmdsn_ret == CMDSN_HIGHER_THAN_EXP) + out_of_order_cmdsn = 1; + else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) +@@ -2075,7 +2088,8 @@ static int iscsit_handle_text_cmd( + iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn)); + + if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) { +- cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); ++ cmdsn_ret = iscsit_sequence_cmd(conn, cmd, ++ (unsigned char *)hdr, hdr->cmdsn); + if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) + return -1; + +@@ -2262,7 +2276,7 @@ iscsit_handle_logout_cmd(struct iscsi_co + if (ret < 0) + return ret; + } else { +- cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); ++ cmdsn_ret = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn); + if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) + logout_remove = 0; + else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) +--- a/drivers/target/iscsi/iscsi_target_erl1.c ++++ b/drivers/target/iscsi/iscsi_target_erl1.c +@@ -1088,7 +1088,7 @@ int iscsit_handle_ooo_cmdsn( + + ooo_cmdsn = iscsit_allocate_ooo_cmdsn(); + if (!ooo_cmdsn) +- return CMDSN_ERROR_CANNOT_RECOVER; ++ return -ENOMEM; + + ooo_cmdsn->cmd = cmd; + ooo_cmdsn->batch_count = (batch) ? +@@ -1099,10 +1099,10 @@ int iscsit_handle_ooo_cmdsn( + + if (iscsit_attach_ooo_cmdsn(sess, ooo_cmdsn) < 0) { + kmem_cache_free(lio_ooo_cache, ooo_cmdsn); +- return CMDSN_ERROR_CANNOT_RECOVER; ++ return -ENOMEM; + } + +- return CMDSN_HIGHER_THAN_EXP; ++ return 0; + } + + static int iscsit_set_dataout_timeout_values( +--- a/drivers/target/iscsi/iscsi_target_util.c ++++ b/drivers/target/iscsi/iscsi_target_util.c +@@ -283,13 +283,12 @@ static inline int iscsit_check_received_ + * Commands may be received out of order if MC/S is in use. + * Ensure they are executed in CmdSN order. + */ +-int iscsit_sequence_cmd( +- struct iscsi_conn *conn, +- struct iscsi_cmd *cmd, +- __be32 cmdsn) ++int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, ++ unsigned char *buf, __be32 cmdsn) + { +- int ret; +- int cmdsn_ret; ++ int ret, cmdsn_ret; ++ bool reject = false; ++ u8 reason = ISCSI_REASON_BOOKMARK_NO_RESOURCES; + + mutex_lock(&conn->sess->cmdsn_mutex); + +@@ -299,9 +298,19 @@ int iscsit_sequence_cmd( + ret = iscsit_execute_cmd(cmd, 0); + if ((ret >= 0) && !list_empty(&conn->sess->sess_ooo_cmdsn_list)) + iscsit_execute_ooo_cmdsns(conn->sess); ++ else if (ret < 0) { ++ reject = true; ++ ret = CMDSN_ERROR_CANNOT_RECOVER; ++ } + break; + case CMDSN_HIGHER_THAN_EXP: + ret = iscsit_handle_ooo_cmdsn(conn->sess, cmd, be32_to_cpu(cmdsn)); ++ if (ret < 0) { ++ reject = true; ++ ret = CMDSN_ERROR_CANNOT_RECOVER; ++ break; ++ } ++ ret = CMDSN_HIGHER_THAN_EXP; + break; + case CMDSN_LOWER_THAN_EXP: + cmd->i_state = ISTATE_REMOVE; +@@ -309,11 +318,16 @@ int iscsit_sequence_cmd( + ret = cmdsn_ret; + break; + default: ++ reason = ISCSI_REASON_PROTOCOL_ERROR; ++ reject = true; + ret = cmdsn_ret; + break; + } + mutex_unlock(&conn->sess->cmdsn_mutex); + ++ if (reject) ++ iscsit_reject_cmd(cmd, reason, buf); ++ + return ret; + } + EXPORT_SYMBOL(iscsit_sequence_cmd); +--- a/drivers/target/iscsi/iscsi_target_util.h ++++ b/drivers/target/iscsi/iscsi_target_util.h +@@ -13,7 +13,8 @@ extern struct iscsi_cmd *iscsit_allocate + extern struct iscsi_seq *iscsit_get_seq_holder_for_datain(struct iscsi_cmd *, u32); + extern struct iscsi_seq *iscsit_get_seq_holder_for_r2t(struct iscsi_cmd *); + extern struct iscsi_r2t *iscsit_get_holder_for_r2tsn(struct iscsi_cmd *, u32); +-int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, __be32 cmdsn); ++extern int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, ++ unsigned char * ,__be32 cmdsn); + extern int iscsit_check_unsolicited_dataout(struct iscsi_cmd *, unsigned char *); + extern struct iscsi_cmd *iscsit_find_cmd_from_itt(struct iscsi_conn *, itt_t); + extern struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump(struct iscsi_conn *, +--- a/include/target/iscsi/iscsi_transport.h ++++ b/include/target/iscsi/iscsi_transport.h +@@ -82,4 +82,5 @@ extern int iscsit_tmr_post_handler(struc + * From iscsi_target_util.c + */ + extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, gfp_t); +-extern int iscsit_sequence_cmd(struct iscsi_conn *, struct iscsi_cmd *, __be32); ++extern int iscsit_sequence_cmd(struct iscsi_conn *, struct iscsi_cmd *, ++ unsigned char *, __be32); diff --git a/queue-3.10/perf-tools-revert-regression-in-configuration-of-python-support.patch b/queue-3.10/perf-tools-revert-regression-in-configuration-of-python-support.patch new file mode 100644 index 00000000000..d3f13a7d55c --- /dev/null +++ b/queue-3.10/perf-tools-revert-regression-in-configuration-of-python-support.patch @@ -0,0 +1,71 @@ +From a363a9da65d253fa7354ce5fd630f4f94df934cc Mon Sep 17 00:00:00 2001 +From: Michael Witten +Date: Wed, 17 Apr 2013 02:23:16 +0000 +Subject: perf tools: Revert regression in configuration of Python support + +From: Michael Witten + +commit a363a9da65d253fa7354ce5fd630f4f94df934cc upstream. + +Among other things, the following: + + commit 31160d7feab786c991780d7f0ce2755a469e0e5e + Date: Tue Jan 8 16:22:36 2013 -0500 + perf tools: Fix GNU make v3.80 compatibility issue + +attempts to aid the user by tapping into an existing error message, +as described in the commit message: + + ... Also fix an issue where _get_attempt was called with only + one argument. This prevented the error message from printing + the name of the variable that can be used to fix the problem. + +or more precisely: + + -$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2))) + +$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2),$(1))) + +However, The "missing" argument was in fact missing on purpose; it's +absence is a signal that the error message should be skipped, because +the failure would be due to the default value, not any user-supplied +value. This can be seen in how `_ge_attempt' uses `gea_err' (in the +config/utilities.mak file): + + _ge_attempt = $(if $(get-executable),$(get-executable),$(_gea_warn)$(call _gea_err,$(2))) + _gea_warn = $(warning The path '$(1)' is not executable.) + _gea_err = $(if $(1),$(error Please set '$(1)' appropriately)) + +That is, because the argument is no longer missing, the value `$(1)' +(associated with `_gea_err') always evaluates to true, thus always +triggering the error condition that is meant to be reserved for +only the case when a user explicitly supplies an invalid value. + +Concretely, the result is a regression in the Makefile's configuration +of python support; rather than gracefully disable support when the +relevant executables cannot be found according to default values, the +build process halts in error as though the user explicitly supplied +the values. + +This new commit simply reverts the offending one-line change. + +Reported-by: Pekka Enberg +Link: http://lkml.kernel.org/r/CAOJsxLHv17Ys3M7P5q25imkUxQW6LE_vABxh1N3Tt7Mv6Ho4iw@mail.gmail.com +Signed-off-by: Michael Witten +Cc: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + tools/perf/config/utilities.mak | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/tools/perf/config/utilities.mak ++++ b/tools/perf/config/utilities.mak +@@ -173,7 +173,7 @@ _ge-abspath = $(if $(is-executable),$(1) + # Usage: absolute-executable-path-or-empty = $(call get-executable-or-default,variable,default) + # + define get-executable-or-default +-$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2),$(1))) ++$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2))) + endef + _ge_attempt = $(if $(get-executable),$(get-executable),$(_gea_warn)$(call _gea_err,$(2))) + _gea_warn = $(warning The path '$(1)' is not executable.) diff --git a/queue-3.10/radeon-kms-do-not-flush-uninitialized-hotplug-work.patch b/queue-3.10/radeon-kms-do-not-flush-uninitialized-hotplug-work.patch new file mode 100644 index 00000000000..e88e9bf74e6 --- /dev/null +++ b/queue-3.10/radeon-kms-do-not-flush-uninitialized-hotplug-work.patch @@ -0,0 +1,112 @@ +From a01c34f72e7cd2624570818f579b5ab464f93de2 Mon Sep 17 00:00:00 2001 +From: Sergey Senozhatsky +Date: Sun, 14 Jul 2013 14:03:27 +0300 +Subject: radeon kms: do not flush uninitialized hotplug work + +From: Sergey Senozhatsky + +commit a01c34f72e7cd2624570818f579b5ab464f93de2 upstream. + +Fix a warning from lockdep caused by calling flush_work() for +uninitialized hotplug work. Initialize hotplug_work, audio_work +and reset_work upon successful radeon_irq_kms_init() completion +and thus perform hotplug flush_work only when rdev->irq.installed +is true. + +[ 4.790019] [drm] Loading CEDAR Microcode +[ 4.790943] r600_cp: Failed to load firmware "radeon/CEDAR_smc.bin" +[ 4.791152] [drm:evergreen_startup] *ERROR* Failed to load firmware! +[ 4.791330] radeon 0000:01:00.0: disabling GPU acceleration + +[ 4.792633] INFO: trying to register non-static key. +[ 4.792792] the code is fine but needs lockdep annotation. +[ 4.792953] turning off the locking correctness validator. + +[ 4.793114] CPU: 2 PID: 1 Comm: swapper/0 Not tainted 3.11.0-rc0-dbg-10676-gfe56456-dirty #1816 +[ 4.793314] Hardware name: Acer Aspire 5741G /Aspire 5741G , BIOS V1.20 02/08/2011 +[ 4.793507] ffffffff821fd810 ffff8801530b9a18 ffffffff8160434e 0000000000000002 +[ 4.794155] ffff8801530b9ad8 ffffffff810b8404 ffff8801530b0798 ffff8801530b0000 +[ 4.794789] ffff8801530b9b00 0000000000000046 00000000000004c0 ffffffff00000000 +[ 4.795418] Call Trace: +[ 4.795573] [] dump_stack+0x4e/0x82 +[ 4.795731] [] __lock_acquire+0x1a64/0x1d30 +[ 4.795893] [] ? dev_vprintk_emit+0x50/0x60 +[ 4.796034] [] lock_acquire+0xa4/0x200 +[ 4.796216] [] ? flush_work+0x5/0x280 +[ 4.796375] [] flush_work+0x3d/0x280 +[ 4.796520] [] ? flush_work+0x5/0x280 +[ 4.796682] [] ? trace_hardirqs_on_caller+0xfd/0x1c0 +[ 4.796862] [] ? delay_tsc+0x95/0xf0 +[ 4.797024] [] radeon_irq_kms_fini+0x2b/0x70 +[ 4.797186] [] evergreen_init+0x2a9/0x2e0 +[ 4.797347] [] radeon_device_init+0x5ef/0x700 +[ 4.797511] [] ? pci_find_capability+0x47/0x50 +[ 4.797672] [] radeon_driver_load_kms+0x8d/0x150 +[ 4.797843] [] drm_get_pci_dev+0x166/0x280 +[ 4.798007] [] ? kfree+0xf5/0x2e0 +[ 4.798168] [] ? radeon_pci_probe+0x98/0xd0 +[ 4.798329] [] radeon_pci_probe+0xaa/0xd0 +[ 4.798489] [] pci_device_probe+0x84/0xe0 +[ 4.798644] [] driver_probe_device+0x76/0x240 +[ 4.798805] [] __driver_attach+0x93/0xa0 +[ 4.798948] [] ? __device_attach+0x40/0x40 +[ 4.799126] [] bus_for_each_dev+0x6b/0xb0 +[ 4.799272] [] driver_attach+0x1e/0x20 +[ 4.799434] [] bus_add_driver+0x1f0/0x280 +[ 4.799596] [] driver_register+0x74/0x150 +[ 4.799758] [] __pci_register_driver+0x5d/0x60 +[ 4.799936] [] ? ttm_init+0x67/0x67 +[ 4.800081] [] drm_pci_init+0x115/0x130 +[ 4.800243] [] ? ttm_init+0x67/0x67 +[ 4.800405] [] radeon_init+0x9c/0xba +[ 4.800586] [] do_one_initcall+0xfa/0x150 +[ 4.800746] [] ? parse_args+0x120/0x330 +[ 4.800909] [] kernel_init_freeable+0x111/0x191 +[ 4.801052] [] ? do_early_param+0x88/0x88 +[ 4.801233] [] ? rest_init+0x140/0x140 +[ 4.801393] [] kernel_init+0xe/0x180 +[ 4.801556] [] ret_from_fork+0x7c/0xb0 +[ 4.801718] [] ? rest_init+0x140/0x140 + +Signed-off-by: Sergey Senozhatsky +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + + drivers/gpu/drm/radeon/radeon_irq_kms.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c ++++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c +@@ -241,9 +241,6 @@ int radeon_irq_kms_init(struct radeon_de + { + int r = 0; + +- INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func); +- INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi); +- + spin_lock_init(&rdev->irq.lock); + r = drm_vblank_init(rdev->ddev, rdev->num_crtc); + if (r) { +@@ -265,6 +262,10 @@ int radeon_irq_kms_init(struct radeon_de + rdev->irq.installed = false; + return r; + } ++ ++ INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func); ++ INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi); ++ + DRM_INFO("radeon: irq initialized.\n"); + return 0; + } +@@ -284,8 +285,8 @@ void radeon_irq_kms_fini(struct radeon_d + rdev->irq.installed = false; + if (rdev->msi_enabled) + pci_disable_msi(rdev->pdev); ++ flush_work(&rdev->hotplug_work); + } +- flush_work(&rdev->hotplug_work); + } + + /** diff --git a/queue-3.10/series b/queue-3.10/series index 9a63ce5b414..a06d2178762 100644 --- a/queue-3.10/series +++ b/queue-3.10/series @@ -90,3 +90,8 @@ usb-gadget-udc-core-fix-the-typo-of-udc-state-attribute.patch mm-mempolicy-fix-mbind_range-vma_adjust-interaction.patch tty_port-fix-refcounting-leak-in-tty_port_tty_hangup.patch livelock-avoidance-in-sget.patch +xen-evtchn-avoid-a-deadlock-when-unbinding-an-event-channel.patch +radeon-kms-do-not-flush-uninitialized-hotplug-work.patch +iscsi-target-fix-iscsit_add_reject-usage-for-iser.patch +iscsi-target-fix-iscsit_sequence_cmd-reject-handling-for-iser.patch +perf-tools-revert-regression-in-configuration-of-python-support.patch diff --git a/queue-3.10/xen-evtchn-avoid-a-deadlock-when-unbinding-an-event-channel.patch b/queue-3.10/xen-evtchn-avoid-a-deadlock-when-unbinding-an-event-channel.patch new file mode 100644 index 00000000000..effc3cd1c20 --- /dev/null +++ b/queue-3.10/xen-evtchn-avoid-a-deadlock-when-unbinding-an-event-channel.patch @@ -0,0 +1,103 @@ +From 179fbd5a45f0d4034cc6fd37b8d367a3b79663c4 Mon Sep 17 00:00:00 2001 +From: David Vrabel +Date: Fri, 19 Jul 2013 15:51:58 +0100 +Subject: xen/evtchn: avoid a deadlock when unbinding an event channel + +From: David Vrabel + +commit 179fbd5a45f0d4034cc6fd37b8d367a3b79663c4 upstream. + +Unbinding an event channel (either with the ioctl or when the evtchn +device is closed) may deadlock because disable_irq() is called with +port_user_lock held which is also locked by the interrupt handler. + +Think of the IOCTL_EVTCHN_UNBIND is being serviced, the routine has +just taken the lock, and an interrupt happens. The evtchn_interrupt +is invoked, tries to take the lock and spins forever. + +A quick glance at the code shows that the spinlock is a local IRQ +variant. Unfortunately that does not help as "disable_irq() waits for +the interrupt handler on all CPUs to stop running. If the irq occurs +on another VCPU, it tries to take port_user_lock and can't because +the unbind ioctl is holding it." (from David). Hence we cannot +depend on the said spinlock to protect us. We could make it a system +wide IRQ disable spinlock but there is a better way. + +We can piggyback on the fact that the existence of the spinlock is +to make get_port_user() checks be up-to-date. And we can alter those +checks to not depend on the spin lock (as it's protected by u->bind_mutex +in the ioctl) and can remove the unnecessary locking (this is +IOCTL_EVTCHN_UNBIND) path. + +In the interrupt handler we cannot use the mutex, but we do not +need it. + +"The unbind disables the irq before making the port user stale, so when +you clear it you are guaranteed that the interrupt handler that might +use that port cannot be running." (from David). + +Hence this patch removes the spinlock usage on the teardown path +and piggybacks on disable_irq happening before we muck with the +get_port_user() data. This ensures that the interrupt handler will +never run on stale data. + +Signed-off-by: David Vrabel +Signed-off-by: Konrad Rzeszutek Wilk +[v1: Expanded the commit description a bit] +Signed-off-by: Jonghwan Choi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/xen/evtchn.c | 21 ++------------------- + 1 file changed, 2 insertions(+), 19 deletions(-) + +--- a/drivers/xen/evtchn.c ++++ b/drivers/xen/evtchn.c +@@ -377,18 +377,12 @@ static long evtchn_ioctl(struct file *fi + if (unbind.port >= NR_EVENT_CHANNELS) + break; + +- spin_lock_irq(&port_user_lock); +- + rc = -ENOTCONN; +- if (get_port_user(unbind.port) != u) { +- spin_unlock_irq(&port_user_lock); ++ if (get_port_user(unbind.port) != u) + break; +- } + + disable_irq(irq_from_evtchn(unbind.port)); + +- spin_unlock_irq(&port_user_lock); +- + evtchn_unbind_from_user(u, unbind.port); + + rc = 0; +@@ -488,26 +482,15 @@ static int evtchn_release(struct inode * + int i; + struct per_user_data *u = filp->private_data; + +- spin_lock_irq(&port_user_lock); +- +- free_page((unsigned long)u->ring); +- + for (i = 0; i < NR_EVENT_CHANNELS; i++) { + if (get_port_user(i) != u) + continue; + + disable_irq(irq_from_evtchn(i)); +- } +- +- spin_unlock_irq(&port_user_lock); +- +- for (i = 0; i < NR_EVENT_CHANNELS; i++) { +- if (get_port_user(i) != u) +- continue; +- + evtchn_unbind_from_user(get_port_user(i), i); + } + ++ free_page((unsigned long)u->ring); + kfree(u->name); + kfree(u); +