diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2009-05-13 13:01:51 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-05-19 01:15:59 -0400 |
commit | 26574401fef6766f6c3ca25b5c13febe662d2a32 (patch) | |
tree | f3ef9fe491dbdece50d77ccc56bb797727b91375 /drivers/infiniband/ulp | |
parent | af38f2989572704a846a5577b5ab3b1e2885cbfb (diff) |
net: Fix ipoib rtnl_lock sysfs deadlock.
Network device sysfs files that grab the rtnl_lock unconditionally
will deadlock if accessed when the network device is being
unregistered. So use trylock and syscall_restart to avoid this
deadlock.
Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/infiniband/ulp')
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_cm.c | 6 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_vlan.c | 6 |
2 files changed, 8 insertions, 4 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 47d588ba2a7f..4248c3139364 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c | |||
@@ -1455,13 +1455,15 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr, | |||
1455 | struct net_device *dev = to_net_dev(d); | 1455 | struct net_device *dev = to_net_dev(d); |
1456 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 1456 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
1457 | 1457 | ||
1458 | if (!rtnl_trylock()) | ||
1459 | return restart_syscall(); | ||
1460 | |||
1458 | /* flush paths if we switch modes so that connections are restarted */ | 1461 | /* flush paths if we switch modes so that connections are restarted */ |
1459 | if (IPOIB_CM_SUPPORTED(dev->dev_addr) && !strcmp(buf, "connected\n")) { | 1462 | if (IPOIB_CM_SUPPORTED(dev->dev_addr) && !strcmp(buf, "connected\n")) { |
1460 | set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); | 1463 | set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); |
1461 | ipoib_warn(priv, "enabling connected mode " | 1464 | ipoib_warn(priv, "enabling connected mode " |
1462 | "will cause multicast packet drops\n"); | 1465 | "will cause multicast packet drops\n"); |
1463 | 1466 | ||
1464 | rtnl_lock(); | ||
1465 | dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO); | 1467 | dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO); |
1466 | rtnl_unlock(); | 1468 | rtnl_unlock(); |
1467 | priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM; | 1469 | priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM; |
@@ -1473,7 +1475,6 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr, | |||
1473 | if (!strcmp(buf, "datagram\n")) { | 1475 | if (!strcmp(buf, "datagram\n")) { |
1474 | clear_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); | 1476 | clear_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); |
1475 | 1477 | ||
1476 | rtnl_lock(); | ||
1477 | if (test_bit(IPOIB_FLAG_CSUM, &priv->flags)) { | 1478 | if (test_bit(IPOIB_FLAG_CSUM, &priv->flags)) { |
1478 | dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; | 1479 | dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; |
1479 | if (priv->hca_caps & IB_DEVICE_UD_TSO) | 1480 | if (priv->hca_caps & IB_DEVICE_UD_TSO) |
@@ -1485,6 +1486,7 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr, | |||
1485 | 1486 | ||
1486 | return count; | 1487 | return count; |
1487 | } | 1488 | } |
1489 | rtnl_unlock(); | ||
1488 | 1490 | ||
1489 | return -EINVAL; | 1491 | return -EINVAL; |
1490 | } | 1492 | } |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c index 4c57f329dd50..e3bf00d8cd25 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c | |||
@@ -61,7 +61,8 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) | |||
61 | 61 | ||
62 | ppriv = netdev_priv(pdev); | 62 | ppriv = netdev_priv(pdev); |
63 | 63 | ||
64 | rtnl_lock(); | 64 | if (!rtnl_trylock()) |
65 | return restart_syscall(); | ||
65 | mutex_lock(&ppriv->vlan_mutex); | 66 | mutex_lock(&ppriv->vlan_mutex); |
66 | 67 | ||
67 | /* | 68 | /* |
@@ -167,7 +168,8 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey) | |||
167 | 168 | ||
168 | ppriv = netdev_priv(pdev); | 169 | ppriv = netdev_priv(pdev); |
169 | 170 | ||
170 | rtnl_lock(); | 171 | if (!rtnl_trylock()) |
172 | return restart_syscall(); | ||
171 | mutex_lock(&ppriv->vlan_mutex); | 173 | mutex_lock(&ppriv->vlan_mutex); |
172 | list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) { | 174 | list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) { |
173 | if (priv->pkey == pkey) { | 175 | if (priv->pkey == pkey) { |