scsi: iscsi: Fix session removal on shutdown
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 commitd1f2ce7763
("scsi: qedi: Fix host removal with running sessions") which made qedi use the common session removal function that waits on userspace instead of rolling its own kernel based removal. Link: https://lore.kernel.org/r/20220616222738.5722-7-michael.christie@oracle.com Fixes:d1f2ce7763
("scsi: qedi: Fix host removal with running sessions") Tested-by: Nilesh Javali <njavali@marvell.com> Reviewed-by: Lee Duncan <lduncan@suse.com> Reviewed-by: Nilesh Javali <njavali@marvell.com> Signed-off-by: Mike Christie <michael.christie@oracle.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
7bf01eb0d4
commit
31500e9027
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -2832,11 +2832,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;
|
||||
@ -2845,7 +2846,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))
|
||||
|
@ -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 @@ remove_host:
|
||||
#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:
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user