From: James Bottomley Date: Mon, 19 Sep 2005 14:50:04 +0000 (-0500) Subject: [SCSI] Fix thread termination for the SCSI error handle X-Git-Tag: v2.6.14-rc3~154^2~11 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3ed7a4704beb66a155acd67b78b7e9a5674d55fb;p=linux-2.6 [SCSI] Fix thread termination for the SCSI error handle From: Alan Stern 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 Modified to simplify the termination loop and correct the sleep condition. Signed-off-by: James Bottomley --- diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index af589fac81..ad53421650 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -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; } diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 540369ff81..69313ba750 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -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