Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+23 −32
Original line number Diff line number Diff line
@@ -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.
	 */
	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.
	 * 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.
	 */
	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));

		/*
		 * 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;
							  " 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;
}

+0 −2
Original line number Diff line number Diff line
@@ -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