aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/inetpeer.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/inetpeer.c')
-rw-r--r--net/ipv4/inetpeer.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index e4cba56a534..cac02ad1425 100644
--- a/net/ipv4/inetpeer.c
+++ b/net/ipv4/inetpeer.c
@@ -86,10 +86,36 @@ void inet_peer_base_init(struct inet_peer_base *bp)
86{ 86{
87 bp->root = peer_avl_empty_rcu; 87 bp->root = peer_avl_empty_rcu;
88 seqlock_init(&bp->lock); 88 seqlock_init(&bp->lock);
89 bp->flush_seq = ~0U;
89 bp->total = 0; 90 bp->total = 0;
90} 91}
91EXPORT_SYMBOL_GPL(inet_peer_base_init); 92EXPORT_SYMBOL_GPL(inet_peer_base_init);
92 93
94static atomic_t v4_seq = ATOMIC_INIT(0);
95static atomic_t v6_seq = ATOMIC_INIT(0);
96
97static atomic_t *inetpeer_seq_ptr(int family)
98{
99 return (family == AF_INET ? &v4_seq : &v6_seq);
100}
101
102static inline void flush_check(struct inet_peer_base *base, int family)
103{
104 atomic_t *fp = inetpeer_seq_ptr(family);
105
106 if (unlikely(base->flush_seq != atomic_read(fp))) {
107 inetpeer_invalidate_tree(base);
108 base->flush_seq = atomic_read(fp);
109 }
110}
111
112void inetpeer_invalidate_family(int family)
113{
114 atomic_t *fp = inetpeer_seq_ptr(family);
115
116 atomic_inc(fp);
117}
118
93#define PEER_MAXDEPTH 40 /* sufficient for about 2^27 nodes */ 119#define PEER_MAXDEPTH 40 /* sufficient for about 2^27 nodes */
94 120
95/* Exported for sysctl_net_ipv4. */ 121/* Exported for sysctl_net_ipv4. */
@@ -437,6 +463,8 @@ struct inet_peer *inet_getpeer(struct inet_peer_base *base,
437 unsigned int sequence; 463 unsigned int sequence;
438 int invalidated, gccnt = 0; 464 int invalidated, gccnt = 0;
439 465
466 flush_check(base, daddr->family);
467
440 /* Attempt a lockless lookup first. 468 /* Attempt a lockless lookup first.
441 * Because of a concurrent writer, we might not find an existing entry. 469 * Because of a concurrent writer, we might not find an existing entry.
442 */ 470 */