[SCSI] zfcp: Dont block zfcp_wq with scan
When running the scsi_scan from the zfcp workqueue and the target device does not respond, the zfcp workqueue can block until the scsi_scan hits a timeout. Move the work to the scsi host workqueue, since this one is also used for the scan from the SCSI midlayer. Signed-off-by: Swen Schillig <swen@vnet.ibm.com> Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
This commit is contained in:
committed by
James Bottomley
parent
ada81b748b
commit
92d5193b46
@ -1176,48 +1176,6 @@ static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
|
||||
}
|
||||
}
|
||||
|
||||
struct zfcp_erp_add_work {
|
||||
struct zfcp_unit *unit;
|
||||
struct work_struct work;
|
||||
};
|
||||
|
||||
static void zfcp_erp_scsi_scan(struct work_struct *work)
|
||||
{
|
||||
struct zfcp_erp_add_work *p =
|
||||
container_of(work, struct zfcp_erp_add_work, work);
|
||||
struct zfcp_unit *unit = p->unit;
|
||||
struct fc_rport *rport = unit->port->rport;
|
||||
|
||||
if (rport && rport->port_state == FC_PORTSTATE_ONLINE)
|
||||
scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
|
||||
scsilun_to_int((struct scsi_lun *)&unit->fcp_lun), 0);
|
||||
atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
|
||||
zfcp_unit_put(unit);
|
||||
wake_up(&unit->port->adapter->erp_done_wqh);
|
||||
kfree(p);
|
||||
}
|
||||
|
||||
static void zfcp_erp_schedule_work(struct zfcp_unit *unit)
|
||||
{
|
||||
struct zfcp_erp_add_work *p;
|
||||
|
||||
p = kzalloc(sizeof(*p), GFP_KERNEL);
|
||||
if (!p) {
|
||||
dev_err(&unit->port->adapter->ccw_device->dev,
|
||||
"Registering unit 0x%016Lx on port 0x%016Lx failed\n",
|
||||
(unsigned long long)unit->fcp_lun,
|
||||
(unsigned long long)unit->port->wwpn);
|
||||
return;
|
||||
}
|
||||
|
||||
zfcp_unit_get(unit);
|
||||
atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
|
||||
INIT_WORK(&p->work, zfcp_erp_scsi_scan);
|
||||
p->unit = unit;
|
||||
if (!queue_work(zfcp_data.work_queue, &p->work))
|
||||
zfcp_unit_put(unit);
|
||||
}
|
||||
|
||||
static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
|
||||
{
|
||||
struct zfcp_adapter *adapter = act->adapter;
|
||||
@ -1226,11 +1184,11 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
|
||||
|
||||
switch (act->action) {
|
||||
case ZFCP_ERP_ACTION_REOPEN_UNIT:
|
||||
flush_work(&port->rport_work);
|
||||
if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device) {
|
||||
if (!(atomic_read(&unit->status) &
|
||||
ZFCP_STATUS_UNIT_SCSI_WORK_PENDING))
|
||||
zfcp_erp_schedule_work(unit);
|
||||
zfcp_unit_get(unit);
|
||||
if (scsi_queue_work(unit->port->adapter->scsi_host,
|
||||
&unit->scsi_work) <= 0)
|
||||
zfcp_unit_put(unit);
|
||||
}
|
||||
zfcp_unit_put(unit);
|
||||
break;
|
||||
|
Reference in New Issue
Block a user