[PATCH rdma-next] RDMA/device: Don't fire uevent before device is fully initialized

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Leon Romanovsky <leonro@xxxxxxxxxxxx>

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@xxxxxxxxxxxx>
---
 drivers/infiniband/core/device.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 8ae4906a60e7..4cdc8588df7f 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -808,6 +808,7 @@ static int add_one_compat_dev(struct ib_device *device,
 	cdev->dev.release = compatdev_release;
 	dev_set_name(&cdev->dev, "%s", dev_name(&device->dev));

+	dev_set_uevent_suppress(&device->dev, true);
 	ret = device_add(&cdev->dev);
 	if (ret)
 		goto add_err;
@@ -828,6 +829,7 @@ static int add_one_compat_dev(struct ib_device *device,
 port_err:
 	device_del(&cdev->dev);
 add_err:
+	dev_set_uevent_suppress(&device->dev, false);
 	put_device(&cdev->dev);
 cdev_err:
 	xa_release(&device->compat_devs, rnet->id);
@@ -845,6 +847,7 @@ static void remove_one_compat_dev(struct ib_device *device, u32 id)
 	mutex_unlock(&device->compat_devs_mutex);
 	if (cdev) {
 		ib_free_port_attrs(cdev);
+		dev_set_uevent_suppress(&device->dev, false);
 		device_del(&cdev->dev);
 		put_device(&cdev->dev);
 	}
@@ -1207,6 +1210,7 @@ static int enable_device_and_get(struct ib_device *device)
 		ret = add_compat_devs(device);
 out:
 	up_read(&devices_rwsem);
+	dev_set_uevent_suppress(&device->dev, false);
 	return ret;
 }

@@ -1244,6 +1248,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
+	 * 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;
@@ -1262,6 +1271,8 @@ int ib_register_device(struct ib_device *device, const char *name)
 	}

 	ret = enable_device_and_get(device);
+	/* Mark for userspace that device is ready */
+	kobject_uevent(&device->dev.kobj, KOBJ_ADD);
 	if (ret) {
 		void (*dealloc_fn)(struct ib_device *);

@@ -1292,6 +1303,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;
--
2.20.1




[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux