diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2010-10-07 06:44:07 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-10-11 15:54:04 -0400 |
commit | 0ed8ddf4045fcfcac36bad753dc4046118c603ec (patch) | |
tree | cf1d9eb14668c4d2257b3519ed7deec8c5cb396d /net/ipv4 | |
parent | d122179a3c0fdc71b88cb9e3605f372b1651a9ff (diff) |
neigh: Protect neigh->ha[] with a seqlock
Add a seqlock in struct neighbour to protect neigh->ha[], and avoid
dirtying neighbour in stress situation (many different flows / dsts)
Dirtying takes place because of read_lock(&n->lock) and n->used writes.
Switching to a seqlock, and writing n->used only on jiffies changes
permits less dirtying.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/arp.c | 6 |
1 files changed, 2 insertions, 4 deletions
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index f35309578170..d8e540c5b071 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c | |||
@@ -502,10 +502,8 @@ int arp_find(unsigned char *haddr, struct sk_buff *skb) | |||
502 | 502 | ||
503 | if (n) { | 503 | if (n) { |
504 | n->used = jiffies; | 504 | n->used = jiffies; |
505 | if (n->nud_state&NUD_VALID || neigh_event_send(n, skb) == 0) { | 505 | if (n->nud_state & NUD_VALID || neigh_event_send(n, skb) == 0) { |
506 | read_lock_bh(&n->lock); | 506 | neigh_ha_snapshot(haddr, n, dev); |
507 | memcpy(haddr, n->ha, dev->addr_len); | ||
508 | read_unlock_bh(&n->lock); | ||
509 | neigh_release(n); | 507 | neigh_release(n); |
510 | return 0; | 508 | return 0; |
511 | } | 509 | } |