Re: [PATCH 04/13] scsi: iscsi: Fix session removal on shutdown

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 5/17/22 15:24, Mike Christie wrote:
When the system is shutting down iscsid is not running, so we will not get
a response to the ISCSI_ERR_INVALID_HOST error event. The system shutdown
will then hang waiting on userspace to remove the session. This has
libiscsi force the destruction of the session from the kernel when
iscsi_host_remove is called from a driver's shutdown callout.

This fixes a regression added in qedi boot with patch:

Commit: d1f2ce77638d ("scsi: qedi: Fix host removal with running
sessions")

where in that patch I had qedi use the common session removal function
that waits on userspace instead of rolling it's own kernel based removal.

Fixes: d1f2ce77638d ("scsi: qedi: Fix host removal with running sessions")
Signed-off-by: Mike Christie <michael.christie@xxxxxxxxxx>
---
  drivers/infiniband/ulp/iser/iscsi_iser.c | 4 ++--
  drivers/scsi/be2iscsi/be_main.c          | 2 +-
  drivers/scsi/bnx2i/bnx2i_iscsi.c         | 2 +-
  drivers/scsi/cxgbi/libcxgbi.c            | 2 +-
  drivers/scsi/iscsi_tcp.c                 | 4 ++--
  drivers/scsi/libiscsi.c                  | 9 +++++++--
  drivers/scsi/qedi/qedi_main.c            | 9 ++++++---
  include/scsi/libiscsi.h                  | 2 +-
  8 files changed, 21 insertions(+), 13 deletions(-)

diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index f8d0bab4424c..e36036b8f386 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -568,7 +568,7 @@ static void iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session)
  	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
iscsi_session_teardown(cls_session);
-	iscsi_host_remove(shost);
+	iscsi_host_remove(shost, false);
  	iscsi_host_free(shost);
  }
@@ -685,7 +685,7 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep,
  	return cls_session;
remove_host:
-	iscsi_host_remove(shost);
+	iscsi_host_remove(shost, false);
  free_host:
  	iscsi_host_free(shost);
  	return NULL;
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 3bb0adefbe06..02026476c39c 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -5745,7 +5745,7 @@ static void beiscsi_remove(struct pci_dev *pcidev)
  	cancel_work_sync(&phba->sess_work);
beiscsi_iface_destroy_default(phba);
-	iscsi_host_remove(phba->shost);
+	iscsi_host_remove(phba->shost, false);
  	beiscsi_disable_port(phba, 1);
/* after cancelling boot_work */
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index 15fbd09baa94..a3c800e04a2e 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -909,7 +909,7 @@ void bnx2i_free_hba(struct bnx2i_hba *hba)
  {
  	struct Scsi_Host *shost = hba->shost;
- iscsi_host_remove(shost);
+	iscsi_host_remove(shost, false);
  	INIT_LIST_HEAD(&hba->ep_ofld_list);
  	INIT_LIST_HEAD(&hba->ep_active_list);
  	INIT_LIST_HEAD(&hba->ep_destroy_list);
diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
index 4365d52c6430..32abdf0fa9aa 100644
--- a/drivers/scsi/cxgbi/libcxgbi.c
+++ b/drivers/scsi/cxgbi/libcxgbi.c
@@ -328,7 +328,7 @@ void cxgbi_hbas_remove(struct cxgbi_device *cdev)
  		chba = cdev->hbas[i];
  		if (chba) {
  			cdev->hbas[i] = NULL;
-			iscsi_host_remove(chba->shost);
+			iscsi_host_remove(chba->shost, false);
  			pci_dev_put(cdev->pdev);
  			iscsi_host_free(chba->shost);
  		}
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 9fee70d6434a..52c6f70d60ec 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -898,7 +898,7 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
  remove_session:
  	iscsi_session_teardown(cls_session);
  remove_host:
-	iscsi_host_remove(shost);
+	iscsi_host_remove(shost, false);
  free_host:
  	iscsi_host_free(shost);
  	return NULL;
@@ -915,7 +915,7 @@ static void iscsi_sw_tcp_session_destroy(struct iscsi_cls_session *cls_session)
  	iscsi_tcp_r2tpool_free(cls_session->dd_data);
  	iscsi_session_teardown(cls_session);
- iscsi_host_remove(shost);
+	iscsi_host_remove(shost, false);
  	iscsi_host_free(shost);
  }
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 797abf4f5399..3ddb701cd29c 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -2828,11 +2828,12 @@ static void iscsi_notify_host_removed(struct iscsi_cls_session *cls_session)
  /**
   * iscsi_host_remove - remove host and sessions
   * @shost: scsi host
+ * @is_shutdown: true if called from a driver shutdown callout
   *
   * If there are any sessions left, this will initiate the removal and wait
   * for the completion.
   */
-void iscsi_host_remove(struct Scsi_Host *shost)
+void iscsi_host_remove(struct Scsi_Host *shost, bool is_shutdown)
  {
  	struct iscsi_host *ihost = shost_priv(shost);
  	unsigned long flags;
@@ -2841,7 +2842,11 @@ void iscsi_host_remove(struct Scsi_Host *shost)
  	ihost->state = ISCSI_HOST_REMOVED;
  	spin_unlock_irqrestore(&ihost->lock, flags);
- iscsi_host_for_each_session(shost, iscsi_notify_host_removed);
+	if (!is_shutdown)
+		iscsi_host_for_each_session(shost, iscsi_notify_host_removed);
+	else
+		iscsi_host_for_each_session(shost, iscsi_force_destroy_session);
+
  	wait_event_interruptible(ihost->session_removal_wq,
  				 ihost->num_sessions == 0);
  	if (signal_pending(current))
diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c
index deebe62e2b41..cecfb2cb4c7b 100644
--- a/drivers/scsi/qedi/qedi_main.c
+++ b/drivers/scsi/qedi/qedi_main.c
@@ -2414,9 +2414,12 @@ static void __qedi_remove(struct pci_dev *pdev, int mode)
  	int rval;
  	u16 retry = 10;
- if (mode == QEDI_MODE_NORMAL || mode == QEDI_MODE_SHUTDOWN) {
-		iscsi_host_remove(qedi->shost);
+	if (mode == QEDI_MODE_NORMAL)
+		iscsi_host_remove(qedi->shost, false);
+	else if (mode == QEDI_MODE_SHUTDOWN)
+		iscsi_host_remove(qedi->shost, true);
+ if (mode == QEDI_MODE_NORMAL || mode == QEDI_MODE_SHUTDOWN) {
  		if (qedi->tmf_thread) {
  			destroy_workqueue(qedi->tmf_thread);
  			qedi->tmf_thread = NULL;
@@ -2791,7 +2794,7 @@ static int __qedi_probe(struct pci_dev *pdev, int mode)
  #ifdef CONFIG_DEBUG_FS
  	qedi_dbg_host_exit(&qedi->dbg_ctx);
  #endif
-	iscsi_host_remove(qedi->shost);
+	iscsi_host_remove(qedi->shost, false);
  stop_iscsi_func:
  	qedi_ops->stop(qedi->cdev);
  stop_slowpath:
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index d0a24779c52d..471422641ab3 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -411,7 +411,7 @@ extern int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev);
  extern struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
  					  int dd_data_size,
  					  bool xmit_can_sleep);
-extern void iscsi_host_remove(struct Scsi_Host *shost);
+extern void iscsi_host_remove(struct Scsi_Host *shost, bool is_shutdown);
  extern void iscsi_host_free(struct Scsi_Host *shost);
  extern int iscsi_target_alloc(struct scsi_target *starget);
  extern int iscsi_host_get_max_scsi_cmds(struct Scsi_Host *shost,

Reviewed-by: Lee Duncan <lduncan@xxxxxxxx>




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]

  Powered by Linux