Skip to content

Commit 0c863ac

Browse files
Nicholas Bellingergregkh
authored andcommitted
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>
1 parent ee44e73 commit 0c863ac

1 file changed

Lines changed: 15 additions & 2 deletions

File tree

drivers/target/target_core_transport.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3058,7 +3058,6 @@ static void target_tmr_work(struct work_struct *work)
30583058
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
30593059
goto check_stop;
30603060
}
3061-
cmd->t_state = TRANSPORT_ISTATE_PROCESSING;
30623061
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
30633062

30643063
cmd->se_tfo->queue_tm_rsp(cmd);
@@ -3071,11 +3070,25 @@ int transport_generic_handle_tmr(
30713070
struct se_cmd *cmd)
30723071
{
30733072
unsigned long flags;
3073+
bool aborted = false;
30743074

30753075
spin_lock_irqsave(&cmd->t_state_lock, flags);
3076-
cmd->transport_state |= CMD_T_ACTIVE;
3076+
if (cmd->transport_state & CMD_T_ABORTED) {
3077+
aborted = true;
3078+
} else {
3079+
cmd->t_state = TRANSPORT_ISTATE_PROCESSING;
3080+
cmd->transport_state |= CMD_T_ACTIVE;
3081+
}
30773082
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
30783083

3084+
if (aborted) {
3085+
pr_warn_ratelimited("handle_tmr caught CMD_T_ABORTED TMR %d"
3086+
"ref_tag: %llu tag: %llu\n", cmd->se_tmr_req->function,
3087+
cmd->se_tmr_req->ref_task_tag, cmd->tag);
3088+
transport_cmd_check_stop_to_fabric(cmd);
3089+
return 0;
3090+
}
3091+
30793092
INIT_WORK(&cmd->work, target_tmr_work);
30803093
queue_work(cmd->se_dev->tmr_wq, &cmd->work);
30813094
return 0;

0 commit comments

Comments
 (0)