mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
net: count hw_addr syncs so that unsync works properly.
[ Upstream commit 4543fbefe6
]
A few drivers use dev_uc_sync/unsync to synchronize the
address lists from master down to slave/lower devices. In
some cases (bond/team) a single address list is synched down
to multiple devices. At the time of unsync, we have a leak
in these lower devices, because "synced" is treated as a
boolean and the address will not be unsynced for anything after
the first device/call.
Treat "synced" as a count (same as refcount) and allow all
unsync calls to work.
Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
ef95e3d5d7
commit
617f13b419
2 changed files with 4 additions and 4 deletions
|
@ -232,9 +232,9 @@ struct netdev_hw_addr {
|
|||
#define NETDEV_HW_ADDR_T_SLAVE 3
|
||||
#define NETDEV_HW_ADDR_T_UNICAST 4
|
||||
#define NETDEV_HW_ADDR_T_MULTICAST 5
|
||||
bool synced;
|
||||
bool global_use;
|
||||
int refcount;
|
||||
int synced;
|
||||
struct rcu_head rcu_head;
|
||||
};
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ static int __hw_addr_add_ex(struct netdev_hw_addr_list *list,
|
|||
ha->type = addr_type;
|
||||
ha->refcount = 1;
|
||||
ha->global_use = global;
|
||||
ha->synced = false;
|
||||
ha->synced = 0;
|
||||
list_add_tail_rcu(&ha->list, &list->list);
|
||||
list->count++;
|
||||
return 0;
|
||||
|
@ -155,7 +155,7 @@ int __hw_addr_sync(struct netdev_hw_addr_list *to_list,
|
|||
addr_len, ha->type);
|
||||
if (err)
|
||||
break;
|
||||
ha->synced = true;
|
||||
ha->synced++;
|
||||
ha->refcount++;
|
||||
} else if (ha->refcount == 1) {
|
||||
__hw_addr_del(to_list, ha->addr, addr_len, ha->type);
|
||||
|
@ -176,7 +176,7 @@ void __hw_addr_unsync(struct netdev_hw_addr_list *to_list,
|
|||
if (ha->synced) {
|
||||
__hw_addr_del(to_list, ha->addr,
|
||||
addr_len, ha->type);
|
||||
ha->synced = false;
|
||||
ha->synced--;
|
||||
__hw_addr_del(from_list, ha->addr,
|
||||
addr_len, ha->type);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue