Patchwork [Quantal] Fix route cache flush event

login
register
mail settings
Submitter Stefan Bader
Date Oct. 8, 2012, 9:59 a.m.
Message ID <1349690358-11609-1-git-send-email-stefan.bader@canonical.com>
Download mbox | patch
Permalink /patch/189967/
State New
Headers show

Comments

Stefan Bader - Oct. 8, 2012, 9:59 a.m.
This would fix at least the generally observable half of the problem
when doing some profisioning in LXC containers.
The other half looks (after most recent comments) like it could be
specific to certain hardware (or at least a certain net setup).

In upstream this silently was done by the followign two patches:
- net: remove delay at device dismantle
- net: reinstate rtnl in call_netdevice_notifiers()

Both end up on removing the check on in_dev completely. And maybe
the agreed stable solution will be to remove the check altogether.
But for now I wanted to keep the remaining cases unmodified and just
moved the NETDEV_UNREGISTER_BATCH handling in from of the check (like
the NETDEV_UNREGISTER case already is).

One thing is odd, though: The event handler was exactly the same back
in Precise. Still my impression was that nobody had the same issue
back there... still it does sound like the inet dev pointer would not
be set anymore on an event that is done as one of the last steps of
unregistering.

-Stefan

From 780d37e9d68a88ce5c21695a4be5f1dda3903c6a Mon Sep 17 00:00:00 2001
From: Stefan Bader <stefan.bader@canonical.com>
Date: Thu, 4 Oct 2012 13:57:11 +0200
Subject: [PATCH] UBUNTU: SAUCE: net/ipv4: Always flush route cache on unregister batch call

When doing (for example) a connect to an unused port on localhost
in a new net namespace, it was observed that lo could not be
removed immediately because there were still references on it.
To release those references could take a very long time (up to
five minutes).

This was tracked down to an element in the route cache which was
supposed to be dropped by a notify call with sending a
NETDEVICE_UNREGISTER_BATCH message, but as in_dev is already unset
then, the case statement never was executed.

Move the handling of that notification up to be done regardless of
the state of in_dev.

BugLink: http://bugs.launchpad.net/bugs/1021471

Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
---
 net/ipv4/fib_frontend.c |   15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)
Tim Gardner - Oct. 8, 2012, 12:44 p.m.

Patch

diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 3854411..f2cabd9 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -998,6 +998,14 @@  static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo
 		fib_disable_ip(dev, 2, -1);
 		return NOTIFY_DONE;
 	}
+	if (event == NETDEV_UNREGISTER_BATCH) {
+		/* The batch unregister is only called on the first
+		 * device in the list of devices being unregistered.
+		 * Therefore we should not pass dev_net(dev) in here.
+		 */
+		rt_cache_flush_batch(NULL);
+		return NOTIFY_DONE;
+	}
 
 	if (!in_dev)
 		return NOTIFY_DONE;
@@ -1020,13 +1028,6 @@  static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo
 	case NETDEV_CHANGE:
 		rt_cache_flush(dev_net(dev), 0);
 		break;
-	case NETDEV_UNREGISTER_BATCH:
-		/* The batch unregister is only called on the first
-		 * device in the list of devices being unregistered.
-		 * Therefore we should not pass dev_net(dev) in here.
-		 */
-		rt_cache_flush_batch(NULL);
-		break;
 	}
 	return NOTIFY_DONE;
 }