Skip to content

Commit

Permalink
scsi: iscsi: Hold task ref during TMF timeout handling
Browse files Browse the repository at this point in the history
For aborts, qedi needs to cleanup the FW then send the TMF from a worker
thread. While it's doing these the cmd could complete normally and the TMF
could time out. libiscsi would then complete the iscsi_task which will call
into the driver to cleanup the driver level resources while it still might
be accessing them for the cleanup/abort.

This has iscsi_eh_abort keep the iscsi_task ref if the TMF times out, so
qedi does not have to worry about if the task is being freed while in use
and does not need to get its own ref.

Link: https://lore.kernel.org/r/20210525181821.7617-18-michael.christie@oracle.com
Reviewed-by: Lee Duncan <lduncan@suse.com>
Signed-off-by: Mike Christie <michael.christie@oracle.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
  • Loading branch information
Mike Christie authored and Martin K. Petersen committed Jun 2, 2021
1 parent 7ce9fc5 commit 99b0603
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 1 deletion.
15 changes: 14 additions & 1 deletion drivers/scsi/libiscsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,11 @@ static bool cleanup_queued_task(struct iscsi_task *task)
__iscsi_put_task(task);
}

if (conn->session->running_aborted_task == task) {
conn->session->running_aborted_task = NULL;
__iscsi_put_task(task);
}

if (conn->task == task) {
conn->task = NULL;
__iscsi_put_task(task);
Expand Down Expand Up @@ -2334,6 +2339,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
iscsi_start_tx(conn);
goto success_unlocked;
case TMF_TIMEDOUT:
session->running_aborted_task = task;
spin_unlock_bh(&session->frwd_lock);
iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST);
goto failed_unlocked;
Expand Down Expand Up @@ -2367,7 +2373,14 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
failed_unlocked:
ISCSI_DBG_EH(session, "abort failed [sc %p itt 0x%x]\n", sc,
task ? task->itt : 0);
iscsi_put_task(task);
/*
* The driver might be accessing the task so hold the ref. The conn
* stop cleanup will drop the ref after ep_disconnect so we know the
* driver's no longer touching the task.
*/
if (!session->running_aborted_task)
iscsi_put_task(task);

iscsi_put_conn(conn->cls_conn);
mutex_unlock(&session->eh_mutex);
return FAILED;
Expand Down
1 change: 1 addition & 0 deletions include/scsi/libiscsi.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ struct iscsi_session {
struct iscsi_tm tmhdr;
struct timer_list tmf_timer;
int tmf_state; /* see TMF_INITIAL, etc.*/
struct iscsi_task *running_aborted_task;

/* iSCSI session-wide sequencing */
uint32_t cmdsn;
Expand Down

0 comments on commit 99b0603

Please sign in to comment.