RDMA/uverbs: Store the specs_root in the struct ib_uverbs_device
authorJason Gunthorpe <jgg@mellanox.com>
Wed, 4 Jul 2018 05:50:23 +0000 (08:50 +0300)
committerJason Gunthorpe <jgg@mellanox.com>
Wed, 4 Jul 2018 19:47:01 +0000 (13:47 -0600)
The specs are required to operate the uverbs file, so they belong inside
the ib_uverbs_device, not inside the ib_device. The spec passed in the
ib_device is just a communication from the driver and should not be used
during runtime.

This also changes the lifetime of the spec memory to match the
ib_uverbs_device, however at this time the spec_root can still contain
driver pointers after disassociation, so it cannot be used if ib_dev is
NULL. This is preparation for another series.

Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
drivers/infiniband/core/rdma_core.c
drivers/infiniband/core/rdma_core.h
drivers/infiniband/core/uverbs_ioctl.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/hw/mlx5/main.c
include/rdma/ib_verbs.h

index 2ddf1c716ba801637622cac1ca89a072d4b3b9de..c67bcdda5760485987c13aa34e293d1b204b38ea 100644 (file)
@@ -52,10 +52,10 @@ int uverbs_ns_idx(u16 *id, unsigned int ns_count)
        return ret;
 }
 
-const struct uverbs_object_spec *uverbs_get_object(const struct ib_device *ibdev,
+const struct uverbs_object_spec *uverbs_get_object(struct ib_uverbs_file *ufile,
                                                   uint16_t object)
 {
-       const struct uverbs_root_spec *object_hash = ibdev->specs_root;
+       const struct uverbs_root_spec *object_hash = ufile->device->specs_root;
        const struct uverbs_object_spec_hash *objects;
        int ret = uverbs_ns_idx(&object, object_hash->num_buckets);
 
index a243cc2a59f76d7527eaf250c135e7807603c9b8..8cede4546b25c6e1c54598a06daaf634b07c7c34 100644 (file)
@@ -44,7 +44,7 @@
 #include <linux/mutex.h>
 
 int uverbs_ns_idx(u16 *id, unsigned int ns_count);
-const struct uverbs_object_spec *uverbs_get_object(const struct ib_device *ibdev,
+const struct uverbs_object_spec *uverbs_get_object(struct ib_uverbs_file *ufile,
                                                   uint16_t object);
 const struct uverbs_method_spec *uverbs_get_method(const struct uverbs_object_spec *object,
                                                   uint16_t method);
index 03065bad8dae8c6e3fdd2becfb664bf3421c25ca..785975a4e3ddaafc60e0052b4fd38d5ebf3f4ee5 100644 (file)
@@ -46,8 +46,7 @@ static bool uverbs_is_attr_cleared(const struct ib_uverbs_attr *uattr,
                           0, uattr->len - len);
 }
 
-static int uverbs_process_attr(struct ib_device *ibdev,
-                              struct ib_ucontext *ucontext,
+static int uverbs_process_attr(struct ib_uverbs_file *ufile,
                               const struct ib_uverbs_attr *uattr,
                               u16 attr_id,
                               const struct uverbs_attr_spec_hash *attr_spec_bucket,
@@ -145,17 +144,18 @@ static int uverbs_process_attr(struct ib_device *ibdev,
                if (uattr->attr_data.reserved)
                        return -EINVAL;
 
-               if (uattr->len != 0 || !ucontext || uattr->data > INT_MAX)
+               if (uattr->len != 0 || !ufile->ucontext ||
+                   uattr->data > INT_MAX)
                        return -EINVAL;
 
                o_attr = &e->obj_attr;
-               object = uverbs_get_object(ibdev, spec->obj.obj_type);
+               object = uverbs_get_object(ufile, spec->obj.obj_type);
                if (!object)
                        return -EINVAL;
 
                o_attr->uobject = uverbs_get_uobject_from_context(
                                        object->type_attrs,
-                                       ucontext,
+                                       ufile->ucontext,
                                        spec->obj.access,
                                        (int)uattr->data);
 
@@ -230,8 +230,7 @@ static int uverbs_finalize_attrs(struct uverbs_attr_bundle *attrs_bundle,
        return ret;
 }
 
-static int uverbs_uattrs_process(struct ib_device *ibdev,
-                                struct ib_ucontext *ucontext,
+static int uverbs_uattrs_process(struct ib_uverbs_file *ufile,
                                 const struct ib_uverbs_attr *uattrs,
                                 size_t num_uattrs,
                                 const struct uverbs_method_spec *method,
@@ -267,9 +266,9 @@ static int uverbs_uattrs_process(struct ib_device *ibdev,
                        num_given_buckets = ret + 1;
 
                attr_spec_bucket = method->attr_buckets[ret];
-               ret = uverbs_process_attr(ibdev, ucontext, uattr, attr_id,
-                                         attr_spec_bucket, &attr_bundle->hash[ret],
-                                         uattr_ptr++);
+               ret = uverbs_process_attr(ufile, uattr, attr_id,
+                                         attr_spec_bucket,
+                                         &attr_bundle->hash[ret], uattr_ptr++);
                if (ret) {
                        uverbs_finalize_attrs(attr_bundle,
                                              method->attr_buckets,
@@ -324,9 +323,8 @@ static int uverbs_handle_method(struct ib_uverbs_attr __user *uattr_ptr,
        int finalize_ret;
        int num_given_buckets;
 
-       num_given_buckets = uverbs_uattrs_process(ibdev, ufile->ucontext, uattrs,
-                                                 num_uattrs, method_spec,
-                                                 attr_bundle, uattr_ptr);
+       num_given_buckets = uverbs_uattrs_process(
+               ufile, uattrs, num_uattrs, method_spec, attr_bundle, uattr_ptr);
        if (num_given_buckets <= 0)
                return -EINVAL;
 
@@ -367,7 +365,7 @@ static long ib_uverbs_cmd_verbs(struct ib_device *ib_dev,
        if (hdr->driver_id != ib_dev->driver_id)
                return -EINVAL;
 
-       object_spec = uverbs_get_object(ib_dev, hdr->object_id);
+       object_spec = uverbs_get_object(file, hdr->object_id);
        if (!object_spec)
                return -EPROTONOSUPPORT;
 
index f5f4bfb59705b6f9a4a638767c155ed3dde524f8..c05ce5ae5415b68de4c0bcd76e718c3289cb63f5 100644 (file)
@@ -161,6 +161,7 @@ static void ib_uverbs_release_dev(struct kobject *kobj)
                container_of(kobj, struct ib_uverbs_device, kobj);
 
        cleanup_srcu_struct(&dev->disassociate_srcu);
+       uverbs_free_spec_tree(dev->specs_root);
        kfree(dev);
 }
 
@@ -1067,7 +1068,7 @@ static void ib_uverbs_add_one(struct ib_device *device)
        if (device_create_file(uverbs_dev->dev, &dev_attr_abi_version))
                goto err_class;
 
-       if (!device->specs_root) {
+       if (!device->driver_specs_root) {
                const struct uverbs_object_tree_def *default_root[] = {
                        uverbs_default_get_objects()};
 
@@ -1075,8 +1076,13 @@ static void ib_uverbs_add_one(struct ib_device *device)
                                                                default_root);
                if (IS_ERR(uverbs_dev->specs_root))
                        goto err_class;
-
-               device->specs_root = uverbs_dev->specs_root;
+       } else {
+               uverbs_dev->specs_root = device->driver_specs_root;
+               /*
+                * Take responsibility to free the specs allocated by the
+                * driver.
+                */
+               device->driver_specs_root = NULL;
        }
 
        ib_set_client_data(device, &uverbs_client, uverbs_dev);
@@ -1241,10 +1247,6 @@ static void ib_uverbs_remove_one(struct ib_device *device, void *client_data)
                ib_uverbs_comp_dev(uverbs_dev);
        if (wait_clients)
                wait_for_completion(&uverbs_dev->comp);
-       if (uverbs_dev->specs_root) {
-               uverbs_free_spec_tree(uverbs_dev->specs_root);
-               device->specs_root = NULL;
-       }
 
        kobject_put(&uverbs_dev->kobj);
 }
index d3867286606c5d806a35f7ac5bb82227dcaed597..0fb80777aade0a48329393675cbd077618f7742f 100644 (file)
@@ -5350,15 +5350,15 @@ static int populate_specs_root(struct mlx5_ib_dev *dev)
            !WARN_ON(num_trees >= ARRAY_SIZE(default_root)))
                default_root[num_trees++] = mlx5_ib_get_devx_tree();
 
-       dev->ib_dev.specs_root =
+       dev->ib_dev.driver_specs_root =
                uverbs_alloc_spec_tree(num_trees, default_root);
 
-       return PTR_ERR_OR_ZERO(dev->ib_dev.specs_root);
+       return PTR_ERR_OR_ZERO(dev->ib_dev.driver_specs_root);
 }
 
 static void depopulate_specs_root(struct mlx5_ib_dev *dev)
 {
-       uverbs_free_spec_tree(dev->ib_dev.specs_root);
+       uverbs_free_spec_tree(dev->ib_dev.driver_specs_root);
 }
 
 static int mlx5_ib_read_counters(struct ib_counters *counters,
index e1130c6c1377489d638075cfbc709aa40d347ac4..8784d5bfc2526c3391e5d5417d9c29f6f07d8643 100644 (file)
@@ -2602,7 +2602,7 @@ struct ib_device {
        const struct cpumask *(*get_vector_affinity)(struct ib_device *ibdev,
                                                     int comp_vector);
 
-       struct uverbs_root_spec         *specs_root;
+       struct uverbs_root_spec         *driver_specs_root;
        enum rdma_driver_id             driver_id;
 };