RDMA/device: Don't fire uevent before device is fully initialized
authorLeon Romanovsky <leonro@mellanox.com>
Sun, 5 May 2019 16:33:20 +0000 (19:33 +0300)
committerJason Gunthorpe <jgg@mellanox.com>
Tue, 7 May 2019 16:02:43 +0000 (13:02 -0300)
When the refcount is 0 the device is invisible to netlink. However in the
patch below the refcount = 1 was moved to after the device_add().  This
creates a race where userspace can issue a netlink query after the
device_add() event and not see the device as visible.

Ensure that no uevent is fired before device is fully registered.

Fixes: d79af7242bb2 ("RDMA/device: Expose ib_device_try_get(()")
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
drivers/infiniband/core/device.c

index 9665c37..78dc07c 100644 (file)
@@ -1303,6 +1303,11 @@ int ib_register_device(struct ib_device *device, const char *name)
 
        ib_device_register_rdmacg(device);
 
+       /*
+        * Ensure that ADD uevent is not fired because it
+        * is too early amd device is not initialized yet.
+        */
+       dev_set_uevent_suppress(&device->dev, true);
        ret = device_add(&device->dev);
        if (ret)
                goto cg_cleanup;
@@ -1315,6 +1320,9 @@ int ib_register_device(struct ib_device *device, const char *name)
        }
 
        ret = enable_device_and_get(device);
+       dev_set_uevent_suppress(&device->dev, false);
+       /* Mark for userspace that device is ready */
+       kobject_uevent(&device->dev.kobj, KOBJ_ADD);
        if (ret) {
                void (*dealloc_fn)(struct ib_device *);
 
@@ -1343,6 +1351,7 @@ int ib_register_device(struct ib_device *device, const char *name)
 dev_cleanup:
        device_del(&device->dev);
 cg_cleanup:
+       dev_set_uevent_suppress(&device->dev, false);
        ib_device_unregister_rdmacg(device);
        ib_cache_cleanup_one(device);
        return ret;