diff options
Diffstat (limited to 'net/ipv4/inetpeer.c')
| -rw-r--r-- | net/ipv4/inetpeer.c | 28 |
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 | } |
| 91 | EXPORT_SYMBOL_GPL(inet_peer_base_init); | 92 | EXPORT_SYMBOL_GPL(inet_peer_base_init); |
| 92 | 93 | ||
| 94 | static atomic_t v4_seq = ATOMIC_INIT(0); | ||
| 95 | static atomic_t v6_seq = ATOMIC_INIT(0); | ||
| 96 | |||
| 97 | static atomic_t *inetpeer_seq_ptr(int family) | ||
| 98 | { | ||
| 99 | return (family == AF_INET ? &v4_seq : &v6_seq); | ||
| 100 | } | ||
| 101 | |||
| 102 | static 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 | |||
| 112 | void 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 | */ |
