[SCSI] Fix thread termination for the SCSI error handle
From: Alan Stern <stern@rowland.harvard.edu> This patch (as561) fixes the error handler's thread-exit code. The kthread_stop call won't wake the thread from a down_interruptible, so the patch gets rid of the semaphore and simply does set_current_state(TASK_INTERRUPTIBLE); Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Modified to simplify the termination loop and correct the sleep condition. Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>hifive-unleashed-5.1
parent
939647ee30
commit
3ed7a4704b
|
@ -50,7 +50,7 @@
|
||||||
void scsi_eh_wakeup(struct Scsi_Host *shost)
|
void scsi_eh_wakeup(struct Scsi_Host *shost)
|
||||||
{
|
{
|
||||||
if (shost->host_busy == shost->host_failed) {
|
if (shost->host_busy == shost->host_failed) {
|
||||||
up(shost->eh_wait);
|
wake_up_process(shost->ehandler);
|
||||||
SCSI_LOG_ERROR_RECOVERY(5,
|
SCSI_LOG_ERROR_RECOVERY(5,
|
||||||
printk("Waking error handler thread\n"));
|
printk("Waking error handler thread\n"));
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (shost->eh_wait == NULL)
|
if (!shost->ehandler)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
spin_lock_irqsave(shost->host_lock, flags);
|
spin_lock_irqsave(shost->host_lock, flags);
|
||||||
|
@ -1591,40 +1591,31 @@ int scsi_error_handler(void *data)
|
||||||
{
|
{
|
||||||
struct Scsi_Host *shost = (struct Scsi_Host *) data;
|
struct Scsi_Host *shost = (struct Scsi_Host *) data;
|
||||||
int rtn;
|
int rtn;
|
||||||
DECLARE_MUTEX_LOCKED(sem);
|
|
||||||
|
|
||||||
current->flags |= PF_NOFREEZE;
|
current->flags |= PF_NOFREEZE;
|
||||||
shost->eh_wait = &sem;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wake up the thread that created us.
|
* Note - we always use TASK_INTERRUPTIBLE even if the module
|
||||||
|
* was loaded as part of the kernel. The reason is that
|
||||||
|
* UNINTERRUPTIBLE would cause this thread to be counted in
|
||||||
|
* the load average as a running process, and an interruptible
|
||||||
|
* wait doesn't.
|
||||||
*/
|
*/
|
||||||
SCSI_LOG_ERROR_RECOVERY(3, printk("Wake up parent of"
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
" scsi_eh_%d\n",shost->host_no));
|
while (!kthread_should_stop()) {
|
||||||
|
if (shost->host_failed == 0 ||
|
||||||
while (1) {
|
shost->host_failed != shost->host_busy) {
|
||||||
/*
|
SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler"
|
||||||
* If we get a signal, it means we are supposed to go
|
" scsi_eh_%d"
|
||||||
* away and die. This typically happens if the user is
|
" sleeping\n",
|
||||||
* trying to unload a module.
|
shost->host_no));
|
||||||
*/
|
schedule();
|
||||||
SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler"
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
" scsi_eh_%d"
|
continue;
|
||||||
" sleeping\n",shost->host_no));
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Note - we always use down_interruptible with the semaphore
|
|
||||||
* even if the module was loaded as part of the kernel. The
|
|
||||||
* reason is that down() will cause this thread to be counted
|
|
||||||
* in the load average as a running process, and down
|
|
||||||
* interruptible doesn't. Given that we need to allow this
|
|
||||||
* thread to die if the driver was loaded as a module, using
|
|
||||||
* semaphores isn't unreasonable.
|
|
||||||
*/
|
|
||||||
down_interruptible(&sem);
|
|
||||||
if (kthread_should_stop())
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
__set_current_state(TASK_RUNNING);
|
||||||
SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler"
|
SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler"
|
||||||
" scsi_eh_%d waking"
|
" scsi_eh_%d waking"
|
||||||
" up\n",shost->host_no));
|
" up\n",shost->host_no));
|
||||||
|
@ -1651,7 +1642,7 @@ int scsi_error_handler(void *data)
|
||||||
* which are still online.
|
* which are still online.
|
||||||
*/
|
*/
|
||||||
scsi_restart_operations(shost);
|
scsi_restart_operations(shost);
|
||||||
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler scsi_eh_%d"
|
SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler scsi_eh_%d"
|
||||||
|
@ -1660,7 +1651,7 @@ int scsi_error_handler(void *data)
|
||||||
/*
|
/*
|
||||||
* Make sure that nobody tries to wake us up again.
|
* Make sure that nobody tries to wake us up again.
|
||||||
*/
|
*/
|
||||||
shost->eh_wait = NULL;
|
shost->ehandler = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -467,8 +467,6 @@ struct Scsi_Host {
|
||||||
|
|
||||||
struct list_head eh_cmd_q;
|
struct list_head eh_cmd_q;
|
||||||
struct task_struct * ehandler; /* Error recovery thread. */
|
struct task_struct * ehandler; /* Error recovery thread. */
|
||||||
struct semaphore * eh_wait; /* The error recovery thread waits
|
|
||||||
on this. */
|
|
||||||
struct semaphore * eh_action; /* Wait for specific actions on the
|
struct semaphore * eh_action; /* Wait for specific actions on the
|
||||||
host. */
|
host. */
|
||||||
unsigned int eh_active:1; /* Indicates the eh thread is awake and active if
|
unsigned int eh_active:1; /* Indicates the eh thread is awake and active if
|
||||||
|
|
Loading…
Reference in New Issue