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: Jason Gunthorpe <jgg@mellanox.com>
This commit is contained in:
@@ -1524,7 +1524,7 @@ struct ib_uobject {
|
||||
atomic_t usecnt; /* protects exclusive access */
|
||||
struct rcu_head rcu; /* kfree_rcu() overhead */
|
||||
|
||||
const struct uverbs_obj_type *type;
|
||||
const struct uverbs_api_object *uapi_object;
|
||||
};
|
||||
|
||||
struct ib_udata {
|
||||
|
@@ -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_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) \
|
||||
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)
|
||||
|
||||
#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), \
|
||||
UVERBS_LOOKUP_READ)
|
||||
|
||||
@@ -76,20 +77,21 @@ static inline void *_uobj_get_obj_read(struct ib_uobject *uobj)
|
||||
uobj_get_read(_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)
|
||||
|
||||
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);
|
||||
#define uobj_perform_destroy(_type, _id, _ufile, _success_res) \
|
||||
__uobj_perform_destroy(uobj_get_type(_type), _uobj_check_id(_id), \
|
||||
_ufile, _success_res)
|
||||
__uobj_perform_destroy(uobj_get_type(_ufile, _type), \
|
||||
_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);
|
||||
|
||||
#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)
|
||||
{
|
||||
@@ -124,11 +126,11 @@ static inline void uobj_alloc_abort(struct ib_uobject *uobj)
|
||||
rdma_alloc_abort_uobject(uobj);
|
||||
}
|
||||
|
||||
static inline struct ib_uobject *__uobj_alloc(const struct uverbs_obj_type *type,
|
||||
struct ib_uverbs_file *ufile,
|
||||
struct ib_device **ib_dev)
|
||||
static inline struct ib_uobject *
|
||||
__uobj_alloc(const struct uverbs_api_object *obj, struct ib_uverbs_file *ufile,
|
||||
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))
|
||||
*ib_dev = uobj->context->device;
|
||||
@@ -136,7 +138,7 @@ static inline struct ib_uobject *__uobj_alloc(const struct uverbs_obj_type *type
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
|
@@ -37,6 +37,7 @@
|
||||
#include <rdma/ib_verbs.h>
|
||||
|
||||
struct uverbs_obj_type;
|
||||
struct uverbs_api_object;
|
||||
|
||||
enum rdma_lookup_mode {
|
||||
UVERBS_LOOKUP_READ,
|
||||
@@ -81,14 +82,14 @@ enum rdma_lookup_mode {
|
||||
* alloc_abort returns.
|
||||
*/
|
||||
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);
|
||||
/* This consumes the kref on uobj */
|
||||
int (*alloc_commit)(struct ib_uobject *uobj);
|
||||
/* This does not consume the kref on 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,
|
||||
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 {
|
||||
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,
|
||||
enum rdma_lookup_mode mode);
|
||||
void rdma_lookup_put_uobject(struct ib_uobject *uobj,
|
||||
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);
|
||||
void rdma_alloc_abort_uobject(struct ib_uobject *uobj);
|
||||
int __must_check rdma_alloc_commit_uobject(struct ib_uobject *uobj);
|
||||
|
Reference in New Issue
Block a user