Skip to content

Commit 4543fbe

Browse files
Vlad Yasevichdavem330
authored andcommitted
net: count hw_addr syncs so that unsync works properly.
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>
1 parent e2409d8 commit 4543fbe

File tree

2 files changed

+4
-4
lines changed

2 files changed

+4
-4
lines changed

include/linux/netdevice.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,9 @@ struct netdev_hw_addr {
210210
#define NETDEV_HW_ADDR_T_SLAVE 3
211211
#define NETDEV_HW_ADDR_T_UNICAST 4
212212
#define NETDEV_HW_ADDR_T_MULTICAST 5
213-
bool synced;
214213
bool global_use;
215214
int refcount;
215+
int synced;
216216
struct rcu_head rcu_head;
217217
};
218218

net/core/dev_addr_lists.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ static int __hw_addr_create_ex(struct netdev_hw_addr_list *list,
3737
ha->type = addr_type;
3838
ha->refcount = 1;
3939
ha->global_use = global;
40-
ha->synced = false;
40+
ha->synced = 0;
4141
list_add_tail_rcu(&ha->list, &list->list);
4242
list->count++;
4343

@@ -165,7 +165,7 @@ int __hw_addr_sync(struct netdev_hw_addr_list *to_list,
165165
addr_len, ha->type);
166166
if (err)
167167
break;
168-
ha->synced = true;
168+
ha->synced++;
169169
ha->refcount++;
170170
} else if (ha->refcount == 1) {
171171
__hw_addr_del(to_list, ha->addr, addr_len, ha->type);
@@ -186,7 +186,7 @@ void __hw_addr_unsync(struct netdev_hw_addr_list *to_list,
186186
if (ha->synced) {
187187
__hw_addr_del(to_list, ha->addr,
188188
addr_len, ha->type);
189-
ha->synced = false;
189+
ha->synced--;
190190
__hw_addr_del(from_list, ha->addr,
191191
addr_len, ha->type);
192192
}

0 commit comments

Comments
 (0)