Merge branch 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar...
[linux-2.6-block.git] / drivers / infiniband / core / device.c
index 61c0c93a2e73e389db4cc158c2c6dff5beb5a5d5..3352a107b4a36756518087eef46615b55372e2a0 100644 (file)
@@ -409,27 +409,44 @@ static int rename_compat_devs(struct ib_device *device)
 
 int ib_device_rename(struct ib_device *ibdev, const char *name)
 {
+       unsigned long index;
+       void *client_data;
        int ret;
 
        down_write(&devices_rwsem);
        if (!strcmp(name, dev_name(&ibdev->dev))) {
-               ret = 0;
-               goto out;
+               up_write(&devices_rwsem);
+               return 0;
        }
 
        if (__ib_device_get_by_name(name)) {
-               ret = -EEXIST;
-               goto out;
+               up_write(&devices_rwsem);
+               return -EEXIST;
        }
 
        ret = device_rename(&ibdev->dev, name);
-       if (ret)
-               goto out;
+       if (ret) {
+               up_write(&devices_rwsem);
+               return ret;
+       }
+
        strlcpy(ibdev->name, name, IB_DEVICE_NAME_MAX);
        ret = rename_compat_devs(ibdev);
-out:
-       up_write(&devices_rwsem);
-       return ret;
+
+       downgrade_write(&devices_rwsem);
+       down_read(&ibdev->client_data_rwsem);
+       xan_for_each_marked(&ibdev->client_data, index, client_data,
+                           CLIENT_DATA_REGISTERED) {
+               struct ib_client *client = xa_load(&clients, index);
+
+               if (!client || !client->rename)
+                       continue;
+
+               client->rename(ibdev, client_data);
+       }
+       up_read(&ibdev->client_data_rwsem);
+       up_read(&devices_rwsem);
+       return 0;
 }
 
 static int alloc_name(struct ib_device *ibdev, const char *name)
@@ -440,7 +457,7 @@ static int alloc_name(struct ib_device *ibdev, const char *name)
        int rc;
        int i;
 
-       lockdep_assert_held_exclusive(&devices_rwsem);
+       lockdep_assert_held_write(&devices_rwsem);
        ida_init(&inuse);
        xa_for_each (&devices, index, device) {
                char buf[IB_DEVICE_NAME_MAX];
@@ -474,14 +491,15 @@ static void ib_device_release(struct device *device)
 
        free_netdevs(dev);
        WARN_ON(refcount_read(&dev->refcount));
-       ib_cache_release_one(dev);
-       ib_security_release_port_pkey_list(dev);
-       xa_destroy(&dev->compat_devs);
-       xa_destroy(&dev->client_data);
-       if (dev->port_data)
+       if (dev->port_data) {
+               ib_cache_release_one(dev);
+               ib_security_release_port_pkey_list(dev);
                kfree_rcu(container_of(dev->port_data, struct ib_port_data_rcu,
                                       pdata[0]),
                          rcu_head);
+       }
+       xa_destroy(&dev->compat_devs);
+       xa_destroy(&dev->client_data);
        kfree_rcu(dev, rcu_head);
 }
 
@@ -1935,6 +1953,9 @@ static void free_netdevs(struct ib_device *ib_dev)
        unsigned long flags;
        unsigned int port;
 
+       if (!ib_dev->port_data)
+               return;
+
        rdma_for_each_port (ib_dev, port) {
                struct ib_port_data *pdata = &ib_dev->port_data[port];
                struct net_device *ndev;