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 --- |