return ret;
 }
 
+static int null_obj_type_class_remove_commit(struct ib_uobject *uobj,
+                                            enum rdma_remove_reason why)
+{
+       return 0;
+}
+
+static const struct uverbs_obj_type null_obj_type = {
+       .type_class = &((const struct uverbs_obj_type_class){
+                       .remove_commit = null_obj_type_class_remove_commit,
+                       /* be cautious */
+                       .needs_kfree_rcu = true}),
+};
+
+int rdma_explicit_destroy(struct ib_uobject *uobject)
+{
+       int ret;
+       struct ib_ucontext *ucontext = uobject->context;
+
+       /* Cleanup is running. Calling this should have been impossible */
+       if (!down_read_trylock(&ucontext->cleanup_rwsem)) {
+               WARN(true, "ib_uverbs: Cleanup is running while removing an uobject\n");
+               return 0;
+       }
+       lockdep_check(uobject, true);
+       ret = uobject->type->type_class->remove_commit(uobject,
+                                                      RDMA_REMOVE_DESTROY);
+       if (ret)
+               return ret;
+
+       uobject->type = &null_obj_type;
+
+       up_read(&ucontext->cleanup_rwsem);
+       return 0;
+}
+
 static void alloc_commit_idr_uobject(struct ib_uobject *uobj)
 {
        uverbs_uobject_add(uobj);
 
 void rdma_alloc_abort_uobject(struct ib_uobject *uobj);
 int __must_check rdma_remove_commit_uobject(struct ib_uobject *uobj);
 int rdma_alloc_commit_uobject(struct ib_uobject *uobj);
+int rdma_explicit_destroy(struct ib_uobject *uobject);
 
 struct uverbs_obj_fd_type {
        /*