A command that has started execution and is then aborted is completed through target_handle_abort() (target_cmd_interrupted() -> target_abort_work()), which bypasses target_complete_ok_work(). target_handle_abort() never calls transport_complete_task_attr(), the only function that releases the SAM task-attribute accounting a command takes in target_handle_task_attr() at execute time: for a SIMPLE command the dev->non_ordered reference, and for an ORDERED command the dev->ordered_sync_in_progress state (cleared, and non_ordered resurrected, by transport_complete_ordered_sync()). The normal completion path (target_complete_ok_work()) and the failure path (transport_generic_request_failure()) both call transport_complete_task_attr() before handling the command; the abort path does not, so aborting an in-flight command leaks the accounting: - Aborting an in-flight SIMPLE command leaks a dev->non_ordered reference. A later ORDERED command then waits forever for non_ordered to drain and every subsequent command piles up on dev->delayed_cmd_list, wedging all I/O to the device. - Aborting an in-flight ORDERED command leaves dev->ordered_sync_in_progress set forever, so target_do_delayed_work() never makes progress and all subsequent commands to the device hang. Call transport_complete_task_attr() from target_handle_abort() as the completion and failure paths do. It is a no-op for commands that never set SCF_TASK_ATTR_SET (e.g. task management requests) and is idempotent via that flag, so it is also safe on the failure path that already called it before dispatching to target_abort_work(). Reproduced over an iSCSI session to a demo-mode LIO target backed by a dm-delay device: an ORDERED WRITE held in flight at the backend is aborted with ABORT_TASK, after which a follow-up command never completes (device wedged); with this patch the follow-up command completes normally. Fixes: ed1227e08099 ("scsi: target: Fix ordered tag handling") Cc: stable@vger.kernel.org Signed-off-by: Yu Zhang --- drivers/target/target_core_transport.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 1111111..2222222 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -870,6 +870,8 @@ static void target_handle_abort(struct se_cmd *cmd) WARN_ON_ONCE(kref_read(&cmd->cmd_kref) == 0); + transport_complete_task_attr(cmd); + transport_lun_remove_cmd(cmd); transport_cmd_check_stop_to_fabric(cmd); -- 2.43.0