struct rw_semaphore vlan_rwsem;
struct mutex mcast_mutex;
+ struct mutex sysfs_mutex;
struct rb_root path_tree;
struct list_head path_list;
if (test_bit(IPOIB_FLAG_GOING_DOWN, &priv->flags))
return -EPERM;
- if (!rtnl_trylock())
+ if (!mutex_trylock(&priv->sysfs_mutex))
return restart_syscall();
+ if (!rtnl_trylock()) {
+ mutex_unlock(&priv->sysfs_mutex);
+ return restart_syscall();
+ }
+
ret = ipoib_set_mode(dev, buf);
/* The assumption is that the function ipoib_set_mode returned
*/
if (ret != -EBUSY)
rtnl_unlock();
+ mutex_unlock(&priv->sysfs_mutex);
return (!ret || ret == -EBUSY) ? count : ret;
}
spin_lock_init(&priv->lock);
init_rwsem(&priv->vlan_rwsem);
mutex_init(&priv->mcast_mutex);
+ mutex_init(&priv->sysfs_mutex);
INIT_LIST_HEAD(&priv->path_list);
INIT_LIST_HEAD(&priv->child_intfs);
cancel_delayed_work(&priv->neigh_reap_task);
flush_workqueue(priv->wq);
+ /* Wrap rtnl_lock/unlock with mutex to protect sysfs calls */
+ mutex_lock(&priv->sysfs_mutex);
unregister_netdev(priv->dev);
+ mutex_unlock(&priv->sysfs_mutex);
+
rn->free_rdma_netdev(priv->dev);
list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list)
snprintf(intf_name, sizeof intf_name, "%s.%04x",
ppriv->dev->name, pkey);
- if (!rtnl_trylock())
+ if (!mutex_trylock(&ppriv->sysfs_mutex))
return restart_syscall();
+ if (!rtnl_trylock()) {
+ mutex_unlock(&ppriv->sysfs_mutex);
+ return restart_syscall();
+ }
+
priv = ipoib_intf_alloc(ppriv->ca, ppriv->port, intf_name);
- if (!priv)
+ if (!priv) {
+ rtnl_unlock();
+ mutex_unlock(&ppriv->sysfs_mutex);
return -ENOMEM;
+ }
down_write(&ppriv->vlan_rwsem);
out:
up_write(&ppriv->vlan_rwsem);
-
rtnl_unlock();
+ mutex_unlock(&ppriv->sysfs_mutex);
if (result) {
free_netdev(priv->dev);
if (test_bit(IPOIB_FLAG_GOING_DOWN, &ppriv->flags))
return -EPERM;
- if (!rtnl_trylock())
+ if (!mutex_trylock(&ppriv->sysfs_mutex))
+ return restart_syscall();
+
+ if (!rtnl_trylock()) {
+ mutex_unlock(&ppriv->sysfs_mutex);
return restart_syscall();
+ }
down_write(&ppriv->vlan_rwsem);
list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) {
}
rtnl_unlock();
+ mutex_unlock(&ppriv->sysfs_mutex);
if (dev) {
free_netdev(dev);