[PATCH #upstream-fixes 2/2] libata: prevent EH from being scheduled after port is detached

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



SCSI EH thread is stopped during SCSI host release which can happen
after ATA host detach and free.  This leads to the following oops.

  general protection fault: 0000 [1] PREEMPT SMP 
  CPU 0 
  Modules linked in: ahci libata
  Pid: 98, comm: kblockd/0 Not tainted 2.6.23-rc2-work #19
  RIP: 0010:[<ffffffff80242aa7>]  [<ffffffff80242aa7>] run_workqueue+0xb7/0x190
  RSP: 0018:ffff81001fd2be80  EFLAGS: 00010087
  RAX: 6b6b6b6b6b6b6b6b RBX: ffff81001fae4a18 RCX: 1240000000000000
  RDX: 6b6b6b6b6b6b6b6b RSI: 9200000000000000 RDI: ffff81001fc1b930
  RBP: ffff81001fd2beb0 R08: fffffffffedc0049 R09: 0000000000000000
  R10: ffffffff80242a09 R11: 0000000000000000 R12: ffff81001fae4a10
  R13: ffff81001fc1b930 R14: 6b6b6b6b6b6b6b6b R15: ffff81001fc1b960
  FS:  0000000000000000(0000) GS:ffffffff808cb000(0000) knlGS:0000000000000000
  CS:  0010 DS: 0018 ES: 0018 CR0: 000000008005003b
  CR2: 00002b531964d890 CR3: 0000000000201000 CR4: 00000000000006e0
  DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
  DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
  Process kblockd/0 (pid: 98, threadinfo ffff81001fd2a000, task ffff81001fe78140)
  Stack:  ffff81001fd2beb0 ffff81001fc1b970 ffff81001fc1b930 ffff81001fd2bec0
   ffff81001fc1b960 0000000000000000 ffff81001fd2bf10 ffffffff8024385a
   0000000000000000 ffff81001fe78140 ffffffff80247450 ffff81001fd2bed8
  Call Trace:
   [<ffffffff8024385a>] worker_thread+0xca/0x130
   [<ffffffff80247450>] autoremove_wake_function+0x0/0x40
   [<ffffffff80243790>] worker_thread+0x0/0x130
   [<ffffffff8024706d>] kthread+0x4d/0x80
   [<ffffffff8020cbf8>] child_rip+0xa/0x12
   [<ffffffff8020c2e0>] restore_args+0x0/0x30
   [<ffffffff80247178>] kthreadd+0xd8/0x160
   [<ffffffff80247020>] kthread+0x0/0x80
   [<ffffffff8020cbee>] child_rip+0x0/0x12

This patch clears ATA_PFLAG_RUNNING after final freeze and moves
ATA_PFLAG_RUNNING check into ata_eh_set_pending() to cover all EH
schedule functions.

Signed-off-by: Tejun Heo <htejun@xxxxxxxxx>
---
 drivers/ata/libata-core.c |    3 ++-
 drivers/ata/libata-eh.c   |    8 +++-----
 2 files changed, 5 insertions(+), 6 deletions(-)

Index: work/drivers/ata/libata-core.c
===================================================================
--- work.orig/drivers/ata/libata-core.c
+++ work/drivers/ata/libata-core.c
@@ -6547,7 +6547,8 @@ void ata_port_detach(struct ata_port *ap
 	 * target.
 	 */
 	spin_lock_irqsave(ap->lock, flags);
-	ata_port_freeze(ap);	/* won't be thawed */
+	ata_port_freeze(ap);			/* won't be thawed */
+	ap->pflags &= ~ATA_PFLAG_RUNNING;	/* port is dead now */
 	spin_unlock_irqrestore(ap->lock, flags);
 
 	ata_port_wait_eh(ap);
Index: work/drivers/ata/libata-eh.c
===================================================================
--- work.orig/drivers/ata/libata-eh.c
+++ work/drivers/ata/libata-eh.c
@@ -648,8 +648,9 @@ static void ata_eh_set_pending(struct at
 {
 	int cnt;
 
-	/* already scheduled? */
-	if (ap->pflags & ATA_PFLAG_EH_PENDING)
+	/* nothing to do if port isn't running or EH is already scheduled */
+	if (!(ap->pflags & ATA_PFLAG_RUNNING) ||
+	    (ap->pflags & ATA_PFLAG_EH_PENDING))
 		return;
 
 	ap->pflags |= ATA_PFLAG_EH_PENDING;
@@ -709,9 +710,6 @@ void ata_port_schedule_eh(struct ata_por
 {
 	WARN_ON(!ap->ops->error_handler);
 
-	if (!(ap->pflags & ATA_PFLAG_RUNNING))
-		return;
-
 	ata_eh_set_pending(ap, 1);
 	scsi_schedule_eh(ap->scsi_host);
 
-
To unsubscribe from this list: send the line "unsubscribe linux-ide" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Filesystems]     [Linux SCSI]     [Linux RAID]     [Git]     [Kernel Newbies]     [Linux Newbie]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Samba]     [Device Mapper]

  Powered by Linux