aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-06-10 03:24:21 -0400
committerDavid S. Miller <davem@davemloft.net>2012-06-11 05:09:10 -0400
commitb48c80ece973e9eddb042f6685b482b261ff0d47 (patch)
tree30262edc9721ac70e423bcc8d51f558d2962b539
parent46517008e1168dc926cf2c47d529efc07eca85c0 (diff)
inet: Add family scope inetpeer flushes.
This implementation can deal with having many inetpeer roots, which is a necessary prerequisite for per-FIB table rooted peer tables. Each family (AF_INET, AF_INET6) has a sequence number which we bump when we get a family invalidation request. Each peer lookup cheaply checks whether the flush sequence of the root we are using is out of date, and if so flushes it and updates the sequence number. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/inetpeer.h2
-rw-r--r--net/ipv4/inetpeer.c28
-rw-r--r--net/ipv4/route.c2
3 files changed, 31 insertions, 1 deletions
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h
index d432489e7109..e15c0862a686 100644
--- a/include/net/inetpeer.h
+++ b/include/net/inetpeer.h
@@ -68,6 +68,7 @@ struct inet_peer {
68struct inet_peer_base { 68struct inet_peer_base {
69 struct inet_peer __rcu *root; 69 struct inet_peer __rcu *root;
70 seqlock_t lock; 70 seqlock_t lock;
71 u32 flush_seq;
71 int total; 72 int total;
72}; 73};
73 74
@@ -168,6 +169,7 @@ extern void inet_putpeer(struct inet_peer *p);
168extern bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout); 169extern bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout);
169 170
170extern void inetpeer_invalidate_tree(struct inet_peer_base *); 171extern void inetpeer_invalidate_tree(struct inet_peer_base *);
172extern void inetpeer_invalidate_family(int family);
171 173
172/* 174/*
173 * temporary check to make sure we dont access rid, ip_id_count, tcp_ts, 175 * temporary check to make sure we dont access rid, ip_id_count, tcp_ts,
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index e4cba56a5349..cac02ad1425d 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 */
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 4f5834c4a667..456a9470fb54 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -935,7 +935,7 @@ static void rt_cache_invalidate(struct net *net)
935 935
936 get_random_bytes(&shuffle, sizeof(shuffle)); 936 get_random_bytes(&shuffle, sizeof(shuffle));
937 atomic_add(shuffle + 1U, &net->ipv4.rt_genid); 937 atomic_add(shuffle + 1U, &net->ipv4.rt_genid);
938 inetpeer_invalidate_tree(net->ipv4.peers); 938 inetpeer_invalidate_family(AF_INET);
939} 939}
940 940
941/* 941/*