Commit 6b0d08f4 authored by Jason Gunthorpe's avatar Jason Gunthorpe

IB/uverbs: Use uverbs_api to manage the object type inside the uobject

Currently the struct uverbs_obj_type stored in the ib_uobject is part of
the .rodata segment of the module that defines the object. This is a
problem if drivers define new uapi objects as we will be left with a
dangling pointer after device disassociation.

Switch the uverbs_obj_type for struct uverbs_api_object, which is
allocated memory that is part of the uverbs_api and is guaranteed to
always exist. Further this moves the 'type_class' into this memory which
means access to the IDR/FD function pointers is also guaranteed. Drivers
cannot define new types.

This makes it safe to continue to use all uobjects, including driver
defined ones, after disassociation.
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
parent 9ed3e5f4
This diff is collapsed.
...@@ -89,7 +89,7 @@ void uverbs_close_fd(struct file *f); ...@@ -89,7 +89,7 @@ void uverbs_close_fd(struct file *f);
* uverbs_finalize_objects are called. * uverbs_finalize_objects are called.
*/ */
struct ib_uobject * struct ib_uobject *
uverbs_get_uobject_from_file(const struct uverbs_obj_type *type_attrs, uverbs_get_uobject_from_file(u16 object_id,
struct ib_uverbs_file *ufile, struct ib_uverbs_file *ufile,
enum uverbs_obj_access access, s64 id); enum uverbs_obj_access access, s64 id);
......
...@@ -57,7 +57,6 @@ static int uverbs_process_attr(struct ib_uverbs_file *ufile, ...@@ -57,7 +57,6 @@ static int uverbs_process_attr(struct ib_uverbs_file *ufile,
const struct uverbs_attr_spec *spec; const struct uverbs_attr_spec *spec;
const struct uverbs_attr_spec *val_spec; const struct uverbs_attr_spec *val_spec;
struct uverbs_attr *e; struct uverbs_attr *e;
const struct uverbs_object_spec *object;
struct uverbs_obj_attr *o_attr; struct uverbs_obj_attr *o_attr;
struct uverbs_attr *elements = attr_bundle_h->attrs; struct uverbs_attr *elements = attr_bundle_h->attrs;
...@@ -145,9 +144,6 @@ static int uverbs_process_attr(struct ib_uverbs_file *ufile, ...@@ -145,9 +144,6 @@ static int uverbs_process_attr(struct ib_uverbs_file *ufile,
return -EINVAL; return -EINVAL;
o_attr = &e->obj_attr; o_attr = &e->obj_attr;
object = uverbs_get_object(ufile, spec->u.obj.obj_type);
if (!object)
return -EINVAL;
/* specs are allowed to have only one destroy attribute */ /* specs are allowed to have only one destroy attribute */
WARN_ON(spec->u.obj.access == UVERBS_ACCESS_DESTROY && WARN_ON(spec->u.obj.access == UVERBS_ACCESS_DESTROY &&
...@@ -162,7 +158,7 @@ static int uverbs_process_attr(struct ib_uverbs_file *ufile, ...@@ -162,7 +158,7 @@ static int uverbs_process_attr(struct ib_uverbs_file *ufile,
* IDR implementation today rejects negative IDs * IDR implementation today rejects negative IDs
*/ */
o_attr->uobject = uverbs_get_uobject_from_file( o_attr->uobject = uverbs_get_uobject_from_file(
object->type_attrs, spec->u.obj.obj_type,
ufile, ufile,
spec->u.obj.access, spec->u.obj.access,
uattr->data_s64); uattr->data_s64);
......
...@@ -1524,7 +1524,7 @@ struct ib_uobject { ...@@ -1524,7 +1524,7 @@ struct ib_uobject {
atomic_t usecnt; /* protects exclusive access */ atomic_t usecnt; /* protects exclusive access */
struct rcu_head rcu; /* kfree_rcu() overhead */ struct rcu_head rcu; /* kfree_rcu() overhead */
const struct uverbs_obj_type *type; const struct uverbs_api_object *uapi_object;
}; };
struct ib_udata { struct ib_udata {
......
...@@ -54,14 +54,15 @@ static inline const struct uverbs_object_tree_def *uverbs_default_get_objects(vo ...@@ -54,14 +54,15 @@ static inline const struct uverbs_object_tree_def *uverbs_default_get_objects(vo
*/ */
#define _uobj_check_id(_id) ((_id) * typecheck(u32, _id)) #define _uobj_check_id(_id) ((_id) * typecheck(u32, _id))
#define uobj_get_type(_object) UVERBS_OBJECT(_object).type_attrs #define uobj_get_type(_ufile, _object) \
uapi_get_object((_ufile)->device->uapi, _object)
#define uobj_get_read(_type, _id, _ufile) \ #define uobj_get_read(_type, _id, _ufile) \
rdma_lookup_get_uobject(uobj_get_type(_type), _ufile, \ rdma_lookup_get_uobject(uobj_get_type(_ufile, _type), _ufile, \
_uobj_check_id(_id), UVERBS_LOOKUP_READ) _uobj_check_id(_id), UVERBS_LOOKUP_READ)
#define ufd_get_read(_type, _fdnum, _ufile) \ #define ufd_get_read(_type, _fdnum, _ufile) \
rdma_lookup_get_uobject(uobj_get_type(_type), _ufile, \ rdma_lookup_get_uobject(uobj_get_type(_ufile, _type), _ufile, \
(_fdnum)*typecheck(s32, _fdnum), \ (_fdnum)*typecheck(s32, _fdnum), \
UVERBS_LOOKUP_READ) UVERBS_LOOKUP_READ)
...@@ -76,20 +77,21 @@ static inline void *_uobj_get_obj_read(struct ib_uobject *uobj) ...@@ -76,20 +77,21 @@ static inline void *_uobj_get_obj_read(struct ib_uobject *uobj)
uobj_get_read(_type, _id, _ufile))) uobj_get_read(_type, _id, _ufile)))
#define uobj_get_write(_type, _id, _ufile) \ #define uobj_get_write(_type, _id, _ufile) \
rdma_lookup_get_uobject(uobj_get_type(_type), _ufile, \ rdma_lookup_get_uobject(uobj_get_type(_ufile, _type), _ufile, \
_uobj_check_id(_id), UVERBS_LOOKUP_WRITE) _uobj_check_id(_id), UVERBS_LOOKUP_WRITE)
int __uobj_perform_destroy(const struct uverbs_obj_type *type, u32 id, int __uobj_perform_destroy(const struct uverbs_api_object *obj, u32 id,
struct ib_uverbs_file *ufile, int success_res); struct ib_uverbs_file *ufile, int success_res);
#define uobj_perform_destroy(_type, _id, _ufile, _success_res) \ #define uobj_perform_destroy(_type, _id, _ufile, _success_res) \
__uobj_perform_destroy(uobj_get_type(_type), _uobj_check_id(_id), \ __uobj_perform_destroy(uobj_get_type(_ufile, _type), \
_ufile, _success_res) _uobj_check_id(_id), _ufile, _success_res)
struct ib_uobject *__uobj_get_destroy(const struct uverbs_obj_type *type, struct ib_uobject *__uobj_get_destroy(const struct uverbs_api_object *obj,
u32 id, struct ib_uverbs_file *ufile); u32 id, struct ib_uverbs_file *ufile);
#define uobj_get_destroy(_type, _id, _ufile) \ #define uobj_get_destroy(_type, _id, _ufile) \
__uobj_get_destroy(uobj_get_type(_type), _uobj_check_id(_id), _ufile) __uobj_get_destroy(uobj_get_type(_ufile, _type), _uobj_check_id(_id), \
_ufile)
static inline void uobj_put_destroy(struct ib_uobject *uobj) static inline void uobj_put_destroy(struct ib_uobject *uobj)
{ {
...@@ -124,11 +126,11 @@ static inline void uobj_alloc_abort(struct ib_uobject *uobj) ...@@ -124,11 +126,11 @@ static inline void uobj_alloc_abort(struct ib_uobject *uobj)
rdma_alloc_abort_uobject(uobj); rdma_alloc_abort_uobject(uobj);
} }
static inline struct ib_uobject *__uobj_alloc(const struct uverbs_obj_type *type, static inline struct ib_uobject *
struct ib_uverbs_file *ufile, __uobj_alloc(const struct uverbs_api_object *obj, struct ib_uverbs_file *ufile,
struct ib_device **ib_dev) struct ib_device **ib_dev)
{ {
struct ib_uobject *uobj = rdma_alloc_begin_uobject(type, ufile); struct ib_uobject *uobj = rdma_alloc_begin_uobject(obj, ufile);
if (!IS_ERR(uobj)) if (!IS_ERR(uobj))
*ib_dev = uobj->context->device; *ib_dev = uobj->context->device;
...@@ -136,7 +138,7 @@ static inline struct ib_uobject *__uobj_alloc(const struct uverbs_obj_type *type ...@@ -136,7 +138,7 @@ static inline struct ib_uobject *__uobj_alloc(const struct uverbs_obj_type *type
} }
#define uobj_alloc(_type, _ufile, _ib_dev) \ #define uobj_alloc(_type, _ufile, _ib_dev) \
__uobj_alloc(uobj_get_type(_type), _ufile, _ib_dev) __uobj_alloc(uobj_get_type(_ufile, _type), _ufile, _ib_dev)
#endif #endif
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <rdma/ib_verbs.h> #include <rdma/ib_verbs.h>
struct uverbs_obj_type; struct uverbs_obj_type;
struct uverbs_api_object;
enum rdma_lookup_mode { enum rdma_lookup_mode {
UVERBS_LOOKUP_READ, UVERBS_LOOKUP_READ,
...@@ -81,14 +82,14 @@ enum rdma_lookup_mode { ...@@ -81,14 +82,14 @@ enum rdma_lookup_mode {
* alloc_abort returns. * alloc_abort returns.
*/ */
struct uverbs_obj_type_class { struct uverbs_obj_type_class {
struct ib_uobject *(*alloc_begin)(const struct uverbs_obj_type *type, struct ib_uobject *(*alloc_begin)(const struct uverbs_api_object *obj,
struct ib_uverbs_file *ufile); struct ib_uverbs_file *ufile);
/* This consumes the kref on uobj */ /* This consumes the kref on uobj */
int (*alloc_commit)(struct ib_uobject *uobj); int (*alloc_commit)(struct ib_uobject *uobj);
/* This does not consume the kref on uobj */ /* This does not consume the kref on uobj */
void (*alloc_abort)(struct ib_uobject *uobj); void (*alloc_abort)(struct ib_uobject *uobj);
struct ib_uobject *(*lookup_get)(const struct uverbs_obj_type *type, struct ib_uobject *(*lookup_get)(const struct uverbs_api_object *obj,
struct ib_uverbs_file *ufile, s64 id, struct ib_uverbs_file *ufile, s64 id,
enum rdma_lookup_mode mode); enum rdma_lookup_mode mode);
void (*lookup_put)(struct ib_uobject *uobj, enum rdma_lookup_mode mode); void (*lookup_put)(struct ib_uobject *uobj, enum rdma_lookup_mode mode);
...@@ -128,12 +129,12 @@ struct uverbs_obj_idr_type { ...@@ -128,12 +129,12 @@ struct uverbs_obj_idr_type {
enum rdma_remove_reason why); enum rdma_remove_reason why);
}; };
struct ib_uobject *rdma_lookup_get_uobject(const struct uverbs_obj_type *type, struct ib_uobject *rdma_lookup_get_uobject(const struct uverbs_api_object *obj,
struct ib_uverbs_file *ufile, s64 id, struct ib_uverbs_file *ufile, s64 id,
enum rdma_lookup_mode mode); enum rdma_lookup_mode mode);
void rdma_lookup_put_uobject(struct ib_uobject *uobj, void rdma_lookup_put_uobject(struct ib_uobject *uobj,
enum rdma_lookup_mode mode); enum rdma_lookup_mode mode);
struct ib_uobject *rdma_alloc_begin_uobject(const struct uverbs_obj_type *type, struct ib_uobject *rdma_alloc_begin_uobject(const struct uverbs_api_object *obj,
struct ib_uverbs_file *ufile); struct ib_uverbs_file *ufile);
void rdma_alloc_abort_uobject(struct ib_uobject *uobj); void rdma_alloc_abort_uobject(struct ib_uobject *uobj);
int __must_check rdma_alloc_commit_uobject(struct ib_uobject *uobj); int __must_check rdma_alloc_commit_uobject(struct ib_uobject *uobj);
......
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