Skip to content

Commit

Permalink
net: dcb: flush lingering app table entries for unregistered devices
Browse files Browse the repository at this point in the history
commit 91b0383 upstream.

If I'm not mistaken (and I don't think I am), the way in which the
dcbnl_ops work is that drivers call dcb_ieee_setapp() and this populates
the application table with dynamically allocated struct dcb_app_type
entries that are kept in the module-global dcb_app_list.

However, nobody keeps exact track of these entries, and although
dcb_ieee_delapp() is supposed to remove them, nobody does so when the
interface goes away (example: driver unbinds from device). So the
dcb_app_list will contain lingering entries with an ifindex that no
longer matches any device in dcb_app_lookup().

Reclaim the lost memory by listening for the NETDEV_UNREGISTER event and
flushing the app table entries of interfaces that are now gone.

In fact something like this used to be done as part of the initial
commit (blamed below), but it was done in dcbnl_exit() -> dcb_flushapp(),
essentially at module_exit time. That became dead code after commit
7a6b6f5 ("DCB: fix kconfig option") which essentially merged
"tristate config DCB" and "bool config DCBNL" into a single "bool config
DCB", so net/dcb/dcbnl.c could not be built as a module anymore.

Commit 36b9ad8 ("net/dcb: make dcbnl.c explicitly non-modular")
recognized this and deleted dcbnl_exit() and dcb_flushapp() altogether,
leaving us with the version we have today.

Since flushing application table entries can and should be done as soon
as the netdevice disappears, fundamentally the commit that is to blame
is the one that introduced the design of this API.

Fixes: 9ab933a ("dcbnl: add appliction tlv handlers")
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
vladimiroltean authored and gregkh committed Mar 8, 2022
1 parent f4c63b2 commit 6a8a4dc
Showing 1 changed file with 44 additions and 0 deletions.
44 changes: 44 additions & 0 deletions net/dcb/dcbnl.c
Expand Up @@ -2063,10 +2063,54 @@ u8 dcb_ieee_getapp_default_prio_mask(const struct net_device *dev)
}
EXPORT_SYMBOL(dcb_ieee_getapp_default_prio_mask);

static void dcbnl_flush_dev(struct net_device *dev)
{
struct dcb_app_type *itr, *tmp;

spin_lock(&dcb_lock);

list_for_each_entry_safe(itr, tmp, &dcb_app_list, list) {
if (itr->ifindex == dev->ifindex) {
list_del(&itr->list);
kfree(itr);
}
}

spin_unlock(&dcb_lock);
}

static int dcbnl_netdevice_event(struct notifier_block *nb,
unsigned long event, void *ptr)
{
struct net_device *dev = netdev_notifier_info_to_dev(ptr);

switch (event) {
case NETDEV_UNREGISTER:
if (!dev->dcbnl_ops)
return NOTIFY_DONE;

dcbnl_flush_dev(dev);

return NOTIFY_OK;
default:
return NOTIFY_DONE;
}
}

static struct notifier_block dcbnl_nb __read_mostly = {
.notifier_call = dcbnl_netdevice_event,
};

static int __init dcbnl_init(void)
{
int err;

INIT_LIST_HEAD(&dcb_app_list);

err = register_netdevice_notifier(&dcbnl_nb);
if (err)
return err;

rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL, 0);
rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL, 0);

Expand Down

0 comments on commit 6a8a4dc

Please sign in to comment.