[1/4] iscsi class: make sure the block/recovery work are done
diff mbox series

Message ID 1593560134-28148-2-git-send-email-michael.christie@oracle.com
State Accepted
Headers show
Series
  • iscsi fixes/cleanups
Related show

Commit Message

Mike Christie June 30, 2020, 11:35 p.m. UTC
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@oracle.com>
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@oracle.com>
---
 drivers/scsi/scsi_transport_iscsi.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

Patch
diff mbox series

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);