diff options
author | Konstantin Khlebnikov <khlebnikov@yandex-team.ru> | 2015-07-14 09:35:53 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-07-16 00:33:39 -0400 |
commit | 6640e673c6f3dbaace085ca2686a8a343dc23a71 (patch) | |
tree | 54c6f43e8d9b0e47dbab468aa2daa693ada3277d /drivers/net/ipvlan | |
parent | 6a725497318545aae246232ed05a8df9cffb0a02 (diff) |
ipvlan: unhash addresses without synchronize_rcu
All structures used in traffic forwarding are rcu-protected:
ipvl_addr, ipvl_dev and ipvl_port. Thus we can unhash addresses
without synchronization. We'll anyway hash it back into the same
bucket: in worst case lockless lookup will scan hash once again.
Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ipvlan')
-rw-r--r-- | drivers/net/ipvlan/ipvlan.h | 2 | ||||
-rw-r--r-- | drivers/net/ipvlan/ipvlan_core.c | 4 | ||||
-rw-r--r-- | drivers/net/ipvlan/ipvlan_main.c | 8 |
3 files changed, 6 insertions, 8 deletions
diff --git a/drivers/net/ipvlan/ipvlan.h b/drivers/net/ipvlan/ipvlan.h index 68e2549c28c6..40f9d7e4a0ea 100644 --- a/drivers/net/ipvlan/ipvlan.h +++ b/drivers/net/ipvlan/ipvlan.h | |||
@@ -122,5 +122,5 @@ struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan, | |||
122 | bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6); | 122 | bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6); |
123 | struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port, | 123 | struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port, |
124 | const void *iaddr, bool is_v6); | 124 | const void *iaddr, bool is_v6); |
125 | void ipvlan_ht_addr_del(struct ipvl_addr *addr, bool sync); | 125 | void ipvlan_ht_addr_del(struct ipvl_addr *addr); |
126 | #endif /* __IPVLAN_H */ | 126 | #endif /* __IPVLAN_H */ |
diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c index 8afbedad620d..8f8628a0adba 100644 --- a/drivers/net/ipvlan/ipvlan_core.c +++ b/drivers/net/ipvlan/ipvlan_core.c | |||
@@ -85,11 +85,9 @@ void ipvlan_ht_addr_add(struct ipvl_dev *ipvlan, struct ipvl_addr *addr) | |||
85 | hlist_add_head_rcu(&addr->hlnode, &port->hlhead[hash]); | 85 | hlist_add_head_rcu(&addr->hlnode, &port->hlhead[hash]); |
86 | } | 86 | } |
87 | 87 | ||
88 | void ipvlan_ht_addr_del(struct ipvl_addr *addr, bool sync) | 88 | void ipvlan_ht_addr_del(struct ipvl_addr *addr) |
89 | { | 89 | { |
90 | hlist_del_init_rcu(&addr->hlnode); | 90 | hlist_del_init_rcu(&addr->hlnode); |
91 | if (sync) | ||
92 | synchronize_rcu(); | ||
93 | } | 91 | } |
94 | 92 | ||
95 | struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan, | 93 | struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan, |
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index 7d81e37c3f76..e995bc501ee6 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c | |||
@@ -171,7 +171,7 @@ static int ipvlan_stop(struct net_device *dev) | |||
171 | dev_uc_del(phy_dev, phy_dev->dev_addr); | 171 | dev_uc_del(phy_dev, phy_dev->dev_addr); |
172 | 172 | ||
173 | list_for_each_entry(addr, &ipvlan->addrs, anode) | 173 | list_for_each_entry(addr, &ipvlan->addrs, anode) |
174 | ipvlan_ht_addr_del(addr, !dev->dismantle); | 174 | ipvlan_ht_addr_del(addr); |
175 | 175 | ||
176 | return 0; | 176 | return 0; |
177 | } | 177 | } |
@@ -505,7 +505,7 @@ static void ipvlan_link_delete(struct net_device *dev, struct list_head *head) | |||
505 | struct ipvl_addr *addr, *next; | 505 | struct ipvl_addr *addr, *next; |
506 | 506 | ||
507 | list_for_each_entry_safe(addr, next, &ipvlan->addrs, anode) { | 507 | list_for_each_entry_safe(addr, next, &ipvlan->addrs, anode) { |
508 | ipvlan_ht_addr_del(addr, !dev->dismantle); | 508 | ipvlan_ht_addr_del(addr); |
509 | list_del(&addr->anode); | 509 | list_del(&addr->anode); |
510 | kfree_rcu(addr, rcu); | 510 | kfree_rcu(addr, rcu); |
511 | } | 511 | } |
@@ -641,7 +641,7 @@ static void ipvlan_del_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr) | |||
641 | if (!addr) | 641 | if (!addr) |
642 | return; | 642 | return; |
643 | 643 | ||
644 | ipvlan_ht_addr_del(addr, true); | 644 | ipvlan_ht_addr_del(addr); |
645 | list_del(&addr->anode); | 645 | list_del(&addr->anode); |
646 | kfree_rcu(addr, rcu); | 646 | kfree_rcu(addr, rcu); |
647 | 647 | ||
@@ -711,7 +711,7 @@ static void ipvlan_del_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr) | |||
711 | if (!addr) | 711 | if (!addr) |
712 | return; | 712 | return; |
713 | 713 | ||
714 | ipvlan_ht_addr_del(addr, true); | 714 | ipvlan_ht_addr_del(addr); |
715 | list_del(&addr->anode); | 715 | list_del(&addr->anode); |
716 | kfree_rcu(addr, rcu); | 716 | kfree_rcu(addr, rcu); |
717 | 717 | ||