lkml.org 
[lkml]   [2007]   [May]   [30]   [last100]   RSS Feed
Views: [more markup]  [less markup]  [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
DateWed, 30 May 2007 08:28:09 -0500
FromJason Wessel <>
Subject[PATCH] Re: [2.6.21.1] soft lockup when removing netconsole module
Attached is a patch to fix the soft lockup problem when removing the 
netconsole module.

It looks different than the original patch I posted because the context 
had to change to maintain 80 column code.  For reference the original 
e-mail + patch was "[BUG] 2.6.21 hang in 
cancel_rearming_delayed_workqueue()" sent on 5/25/07.

Jason.


From 102a018d601e954f658d272d4daeef139ae40e0e Mon Sep 17 00:00:00 2001
From: Jason Wessel <jason.wessel@windriver.com>
Date: Wed, 30 May 2007 08:03:52 -0500
Subject: [PATCH] The netpoll_cleanup handler can hang the kernel if there is no work in
the work queue because a call to cancel_rearming_delayed_work() with
no work goes into an infinite loop.

The typical case where this is a problem is on removing a kernel
module such as the netconsole driver or kgdboe.

To maintain 80 column code, the function had to have one level of braces
dropped.

Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
---
 net/core/netpoll.c |   36 +++++++++++++++++++-----------------
 1 files changed, 19 insertions(+), 17 deletions(-)
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 4581ece..28fa50e 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -766,30 +766,32 @@ void netpoll_cleanup(struct netpoll *np)
 	struct netpoll_info *npinfo;
 	unsigned long flags;
 
-	if (np->dev) {
-		npinfo = np->dev->npinfo;
-		if (npinfo) {
-			if (npinfo->rx_np == np) {
-				spin_lock_irqsave(&npinfo->rx_lock, flags);
-				npinfo->rx_np = NULL;
-				npinfo->rx_flags &= ~NETPOLL_RX_ENABLED;
-				spin_unlock_irqrestore(&npinfo->rx_lock, flags);
-			}
+	if (!np->dev)
+		return;
+
+	npinfo = np->dev->npinfo;
+	if (npinfo) {
+		if (npinfo->rx_np == np) {
+			spin_lock_irqsave(&npinfo->rx_lock, flags);
+			npinfo->rx_np = NULL;
+			npinfo->rx_flags &= ~NETPOLL_RX_ENABLED;
+			spin_unlock_irqrestore(&npinfo->rx_lock, flags);
+		}
 
-			np->dev->npinfo = NULL;
-			if (atomic_dec_and_test(&npinfo->refcnt)) {
-				skb_queue_purge(&npinfo->arp_tx);
-				skb_queue_purge(&npinfo->txq);
+		np->dev->npinfo = NULL;
+		if (atomic_dec_and_test(&npinfo->refcnt)) {
+			skb_queue_purge(&npinfo->arp_tx);
+			skb_queue_purge(&npinfo->txq);
+			if (delayed_work_pending(&npinfo->tx_work)) {
 				cancel_rearming_delayed_work(&npinfo->tx_work);
 				flush_scheduled_work();
-
-				kfree(npinfo);
 			}
-		}
 
-		dev_put(np->dev);
+			kfree(npinfo);
+		}
 	}
 
+	dev_put(np->dev);
 	np->dev = NULL;
 }
 
-- 
1.5.0.6
\
 
 \ /
  Last update: 2007-05-30 13:31    [from the cache]
©2003-2008