[PATCH 3.10 39/54] ipv6: probe routes asynchronous in rt6_probe
3.10-stable review patch. If anyone has any objections, please let me know. -- From: Hannes Frederic Sowa [ Upstream commit c2f17e827b419918c856131f592df9521e1a38e3 ] Routes need to be probed asynchronous otherwise the call stack gets exhausted when the kernel attemps to deliver another skb inline, like e.g. xt_TEE does, and we probe at the same time. We update neigh->updated still at once, otherwise we would send to many probes. Cc: Julian Anastasov Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/route.c | 38 +++--- 1 file changed, 31 insertions(+), 7 deletions(-) --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -473,6 +473,24 @@ out: } #ifdef CONFIG_IPV6_ROUTER_PREF +struct __rt6_probe_work { + struct work_struct work; + struct in6_addr target; + struct net_device *dev; +}; + +static void rt6_probe_deferred(struct work_struct *w) +{ + struct in6_addr mcaddr; + struct __rt6_probe_work *work = + container_of(w, struct __rt6_probe_work, work); + + addrconf_addr_solict_mult(>target, ); + ndisc_send_ns(work->dev, NULL, >target, , NULL); + dev_put(work->dev); + kfree(w); +} + static void rt6_probe(struct rt6_info *rt) { struct neighbour *neigh; @@ -496,17 +514,23 @@ static void rt6_probe(struct rt6_info *r if (!neigh || time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) { - struct in6_addr mcaddr; - struct in6_addr *target; + struct __rt6_probe_work *work; - if (neigh) { + work = kmalloc(sizeof(*work), GFP_ATOMIC); + + if (neigh && work) neigh->updated = jiffies; + + if (neigh) write_unlock(>lock); - } - target = (struct in6_addr *)>rt6i_gateway; - addrconf_addr_solict_mult(target, ); - ndisc_send_ns(rt->dst.dev, NULL, target, , NULL); + if (work) { + INIT_WORK(>work, rt6_probe_deferred); + work->target = rt->rt6i_gateway; + dev_hold(rt->dst.dev); + work->dev = rt->dst.dev; + schedule_work(>work); + } } else { out: write_unlock(>lock); -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 3.10 39/54] ipv6: probe routes asynchronous in rt6_probe
3.10-stable review patch. If anyone has any objections, please let me know. -- From: Hannes Frederic Sowa han...@stressinduktion.org [ Upstream commit c2f17e827b419918c856131f592df9521e1a38e3 ] Routes need to be probed asynchronous otherwise the call stack gets exhausted when the kernel attemps to deliver another skb inline, like e.g. xt_TEE does, and we probe at the same time. We update neigh-updated still at once, otherwise we would send to many probes. Cc: Julian Anastasov j...@ssi.bg Signed-off-by: Hannes Frederic Sowa han...@stressinduktion.org Signed-off-by: David S. Miller da...@davemloft.net Signed-off-by: Greg Kroah-Hartman gre...@linuxfoundation.org --- net/ipv6/route.c | 38 +++--- 1 file changed, 31 insertions(+), 7 deletions(-) --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -473,6 +473,24 @@ out: } #ifdef CONFIG_IPV6_ROUTER_PREF +struct __rt6_probe_work { + struct work_struct work; + struct in6_addr target; + struct net_device *dev; +}; + +static void rt6_probe_deferred(struct work_struct *w) +{ + struct in6_addr mcaddr; + struct __rt6_probe_work *work = + container_of(w, struct __rt6_probe_work, work); + + addrconf_addr_solict_mult(work-target, mcaddr); + ndisc_send_ns(work-dev, NULL, work-target, mcaddr, NULL); + dev_put(work-dev); + kfree(w); +} + static void rt6_probe(struct rt6_info *rt) { struct neighbour *neigh; @@ -496,17 +514,23 @@ static void rt6_probe(struct rt6_info *r if (!neigh || time_after(jiffies, neigh-updated + rt-rt6i_idev-cnf.rtr_probe_interval)) { - struct in6_addr mcaddr; - struct in6_addr *target; + struct __rt6_probe_work *work; - if (neigh) { + work = kmalloc(sizeof(*work), GFP_ATOMIC); + + if (neigh work) neigh-updated = jiffies; + + if (neigh) write_unlock(neigh-lock); - } - target = (struct in6_addr *)rt-rt6i_gateway; - addrconf_addr_solict_mult(target, mcaddr); - ndisc_send_ns(rt-dst.dev, NULL, target, mcaddr, NULL); + if (work) { + INIT_WORK(work-work, rt6_probe_deferred); + work-target = rt-rt6i_gateway; + dev_hold(rt-dst.dev); + work-dev = rt-dst.dev; + schedule_work(work-work); + } } else { out: write_unlock(neigh-lock); -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/