]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
RDMA/core: Remove uverbs_async_event_release()
authorJason Gunthorpe <jgg@nvidia.com>
Tue, 26 May 2026 01:22:39 +0000 (22:22 -0300)
committerJason Gunthorpe <jgg@nvidia.com>
Tue, 26 May 2026 13:09:37 +0000 (10:09 -0300)
Instead of having an alternative fops release always use the standard
uverbs_uobject_fd_release() and route the special async behavior back up
through uverbs_obj_fd_type ops pointer.

This removes a dependency where the technically lower level rdma_core.c is
referring to a symbol from uverbs_std_types_async_fd.c.

Link: https://patch.msgid.link/r/3-v3-43aba1969751+1988-ib_uverbs_support_ko_jgg@nvidia.com
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
drivers/infiniband/core/rdma_core.c
drivers/infiniband/core/uverbs.h
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/core/uverbs_std_types_async_fd.c
drivers/infiniband/core/uverbs_uapi.c
include/rdma/uverbs_types.h

index 5018ec837056ff1a943d20327a63a8cfeb6a7136..8934d0d227ab7670ee1762aa6e0cf0d1ca672e91 100644 (file)
@@ -465,8 +465,8 @@ alloc_begin_fd_uobject(const struct uverbs_api_object *obj,
 
        fd_type =
                container_of(obj->type_attrs, struct uverbs_obj_fd_type, type);
-       if (WARN_ON(fd_type->fops && fd_type->fops->release != &uverbs_uobject_fd_release &&
-                   fd_type->fops->release != &uverbs_async_event_release)) {
+       if (WARN_ON(fd_type->fops &&
+                   fd_type->fops->release != &uverbs_uobject_fd_release)) {
                ret = ERR_PTR(-EINVAL);
                goto err_fd;
        }
@@ -846,13 +846,37 @@ int uverbs_uobject_release(struct ib_uobject *uobj)
  */
 int uverbs_uobject_fd_release(struct inode *inode, struct file *filp)
 {
+       void (*release_cleanup)(struct ib_uobject *uobj) = NULL;
+       struct ib_uobject *uobj = filp->private_data;
+       const struct uverbs_obj_type *type_attrs;
+       int ret;
+
        /*
         * This can only happen if the fput came from alloc_abort_fd_uobject()
         */
-       if (!filp->private_data)
+       if (!uobj)
                return 0;
 
-       return uverbs_uobject_release(filp->private_data);
+       /*
+        * uverbs_disassociate_api() can NULL type_attrs after disassociate, but
+        * it won't if release_cleanup is used.
+        */
+       type_attrs = READ_ONCE(uobj->uapi_object->type_attrs);
+       if (type_attrs)
+               release_cleanup = container_of(type_attrs,
+                                              struct uverbs_obj_fd_type, type)
+                                         ->release_cleanup;
+       if (release_cleanup)
+               uverbs_uobject_get(uobj);
+
+       ret = uverbs_uobject_release(uobj);
+
+       if (release_cleanup) {
+               release_cleanup(uobj);
+               uverbs_uobject_put(uobj);
+       }
+
+       return ret;
 }
 EXPORT_SYMBOL(uverbs_uobject_fd_release);
 
index 1563169c65009eec540848e0f54f3f447a3a0950..a1de8fe9c90bf104e402d4e66e2caf4a18e860aa 100644 (file)
@@ -203,7 +203,6 @@ void ib_uverbs_init_event_queue(struct ib_uverbs_event_queue *ev_queue);
 void ib_uverbs_init_async_event_file(struct ib_uverbs_async_event_file *ev_file);
 void ib_uverbs_free_event_queue(struct ib_uverbs_event_queue *event_queue);
 void ib_uverbs_flow_resources_free(struct ib_uflow_resources *uflow_res);
-int uverbs_async_event_release(struct inode *inode, struct file *filp);
 
 int ib_alloc_ucontext(struct uverbs_attr_bundle *attrs);
 int ib_init_ucontext(struct uverbs_attr_bundle *attrs);
index 15d8387718c050dee9366fe02b4ff298cef777bc..a937d276c5c076071efd64f6bacb30e042f288e4 100644 (file)
@@ -338,7 +338,7 @@ const struct file_operations uverbs_async_event_fops = {
        .owner   = THIS_MODULE,
        .read    = ib_uverbs_async_event_read,
        .poll    = ib_uverbs_async_event_poll,
-       .release = uverbs_async_event_release,
+       .release = uverbs_uobject_fd_release,
        .fasync  = ib_uverbs_async_event_fasync,
 };
 
index cc24cfdf7aee6603f814fccad2cf3db711ed71ec..671f510bca496fbcbe5e770c50880160bbe4d49d 100644 (file)
@@ -32,14 +32,9 @@ static void uverbs_async_event_destroy_uobj(struct ib_uobject *uobj,
                                        NULL, NULL);
 }
 
-int uverbs_async_event_release(struct inode *inode, struct file *filp)
+static void uverbs_async_event_free_event_queue(struct ib_uobject *uobj)
 {
        struct ib_uverbs_async_event_file *event_file;
-       struct ib_uobject *uobj = filp->private_data;
-       int ret;
-
-       if (!uobj)
-               return uverbs_uobject_fd_release(inode, filp);
 
        event_file =
                container_of(uobj, struct ib_uverbs_async_event_file, uobj);
@@ -50,11 +45,7 @@ int uverbs_async_event_release(struct inode *inode, struct file *filp)
         * release. The user knows it has reached the end of the event stream
         * when it sees IB_EVENT_DEVICE_FATAL.
         */
-       uverbs_uobject_get(uobj);
-       ret = uverbs_uobject_fd_release(inode, filp);
        ib_uverbs_free_event_queue(&event_file->ev_queue);
-       uverbs_uobject_put(uobj);
-       return ret;
 }
 
 DECLARE_UVERBS_NAMED_METHOD(
@@ -66,11 +57,12 @@ DECLARE_UVERBS_NAMED_METHOD(
 
 DECLARE_UVERBS_NAMED_OBJECT(
        UVERBS_OBJECT_ASYNC_EVENT,
-       UVERBS_TYPE_ALLOC_FD(sizeof(struct ib_uverbs_async_event_file),
-                            uverbs_async_event_destroy_uobj,
-                            &uverbs_async_event_fops,
-                            "[infinibandevent]",
-                            O_RDONLY),
+       UVERBS_TYPE_ALLOC_FD_RELEASE(sizeof(struct ib_uverbs_async_event_file),
+                                    uverbs_async_event_destroy_uobj,
+                                    uverbs_async_event_free_event_queue,
+                                    &uverbs_async_event_fops,
+                                    "[infinibandevent]",
+                                    O_RDONLY),
        &UVERBS_METHOD(UVERBS_METHOD_ASYNC_EVENT_ALLOC));
 
 const struct uapi_definition uverbs_def_obj_async_fd[] = {
index 31b248295854bdb3f719715cbb2fa000257395c0..4e2e556c8119b560414e9d9184e50776e567b258 100644 (file)
@@ -718,12 +718,25 @@ void uverbs_disassociate_api(struct uverbs_api *uapi)
                if (uapi_key_is_object(iter.index)) {
                        struct uverbs_api_object *object_elm =
                                rcu_dereference_protected(*slot, true);
+                       const struct uverbs_obj_type *type_attrs =
+                               object_elm->type_attrs;
 
                        /*
                         * Some type_attrs are in the driver module. We don't
                         * bother to keep track of which since there should be
                         * no use of this after disassociate.
+                        *
+                        * release_cleanup is the exception because
+                        * uverbs_uobject_fd_release() needs it. In this case
+                        * the module reference held by the fops will guarentee
+                        * the type_class remains valid too.
                         */
+                       if (type_attrs &&
+                           type_attrs->type_class == &uverbs_fd_class &&
+                           container_of(type_attrs, struct uverbs_obj_fd_type,
+                                        type)->release_cleanup)
+                               continue;
+
                        object_elm->type_attrs = NULL;
                } else if (uapi_key_is_attr(iter.index)) {
                        struct uverbs_api_attr *elm =
index 6a253b7dc5ea663c8a2fdb4ce318d2ce64bfd43f..5a07f9a6dcd1f6e2faaf2df25d2661d5bf2a170e 100644 (file)
@@ -147,6 +147,7 @@ struct uverbs_obj_fd_type {
        struct uverbs_obj_type  type;
        void (*destroy_object)(struct ib_uobject *uobj,
                               enum rdma_remove_reason why);
+       void (*release_cleanup)(struct ib_uobject *uobj);
        const struct file_operations    *fops;
        const char                      *name;
        int                             flags;
@@ -190,7 +191,8 @@ int uverbs_uobject_release(struct ib_uobject *uobj);
 
 #define UVERBS_BUILD_BUG_ON(cond) (sizeof(char[1 - 2 * !!(cond)]) -    \
                                   sizeof(char))
-#define UVERBS_TYPE_ALLOC_FD(_obj_size, _destroy_object, _fops, _name, _flags) \
+#define UVERBS_TYPE_ALLOC_FD_RELEASE(_obj_size, _destroy_object,       \
+                                    _release_cleanup, _fops, _name, _flags) \
        ((&((const struct uverbs_obj_fd_type)                           \
         {.type = {                                                     \
                .type_class = &uverbs_fd_class,                         \
@@ -199,9 +201,13 @@ int uverbs_uobject_release(struct ib_uobject *uobj);
                                            sizeof(struct ib_uobject)), \
         },                                                             \
         .destroy_object = _destroy_object,                             \
+        .release_cleanup = _release_cleanup,                           \
         .fops = _fops,                                                 \
         .name = _name,                                                 \
         .flags = _flags}))->type)
+#define UVERBS_TYPE_ALLOC_FD(_obj_size, _destroy_object, _fops, _name, _flags) \
+       UVERBS_TYPE_ALLOC_FD_RELEASE(_obj_size, _destroy_object, NULL,  \
+                                    _fops, _name, _flags)
 #define UVERBS_TYPE_ALLOC_IDR_SZ(_size, _destroy_object)       \
        ((&((const struct uverbs_obj_idr_type)                          \
         {.type = {                                                     \