diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2014-06-09 19:36:51 -0400 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2014-06-10 00:19:31 -0400 |
commit | a95d6511303b848da45ee27b35018bb58087bdc6 (patch) | |
tree | eefd06649a284d2c84db54e423488ce55b1c59f2 /drivers/target | |
parent | f15e9cd910c4d9da7de43f2181f362082fc45f0f (diff) |
target: Use complete_all for se_cmd->t_transport_stop_comp
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 <thomas@glanzmann.de>
Cc: Charalampos Pournaris <charpour@gmail.com>
Cc: stable@vger.kernel.org # 3.10+
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r-- | drivers/target/target_core_transport.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 195435bf1140..15dbf6e97289 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c | |||
@@ -562,7 +562,7 @@ static int transport_cmd_check_stop(struct se_cmd *cmd, bool remove_from_lists, | |||
562 | 562 | ||
563 | spin_unlock_irqrestore(&cmd->t_state_lock, flags); | 563 | spin_unlock_irqrestore(&cmd->t_state_lock, flags); |
564 | 564 | ||
565 | complete(&cmd->t_transport_stop_comp); | 565 | complete_all(&cmd->t_transport_stop_comp); |
566 | return 1; | 566 | return 1; |
567 | } | 567 | } |
568 | 568 | ||
@@ -687,7 +687,7 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) | |||
687 | if (cmd->transport_state & CMD_T_ABORTED && | 687 | if (cmd->transport_state & CMD_T_ABORTED && |
688 | cmd->transport_state & CMD_T_STOP) { | 688 | cmd->transport_state & CMD_T_STOP) { |
689 | spin_unlock_irqrestore(&cmd->t_state_lock, flags); | 689 | spin_unlock_irqrestore(&cmd->t_state_lock, flags); |
690 | complete(&cmd->t_transport_stop_comp); | 690 | complete_all(&cmd->t_transport_stop_comp); |
691 | return; | 691 | return; |
692 | } else if (!success) { | 692 | } else if (!success) { |
693 | INIT_WORK(&cmd->work, target_complete_failure_work); | 693 | INIT_WORK(&cmd->work, target_complete_failure_work); |
@@ -1761,7 +1761,7 @@ void target_execute_cmd(struct se_cmd *cmd) | |||
1761 | cmd->se_tfo->get_task_tag(cmd)); | 1761 | cmd->se_tfo->get_task_tag(cmd)); |
1762 | 1762 | ||
1763 | spin_unlock_irq(&cmd->t_state_lock); | 1763 | spin_unlock_irq(&cmd->t_state_lock); |
1764 | complete(&cmd->t_transport_stop_comp); | 1764 | complete_all(&cmd->t_transport_stop_comp); |
1765 | return; | 1765 | return; |
1766 | } | 1766 | } |
1767 | 1767 | ||