aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <jejb@titanic.(none)>2005-09-19 10:50:04 -0400
committerJames Bottomley <jejb@titanic.(none)>2005-09-19 10:50:04 -0400
commit3ed7a4704beb66a155acd67b78b7e9a5674d55fb (patch)
tree0a0ad71a64888fb2ab69e2b0acb99005dbc3af04
parent939647ee308e0ad924e776657704c7bedd498664 (diff)
[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>
-rw-r--r--drivers/scsi/scsi_error.c55
-rw-r--r--include/scsi/scsi_host.h2
2 files changed, 23 insertions, 34 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index af589fac814d..ad5342165079 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -50,7 +50,7 @@
50void scsi_eh_wakeup(struct Scsi_Host *shost) 50void scsi_eh_wakeup(struct Scsi_Host *shost)
51{ 51{
52 if (shost->host_busy == shost->host_failed) { 52 if (shost->host_busy == shost->host_failed) {
53 up(shost->eh_wait); 53 wake_up_process(shost->ehandler);
54 SCSI_LOG_ERROR_RECOVERY(5, 54 SCSI_LOG_ERROR_RECOVERY(5,
55 printk("Waking error handler thread\n")); 55 printk("Waking error handler thread\n"));
56 } 56 }
@@ -70,7 +70,7 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag)
70 unsigned long flags; 70 unsigned long flags;
71 int ret = 0; 71 int ret = 0;
72 72
73 if (shost->eh_wait == NULL) 73 if (!shost->ehandler)
74 return 0; 74 return 0;
75 75
76 spin_lock_irqsave(shost->host_lock, flags); 76 spin_lock_irqsave(shost->host_lock, flags);
@@ -1591,40 +1591,31 @@ int scsi_error_handler(void *data)
1591{ 1591{
1592 struct Scsi_Host *shost = (struct Scsi_Host *) data; 1592 struct Scsi_Host *shost = (struct Scsi_Host *) data;
1593 int rtn; 1593 int rtn;
1594 DECLARE_MUTEX_LOCKED(sem);
1595 1594
1596 current->flags |= PF_NOFREEZE; 1595 current->flags |= PF_NOFREEZE;
1597 shost->eh_wait = &sem;
1598 1596
1597
1599 /* 1598 /*
1600 * Wake up the thread that created us. 1599 * Note - we always use TASK_INTERRUPTIBLE even if the module
1600 * was loaded as part of the kernel. The reason is that
1601 * UNINTERRUPTIBLE would cause this thread to be counted in
1602 * the load average as a running process, and an interruptible
1603 * wait doesn't.
1601 */ 1604 */
1602 SCSI_LOG_ERROR_RECOVERY(3, printk("Wake up parent of" 1605 set_current_state(TASK_INTERRUPTIBLE);
1603 " scsi_eh_%d\n",shost->host_no)); 1606 while (!kthread_should_stop()) {
1604 1607 if (shost->host_failed == 0 ||
1605 while (1) { 1608 shost->host_failed != shost->host_busy) {
1606 /* 1609 SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler"
1607 * If we get a signal, it means we are supposed to go 1610 " scsi_eh_%d"
1608 * away and die. This typically happens if the user is 1611 " sleeping\n",
1609 * trying to unload a module. 1612 shost->host_no));
1610 */ 1613 schedule();
1611 SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler" 1614 set_current_state(TASK_INTERRUPTIBLE);
1612 " scsi_eh_%d" 1615 continue;
1613 " sleeping\n",shost->host_no)); 1616 }
1614
1615 /*
1616 * Note - we always use down_interruptible with the semaphore
1617 * even if the module was loaded as part of the kernel. The
1618 * reason is that down() will cause this thread to be counted
1619 * in the load average as a running process, and down
1620 * interruptible doesn't. Given that we need to allow this
1621 * thread to die if the driver was loaded as a module, using
1622 * semaphores isn't unreasonable.
1623 */
1624 down_interruptible(&sem);
1625 if (kthread_should_stop())
1626 break;
1627 1617
1618 __set_current_state(TASK_RUNNING);
1628 SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler" 1619 SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler"
1629 " scsi_eh_%d waking" 1620 " scsi_eh_%d waking"
1630 " up\n",shost->host_no)); 1621 " up\n",shost->host_no));
@@ -1651,7 +1642,7 @@ int scsi_error_handler(void *data)
1651 * which are still online. 1642 * which are still online.
1652 */ 1643 */
1653 scsi_restart_operations(shost); 1644 scsi_restart_operations(shost);
1654 1645 set_current_state(TASK_INTERRUPTIBLE);
1655 } 1646 }
1656 1647
1657 SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler scsi_eh_%d" 1648 SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler scsi_eh_%d"
@@ -1660,7 +1651,7 @@ int scsi_error_handler(void *data)
1660 /* 1651 /*
1661 * Make sure that nobody tries to wake us up again. 1652 * Make sure that nobody tries to wake us up again.
1662 */ 1653 */
1663 shost->eh_wait = NULL; 1654 shost->ehandler = NULL;
1664 return 0; 1655 return 0;
1665} 1656}
1666 1657
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 540369ff815c..69313ba7505b 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -467,8 +467,6 @@ struct Scsi_Host {
467 467
468 struct list_head eh_cmd_q; 468 struct list_head eh_cmd_q;
469 struct task_struct * ehandler; /* Error recovery thread. */ 469 struct task_struct * ehandler; /* Error recovery thread. */
470 struct semaphore * eh_wait; /* The error recovery thread waits
471 on this. */
472 struct semaphore * eh_action; /* Wait for specific actions on the 470 struct semaphore * eh_action; /* Wait for specific actions on the
473 host. */ 471 host. */
474 unsigned int eh_active:1; /* Indicates the eh thread is awake and active if 472 unsigned int eh_active:1; /* Indicates the eh thread is awake and active if