Commit c27f6aa8 authored by Jason Gunthorpe's avatar Jason Gunthorpe

RDMA/uverbs: Factor out the add/get pattern into a helper

The next patch needs another copy of this, provide a simple helper to
reduce the coding. uapi_add_get_elm() returns an existing entry or adds a
new one.
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
parent 0cbf432d
...@@ -26,6 +26,27 @@ static void *uapi_add_elm(struct uverbs_api *uapi, u32 key, size_t alloc_size) ...@@ -26,6 +26,27 @@ static void *uapi_add_elm(struct uverbs_api *uapi, u32 key, size_t alloc_size)
return elm; return elm;
} }
static void *uapi_add_get_elm(struct uverbs_api *uapi, u32 key,
size_t alloc_size, bool *exists)
{
void *elm;
elm = uapi_add_elm(uapi, key, alloc_size);
if (!IS_ERR(elm)) {
*exists = false;
return elm;
}
if (elm != ERR_PTR(-EEXIST))
return elm;
elm = radix_tree_lookup(&uapi->radix, key);
if (WARN_ON(!elm))
return ERR_PTR(-EINVAL);
*exists = true;
return elm;
}
static int uapi_merge_method(struct uverbs_api *uapi, static int uapi_merge_method(struct uverbs_api *uapi,
struct uverbs_api_object *obj_elm, u32 obj_key, struct uverbs_api_object *obj_elm, u32 obj_key,
const struct uverbs_method_def *method, const struct uverbs_method_def *method,
...@@ -34,23 +55,21 @@ static int uapi_merge_method(struct uverbs_api *uapi, ...@@ -34,23 +55,21 @@ static int uapi_merge_method(struct uverbs_api *uapi,
u32 method_key = obj_key | uapi_key_ioctl_method(method->id); u32 method_key = obj_key | uapi_key_ioctl_method(method->id);
struct uverbs_api_ioctl_method *method_elm; struct uverbs_api_ioctl_method *method_elm;
unsigned int i; unsigned int i;
bool exists;
if (!method->attrs) if (!method->attrs)
return 0; return 0;
method_elm = uapi_add_elm(uapi, method_key, sizeof(*method_elm)); method_elm = uapi_add_get_elm(uapi, method_key, sizeof(*method_elm),
if (IS_ERR(method_elm)) { &exists);
if (method_elm != ERR_PTR(-EEXIST)) if (IS_ERR(method_elm))
return PTR_ERR(method_elm); return PTR_ERR(method_elm);
if (exists) {
/* /*
* This occurs when a driver uses ADD_UVERBS_ATTRIBUTES_SIMPLE * This occurs when a driver uses ADD_UVERBS_ATTRIBUTES_SIMPLE
*/ */
if (WARN_ON(method->handler)) if (WARN_ON(method->handler))
return -EINVAL; return -EINVAL;
method_elm = radix_tree_lookup(&uapi->radix, method_key);
if (WARN_ON(!method_elm))
return -EINVAL;
} else { } else {
WARN_ON(!method->handler); WARN_ON(!method->handler);
rcu_assign_pointer(method_elm->handler, method->handler); rcu_assign_pointer(method_elm->handler, method->handler);
...@@ -105,34 +124,29 @@ static int uapi_merge_obj_tree(struct uverbs_api *uapi, ...@@ -105,34 +124,29 @@ static int uapi_merge_obj_tree(struct uverbs_api *uapi,
struct uverbs_api_object *obj_elm; struct uverbs_api_object *obj_elm;
unsigned int i; unsigned int i;
u32 obj_key; u32 obj_key;
bool exists;
int rc; int rc;
obj_key = uapi_key_obj(obj->id); obj_key = uapi_key_obj(obj->id);
obj_elm = uapi_add_elm(uapi, obj_key, sizeof(*obj_elm)); obj_elm = uapi_add_get_elm(uapi, obj_key, sizeof(*obj_elm), &exists);
if (IS_ERR(obj_elm)) { if (IS_ERR(obj_elm))
if (obj_elm != ERR_PTR(-EEXIST)) return PTR_ERR(obj_elm);
return PTR_ERR(obj_elm);
/* This occurs when a driver uses ADD_UVERBS_METHODS */ if (obj->type_attrs) {
if (WARN_ON(obj->type_attrs)) if (WARN_ON(obj_elm->type_attrs))
return -EINVAL; return -EINVAL;
obj_elm = radix_tree_lookup(&uapi->radix, obj_key);
if (WARN_ON(!obj_elm))
return -EINVAL;
} else {
obj_elm->type_attrs = obj->type_attrs; obj_elm->type_attrs = obj->type_attrs;
if (obj->type_attrs) { obj_elm->type_class = obj->type_attrs->type_class;
obj_elm->type_class = obj->type_attrs->type_class; /*
/* * Today drivers are only permitted to use idr_class
* Today drivers are only permitted to use idr_class * types. They cannot use FD types because we currently have
* types. They cannot use FD types because we * no way to revoke the fops pointer after device
* currently have no way to revoke the fops pointer * disassociation.
* after device disassociation. */
*/ if (WARN_ON(is_driver &&
if (WARN_ON(is_driver && obj->type_attrs->type_class != obj->type_attrs->type_class != &uverbs_idr_class))
&uverbs_idr_class)) return -EINVAL;
return -EINVAL;
}
} }
if (!obj->methods) if (!obj->methods)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment