Commit 3ed7a470 authored by James Bottomley's avatar James Bottomley

[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: default avatarAlan Stern <stern@rowland.harvard.edu>

Modified to simplify the termination loop and correct the sleep condition.
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 939647ee
......@@ -50,7 +50,7 @@
void scsi_eh_wakeup(struct Scsi_Host *shost)
{
if (shost->host_busy == shost->host_failed) {
up(shost->eh_wait);
wake_up_process(shost->ehandler);
SCSI_LOG_ERROR_RECOVERY(5,
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;
int ret = 0;
if (shost->eh_wait == NULL)
if (!shost->ehandler)
return 0;
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;
int rtn;
DECLARE_MUTEX_LOCKED(sem);
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"
" scsi_eh_%d\n",shost->host_no));
while (1) {
/*
* If we get a signal, it means we are supposed to go
* away and die. This typically happens if the user is
* trying to unload a module.
*/
SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler"
" scsi_eh_%d"
" 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_INTERRUPTIBLE);
while (!kthread_should_stop()) {
if (shost->host_failed == 0 ||
shost->host_failed != shost->host_busy) {
SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler"
" scsi_eh_%d"
" sleeping\n",
shost->host_no));
schedule();
set_current_state(TASK_INTERRUPTIBLE);
continue;
}
__set_current_state(TASK_RUNNING);
SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler"
" scsi_eh_%d waking"
" up\n",shost->host_no));
......@@ -1651,7 +1642,7 @@ int scsi_error_handler(void *data)
* which are still online.
*/
scsi_restart_operations(shost);
set_current_state(TASK_INTERRUPTIBLE);
}
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.
*/
shost->eh_wait = NULL;
shost->ehandler = NULL;
return 0;
}
......
......@@ -467,8 +467,6 @@ struct Scsi_Host {
struct list_head eh_cmd_q;
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
host. */
unsigned int eh_active:1; /* Indicates the eh thread is awake and active if
......
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