Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4543fbef authored by Vlad Yasevich's avatar Vlad Yasevich Committed by David S. Miller
Browse files

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: default avatarVlad Yasevich <vyasevic@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e2409d83
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -210,9 +210,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;
};

+3 −3
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ static int __hw_addr_create_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++;

@@ -165,7 +165,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);
@@ -186,7 +186,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);
		}