When max_active=1 we knew the block work was always before the unblock and the recovery work had either run or was pending behind the unblock. With the patch to enable max_active=2: commit 3ce419662dd4c9cf8db7869c4972ad51ccdf2ee3 Author: Bob Liu <bob.liu@xxxxxxxxxx> Date: Tue May 5 09:19:08 2020 +0800 scsi: iscsi: Register sysfs for iscsi workqueue for the iscsi_eh_timer_workq we could have the block or recovery work works on different threads than the unblock. __iscsi_unblock_session only tries to cancel the recovery work and so the block work could be running still, or the recovery work could be running (non pending state) or we could race and the unblock work could run cancel_delayed_work then the block work could queue the recovery work. This patches fixes this by making sure the block and recovery works are done before updating the session state and its devices. Signed-off-by: Mike Christie <michael.christie@xxxxxxxxxx> --- drivers/scsi/scsi_transport_iscsi.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index f4cc08e..bbf2eb7 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1947,10 +1947,11 @@ static void __iscsi_unblock_session(struct work_struct *work) ISCSI_DBG_TRANS_SESSION(session, "Unblocking session\n"); /* - * The recovery and unblock work get run from the same workqueue, - * so try to cancel it if it was going to run after this unblock. + * Make sure we do not race with the block or recovery work, so + * they can't overwrite our state update here. */ - cancel_delayed_work(&session->recovery_work); + flush_work(&session->block_work); + cancel_delayed_work_sync(&session->recovery_work); spin_lock_irqsave(&session->lock, flags); session->state = ISCSI_SESSION_LOGGED_IN; spin_unlock_irqrestore(&session->lock, flags); -- 1.8.3.1