Commit 76010976 authored by Jason Gunthorpe's avatar Jason Gunthorpe

IB/ipoib: Consolidate checking of the proposed child interface

Move all the checking for pkey and other validity to the __ipoib_vlan_add
function. This removes the last difference from the control flow
of the __ipoib_vlan_add to make the overall design simpler to
understand.
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
Signed-off-by: default avatarErez Shitrit <erezsh@mellanox.com>
Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
parent 13476d35
...@@ -122,9 +122,6 @@ static int ipoib_new_child_link(struct net *src_net, struct net_device *dev, ...@@ -122,9 +122,6 @@ static int ipoib_new_child_link(struct net *src_net, struct net_device *dev,
} else } else
child_pkey = nla_get_u16(data[IFLA_IPOIB_PKEY]); child_pkey = nla_get_u16(data[IFLA_IPOIB_PKEY]);
if (child_pkey == 0 || child_pkey == 0x8000)
return -EINVAL;
err = __ipoib_vlan_add(ppriv, ipoib_priv(dev), err = __ipoib_vlan_add(ppriv, ipoib_priv(dev),
child_pkey, IPOIB_RTNL_CHILD); child_pkey, IPOIB_RTNL_CHILD);
......
...@@ -50,6 +50,39 @@ static ssize_t show_parent(struct device *d, struct device_attribute *attr, ...@@ -50,6 +50,39 @@ static ssize_t show_parent(struct device *d, struct device_attribute *attr,
} }
static DEVICE_ATTR(parent, S_IRUGO, show_parent, NULL); static DEVICE_ATTR(parent, S_IRUGO, show_parent, NULL);
static bool is_child_unique(struct ipoib_dev_priv *ppriv,
struct ipoib_dev_priv *priv)
{
struct ipoib_dev_priv *tpriv;
ASSERT_RTNL();
/*
* Since the legacy sysfs interface uses pkey for deletion it cannot
* support more than one interface with the same pkey, it creates
* ambiguity. The RTNL interface deletes using the netdev so it does
* not have a problem to support duplicated pkeys.
*/
if (priv->child_type != IPOIB_LEGACY_CHILD)
return true;
/*
* First ensure this isn't a duplicate. We check the parent device and
* then all of the legacy child interfaces to make sure the Pkey
* doesn't match.
*/
if (ppriv->pkey == priv->pkey)
return false;
list_for_each_entry(tpriv, &ppriv->child_intfs, list) {
if (tpriv->pkey == priv->pkey &&
tpriv->child_type == IPOIB_LEGACY_CHILD)
return false;
}
return true;
}
/* /*
* NOTE: If this function fails then the priv->dev will remain valid, however * NOTE: If this function fails then the priv->dev will remain valid, however
* priv can have been freed and must not be touched by caller in the error * priv can have been freed and must not be touched by caller in the error
...@@ -73,10 +106,20 @@ int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv, ...@@ -73,10 +106,20 @@ int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv,
*/ */
WARN_ON(ppriv->dev->reg_state != NETREG_REGISTERED); WARN_ON(ppriv->dev->reg_state != NETREG_REGISTERED);
if (pkey == 0 || pkey == 0x8000) {
result = -EINVAL;
goto out_early;
}
priv->parent = ppriv->dev; priv->parent = ppriv->dev;
priv->pkey = pkey; priv->pkey = pkey;
priv->child_type = type; priv->child_type = type;
if (!is_child_unique(ppriv, priv)) {
result = -ENOTUNIQ;
goto out_early;
}
/* We do not need to touch priv if register_netdevice fails */ /* We do not need to touch priv if register_netdevice fails */
ndev->priv_destructor = ipoib_intf_free; ndev->priv_destructor = ipoib_intf_free;
...@@ -88,9 +131,7 @@ int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv, ...@@ -88,9 +131,7 @@ int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv,
* register_netdevice sometimes calls priv_destructor, * register_netdevice sometimes calls priv_destructor,
* sometimes not. Make sure it was done. * sometimes not. Make sure it was done.
*/ */
if (ndev->priv_destructor) goto out_early;
ndev->priv_destructor(ndev);
return result;
} }
/* RTNL childs don't need proprietary sysfs entries */ /* RTNL childs don't need proprietary sysfs entries */
...@@ -111,6 +152,11 @@ int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv, ...@@ -111,6 +152,11 @@ int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv,
sysfs_failed: sysfs_failed:
unregister_netdevice(priv->dev); unregister_netdevice(priv->dev);
return -ENOMEM; return -ENOMEM;
out_early:
if (ndev->priv_destructor)
ndev->priv_destructor(ndev);
return result;
} }
int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
...@@ -118,17 +164,11 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) ...@@ -118,17 +164,11 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
struct ipoib_dev_priv *ppriv, *priv; struct ipoib_dev_priv *ppriv, *priv;
char intf_name[IFNAMSIZ]; char intf_name[IFNAMSIZ];
struct net_device *ndev; struct net_device *ndev;
struct ipoib_dev_priv *tpriv;
int result; int result;
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN))
return -EPERM; return -EPERM;
ppriv = ipoib_priv(pdev);
snprintf(intf_name, sizeof(intf_name), "%s.%04x",
ppriv->dev->name, pkey);
if (!rtnl_trylock()) if (!rtnl_trylock())
return restart_syscall(); return restart_syscall();
...@@ -137,23 +177,10 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) ...@@ -137,23 +177,10 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
return -EPERM; return -EPERM;
} }
/* ppriv = ipoib_priv(pdev);
* First ensure this isn't a duplicate. We check the parent device and
* then all of the legacy child interfaces to make sure the Pkey
* doesn't match.
*/
if (ppriv->pkey == pkey) {
result = -ENOTUNIQ;
goto out;
}
list_for_each_entry(tpriv, &ppriv->child_intfs, list) { snprintf(intf_name, sizeof(intf_name), "%s.%04x",
if (tpriv->pkey == pkey && ppriv->dev->name, pkey);
tpriv->child_type == IPOIB_LEGACY_CHILD) {
result = -ENOTUNIQ;
goto out;
}
}
priv = ipoib_intf_alloc(ppriv->ca, ppriv->port, intf_name); priv = ipoib_intf_alloc(ppriv->ca, ppriv->port, intf_name);
if (!priv) { if (!priv) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment