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 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 { ...@@ -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
......
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