netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch net 0/2] net: ipv4: fix couple of addr lifetime related bugs
@ 2013-04-05  9:39 Jiri Pirko
  2013-04-05  9:39 ` [patch net 1/2] net: ipv4: reset check_lifetime_work after changing lifetime Jiri Pirko
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Jiri Pirko @ 2013-04-05  9:39 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuznet, jmorris, yoshfuji, kaber

Jiri Pirko (2):
  net: ipv4: reset check_lifetime_work after changing lifetime
  net: ipv4: fix schelude while atomic bug in check_lifetime()

 net/ipv4/devinet.c | 60 +++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 44 insertions(+), 16 deletions(-)

-- 
1.8.1.2

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [patch net 1/2] net: ipv4: reset check_lifetime_work after changing lifetime
  2013-04-05  9:39 [patch net 0/2] net: ipv4: fix couple of addr lifetime related bugs Jiri Pirko
@ 2013-04-05  9:39 ` Jiri Pirko
  2013-04-05  9:39 ` [patch net 2/2] net: ipv4: fix schedule while atomic bug in check_lifetime() Jiri Pirko
  2013-04-08 16:05 ` [patch net 0/2] net: ipv4: fix couple of addr lifetime related bugs David Miller
  2 siblings, 0 replies; 4+ messages in thread
From: Jiri Pirko @ 2013-04-05  9:39 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuznet, jmorris, yoshfuji, kaber

This will result in calling check_lifetime in nearest opportunity and
that function will adjust next time to call check_lifetime correctly.
Without this, check_lifetime is called in time computed by previous run,
not affecting modified lifetime.

Introduced by: commit 5c766d642bcaf "ipv4: introduce address lifetime"

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 net/ipv4/devinet.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 96083b7..00386e0 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -804,6 +804,8 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg
 			return -EEXIST;
 		ifa = ifa_existing;
 		set_ifa_lifetime(ifa, valid_lft, prefered_lft);
+		cancel_delayed_work(&check_lifetime_work);
+		schedule_delayed_work(&check_lifetime_work, 0);
 		rtmsg_ifa(RTM_NEWADDR, ifa, nlh, NETLINK_CB(skb).portid);
 		blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);
 	}
-- 
1.8.1.2

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [patch net 2/2] net: ipv4: fix schedule while atomic bug in check_lifetime()
  2013-04-05  9:39 [patch net 0/2] net: ipv4: fix couple of addr lifetime related bugs Jiri Pirko
  2013-04-05  9:39 ` [patch net 1/2] net: ipv4: reset check_lifetime_work after changing lifetime Jiri Pirko
@ 2013-04-05  9:39 ` Jiri Pirko
  2013-04-08 16:05 ` [patch net 0/2] net: ipv4: fix couple of addr lifetime related bugs David Miller
  2 siblings, 0 replies; 4+ messages in thread
From: Jiri Pirko @ 2013-04-05  9:39 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuznet, jmorris, yoshfuji, kaber

move might_sleep operations out of the rcu_read_lock() section.
Also fix iterating over ifa_dev->ifa_list

Introduced by: commit 5c766d642bcaf "ipv4: introduce address lifetime"

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 net/ipv4/devinet.c | 58 +++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 42 insertions(+), 16 deletions(-)

diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 00386e0..c6287cd 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -587,13 +587,16 @@ static void check_lifetime(struct work_struct *work)
 {
 	unsigned long now, next, next_sec, next_sched;
 	struct in_ifaddr *ifa;
+	struct hlist_node *n;
 	int i;
 
 	now = jiffies;
 	next = round_jiffies_up(now + ADDR_CHECK_FREQUENCY);
 
-	rcu_read_lock();
 	for (i = 0; i < IN4_ADDR_HSIZE; i++) {
+		bool change_needed = false;
+
+		rcu_read_lock();
 		hlist_for_each_entry_rcu(ifa, &inet_addr_lst[i], hash) {
 			unsigned long age;
 
@@ -606,16 +609,7 @@ static void check_lifetime(struct work_struct *work)
 
 			if (ifa->ifa_valid_lft != INFINITY_LIFE_TIME &&
 			    age >= ifa->ifa_valid_lft) {
-				struct in_ifaddr **ifap ;
-
-				rtnl_lock();
-				for (ifap = &ifa->ifa_dev->ifa_list;
-				     *ifap != NULL; ifap = &ifa->ifa_next) {
-					if (*ifap == ifa)
-						inet_del_ifa(ifa->ifa_dev,
-							     ifap, 1);
-				}
-				rtnl_unlock();
+				change_needed = true;
 			} else if (ifa->ifa_preferred_lft ==
 				   INFINITY_LIFE_TIME) {
 				continue;
@@ -625,10 +619,8 @@ static void check_lifetime(struct work_struct *work)
 					next = ifa->ifa_tstamp +
 					       ifa->ifa_valid_lft * HZ;
 
-				if (!(ifa->ifa_flags & IFA_F_DEPRECATED)) {
-					ifa->ifa_flags |= IFA_F_DEPRECATED;
-					rtmsg_ifa(RTM_NEWADDR, ifa, NULL, 0);
-				}
+				if (!(ifa->ifa_flags & IFA_F_DEPRECATED))
+					change_needed = true;
 			} else if (time_before(ifa->ifa_tstamp +
 					       ifa->ifa_preferred_lft * HZ,
 					       next)) {
@@ -636,8 +628,42 @@ static void check_lifetime(struct work_struct *work)
 				       ifa->ifa_preferred_lft * HZ;
 			}
 		}
+		rcu_read_unlock();
+		if (!change_needed)
+			continue;
+		rtnl_lock();
+		hlist_for_each_entry_safe(ifa, n, &inet_addr_lst[i], hash) {
+			unsigned long age;
+
+			if (ifa->ifa_flags & IFA_F_PERMANENT)
+				continue;
+
+			/* We try to batch several events at once. */
+			age = (now - ifa->ifa_tstamp +
+			       ADDRCONF_TIMER_FUZZ_MINUS) / HZ;
+
+			if (ifa->ifa_valid_lft != INFINITY_LIFE_TIME &&
+			    age >= ifa->ifa_valid_lft) {
+				struct in_ifaddr **ifap;
+
+				for (ifap = &ifa->ifa_dev->ifa_list;
+				     *ifap != NULL; ifap = &(*ifap)->ifa_next) {
+					if (*ifap == ifa) {
+						inet_del_ifa(ifa->ifa_dev,
+							     ifap, 1);
+						break;
+					}
+				}
+			} else if (ifa->ifa_preferred_lft !=
+				   INFINITY_LIFE_TIME &&
+				   age >= ifa->ifa_preferred_lft &&
+				   !(ifa->ifa_flags & IFA_F_DEPRECATED)) {
+				ifa->ifa_flags |= IFA_F_DEPRECATED;
+				rtmsg_ifa(RTM_NEWADDR, ifa, NULL, 0);
+			}
+		}
+		rtnl_unlock();
 	}
-	rcu_read_unlock();
 
 	next_sec = round_jiffies_up(next);
 	next_sched = next;
-- 
1.8.1.2

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [patch net 0/2] net: ipv4: fix couple of addr lifetime related bugs
  2013-04-05  9:39 [patch net 0/2] net: ipv4: fix couple of addr lifetime related bugs Jiri Pirko
  2013-04-05  9:39 ` [patch net 1/2] net: ipv4: reset check_lifetime_work after changing lifetime Jiri Pirko
  2013-04-05  9:39 ` [patch net 2/2] net: ipv4: fix schedule while atomic bug in check_lifetime() Jiri Pirko
@ 2013-04-08 16:05 ` David Miller
  2 siblings, 0 replies; 4+ messages in thread
From: David Miller @ 2013-04-08 16:05 UTC (permalink / raw)
  To: jiri; +Cc: netdev, kuznet, jmorris, yoshfuji, kaber

From: Jiri Pirko <jiri@resnulli.us>
Date: Fri,  5 Apr 2013 11:39:37 +0200

> Jiri Pirko (2):
>   net: ipv4: reset check_lifetime_work after changing lifetime
>   net: ipv4: fix schelude while atomic bug in check_lifetime()

Both applied, thanks Jiri.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2013-04-08 16:05 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-05  9:39 [patch net 0/2] net: ipv4: fix couple of addr lifetime related bugs Jiri Pirko
2013-04-05  9:39 ` [patch net 1/2] net: ipv4: reset check_lifetime_work after changing lifetime Jiri Pirko
2013-04-05  9:39 ` [patch net 2/2] net: ipv4: fix schedule while atomic bug in check_lifetime() Jiri Pirko
2013-04-08 16:05 ` [patch net 0/2] net: ipv4: fix couple of addr lifetime related bugs David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).