[SCSI] fix oops on usb storage device disconnect

We fix the oops by enforcing the host state model.  There have also
been two extra states added: SHOST_CANCEL_RECOVERY and
SHOST_DEL_RECOVERY so we can take the model through host removal while
the recovery thread is active.

Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
这个提交包含在:
James Bottomley
2005-09-18 15:05:20 -05:00
提交者 James Bottomley
父节点 a64358db12
当前提交 939647ee30
修改 8 个文件,包含 66 行新增16 行删除

查看文件

@@ -68,19 +68,24 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag)
{
struct Scsi_Host *shost = scmd->device->host;
unsigned long flags;
int ret = 0;
if (shost->eh_wait == NULL)
return 0;
spin_lock_irqsave(shost->host_lock, flags);
if (scsi_host_set_state(shost, SHOST_RECOVERY))
if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY))
goto out_unlock;
ret = 1;
scmd->eh_eflags |= eh_flag;
list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q);
scsi_host_set_state(shost, SHOST_RECOVERY);
shost->host_failed++;
scsi_eh_wakeup(shost);
out_unlock:
spin_unlock_irqrestore(shost->host_lock, flags);
return 1;
return ret;
}
/**
@@ -176,8 +181,8 @@ void scsi_times_out(struct scsi_cmnd *scmd)
}
if (unlikely(!scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) {
panic("Error handler thread not present at %p %p %s %d",
scmd, scmd->device->host, __FILE__, __LINE__);
scmd->result |= DID_TIME_OUT << 16;
__scsi_done(scmd);
}
}
@@ -196,8 +201,7 @@ int scsi_block_when_processing_errors(struct scsi_device *sdev)
{
int online;
wait_event(sdev->host->host_wait, (sdev->host->shost_state !=
SHOST_RECOVERY));
wait_event(sdev->host->host_wait, !scsi_host_in_recovery(sdev->host));
online = scsi_device_online(sdev);
@@ -1441,6 +1445,7 @@ static void scsi_eh_lock_door(struct scsi_device *sdev)
static void scsi_restart_operations(struct Scsi_Host *shost)
{
struct scsi_device *sdev;
unsigned long flags;
/*
* If the door was locked, we need to insert a door lock request
@@ -1460,7 +1465,11 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n",
__FUNCTION__));
scsi_host_set_state(shost, SHOST_RUNNING);
spin_lock_irqsave(shost->host_lock, flags);
if (scsi_host_set_state(shost, SHOST_RUNNING))
if (scsi_host_set_state(shost, SHOST_CANCEL))
BUG_ON(scsi_host_set_state(shost, SHOST_DEL));
spin_unlock_irqrestore(shost->host_lock, flags);
wake_up(&shost->host_wait);