device: fix vlan device issues with disappearing lower devices
authorFelix Fietkau <nbd@nbd.name>
Fri, 30 Dec 2022 15:38:41 +0000 (16:38 +0100)
committerFelix Fietkau <nbd@nbd.name>
Fri, 30 Dec 2022 15:38:42 +0000 (16:38 +0100)
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 <nbd@nbd.name>
device.c

index b3d0e85f8550de45fbabeb8f17028ddf8af1573e..d6610c704b87674aaa43d2abc71971179e8a3996 100644 (file)
--- 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)