target: Fix early transport_generic_handle_tmr abort scenario
authorNicholas Bellinger <nab@linux-iscsi.org>
Wed, 7 Dec 2016 06:45:46 +0000 (22:45 -0800)
committerNicholas Bellinger <nab@linux-iscsi.org>
Wed, 8 Feb 2017 15:47:19 +0000 (07:47 -0800)
commitc54eeffbe9338fa982dc853d816fda9202a13b5a
treed2ae7722aa231eb23c2a89fcaf430461f9eed320
parent0583c261e6325f392c1f7a1b9112e31298e1a4bd
target: Fix early transport_generic_handle_tmr abort scenario

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>
Cc: stable@vger.kernel.org # 3.14+
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
drivers/target/target_core_transport.c