Skip to content

Commit

Permalink
RDMA/uverbs: Fix error unwind in ib_uverbs_add_one
Browse files Browse the repository at this point in the history
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: c5c4d92 ("RDMA/uverbs: Use cdev_device_add() instead of cdev_add()")
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Reviewed-by: Parav Pandit <parav@mellanox.com>
  • Loading branch information
Jason Gunthorpe committed Sep 19, 2018
1 parent 0965cc9 commit 0099103
Showing 1 changed file with 10 additions and 13 deletions.
23 changes: 10 additions & 13 deletions drivers/infiniband/core/uverbs_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1028,13 +1028,21 @@ 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;
mutex_init(&uverbs_dev->xrcd_tree_mutex);
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)
Expand All @@ -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,
Expand All @@ -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;
}

Expand Down

0 comments on commit 0099103

Please sign in to comment.