Commit 1117ef8a authored by Brian King's avatar Brian King Committed by James Bottomley

[SCSI] ibmvscsi: Fix error path deadlock

Fixes a deadlock that can occur if we hit a command timeout
during the virtual adapter initialization. The event done
functions are written with the assumption that no locks are held,
however, when purging requests this is not true. Fix up the
purge function to drop the lock so that the done function
is not called with the lock held, which can cause a deadlock.
Signed-off-by: default avatarBrian King <brking@linux.vnet.ibm.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 0f33ece5
...@@ -474,23 +474,26 @@ static int map_data_for_srp_cmd(struct scsi_cmnd *cmd, ...@@ -474,23 +474,26 @@ static int map_data_for_srp_cmd(struct scsi_cmnd *cmd,
*/ */
static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code) static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code)
{ {
struct srp_event_struct *tmp_evt, *pos; struct srp_event_struct *evt;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(hostdata->host->host_lock, flags); spin_lock_irqsave(hostdata->host->host_lock, flags);
list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) { while (!list_empty(&hostdata->sent)) {
list_del(&tmp_evt->list); evt = list_first_entry(&hostdata->sent, struct srp_event_struct, list);
del_timer(&tmp_evt->timer); list_del(&evt->list);
if (tmp_evt->cmnd) { del_timer(&evt->timer);
tmp_evt->cmnd->result = (error_code << 16);
unmap_cmd_data(&tmp_evt->iu.srp.cmd, spin_unlock_irqrestore(hostdata->host->host_lock, flags);
tmp_evt, if (evt->cmnd) {
tmp_evt->hostdata->dev); evt->cmnd->result = (error_code << 16);
if (tmp_evt->cmnd_done) unmap_cmd_data(&evt->iu.srp.cmd, evt,
tmp_evt->cmnd_done(tmp_evt->cmnd); evt->hostdata->dev);
} else if (tmp_evt->done) if (evt->cmnd_done)
tmp_evt->done(tmp_evt); evt->cmnd_done(evt->cmnd);
free_event_struct(&tmp_evt->hostdata->pool, tmp_evt); } else if (evt->done)
evt->done(evt);
free_event_struct(&evt->hostdata->pool, evt);
spin_lock_irqsave(hostdata->host->host_lock, flags);
} }
spin_unlock_irqrestore(hostdata->host->host_lock, flags); spin_unlock_irqrestore(hostdata->host->host_lock, flags);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment