From: Greg Kroah-Hartman Date: Sat, 28 Jun 2014 00:11:08 +0000 (-0700) Subject: 3.10-stable patches X-Git-Tag: v3.4.96~24 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7ead85c472dd24468946256a03cf5f4d610bbeaf;p=thirdparty%2Fkernel%2Fstable-queue.git 3.10-stable patches added patches: iscsi-target-fix-abort_task-connection-reset-iscsi_queue_req-memory-leak.patch scsi_cmnd-introduce-scsi_transfer_length-helper.patch target-report-correct-response-length-for-some-commands.patch target-set-cmd_t_active-bit-for-task-management-requests.patch target-use-complete_all-for-se_cmd-t_transport_stop_comp.patch --- diff --git a/queue-3.10/iscsi-target-fix-abort_task-connection-reset-iscsi_queue_req-memory-leak.patch b/queue-3.10/iscsi-target-fix-abort_task-connection-reset-iscsi_queue_req-memory-leak.patch new file mode 100644 index 00000000000..a36460b56a0 --- /dev/null +++ b/queue-3.10/iscsi-target-fix-abort_task-connection-reset-iscsi_queue_req-memory-leak.patch @@ -0,0 +1,48 @@ +From bbc050488525e1ab1194c27355f63c66814385b8 Mon Sep 17 00:00:00 2001 +From: Nicholas Bellinger +Date: Tue, 10 Jun 2014 04:03:54 +0000 +Subject: iscsi-target: Fix ABORT_TASK + connection reset iscsi_queue_req memory leak + +From: Nicholas Bellinger + +commit bbc050488525e1ab1194c27355f63c66814385b8 upstream. + +This patch fixes a iscsi_queue_req memory leak when ABORT_TASK response +has been queued by TFO->queue_tm_rsp() -> lio_queue_tm_rsp() after a +long standing I/O completes, but the connection has already reset and +waiting for cleanup to complete in iscsit_release_commands_from_conn() +-> transport_generic_free_cmd() -> transport_wait_for_tasks() code. + +It moves iscsit_free_queue_reqs_for_conn() after the per-connection command +list has been released, so that the associated se_cmd tag can be completed + +released by target-core before freeing any remaining iscsi_queue_req memory +for the connection generated by lio_queue_tm_rsp(). + +Cc: Thomas Glanzmann +Cc: Charalampos Pournaris +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/iscsi/iscsi_target.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -4151,8 +4151,6 @@ int iscsit_close_connection( + if (conn->conn_transport->iscsit_wait_conn) + conn->conn_transport->iscsit_wait_conn(conn); + +- iscsit_free_queue_reqs_for_conn(conn); +- + /* + * During Connection recovery drop unacknowledged out of order + * commands for this connection, and prepare the other commands +@@ -4169,6 +4167,7 @@ int iscsit_close_connection( + iscsit_clear_ooo_cmdsns_for_conn(conn); + iscsit_release_commands_from_conn(conn); + } ++ iscsit_free_queue_reqs_for_conn(conn); + + /* + * Handle decrementing session or connection usage count if diff --git a/queue-3.10/scsi_cmnd-introduce-scsi_transfer_length-helper.patch b/queue-3.10/scsi_cmnd-introduce-scsi_transfer_length-helper.patch new file mode 100644 index 00000000000..b3c7f650119 --- /dev/null +++ b/queue-3.10/scsi_cmnd-introduce-scsi_transfer_length-helper.patch @@ -0,0 +1,56 @@ +From 8846bab180fa2bcfe02d4ba5288fbaba12c8f4f3 Mon Sep 17 00:00:00 2001 +From: Sagi Grimberg +Date: Wed, 11 Jun 2014 12:09:57 +0300 +Subject: scsi_cmnd: Introduce scsi_transfer_length helper + +From: Sagi Grimberg + +commit 8846bab180fa2bcfe02d4ba5288fbaba12c8f4f3 upstream. + +In case protection information exists on the wire +scsi transports should include it in the transfer +byte count (even if protection information does not +exist in the host memory space). This helper will +compute the total transfer length from the scsi +command data length and protection attributes. + +Signed-off-by: Sagi Grimberg +Signed-off-by: Martin K. Petersen +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + include/scsi/scsi_cmnd.h | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +--- a/include/scsi/scsi_cmnd.h ++++ b/include/scsi/scsi_cmnd.h +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + + struct Scsi_Host; + struct scsi_device; +@@ -309,4 +310,20 @@ static inline void set_driver_byte(struc + cmd->result = (cmd->result & 0x00ffffff) | (status << 24); + } + ++static inline unsigned scsi_transfer_length(struct scsi_cmnd *scmd) ++{ ++ unsigned int xfer_len = blk_rq_bytes(scmd->request); ++ unsigned int prot_op = scsi_get_prot_op(scmd); ++ unsigned int sector_size = scmd->device->sector_size; ++ ++ switch (prot_op) { ++ case SCSI_PROT_NORMAL: ++ case SCSI_PROT_WRITE_STRIP: ++ case SCSI_PROT_READ_INSERT: ++ return xfer_len; ++ } ++ ++ return xfer_len + (xfer_len >> ilog2(sector_size)) * 8; ++} ++ + #endif /* _SCSI_SCSI_CMND_H */ diff --git a/queue-3.10/series b/queue-3.10/series index db6bbc44db8..89b87a73719 100644 --- a/queue-3.10/series +++ b/queue-3.10/series @@ -49,3 +49,8 @@ bluetooth-hci_ldisc-fix-deadlock-condition.patch bluetooth-fix-l2cap-deadlock.patch target-iser-bail-from-accept_np-if-np_thread-is-trying-to-close.patch target-iser-fix-hangs-in-connection-teardown.patch +target-set-cmd_t_active-bit-for-task-management-requests.patch +target-use-complete_all-for-se_cmd-t_transport_stop_comp.patch +iscsi-target-fix-abort_task-connection-reset-iscsi_queue_req-memory-leak.patch +target-report-correct-response-length-for-some-commands.patch +scsi_cmnd-introduce-scsi_transfer_length-helper.patch diff --git a/queue-3.10/target-report-correct-response-length-for-some-commands.patch b/queue-3.10/target-report-correct-response-length-for-some-commands.patch new file mode 100644 index 00000000000..81cc8ca3caf --- /dev/null +++ b/queue-3.10/target-report-correct-response-length-for-some-commands.patch @@ -0,0 +1,145 @@ +From 2426bd456a61407388b6e61fc5f98dbcbebc50e2 Mon Sep 17 00:00:00 2001 +From: Roland Dreier +Date: Tue, 10 Jun 2014 11:07:47 -0700 +Subject: target: Report correct response length for some commands + +From: Roland Dreier + +commit 2426bd456a61407388b6e61fc5f98dbcbebc50e2 upstream. + +When an initiator sends an allocation length bigger than what its +command consumes, the target should only return the actual response data +and set the residual length to the unused part of the allocation length. + +Add a helper function that command handlers (INQUIRY, READ CAPACITY, +etc) can use to do this correctly, and use this code to get the correct +residual for commands that don't use the full initiator allocation in the +handlers for READ CAPACITY, READ CAPACITY(16), INQUIRY, MODE SENSE and +REPORT LUNS. + +This addresses a handful of failures as reported by Christophe with +the Windows Certification Kit: + + http://permalink.gmane.org/gmane.linux.scsi.target.devel/6515 + +Signed-off-by: Roland Dreier +Tested-by: Christophe Vu-Brugier +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/target_core_sbc.c | 4 ++-- + drivers/target/target_core_spc.c | 9 ++++++--- + drivers/target/target_core_transport.c | 17 +++++++++++++++++ + include/target/target_core_backend.h | 1 + + 4 files changed, 26 insertions(+), 5 deletions(-) + +--- a/drivers/target/target_core_sbc.c ++++ b/drivers/target/target_core_sbc.c +@@ -63,7 +63,7 @@ sbc_emulate_readcapacity(struct se_cmd * + transport_kunmap_data_sg(cmd); + } + +- target_complete_cmd(cmd, GOOD); ++ target_complete_cmd_with_length(cmd, GOOD, 8); + return 0; + } + +@@ -101,7 +101,7 @@ sbc_emulate_readcapacity_16(struct se_cm + transport_kunmap_data_sg(cmd); + } + +- target_complete_cmd(cmd, GOOD); ++ target_complete_cmd_with_length(cmd, GOOD, 32); + return 0; + } + +--- a/drivers/target/target_core_spc.c ++++ b/drivers/target/target_core_spc.c +@@ -628,6 +628,7 @@ spc_emulate_inquiry(struct se_cmd *cmd) + unsigned char buf[SE_INQUIRY_BUF]; + sense_reason_t ret; + int p; ++ int len = 0; + + memset(buf, 0, SE_INQUIRY_BUF); + +@@ -645,6 +646,7 @@ spc_emulate_inquiry(struct se_cmd *cmd) + } + + ret = spc_emulate_inquiry_std(cmd, buf); ++ len = buf[4] + 5; + goto out; + } + +@@ -652,6 +654,7 @@ spc_emulate_inquiry(struct se_cmd *cmd) + if (cdb[2] == evpd_handlers[p].page) { + buf[1] = cdb[2]; + ret = evpd_handlers[p].emulate(cmd, buf); ++ len = get_unaligned_be16(&buf[2]) + 4; + goto out; + } + } +@@ -667,7 +670,7 @@ out: + } + + if (!ret) +- target_complete_cmd(cmd, GOOD); ++ target_complete_cmd_with_length(cmd, GOOD, len); + return ret; + } + +@@ -985,7 +988,7 @@ set_length: + transport_kunmap_data_sg(cmd); + } + +- target_complete_cmd(cmd, GOOD); ++ target_complete_cmd_with_length(cmd, GOOD, length); + return 0; + } + +@@ -1162,7 +1165,7 @@ done: + buf[3] = (lun_count & 0xff); + transport_kunmap_data_sg(cmd); + +- target_complete_cmd(cmd, GOOD); ++ target_complete_cmd_with_length(cmd, GOOD, 8 + lun_count * 8); + return 0; + } + EXPORT_SYMBOL(spc_emulate_report_luns); +--- a/drivers/target/target_core_transport.c ++++ b/drivers/target/target_core_transport.c +@@ -633,6 +633,23 @@ void target_complete_cmd(struct se_cmd * + } + EXPORT_SYMBOL(target_complete_cmd); + ++void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int length) ++{ ++ if (scsi_status == SAM_STAT_GOOD && length < cmd->data_length) { ++ if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) { ++ cmd->residual_count += cmd->data_length - length; ++ } else { ++ cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT; ++ cmd->residual_count = cmd->data_length - length; ++ } ++ ++ cmd->data_length = length; ++ } ++ ++ target_complete_cmd(cmd, scsi_status); ++} ++EXPORT_SYMBOL(target_complete_cmd_with_length); ++ + static void target_add_to_state_list(struct se_cmd *cmd) + { + struct se_device *dev = cmd->se_dev; +--- a/include/target/target_core_backend.h ++++ b/include/target/target_core_backend.h +@@ -50,6 +50,7 @@ int transport_subsystem_register(struct + void transport_subsystem_release(struct se_subsystem_api *); + + void target_complete_cmd(struct se_cmd *, u8); ++void target_complete_cmd_with_length(struct se_cmd *, u8, int); + + sense_reason_t spc_parse_cdb(struct se_cmd *cmd, unsigned int *size); + sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd); diff --git a/queue-3.10/target-set-cmd_t_active-bit-for-task-management-requests.patch b/queue-3.10/target-set-cmd_t_active-bit-for-task-management-requests.patch new file mode 100644 index 00000000000..86a3663ac99 --- /dev/null +++ b/queue-3.10/target-set-cmd_t_active-bit-for-task-management-requests.patch @@ -0,0 +1,42 @@ +From f15e9cd910c4d9da7de43f2181f362082fc45f0f Mon Sep 17 00:00:00 2001 +From: Nicholas Bellinger +Date: Mon, 9 Jun 2014 23:13:20 +0000 +Subject: target: Set CMD_T_ACTIVE bit for Task Management Requests + +From: Nicholas Bellinger + +commit f15e9cd910c4d9da7de43f2181f362082fc45f0f upstream. + +This patch fixes a bug where se_cmd descriptors associated with a +Task Management Request (TMR) where not setting CMD_T_ACTIVE before +being dispatched into target_tmr_work() process context. + +This is required in order for transport_generic_free_cmd() -> +transport_wait_for_tasks() to wait on se_cmd->t_transport_stop_comp +if a session reset event occurs while an ABORT_TASK is outstanding +waiting for another I/O to complete. + +Cc: Thomas Glanzmann +Cc: Charalampos Pournaris +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/target_core_transport.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/target/target_core_transport.c ++++ b/drivers/target/target_core_transport.c +@@ -2877,6 +2877,12 @@ static void target_tmr_work(struct work_ + int transport_generic_handle_tmr( + struct se_cmd *cmd) + { ++ unsigned long flags; ++ ++ spin_lock_irqsave(&cmd->t_state_lock, flags); ++ cmd->transport_state |= CMD_T_ACTIVE; ++ spin_unlock_irqrestore(&cmd->t_state_lock, flags); ++ + INIT_WORK(&cmd->work, target_tmr_work); + queue_work(cmd->se_dev->tmr_wq, &cmd->work); + return 0; diff --git a/queue-3.10/target-use-complete_all-for-se_cmd-t_transport_stop_comp.patch b/queue-3.10/target-use-complete_all-for-se_cmd-t_transport_stop_comp.patch new file mode 100644 index 00000000000..411a24b84d1 --- /dev/null +++ b/queue-3.10/target-use-complete_all-for-se_cmd-t_transport_stop_comp.patch @@ -0,0 +1,56 @@ +From a95d6511303b848da45ee27b35018bb58087bdc6 Mon Sep 17 00:00:00 2001 +From: Nicholas Bellinger +Date: Mon, 9 Jun 2014 23:36:51 +0000 +Subject: target: Use complete_all for se_cmd->t_transport_stop_comp + +From: Nicholas Bellinger + +commit a95d6511303b848da45ee27b35018bb58087bdc6 upstream. + +This patch fixes a bug where multiple waiters on ->t_transport_stop_comp +occurs due to a concurrent ABORT_TASK and session reset both invoking +transport_wait_for_tasks(), while waiting for the associated se_cmd +descriptor backend processing to complete. + +For this case, complete_all() should be invoked in order to wake up +both waiters in core_tmr_abort_task() + transport_generic_free_cmd() +process contexts. + +Cc: Thomas Glanzmann +Cc: Charalampos Pournaris +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/target_core_transport.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/target/target_core_transport.c ++++ b/drivers/target/target_core_transport.c +@@ -488,7 +488,7 @@ static int transport_cmd_check_stop(stru + + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + +- complete(&cmd->t_transport_stop_comp); ++ complete_all(&cmd->t_transport_stop_comp); + return 1; + } + +@@ -617,7 +617,7 @@ void target_complete_cmd(struct se_cmd * + if (cmd->transport_state & CMD_T_ABORTED && + cmd->transport_state & CMD_T_STOP) { + spin_unlock_irqrestore(&cmd->t_state_lock, flags); +- complete(&cmd->t_transport_stop_comp); ++ complete_all(&cmd->t_transport_stop_comp); + return; + } else if (cmd->transport_state & CMD_T_FAILED) { + INIT_WORK(&cmd->work, target_complete_failure_work); +@@ -1688,7 +1688,7 @@ void target_execute_cmd(struct se_cmd *c + cmd->se_tfo->get_task_tag(cmd)); + + spin_unlock_irq(&cmd->t_state_lock); +- complete(&cmd->t_transport_stop_comp); ++ complete_all(&cmd->t_transport_stop_comp); + return; + } +