route.c (2af48d430aee5ded45cc6d6b4b10a5e76130885f) route.c (951f788a80ff8b6339c5c1ab888b0d4b4352efd8)
1/*
2 * Linux INET6 implementation
3 * FIB front-end.
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 *
8 * This program is free software; you can redistribute it and/or

--- 1122 unchanged lines hidden (view full) ---

1131
1132 dst_hold(&net->ipv6.ip6_null_entry->dst);
1133 return net->ipv6.ip6_null_entry;
1134 }
1135
1136 dst_hold(&pcpu_rt->dst);
1137 p = this_cpu_ptr(rt->rt6i_pcpu);
1138 prev = cmpxchg(p, NULL, pcpu_rt);
1/*
2 * Linux INET6 implementation
3 * FIB front-end.
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 *
8 * This program is free software; you can redistribute it and/or

--- 1122 unchanged lines hidden (view full) ---

1131
1132 dst_hold(&net->ipv6.ip6_null_entry->dst);
1133 return net->ipv6.ip6_null_entry;
1134 }
1135
1136 dst_hold(&pcpu_rt->dst);
1137 p = this_cpu_ptr(rt->rt6i_pcpu);
1138 prev = cmpxchg(p, NULL, pcpu_rt);
1139 if (prev) {
1140 /* If someone did it before us, return prev instead */
1141 /* release refcnt taken by ip6_rt_pcpu_alloc() */
1142 dst_release_immediate(&pcpu_rt->dst);
1143 /* release refcnt taken by above dst_hold() */
1144 dst_release_immediate(&pcpu_rt->dst);
1145 dst_hold(&prev->dst);
1146 pcpu_rt = prev;
1147 }
1139 BUG_ON(prev);
1148
1149 rt6_dst_from_metrics_check(pcpu_rt);
1150 return pcpu_rt;
1151}
1152
1153/* exception hash table implementation
1154 */
1155static DEFINE_SPINLOCK(rt6_exception_lock);

--- 578 unchanged lines hidden (view full) ---

1734 return uncached_rt;
1735
1736 } else {
1737 /* Get a percpu copy */
1738
1739 struct rt6_info *pcpu_rt;
1740
1741 dst_use_noref(&rt->dst, jiffies);
1140
1141 rt6_dst_from_metrics_check(pcpu_rt);
1142 return pcpu_rt;
1143}
1144
1145/* exception hash table implementation
1146 */
1147static DEFINE_SPINLOCK(rt6_exception_lock);

--- 578 unchanged lines hidden (view full) ---

1726 return uncached_rt;
1727
1728 } else {
1729 /* Get a percpu copy */
1730
1731 struct rt6_info *pcpu_rt;
1732
1733 dst_use_noref(&rt->dst, jiffies);
1734 local_bh_disable();
1742 pcpu_rt = rt6_get_pcpu_route(rt);
1743
1735 pcpu_rt = rt6_get_pcpu_route(rt);
1736
1744 if (pcpu_rt) {
1745 rcu_read_unlock();
1746 } else {
1737 if (!pcpu_rt) {
1747 /* atomic_inc_not_zero() is needed when using rcu */
1748 if (atomic_inc_not_zero(&rt->rt6i_ref)) {
1738 /* atomic_inc_not_zero() is needed when using rcu */
1739 if (atomic_inc_not_zero(&rt->rt6i_ref)) {
1749 /* We have to do the read_unlock first
1750 * because rt6_make_pcpu_route() may trigger
1751 * ip6_dst_gc() which will take the write_lock.
1752 *
1753 * No dst_hold() on rt is needed because grabbing
1740 /* No dst_hold() on rt is needed because grabbing
1754 * rt->rt6i_ref makes sure rt can't be released.
1755 */
1741 * rt->rt6i_ref makes sure rt can't be released.
1742 */
1756 rcu_read_unlock();
1757 pcpu_rt = rt6_make_pcpu_route(rt);
1758 rt6_release(rt);
1759 } else {
1760 /* rt is already removed from tree */
1743 pcpu_rt = rt6_make_pcpu_route(rt);
1744 rt6_release(rt);
1745 } else {
1746 /* rt is already removed from tree */
1761 rcu_read_unlock();
1762 pcpu_rt = net->ipv6.ip6_null_entry;
1763 dst_hold(&pcpu_rt->dst);
1764 }
1765 }
1747 pcpu_rt = net->ipv6.ip6_null_entry;
1748 dst_hold(&pcpu_rt->dst);
1749 }
1750 }
1766
1751 local_bh_enable();
1752 rcu_read_unlock();
1767 trace_fib6_table_lookup(net, pcpu_rt, table->tb6_id, fl6);
1768 return pcpu_rt;
1769 }
1770}
1771EXPORT_SYMBOL_GPL(ip6_pol_route);
1772
1773static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *table,
1774 struct flowi6 *fl6, int flags)

--- 3056 unchanged lines hidden ---
1753 trace_fib6_table_lookup(net, pcpu_rt, table->tb6_id, fl6);
1754 return pcpu_rt;
1755 }
1756}
1757EXPORT_SYMBOL_GPL(ip6_pol_route);
1758
1759static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *table,
1760 struct flowi6 *fl6, int flags)

--- 3056 unchanged lines hidden ---