Commit 87ad80ab authored by Jason Gunthorpe's avatar Jason Gunthorpe

IB/uverbs: Consolidate uobject destruction

There are several flows that can destroy a uobject and each one is
minimized and sprinkled throughout the code base, making it difficult to
understand and very hard to modify the destroy path.

Consolidate all of these into uverbs_destroy_uobject() and call it in all
cases where a uobject has to be destroyed.

This makes one change to the lifecycle, during any abort (eg when
alloc_commit is not called) we always call out to alloc_abort, even if
remove_commit needs to be called to delete a HW object.

This also renames RDMA_REMOVE_DURING_CLEANUP to RDMA_REMOVE_ABORT to
clarify its actual usage and revises some of the comments to reflect what
the life cycle is for the type implementation.
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
parent 32ed5c00
This diff is collapsed.
...@@ -1467,8 +1467,8 @@ enum rdma_remove_reason { ...@@ -1467,8 +1467,8 @@ enum rdma_remove_reason {
RDMA_REMOVE_CLOSE, RDMA_REMOVE_CLOSE,
/* Driver is being hot-unplugged. This call should delete the actual object itself */ /* Driver is being hot-unplugged. This call should delete the actual object itself */
RDMA_REMOVE_DRIVER_REMOVE, RDMA_REMOVE_DRIVER_REMOVE,
/* Context is being cleaned-up, but commit was just completed */ /* uobj is being cleaned-up before being committed */
RDMA_REMOVE_DURING_CLEANUP, RDMA_REMOVE_ABORT,
}; };
struct ib_rdmacg_object { struct ib_rdmacg_object {
......
...@@ -38,53 +38,49 @@ ...@@ -38,53 +38,49 @@
struct uverbs_obj_type; struct uverbs_obj_type;
struct uverbs_obj_type_class { /*
/* * The following sequences are valid:
* Get an ib_uobject that corresponds to the given id from ucontext, * Success flow:
* These functions could create or destroy objects if required. * alloc_begin
* The action will be finalized only when commit, abort or put fops are * alloc_commit
* called. * [..]
* The flow of the different actions is: * Access flow:
* [alloc]: Starts with alloc_begin. The handlers logic is than * lookup_get(exclusive=false) & uverbs_try_lock_object
* executed. If the handler is successful, alloc_commit * lookup_put(exclusive=false) via rdma_lookup_put_uobject
* is called and the object is inserted to the repository. * Destruction flow:
* Once alloc_commit completes the object is visible to * lookup_get(exclusive=true) & uverbs_try_lock_object
* other threads and userspace. * remove_commit
e Otherwise, alloc_abort is called and the object is * lookup_put(exclusive=true) via rdma_lookup_put_uobject
* destroyed. *
* [lookup]: Starts with lookup_get which fetches and locks the * Allocate Error flow #1
* object. After the handler finished using the object, it * alloc_begin
* needs to call lookup_put to unlock it. The exclusive * alloc_abort
* flag indicates if the object is locked for exclusive * Allocate Error flow #2
* access. * alloc_begin
* [remove]: Starts with lookup_get with exclusive flag set. This * remove_commit
* locks the object for exclusive access. If the handler * alloc_abort
* code completed successfully, remove_commit is called * Allocate Error flow #3
* and the ib_uobject is removed from the context's * alloc_begin
* uobjects repository and put. The object itself is * alloc_commit (fails)
* destroyed as well. Once remove succeeds new krefs to * remove_commit
* the object cannot be acquired by other threads or * alloc_abort
* userspace and the hardware driver is removed from the *
* object. Other krefs on the object may still exist. * In all cases the caller must hold the ufile kref until alloc_commit or
* If the handler code failed, lookup_put should be * alloc_abort returns.
* called. This callback is used when the context
* is destroyed as well (process termination,
* reset flow).
*/ */
struct uverbs_obj_type_class {
struct ib_uobject *(*alloc_begin)(const struct uverbs_obj_type *type, struct ib_uobject *(*alloc_begin)(const struct uverbs_obj_type *type,
struct ib_uverbs_file *ufile); struct ib_uverbs_file *ufile);
/* 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 */
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_obj_type *type,
struct ib_uverbs_file *ufile, s64 id, struct ib_uverbs_file *ufile, s64 id,
bool exclusive); bool exclusive);
void (*lookup_put)(struct ib_uobject *uobj, bool exclusive); void (*lookup_put)(struct ib_uobject *uobj, bool exclusive);
/* /* This does not consume the kref on uobj */
* Must be called with the exclusive lock held. If successful uobj is
* invalid on return. On failure uobject is left completely
* unchanged
*/
int __must_check (*remove_commit)(struct ib_uobject *uobj, int __must_check (*remove_commit)(struct ib_uobject *uobj,
enum rdma_remove_reason why); enum rdma_remove_reason why);
u8 needs_kfree_rcu; u8 needs_kfree_rcu;
......
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