From: Jason Gunthorpe <j...@nvidia.com>

[ Upstream commit f553246f7f794675da1794ae7ee07d1f35e561ae ]

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-l...@kernel.org
Signed-off-by: Leon Romanovsky <leo...@nvidia.com>
Signed-off-by: Jason Gunthorpe <j...@nvidia.com>
Signed-off-by: Sasha Levin <sas...@kernel.org>
---
 drivers/infiniband/core/rdma_core.c | 30 ++++++++++++++---------------
 include/rdma/ib_verbs.h             |  5 -----
 2 files changed, 15 insertions(+), 20 deletions(-)

diff --git a/drivers/infiniband/core/rdma_core.c 
b/drivers/infiniband/core/rdma_core.c
index 6d3ed7c6e19eb..3962da54ffbf4 100644
--- a/drivers/infiniband/core/rdma_core.c
+++ b/drivers/infiniband/core/rdma_core.c
@@ -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);
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 5b4f0efc4241f..ef7b786b8675c 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -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 {
-- 
2.27.0



Reply via email to