Skip to content

Commit edb5abb

Browse files
author
Roland Dreier
committed
IPoIB: Avoid free_netdev() BUG when destroying a child interface
We have to release the RTNL before calling free_netdev() so that the device state has a chance to become NETREG_UNREGISTERED. Otherwise when removing a child interface, we hit the BUG() that tests the device state in free_netdev(). Reported-by: Yossi Etigin <yosefe@voltaire.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
1 parent 5d80f8e commit edb5abb

File tree

1 file changed

+15
-10
lines changed

1 file changed

+15
-10
lines changed

drivers/infiniband/ulp/ipoib/ipoib_vlan.c

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,14 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
7070
*/
7171
if (ppriv->pkey == pkey) {
7272
result = -ENOTUNIQ;
73+
priv = NULL;
7374
goto err;
7475
}
7576

7677
list_for_each_entry(priv, &ppriv->child_intfs, list) {
7778
if (priv->pkey == pkey) {
7879
result = -ENOTUNIQ;
80+
priv = NULL;
7981
goto err;
8082
}
8183
}
@@ -96,7 +98,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
9698

9799
result = ipoib_set_dev_features(priv, ppriv->ca);
98100
if (result)
99-
goto device_init_failed;
101+
goto err;
100102

101103
priv->pkey = pkey;
102104

@@ -109,7 +111,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
109111
ipoib_warn(ppriv, "failed to initialize subinterface: "
110112
"device %s, port %d",
111113
ppriv->ca->name, ppriv->port);
112-
goto device_init_failed;
114+
goto err;
113115
}
114116

115117
result = register_netdevice(priv->dev);
@@ -146,19 +148,19 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
146148
register_failed:
147149
ipoib_dev_cleanup(priv->dev);
148150

149-
device_init_failed:
150-
free_netdev(priv->dev);
151-
152151
err:
153152
mutex_unlock(&ppriv->vlan_mutex);
154153
rtnl_unlock();
154+
if (priv)
155+
free_netdev(priv->dev);
156+
155157
return result;
156158
}
157159

158160
int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
159161
{
160162
struct ipoib_dev_priv *ppriv, *priv, *tpriv;
161-
int ret = -ENOENT;
163+
struct net_device *dev = NULL;
162164

163165
if (!capable(CAP_NET_ADMIN))
164166
return -EPERM;
@@ -172,14 +174,17 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
172174
unregister_netdevice(priv->dev);
173175
ipoib_dev_cleanup(priv->dev);
174176
list_del(&priv->list);
175-
free_netdev(priv->dev);
176-
177-
ret = 0;
177+
dev = priv->dev;
178178
break;
179179
}
180180
}
181181
mutex_unlock(&ppriv->vlan_mutex);
182182
rtnl_unlock();
183183

184-
return ret;
184+
if (dev) {
185+
free_netdev(dev);
186+
return 0;
187+
}
188+
189+
return -ENODEV;
185190
}

0 commit comments

Comments
 (0)