Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions drivers/net/macvlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ struct macvlan_port {

struct macvlan_source_entry {
struct hlist_node hlist;
struct macvlan_dev *vlan;
struct macvlan_dev __rcu *vlan;
unsigned char addr[6+2] __aligned(sizeof(u16));
struct rcu_head rcu;
};
Expand Down Expand Up @@ -145,7 +145,7 @@ static struct macvlan_source_entry *macvlan_hash_lookup_source(

hlist_for_each_entry_rcu(entry, h, hlist, lockdep_rtnl_is_held()) {
if (ether_addr_equal_64bits(entry->addr, addr) &&
entry->vlan == vlan)
rcu_access_pointer(entry->vlan) == vlan)
return entry;
}
return NULL;
Expand All @@ -167,7 +167,7 @@ static int macvlan_hash_add_source(struct macvlan_dev *vlan,
return -ENOMEM;

ether_addr_copy(entry->addr, addr);
entry->vlan = vlan;
RCU_INIT_POINTER(entry->vlan, vlan);
h = &port->vlan_source_hash[macvlan_eth_hash(addr)];
hlist_add_head_rcu(&entry->hlist, h);
vlan->macaddr_count++;
Expand All @@ -186,6 +186,7 @@ static void macvlan_hash_add(struct macvlan_dev *vlan)

static void macvlan_hash_del_source(struct macvlan_source_entry *entry)
{
RCU_INIT_POINTER(entry->vlan, NULL);
hlist_del_rcu(&entry->hlist);
kfree_rcu(entry, rcu);
}
Expand Down Expand Up @@ -389,7 +390,7 @@ static void macvlan_flush_sources(struct macvlan_port *port,
int i;

hash_for_each_safe(port->vlan_source_hash, i, next, entry, hlist)
if (entry->vlan == vlan)
if (rcu_access_pointer(entry->vlan) == vlan)
macvlan_hash_del_source(entry);

vlan->macaddr_count = 0;
Expand Down Expand Up @@ -432,9 +433,14 @@ static bool macvlan_forward_source(struct sk_buff *skb,

hlist_for_each_entry_rcu(entry, h, hlist) {
if (ether_addr_equal_64bits(entry->addr, addr)) {
if (entry->vlan->flags & MACVLAN_FLAG_NODST)
struct macvlan_dev *vlan = rcu_dereference(entry->vlan);

if (!vlan)
continue;

if (vlan->flags & MACVLAN_FLAG_NODST)
consume = true;
macvlan_forward_source_one(skb, entry->vlan);
macvlan_forward_source_one(skb, vlan);
}
}

Expand Down Expand Up @@ -1675,7 +1681,7 @@ static int macvlan_fill_info_macaddr(struct sk_buff *skb,
struct macvlan_source_entry *entry;

hlist_for_each_entry_rcu(entry, h, hlist, lockdep_rtnl_is_held()) {
if (entry->vlan != vlan)
if (rcu_access_pointer(entry->vlan) != vlan)
continue;
if (nla_put(skb, IFLA_MACVLAN_MACADDR, ETH_ALEN, entry->addr))
return 1;
Expand Down
Loading