aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBrian King <brking@linux.vnet.ibm.com>2010-06-17 14:56:02 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-07-27 13:03:46 -0400
commit1117ef8aed95521f46dae3052c7120baae48c2bb (patch)
tree212f2b5fdfd67f619c8ac3930aef2c5fa9825cfa /drivers
parent0f33ece5bc3d5a9567b65cfbc736e8f206ecfc7b (diff)
[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: Brian King <brking@linux.vnet.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c31
1 files changed, 17 insertions, 14 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index e50fad96329c..83b5a174164c 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -474,23 +474,26 @@ static int map_data_for_srp_cmd(struct scsi_cmnd *cmd,
474 */ 474 */
475static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code) 475static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code)
476{ 476{
477 struct srp_event_struct *tmp_evt, *pos; 477 struct srp_event_struct *evt;
478 unsigned long flags; 478 unsigned long flags;
479 479
480 spin_lock_irqsave(hostdata->host->host_lock, flags); 480 spin_lock_irqsave(hostdata->host->host_lock, flags);
481 list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) { 481 while (!list_empty(&hostdata->sent)) {
482 list_del(&tmp_evt->list); 482 evt = list_first_entry(&hostdata->sent, struct srp_event_struct, list);
483 del_timer(&tmp_evt->timer); 483 list_del(&evt->list);
484 if (tmp_evt->cmnd) { 484 del_timer(&evt->timer);
485 tmp_evt->cmnd->result = (error_code << 16); 485
486 unmap_cmd_data(&tmp_evt->iu.srp.cmd, 486 spin_unlock_irqrestore(hostdata->host->host_lock, flags);
487 tmp_evt, 487 if (evt->cmnd) {
488 tmp_evt->hostdata->dev); 488 evt->cmnd->result = (error_code << 16);
489 if (tmp_evt->cmnd_done) 489 unmap_cmd_data(&evt->iu.srp.cmd, evt,
490 tmp_evt->cmnd_done(tmp_evt->cmnd); 490 evt->hostdata->dev);
491 } else if (tmp_evt->done) 491 if (evt->cmnd_done)
492 tmp_evt->done(tmp_evt); 492 evt->cmnd_done(evt->cmnd);
493 free_event_struct(&tmp_evt->hostdata->pool, tmp_evt); 493 } else if (evt->done)
494 evt->done(evt);
495 free_event_struct(&evt->hostdata->pool, evt);
496 spin_lock_irqsave(hostdata->host->host_lock, flags);
494 } 497 }
495 spin_unlock_irqrestore(hostdata->host->host_lock, flags); 498 spin_unlock_irqrestore(hostdata->host->host_lock, flags);
496} 499}