kmem_cache_free(fib6_node_kmem, fn);
}
-static void rt6_rcu_free(struct rt6_info *rt)
-{
- call_rcu(&rt->dst.rcu_head, dst_rcu_free);
-}
-
static void rt6_free_pcpu(struct rt6_info *non_pcpu_rt)
{
int cpu;
if (pcpu_rt) {
dst_dev_put(&pcpu_rt->dst);
dst_release(&pcpu_rt->dst);
- rt6_rcu_free(pcpu_rt);
*ppcpu_rt = NULL;
}
}
rt6_free_pcpu(rt);
dst_dev_put(&rt->dst);
dst_release(&rt->dst);
- rt6_rcu_free(rt);
}
}
/* Always release dst as dst->__refcnt is guaranteed
* to be taken before entering this function
*/
- dst_release(&rt->dst);
- if (!(rt->dst.flags & DST_NOCACHE))
- dst_free(&rt->dst);
+ dst_release_immediate(&rt->dst);
}
return err;
/* Always release dst as dst->__refcnt is guaranteed
* to be taken before entering this function
*/
- dst_release(&rt->dst);
- if (!(rt->dst.flags & DST_NOCACHE))
- dst_free(&rt->dst);
+ dst_release_immediate(&rt->dst);
return err;
#endif
}
int flags)
{
struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev,
- 1, DST_OBSOLETE_FORCE_CHK, flags);
+ 1, DST_OBSOLETE_FORCE_CHK,
+ flags | DST_NOGC);
if (rt)
rt6_info_init(rt);
*p = NULL;
}
} else {
- dst_release(&rt->dst);
- if (!(flags & DST_NOCACHE))
- dst_destroy((struct dst_entry *)rt);
+ dst_release_immediate(&rt->dst);
return NULL;
}
}
prev = cmpxchg(p, NULL, pcpu_rt);
if (prev) {
/* If someone did it before us, return prev instead */
- dst_release(&pcpu_rt->dst);
- dst_destroy(&pcpu_rt->dst);
+ dst_release_immediate(&pcpu_rt->dst);
pcpu_rt = prev;
}
} else {
* since rt is going away anyway. The next
* dst_check() will trigger a re-lookup.
*/
- dst_release(&pcpu_rt->dst);
- dst_destroy(&pcpu_rt->dst);
+ dst_release_immediate(&pcpu_rt->dst);
pcpu_rt = rt;
}
dst_hold(&pcpu_rt->dst);
struct net_device *loopback_dev = net->loopback_dev;
struct dst_entry *new = NULL;
-
rt = dst_alloc(&ip6_dst_blackhole_ops, loopback_dev, 1,
- DST_OBSOLETE_NONE, 0);
+ DST_OBSOLETE_NONE, DST_NOGC);
if (rt) {
rt6_info_init(rt);
#ifdef CONFIG_IPV6_SUBTREES
memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key));
#endif
-
- dst_free(new);
}
dst_release(dst_orig);
rt->rt6i_idev = idev;
dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 0);
- spin_lock_bh(&icmp6_dst_lock);
- rt->dst.next = icmp6_dst_gc_list;
- icmp6_dst_gc_list = &rt->dst;
- spin_unlock_bh(&icmp6_dst_lock);
-
- fib6_force_start_gc(net);
+ /* Add this dst into uncached_list so that rt6_ifdown() can
+ * do proper release of the net_device
+ */
+ rt6_uncached_list_add(rt);
dst = xfrm_lookup(net, &rt->dst, flowi6_to_flowi(fl6), NULL, 0);
dev_put(dev);
if (idev)
in6_dev_put(idev);
- if (rt) {
- dst_release(&rt->dst);
- dst_free(&rt->dst);
- }
+ if (rt)
+ dst_release_immediate(&rt->dst);
return ERR_PTR(err);
}
return err;
out:
- if (rt) {
- dst_release(&rt->dst);
- dst_free(&rt->dst);
- }
+ if (rt)
+ dst_release_immediate(&rt->dst);
return err;
}
err = ip6_route_info_append(&rt6_nh_list, rt, &r_cfg);
if (err) {
- dst_release(&rt->dst);
- dst_free(&rt->dst);
+ dst_release_immediate(&rt->dst);
goto cleanup;
}
cleanup:
list_for_each_entry_safe(nh, nh_safe, &rt6_nh_list, next) {
- if (nh->rt6_info) {
- dst_release(&nh->rt6_info->dst);
- dst_free(&nh->rt6_info->dst);
- }
+ if (nh->rt6_info)
+ dst_release_immediate(&nh->rt6_info->dst);
kfree(nh->mxc.mx);
list_del(&nh->next);
kfree(nh);