net: bridge: vlan: check for errors from __vlan_del in __vlan_flush
authorVladimir Oltean <vladimir.oltean@nxp.com>
Mon, 14 Feb 2022 23:36:46 +0000 (01:36 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 15 Feb 2022 14:37:28 +0000 (14:37 +0000)
If the following call path returns an error from switchdev:

nbp_vlan_flush
-> __vlan_del
   -> __vlan_vid_del
      -> br_switchdev_port_vlan_del
-> __vlan_group_free
   -> WARN_ON(!list_empty(&vg->vlan_list));

then the deletion of the net_bridge_vlan is silently halted, which will
trigger the WARN_ON from __vlan_group_free().

The WARN_ON is rather unhelpful, because nothing about the source of the
error is printed. Add a print to catch errors from __vlan_del.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/bridge/br_vlan.c

index 1402d5ca242dc3d74c74b12d897efe56e6a92cb8..6315e43a7a3eff8f53b77fc38c334504a8a0e53a 100644 (file)
@@ -404,6 +404,7 @@ static void __vlan_flush(const struct net_bridge *br,
 {
        struct net_bridge_vlan *vlan, *tmp;
        u16 v_start = 0, v_end = 0;
+       int err;
 
        __vlan_delete_pvid(vg, vg->pvid);
        list_for_each_entry_safe(vlan, tmp, &vg->vlan_list, vlist) {
@@ -417,7 +418,13 @@ static void __vlan_flush(const struct net_bridge *br,
                }
                v_end = vlan->vid;
 
-               __vlan_del(vlan);
+               err = __vlan_del(vlan);
+               if (err) {
+                       br_err(br,
+                              "port %u(%s) failed to delete vlan %d: %pe\n",
+                              (unsigned int) p->port_no, p->dev->name,
+                              vlan->vid, ERR_PTR(err));
+               }
        }
 
        /* notify about the last/whole vlan range */