From 0099103926b68e6675a1be4644848f5b1c1b6f97 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Mon, 17 Sep 2018 15:44:46 -0600 Subject: [PATCH] RDMA/uverbs: Fix error unwind in ib_uverbs_add_one The error path has several mistakes - cdev_del should not be called if cdev_device_add fails - We must call put_device on all the goto exit paths as that is what frees the uapi, SRCU and the struct itself. While we are here consolidate all the uvdev_dev init that cannot fail at the top. Fixes: c5c4d92e70f3 ("RDMA/uverbs: Use cdev_device_add() instead of cdev_add()") Signed-off-by: Jason Gunthorpe Reviewed-by: Parav Pandit --- drivers/infiniband/core/uverbs_main.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 176271db9ed7..db6de9157668 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -1028,6 +1028,12 @@ static void ib_uverbs_add_one(struct ib_device *device) return; } + device_initialize(&uverbs_dev->dev); + uverbs_dev->dev.class = uverbs_class; + uverbs_dev->dev.parent = device->dev.parent; + uverbs_dev->dev.release = ib_uverbs_release_dev; + uverbs_dev->groups[0] = &dev_attr_group; + uverbs_dev->dev.groups = uverbs_dev->groups; atomic_set(&uverbs_dev->refcount, 1); init_completion(&uverbs_dev->comp); uverbs_dev->xrcd_tree = RB_ROOT; @@ -1035,6 +1041,8 @@ static void ib_uverbs_add_one(struct ib_device *device) mutex_init(&uverbs_dev->lists_mutex); INIT_LIST_HEAD(&uverbs_dev->uverbs_file_list); INIT_LIST_HEAD(&uverbs_dev->uverbs_events_file_list); + rcu_assign_pointer(uverbs_dev->ib_dev, device); + uverbs_dev->num_comp_vectors = device->num_comp_vectors; devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES); if (devnum >= IB_UVERBS_MAX_DEVICES) @@ -1046,19 +1054,10 @@ static void ib_uverbs_add_one(struct ib_device *device) else base = IB_UVERBS_BASE_DEV + devnum; - rcu_assign_pointer(uverbs_dev->ib_dev, device); - uverbs_dev->num_comp_vectors = device->num_comp_vectors; - if (ib_uverbs_create_uapi(device, uverbs_dev)) goto err_uapi; - device_initialize(&uverbs_dev->dev); - uverbs_dev->dev.class = uverbs_class; - uverbs_dev->dev.parent = device->dev.parent; uverbs_dev->dev.devt = base; - uverbs_dev->dev.release = ib_uverbs_release_dev; - uverbs_dev->groups[0] = &dev_attr_group; - uverbs_dev->dev.groups = uverbs_dev->groups; dev_set_name(&uverbs_dev->dev, "uverbs%d", uverbs_dev->devnum); cdev_init(&uverbs_dev->cdev, @@ -1067,20 +1066,18 @@ static void ib_uverbs_add_one(struct ib_device *device) ret = cdev_device_add(&uverbs_dev->cdev, &uverbs_dev->dev); if (ret) - goto err_cdev; + goto err_uapi; ib_set_client_data(device, &uverbs_client, uverbs_dev); return; -err_cdev: - cdev_del(&uverbs_dev->cdev); - put_device(&uverbs_dev->dev); err_uapi: clear_bit(devnum, dev_map); err: if (atomic_dec_and_test(&uverbs_dev->refcount)) ib_uverbs_comp_dev(uverbs_dev); wait_for_completion(&uverbs_dev->comp); + put_device(&uverbs_dev->dev); return; } -- 2.30.2