aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRafał Miłecki <rafal@milecki.pl>2019-02-28 16:57:33 -0500
committerJacek Anaszewski <jacek.anaszewski@gmail.com>2019-03-26 15:25:37 -0400
commit4cb6560514fa19d556954b88128f3846fee66a03 (patch)
tree9dd276209cb3df77c581cb4c31b04310b5a35b92 /drivers
parent9e98c678c2d6ae3a17cb2de55d17f69dddaa231b (diff)
leds: trigger: netdev: fix refcnt leak on interface rename
Renaming a netdev-trigger-tracked interface was resulting in an unbalanced dev_hold(). Example: > iw phy phy0 interface add foo type __ap > echo netdev > trigger > echo foo > device_name > ip link set foo name bar > iw dev bar del [ 237.355366] unregister_netdevice: waiting for bar to become free. Usage count = 1 [ 247.435362] unregister_netdevice: waiting for bar to become free. Usage count = 1 [ 257.545366] unregister_netdevice: waiting for bar to become free. Usage count = 1 Above problem was caused by trigger checking a dev->name which obviously changes after renaming an interface. It meant missing all further events including the NETDEV_UNREGISTER which is required for calling dev_put(). This change fixes that by: 1) Comparing device struct *address* for notification-filtering purposes 2) Dropping unneeded NETDEV_CHANGENAME code (no behavior change) Fixes: 06f502f57d0d ("leds: trigger: Introduce a NETDEV trigger") Signed-off-by: Rafał Miłecki <rafal@milecki.pl> Acked-by: Pavel Machek <pavel@ucw.cz> Signed-off-by: Jacek Anaszewski <jacek.anaszewski@gmail.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/leds/trigger/ledtrig-netdev.c13
1 files changed, 5 insertions, 8 deletions
diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c
index 3dd3ed46d473..167a94c02d05 100644
--- a/drivers/leds/trigger/ledtrig-netdev.c
+++ b/drivers/leds/trigger/ledtrig-netdev.c
@@ -301,11 +301,11 @@ static int netdev_trig_notify(struct notifier_block *nb,
301 container_of(nb, struct led_netdev_data, notifier); 301 container_of(nb, struct led_netdev_data, notifier);
302 302
303 if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE 303 if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE
304 && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER 304 && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER)
305 && evt != NETDEV_CHANGENAME)
306 return NOTIFY_DONE; 305 return NOTIFY_DONE;
307 306
308 if (strcmp(dev->name, trigger_data->device_name)) 307 if (!(dev == trigger_data->net_dev ||
308 (evt == NETDEV_REGISTER && !strcmp(dev->name, trigger_data->device_name))))
309 return NOTIFY_DONE; 309 return NOTIFY_DONE;
310 310
311 cancel_delayed_work_sync(&trigger_data->work); 311 cancel_delayed_work_sync(&trigger_data->work);
@@ -320,12 +320,9 @@ static int netdev_trig_notify(struct notifier_block *nb,
320 dev_hold(dev); 320 dev_hold(dev);
321 trigger_data->net_dev = dev; 321 trigger_data->net_dev = dev;
322 break; 322 break;
323 case NETDEV_CHANGENAME:
324 case NETDEV_UNREGISTER: 323 case NETDEV_UNREGISTER:
325 if (trigger_data->net_dev) { 324 dev_put(trigger_data->net_dev);
326 dev_put(trigger_data->net_dev); 325 trigger_data->net_dev = NULL;
327 trigger_data->net_dev = NULL;
328 }
329 break; 326 break;
330 case NETDEV_UP: 327 case NETDEV_UP:
331 case NETDEV_CHANGE: 328 case NETDEV_CHANGE: