diff options
| author | Nicholas Bellinger <nab@linux-iscsi.org> | 2016-12-07 01:45:46 -0500 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-02-14 18:25:36 -0500 |
| commit | 88e865c5d813e400ad0b135c39fe5842e95df6f4 (patch) | |
| tree | c73e3ada46ef733f497175a2da4ff7ffd2f35c05 /drivers/target | |
| parent | 4b99bb2e3643d2be438393b95a0572593c5205cf (diff) | |
target: Fix early transport_generic_handle_tmr abort scenario
commit c54eeffbe9338fa982dc853d816fda9202a13b5a upstream.
This patch fixes a bug where incoming task management requests
can be explicitly aborted during an active LUN_RESET, but who's
struct work_struct are canceled in-flight before execution.
This occurs when core_tmr_drain_tmr_list() invokes cancel_work_sync()
for the incoming se_tmr_req->task_cmd->work, resulting in cmd->work
for target_tmr_work() never getting invoked and the aborted TMR
waiting indefinately within transport_wait_for_tasks().
To address this case, perform a CMD_T_ABORTED check early in
transport_generic_handle_tmr(), and invoke the normal path via
transport_cmd_check_stop_to_fabric() to complete any TMR kthreads
blocked waiting for CMD_T_STOP in transport_wait_for_tasks().
Also, move the TRANSPORT_ISTATE_PROCESSING assignment earlier
into transport_generic_handle_tmr() so the existing check in
core_tmr_drain_tmr_list() avoids attempting abort the incoming
se_tmr_req->task_cmd->work if it has already been queued into
se_device->tmr_wq.
Reported-by: Rob Millner <rlm@daterainc.com>
Tested-by: Rob Millner <rlm@daterainc.com>
Cc: Rob Millner <rlm@daterainc.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/target')
| -rw-r--r-- | drivers/target/target_core_transport.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 7dfefd66df93..f5aed8901d70 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c | |||
| @@ -3086,7 +3086,6 @@ static void target_tmr_work(struct work_struct *work) | |||
| 3086 | spin_unlock_irqrestore(&cmd->t_state_lock, flags); | 3086 | spin_unlock_irqrestore(&cmd->t_state_lock, flags); |
| 3087 | goto check_stop; | 3087 | goto check_stop; |
| 3088 | } | 3088 | } |
| 3089 | cmd->t_state = TRANSPORT_ISTATE_PROCESSING; | ||
| 3090 | spin_unlock_irqrestore(&cmd->t_state_lock, flags); | 3089 | spin_unlock_irqrestore(&cmd->t_state_lock, flags); |
| 3091 | 3090 | ||
| 3092 | cmd->se_tfo->queue_tm_rsp(cmd); | 3091 | cmd->se_tfo->queue_tm_rsp(cmd); |
| @@ -3099,11 +3098,25 @@ int transport_generic_handle_tmr( | |||
| 3099 | struct se_cmd *cmd) | 3098 | struct se_cmd *cmd) |
| 3100 | { | 3099 | { |
| 3101 | unsigned long flags; | 3100 | unsigned long flags; |
| 3101 | bool aborted = false; | ||
| 3102 | 3102 | ||
| 3103 | spin_lock_irqsave(&cmd->t_state_lock, flags); | 3103 | spin_lock_irqsave(&cmd->t_state_lock, flags); |
| 3104 | cmd->transport_state |= CMD_T_ACTIVE; | 3104 | if (cmd->transport_state & CMD_T_ABORTED) { |
| 3105 | aborted = true; | ||
| 3106 | } else { | ||
| 3107 | cmd->t_state = TRANSPORT_ISTATE_PROCESSING; | ||
| 3108 | cmd->transport_state |= CMD_T_ACTIVE; | ||
| 3109 | } | ||
| 3105 | spin_unlock_irqrestore(&cmd->t_state_lock, flags); | 3110 | spin_unlock_irqrestore(&cmd->t_state_lock, flags); |
| 3106 | 3111 | ||
| 3112 | if (aborted) { | ||
| 3113 | pr_warn_ratelimited("handle_tmr caught CMD_T_ABORTED TMR %d" | ||
| 3114 | "ref_tag: %llu tag: %llu\n", cmd->se_tmr_req->function, | ||
| 3115 | cmd->se_tmr_req->ref_task_tag, cmd->tag); | ||
| 3116 | transport_cmd_check_stop_to_fabric(cmd); | ||
| 3117 | return 0; | ||
| 3118 | } | ||
| 3119 | |||
| 3107 | INIT_WORK(&cmd->work, target_tmr_work); | 3120 | INIT_WORK(&cmd->work, target_tmr_work); |
| 3108 | queue_work(cmd->se_dev->tmr_wq, &cmd->work); | 3121 | queue_work(cmd->se_dev->tmr_wq, &cmd->work); |
| 3109 | return 0; | 3122 | return 0; |
