OSDN Git Service

RDMA/core: Change how failing destroy is handled during uobj abort
authorJason Gunthorpe <jgg@nvidia.com>
Wed, 2 Sep 2020 08:17:08 +0000 (11:17 +0300)
committerJason Gunthorpe <jgg@nvidia.com>
Wed, 9 Sep 2020 16:16:48 +0000 (13:16 -0300)
Currently it triggers a WARN_ON and then goes ahead and destroys the
uobject anyhow, leaking any driver memory.

The only place that leaks driver memory should be during FD close() in
uverbs_destroy_ufile_hw().

Drivers are only allowed to fail destroy uobjects if they guarantee
destroy will eventually succeed. uverbs_destroy_ufile_hw() provides the
loop to give the driver that chance.

Link: https://lore.kernel.org/r/20200902081708.746631-1-leon@kernel.org
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
drivers/infiniband/core/rdma_core.c
include/rdma/ib_verbs.h

index e1c616e..d2b5417 100644 (file)
@@ -130,17 +130,6 @@ static int uverbs_destroy_uobject(struct ib_uobject *uobj,
        lockdep_assert_held(&ufile->hw_destroy_rwsem);
        assert_uverbs_usecnt(uobj, UVERBS_LOOKUP_WRITE);
 
-       if (reason == RDMA_REMOVE_ABORT_HWOBJ) {
-               reason = RDMA_REMOVE_ABORT;
-               ret = uobj->uapi_object->type_class->destroy_hw(uobj, reason,
-                                                               attrs);
-               /*
-                * Drivers are not permitted to ignore RDMA_REMOVE_ABORT, see
-                * ib_is_destroy_retryable, cleanup_retryable == false here.
-                */
-               WARN_ON(ret);
-       }
-
        if (reason == RDMA_REMOVE_ABORT) {
                WARN_ON(!list_empty(&uobj->list));
                WARN_ON(!uobj->context);
@@ -674,11 +663,22 @@ void rdma_alloc_abort_uobject(struct ib_uobject *uobj,
                              bool hw_obj_valid)
 {
        struct ib_uverbs_file *ufile = uobj->ufile;
+       int ret;
+
+       if (hw_obj_valid) {
+               ret = uobj->uapi_object->type_class->destroy_hw(
+                       uobj, RDMA_REMOVE_ABORT, attrs);
+               /*
+                * If the driver couldn't destroy the object then go ahead and
+                * commit it. Leaking objects that can't be destroyed is only
+                * done during FD close after the driver has a few more tries to
+                * destroy it.
+                */
+               if (WARN_ON(ret))
+                       return rdma_alloc_commit_uobject(uobj, attrs);
+       }
 
-       uverbs_destroy_uobject(uobj,
-                              hw_obj_valid ? RDMA_REMOVE_ABORT_HWOBJ :
-                                             RDMA_REMOVE_ABORT,
-                              attrs);
+       uverbs_destroy_uobject(uobj, RDMA_REMOVE_ABORT, attrs);
 
        /* Matches the down_read in rdma_alloc_begin_uobject */
        up_read(&ufile->hw_destroy_rwsem);
index c868609..3781d36 100644 (file)
@@ -1463,11 +1463,6 @@ enum rdma_remove_reason {
        RDMA_REMOVE_DRIVER_REMOVE,
        /* uobj is being cleaned-up before being committed */
        RDMA_REMOVE_ABORT,
-       /*
-        * uobj has been fully created, with the uobj->object set, but is being
-        * cleaned up before being comitted
-        */
-       RDMA_REMOVE_ABORT_HWOBJ,
 };
 
 struct ib_rdmacg_object {