diff --git a/drivers/infiniband/core/rdma_core.c b/drivers/infiniband/core/rdma_core.c index a63844ba8414..9e84ded6d3be 100644 --- a/drivers/infiniband/core/rdma_core.c +++ b/drivers/infiniband/core/rdma_core.c @@ -924,10 +924,7 @@ int uverbs_finalize_object(struct ib_uobject *uobj, rdma_lookup_put_uobject(uobj, true); break; case UVERBS_ACCESS_DESTROY: - if (commit) - ret = rdma_remove_commit_uobject(uobj); - else - rdma_lookup_put_uobject(uobj, true); + rdma_lookup_put_uobject(uobj, true); break; case UVERBS_ACCESS_NEW: if (commit) diff --git a/drivers/infiniband/core/uverbs_ioctl.c b/drivers/infiniband/core/uverbs_ioctl.c index 23a1777f26e2..404acfcdbeb2 100644 --- a/drivers/infiniband/core/uverbs_ioctl.c +++ b/drivers/infiniband/core/uverbs_ioctl.c @@ -51,6 +51,7 @@ static int uverbs_process_attr(struct ib_uverbs_file *ufile, u16 attr_id, const struct uverbs_attr_spec_hash *attr_spec_bucket, struct uverbs_attr_bundle_hash *attr_bundle_h, + struct uverbs_obj_attr **destroy_attr, struct ib_uverbs_attr __user *uattr_ptr) { const struct uverbs_attr_spec *spec; @@ -148,6 +149,12 @@ static int uverbs_process_attr(struct ib_uverbs_file *ufile, if (!object) return -EINVAL; + /* specs are allowed to have only one destroy attribute */ + WARN_ON(spec->u.obj.access == UVERBS_ACCESS_DESTROY && + *destroy_attr); + if (spec->u.obj.access == UVERBS_ACCESS_DESTROY) + *destroy_attr = o_attr; + /* * The type of uattr->data is u64 for UVERBS_ATTR_TYPE_IDR and * s64 for UVERBS_ATTR_TYPE_FD. We can cast the u64 to s64 @@ -235,6 +242,7 @@ static int uverbs_uattrs_process(struct ib_uverbs_file *ufile, size_t num_uattrs, const struct uverbs_method_spec *method, struct uverbs_attr_bundle *attr_bundle, + struct uverbs_obj_attr **destroy_attr, struct ib_uverbs_attr __user *uattr_ptr) { size_t i; @@ -268,7 +276,8 @@ static int uverbs_uattrs_process(struct ib_uverbs_file *ufile, attr_spec_bucket = method->attr_buckets[ret]; ret = uverbs_process_attr(ufile, uattr, attr_id, attr_spec_bucket, - &attr_bundle->hash[ret], uattr_ptr++); + &attr_bundle->hash[ret], destroy_attr, + uattr_ptr++); if (ret) { uverbs_finalize_attrs(attr_bundle, method->attr_buckets, @@ -322,9 +331,11 @@ static int uverbs_handle_method(struct ib_uverbs_attr __user *uattr_ptr, int ret; int finalize_ret; int num_given_buckets; + struct uverbs_obj_attr *destroy_attr = NULL; - num_given_buckets = uverbs_uattrs_process( - ufile, uattrs, num_uattrs, method_spec, attr_bundle, uattr_ptr); + num_given_buckets = + uverbs_uattrs_process(ufile, uattrs, num_uattrs, method_spec, + attr_bundle, &destroy_attr, uattr_ptr); if (num_given_buckets <= 0) return -EINVAL; @@ -333,7 +344,18 @@ static int uverbs_handle_method(struct ib_uverbs_attr __user *uattr_ptr, if (ret) goto cleanup; + /* + * We destroy the HW object before invoking the handler, handlers do + * not get to manipulate the HW objects. + */ + if (destroy_attr) { + ret = rdma_explicit_destroy(destroy_attr->uobject); + if (ret) + goto cleanup; + } + ret = method_spec->handler(ibdev, ufile, attr_bundle); + cleanup: finalize_ret = uverbs_finalize_attrs(attr_bundle, method_spec->attr_buckets, diff --git a/drivers/infiniband/core/uverbs_std_types_cq.c b/drivers/infiniband/core/uverbs_std_types_cq.c index 3179203a2dd7..68c86e6e932e 100644 --- a/drivers/infiniband/core/uverbs_std_types_cq.c +++ b/drivers/infiniband/core/uverbs_std_types_cq.c @@ -179,21 +179,12 @@ static int UVERBS_HANDLER(UVERBS_METHOD_CQ_DESTROY)(struct ib_device *ib_dev, { struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs, UVERBS_ATTR_DESTROY_CQ_HANDLE); - struct ib_uverbs_destroy_cq_resp resp; - struct ib_ucq_object *obj; - int ret; - - if (IS_ERR(uobj)) - return PTR_ERR(uobj); - - obj = container_of(uobj, struct ib_ucq_object, uobject); - - ret = rdma_explicit_destroy(uobj); - if (ret) - return ret; - - resp.comp_events_reported = obj->comp_events_reported; - resp.async_events_reported = obj->async_events_reported; + struct ib_ucq_object *obj = + container_of(uobj, struct ib_ucq_object, uobject); + struct ib_uverbs_destroy_cq_resp resp = { + .comp_events_reported = obj->comp_events_reported, + .async_events_reported = obj->async_events_reported + }; return uverbs_copy_to(attrs, UVERBS_ATTR_DESTROY_CQ_RESP, &resp, sizeof(resp));