From 81c1fbcba2f27f687c2a471f341502d47679f401 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 30 Dec 2022 16:38:41 +0100 Subject: device: fix vlan device issues with disappearing lower devices In some cases, if a VLAN is created on top of a bridge, a config reload can lead to the bridge being torn down while netifd still considers the VLAN device to be up. In that case even a setup retry of an interface on top of the vlan does not recreate the vlan device, because it is still claimed. Fix this by releasing all device claims whenever a device goes away. Signed-off-by: Felix Fietkau --- device.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/device.c b/device.c index b3d0e85..d6610c7 100644 --- a/device.c +++ b/device.c @@ -472,6 +472,17 @@ static void __init dev_init(void) avl_init(&devices, avl_strcmp, true, NULL); } +static int device_release_cb(void *ctx, struct safe_list *list) +{ + struct device_user *dep = container_of(list, struct device_user, list); + + if (!dep->dev || !dep->claimed) + return 0; + + device_release(dep); + return 0; +} + static int device_broadcast_cb(void *ctx, struct safe_list *list) { struct device_user *dep = container_of(list, struct device_user, list); @@ -771,6 +782,8 @@ void device_set_present(struct device *dev, bool state) D(DEVICE, "%s '%s' %s present\n", dev->type->name, dev->ifname, state ? "is now" : "is no longer" ); dev->sys_present = state; device_refresh_present(dev); + if (!state) + safe_list_for_each(&dev->users, device_release_cb, NULL); } void device_set_link(struct device *dev, bool state) -- cgit v1.2.1