diff mbox series

[for-rc] RDMA/uverbs: Pass udata on uverbs error unwind

Message ID 20190522080643.52654-1-galpress@amazon.com (mailing list archive)
State Mainlined
Commit 6876aaedc8a11ed182aba1942dac44e9940bfe6c
Delegated to: Jason Gunthorpe
Headers show
Series [for-rc] RDMA/uverbs: Pass udata on uverbs error unwind | expand

Commit Message

Gal Pressman May 22, 2019, 8:06 a.m. UTC
When destroy_* is called as a result of uverbs create cleanup flow a
cleared udata should be passed instead of NULL to indicate that it is
called under user flow.

Fixes: bc38a6abdd5a ("[PATCH] IB uverbs: core implementation")
Fixes: 67cdb40ca444 ("[IB] uverbs: Implement more commands")
Fixes: 42849b2697c3 ("RDMA/uverbs: Export ib_open_qp() capability to user space")
Fixes: 9ee79fce3642 ("IB/core: Add completion queue (cq) object actions")
Signed-off-by: Gal Pressman <galpress@amazon.com>
---
 drivers/infiniband/core/uverbs_cmd.c          | 9 +++++----
 drivers/infiniband/core/uverbs_std_types_cq.c | 2 +-
 2 files changed, 6 insertions(+), 5 deletions(-)

Comments

Gal Pressman May 22, 2019, 8:10 a.m. UTC | #1
On 22/05/2019 11:06, Gal Pressman wrote:
> When destroy_* is called as a result of uverbs create cleanup flow a
> cleared udata should be passed instead of NULL to indicate that it is
> called under user flow.
> 
> Fixes: bc38a6abdd5a ("[PATCH] IB uverbs: core implementation")
> Fixes: 67cdb40ca444 ("[IB] uverbs: Implement more commands")
> Fixes: 42849b2697c3 ("RDMA/uverbs: Export ib_open_qp() capability to user space")
> Fixes: 9ee79fce3642 ("IB/core: Add completion queue (cq) object actions")
> Signed-off-by: Gal Pressman <galpress@amazon.com>

Forgot to mention, this patch is applied on top of Jason's fix:
https://patchwork.kernel.org/patch/10954379/
Jason Gunthorpe May 22, 2019, 2:56 p.m. UTC | #2
On Wed, May 22, 2019 at 11:06:43AM +0300, Gal Pressman wrote:
> When destroy_* is called as a result of uverbs create cleanup flow a
> cleared udata should be passed instead of NULL to indicate that it is
> called under user flow.
> 
> Fixes: bc38a6abdd5a ("[PATCH] IB uverbs: core implementation")
> Fixes: 67cdb40ca444 ("[IB] uverbs: Implement more commands")
> Fixes: 42849b2697c3 ("RDMA/uverbs: Export ib_open_qp() capability to user space")
> Fixes: 9ee79fce3642 ("IB/core: Add completion queue (cq) object actions")
> Signed-off-by: Gal Pressman <galpress@amazon.com>
> ---
>  drivers/infiniband/core/uverbs_cmd.c          | 9 +++++----
>  drivers/infiniband/core/uverbs_std_types_cq.c | 2 +-
>  2 files changed, 6 insertions(+), 5 deletions(-)

Yes, but I think this only got broken by Shamir's latest work, so
those fixes lines are a bit overbroad
 
> diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
> index a9b32ebb9beb..63fe14c7c68f 100644
> --- a/drivers/infiniband/core/uverbs_cmd.c
> +++ b/drivers/infiniband/core/uverbs_cmd.c
> @@ -1053,7 +1053,7 @@ static struct ib_ucq_object *create_cq(struct uverbs_attr_bundle *attrs,
>  	return obj;
>  
>  err_cb:
> -	ib_destroy_cq(cq);
> +	ib_destroy_cq_user(cq, uverbs_get_cleared_udata(attrs));
>  
>  err_file:
>  	if (ev_file)
> @@ -1489,7 +1489,7 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
>  
>  	return uobj_alloc_commit(&obj->uevent.uobject, attrs);
>  err_cb:
> -	ib_destroy_qp(qp);
> +	ib_destroy_qp_user(qp, uverbs_get_cleared_udata(attrs));

Blah, the more I look at this, the more wrongly it seems.

The ioctl code handles this by destroying the uobject as part of
alloc_abort - which automatically uses the right flow.

We hacked up a special uobj_alloc_abort/rdma_alloc_abort_uobject that
nulls the uobj->object to prevernt this.

But this now seems like a mistake

I once sketched out a patch to remove *all* of these destroys from the
uverbs_cmd.c, so maybe we should do that as well.. Here is the old version:

Jason

From cf37a512ad366f4634fa7a9c7358bdf91b7b5c73 Mon Sep 17 00:00:00 2001
Date: Wed, 13 Feb 2019 19:07:05 +0200
Subject: [PATCH] RDMA/uverbs: Rely on abort_uobject to cleanup

Make write commands more like ioctl commands and rely on the
abort_uobject flow to clean up and destroy the HW object during error
unwind.

Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
---
 drivers/infiniband/core/rdma_core.c           |  1 -
 drivers/infiniband/core/uverbs_cmd.c          | 85 ++++++-------------
 .../core/uverbs_std_types_counters.c          | 10 +--
 drivers/infiniband/core/uverbs_std_types_cq.c | 10 +--
 4 files changed, 28 insertions(+), 78 deletions(-)

diff --git a/drivers/infiniband/core/rdma_core.c b/drivers/infiniband/core/rdma_core.c
index a260d2f8e0b771..3599b97b00b59b 100644
--- a/drivers/infiniband/core/rdma_core.c
+++ b/drivers/infiniband/core/rdma_core.c
@@ -679,7 +679,6 @@ void rdma_alloc_abort_uobject(struct ib_uobject *uobj)
 {
 	struct ib_uverbs_file *ufile = uobj->ufile;
 
-	uobj->object = NULL;
 	uverbs_destroy_uobject(uobj, RDMA_REMOVE_ABORT);
 
 	/* Matches the down_read in rdma_alloc_begin_uobject */
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 5ac143f22df009..15f31c915cd1fd 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -430,12 +430,10 @@ static int ib_uverbs_alloc_pd(struct uverbs_attr_bundle *attrs)
 
 	ret = uverbs_response(attrs, &resp, sizeof(resp));
 	if (ret)
-		goto err_copy;
+		goto err;
 
 	return uobj_alloc_commit(uobj);
 
-err_copy:
-	ib_dealloc_pd(pd);
 err_alloc:
 	kfree(pd);
 err:
@@ -609,20 +607,20 @@ static int ib_uverbs_open_xrcd(struct uverbs_attr_bundle *attrs)
 	memset(&resp, 0, sizeof resp);
 	resp.xrcd_handle = obj->uobject.id;
 
+	ret = uverbs_response(attrs, &resp, sizeof(resp));
+	if (ret)
+		goto err;
+
 	if (inode) {
 		if (new_xrcd) {
 			/* create new inode/xrcd table entry */
 			ret = xrcd_table_insert(ibudev, inode, xrcd);
 			if (ret)
-				goto err_dealloc_xrcd;
+				goto err;
 		}
 		atomic_inc(&xrcd->usecnt);
 	}
 
-	ret = uverbs_response(attrs, &resp, sizeof(resp));
-	if (ret)
-		goto err_copy;
-
 	if (f.file)
 		fdput(f);
 
@@ -630,16 +628,6 @@ static int ib_uverbs_open_xrcd(struct uverbs_attr_bundle *attrs)
 
 	return uobj_alloc_commit(&obj->uobject);
 
-err_copy:
-	if (inode) {
-		if (new_xrcd)
-			xrcd_table_delete(ibudev, inode);
-		atomic_dec(&xrcd->usecnt);
-	}
-
-err_dealloc_xrcd:
-	ib_dealloc_xrcd(xrcd);
-
 err:
 	uobj_alloc_abort(&obj->uobject);
 
@@ -754,15 +742,12 @@ static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs)
 
 	ret = uverbs_response(attrs, &resp, sizeof(resp));
 	if (ret)
-		goto err_copy;
+		goto err_put;
 
 	uobj_put_obj_read(pd);
 
 	return uobj_alloc_commit(uobj);
 
-err_copy:
-	ib_dereg_mr(mr);
-
 err_put:
 	uobj_put_obj_read(pd);
 
@@ -905,13 +890,11 @@ static int ib_uverbs_alloc_mw(struct uverbs_attr_bundle *attrs)
 
 	ret = uverbs_response(attrs, &resp, sizeof(resp));
 	if (ret)
-		goto err_copy;
+		goto err_put;
 
 	uobj_put_obj_read(pd);
 	return uobj_alloc_commit(uobj);
 
-err_copy:
-	uverbs_dealloc_mw(mw);
 err_put:
 	uobj_put_obj_read(pd);
 err_free:
@@ -1025,16 +1008,13 @@ static struct ib_ucq_object *create_cq(struct uverbs_attr_bundle *attrs,
 
 	ret = uverbs_response(attrs, &resp, sizeof(resp));
 	if (ret)
-		goto err_cb;
+		goto err;
 
 	ret = uobj_alloc_commit(&obj->uobject);
 	if (ret)
 		return ERR_PTR(ret);
 	return obj;
 
-err_cb:
-	ib_destroy_cq(cq);
-
 err_file:
 	if (ev_file)
 		ib_uverbs_release_ucq(attrs->ufile, ev_file, obj);
@@ -1404,12 +1384,9 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
 		ret = PTR_ERR(qp);
 		goto err_put;
 	}
+	obj->uevent.uobject.object = qp;
 
 	if (cmd->qp_type != IB_QPT_XRC_TGT) {
-		ret = ib_create_qp_security(qp, device);
-		if (ret)
-			goto err_cb;
-
 		qp->real_qp	  = qp;
 		qp->pd		  = pd;
 		qp->send_cq	  = attr.send_cq;
@@ -1430,13 +1407,15 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
 			atomic_inc(&attr.srq->usecnt);
 		if (ind_tbl)
 			atomic_inc(&ind_tbl->usecnt);
+
+		ret = ib_create_qp_security(qp, device);
+		if (ret)
+			goto err_put;
 	} else {
 		/* It is done in _ib_create_qp for other QP types */
 		qp->uobject = &obj->uevent.uobject;
 	}
 
-	obj->uevent.uobject.object = qp;
-
 	memset(&resp, 0, sizeof resp);
 	resp.base.qpn             = qp->qp_num;
 	resp.base.qp_handle       = obj->uevent.uobject.id;
@@ -1449,7 +1428,7 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
 
 	ret = uverbs_response(attrs, &resp, sizeof(resp));
 	if (ret)
-		goto err_cb;
+		goto err_put;
 
 	if (xrcd) {
 		obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object,
@@ -1470,8 +1449,6 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
 		uobj_put_obj_read(ind_tbl);
 
 	return uobj_alloc_commit(&obj->uevent.uobject);
-err_cb:
-	ib_destroy_qp(qp);
 
 err_put:
 	if (!IS_ERR(xrcd_uobj))
@@ -1594,7 +1571,7 @@ static int ib_uverbs_open_qp(struct uverbs_attr_bundle *attrs)
 
 	ret = uverbs_response(attrs, &resp, sizeof(resp));
 	if (ret)
-		goto err_destroy;
+		goto err_xrcd;
 
 	obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object, uobject);
 	atomic_inc(&obj->uxrcd->refcnt);
@@ -1603,8 +1580,6 @@ static int ib_uverbs_open_qp(struct uverbs_attr_bundle *attrs)
 
 	return uobj_alloc_commit(&obj->uevent.uobject);
 
-err_destroy:
-	ib_destroy_qp(qp);
 err_xrcd:
 	uobj_put_read(xrcd_uobj);
 err_put:
@@ -2440,14 +2415,11 @@ static int ib_uverbs_create_ah(struct uverbs_attr_bundle *attrs)
 
 	ret = uverbs_response(attrs, &resp, sizeof(resp));
 	if (ret)
-		goto err_copy;
+		goto err_put;
 
 	uobj_put_obj_read(pd);
 	return uobj_alloc_commit(uobj);
 
-err_copy:
-	rdma_destroy_ah(ah, RDMA_DESTROY_AH_SLEEPABLE);
-
 err_put:
 	uobj_put_obj_read(pd);
 
@@ -2950,14 +2922,12 @@ static int ib_uverbs_ex_create_wq(struct uverbs_attr_bundle *attrs)
 	resp.response_length = uverbs_response_length(attrs, sizeof(resp));
 	err = uverbs_response(attrs, &resp, sizeof(resp));
 	if (err)
-		goto err_copy;
+		goto err_put_cq;
 
 	uobj_put_obj_read(pd);
 	uobj_put_obj_read(cq);
 	return uobj_alloc_commit(&obj->uevent.uobject);
 
-err_copy:
-	ib_destroy_wq(wq);
 err_put_cq:
 	uobj_put_obj_read(cq);
 err_put_pd:
@@ -3105,6 +3075,7 @@ static int ib_uverbs_ex_create_rwq_ind_table(struct uverbs_attr_bundle *attrs)
 		goto err_uobj;
 	}
 
+	wqs = NULL;
 	rwq_ind_tbl->ind_tbl = wqs;
 	rwq_ind_tbl->log_ind_tbl_size = init_attr.log_ind_tbl_size;
 	rwq_ind_tbl->uobject = uobj;
@@ -3121,7 +3092,7 @@ static int ib_uverbs_ex_create_rwq_ind_table(struct uverbs_attr_bundle *attrs)
 
 	err = uverbs_response(attrs, &resp, sizeof(resp));
 	if (err)
-		goto err_copy;
+		goto err_uobj;
 
 	kfree(wqs_handles);
 
@@ -3130,8 +3101,6 @@ static int ib_uverbs_ex_create_rwq_ind_table(struct uverbs_attr_bundle *attrs)
 
 	return uobj_alloc_commit(uobj);
 
-err_copy:
-	ib_destroy_rwq_ind_table(rwq_ind_tbl);
 err_uobj:
 	uobj_alloc_abort(uobj);
 put_wqs:
@@ -3293,23 +3262,20 @@ static int ib_uverbs_ex_create_flow(struct uverbs_attr_bundle *attrs)
 		goto err_free;
 	}
 
-	ib_set_flow(uobj, flow_id, qp, qp->device, uflow_res);
-
 	memset(&resp, 0, sizeof(resp));
 	resp.flow_handle = uobj->id;
 
 	err = uverbs_response(attrs, &resp, sizeof(resp));
 	if (err)
-		goto err_copy;
+		goto err_free;
+
+	ib_set_flow(uobj, flow_id, qp, qp->device, uflow_res);
 
 	uobj_put_obj_read(qp);
 	kfree(flow_attr);
 	if (cmd.flow_attr.num_of_specs)
 		kfree(kern_flow_attr);
 	return uobj_alloc_commit(uobj);
-err_copy:
-	if (!qp->device->ops.destroy_flow(flow_id))
-		atomic_dec(&qp->usecnt);
 err_free:
 	ib_uverbs_flow_resources_free(uflow_res);
 err_free_flow_attr:
@@ -3441,7 +3407,7 @@ static int __uverbs_create_xsrq(struct uverbs_attr_bundle *attrs,
 
 	ret = uverbs_response(attrs, &resp, sizeof(resp));
 	if (ret)
-		goto err_copy;
+		goto err;
 
 	if (cmd->srq_type == IB_SRQT_XRC)
 		uobj_put_read(xrcd_uobj);
@@ -3452,9 +3418,6 @@ static int __uverbs_create_xsrq(struct uverbs_attr_bundle *attrs,
 	uobj_put_obj_read(pd);
 	return uobj_alloc_commit(&obj->uevent.uobject);
 
-err_copy:
-	ib_destroy_srq(srq);
-
 err_put:
 	uobj_put_obj_read(pd);
 
diff --git a/drivers/infiniband/core/uverbs_std_types_counters.c b/drivers/infiniband/core/uverbs_std_types_counters.c
index 309c5e80988d2e..9b096d7e36cf59 100644
--- a/drivers/infiniband/core/uverbs_std_types_counters.c
+++ b/drivers/infiniband/core/uverbs_std_types_counters.c
@@ -54,7 +54,6 @@ static int UVERBS_HANDLER(UVERBS_METHOD_COUNTERS_CREATE)(
 		attrs, UVERBS_ATTR_CREATE_COUNTERS_HANDLE);
 	struct ib_device *ib_dev = uobj->context->device;
 	struct ib_counters *counters;
-	int ret;
 
 	/*
 	 * This check should be removed once the infrastructure
@@ -65,10 +64,8 @@ static int UVERBS_HANDLER(UVERBS_METHOD_COUNTERS_CREATE)(
 		return -EOPNOTSUPP;
 
 	counters = ib_dev->ops.create_counters(ib_dev, attrs);
-	if (IS_ERR(counters)) {
-		ret = PTR_ERR(counters);
-		goto err_create_counters;
-	}
+	if (IS_ERR(counters))
+		return PTR_ERR(counters);
 
 	counters->device = ib_dev;
 	counters->uobject = uobj;
@@ -76,9 +73,6 @@ static int UVERBS_HANDLER(UVERBS_METHOD_COUNTERS_CREATE)(
 	atomic_set(&counters->usecnt, 0);
 
 	return 0;
-
-err_create_counters:
-	return ret;
 }
 
 static int UVERBS_HANDLER(UVERBS_METHOD_COUNTERS_READ)(
diff --git a/drivers/infiniband/core/uverbs_std_types_cq.c b/drivers/infiniband/core/uverbs_std_types_cq.c
index a59ea89e3f2b06..f9f4c1460c7a58 100644
--- a/drivers/infiniband/core/uverbs_std_types_cq.c
+++ b/drivers/infiniband/core/uverbs_std_types_cq.c
@@ -128,14 +128,8 @@ static int UVERBS_HANDLER(UVERBS_METHOD_CQ_CREATE)(
 	cq->res.type = RDMA_RESTRACK_CQ;
 	rdma_restrack_uadd(&cq->res);
 
-	ret = uverbs_copy_to(attrs, UVERBS_ATTR_CREATE_CQ_RESP_CQE, &cq->cqe,
-			     sizeof(cq->cqe));
-	if (ret)
-		goto err_cq;
-
-	return 0;
-err_cq:
-	ib_destroy_cq(cq);
+	return uverbs_copy_to(attrs, UVERBS_ATTR_CREATE_CQ_RESP_CQE, &cq->cqe,
+			      sizeof(cq->cqe));
 
 err_event_file:
 	if (ev_file)
Gal Pressman May 24, 2019, 6:33 a.m. UTC | #3
On 22/05/2019 17:56, Jason Gunthorpe wrote:
> On Wed, May 22, 2019 at 11:06:43AM +0300, Gal Pressman wrote:
>> When destroy_* is called as a result of uverbs create cleanup flow a
>> cleared udata should be passed instead of NULL to indicate that it is
>> called under user flow.
>>
>> Fixes: bc38a6abdd5a ("[PATCH] IB uverbs: core implementation")
>> Fixes: 67cdb40ca444 ("[IB] uverbs: Implement more commands")
>> Fixes: 42849b2697c3 ("RDMA/uverbs: Export ib_open_qp() capability to user space")
>> Fixes: 9ee79fce3642 ("IB/core: Add completion queue (cq) object actions")
>> Signed-off-by: Gal Pressman <galpress@amazon.com>
>> ---
>>  drivers/infiniband/core/uverbs_cmd.c          | 9 +++++----
>>  drivers/infiniband/core/uverbs_std_types_cq.c | 2 +-
>>  2 files changed, 6 insertions(+), 5 deletions(-)
> 
> Yes, but I think this only got broken by Shamir's latest work, so
> those fixes lines are a bit overbroad
>  
>> diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
>> index a9b32ebb9beb..63fe14c7c68f 100644
>> --- a/drivers/infiniband/core/uverbs_cmd.c
>> +++ b/drivers/infiniband/core/uverbs_cmd.c
>> @@ -1053,7 +1053,7 @@ static struct ib_ucq_object *create_cq(struct uverbs_attr_bundle *attrs,
>>  	return obj;
>>  
>>  err_cb:
>> -	ib_destroy_cq(cq);
>> +	ib_destroy_cq_user(cq, uverbs_get_cleared_udata(attrs));
>>  
>>  err_file:
>>  	if (ev_file)
>> @@ -1489,7 +1489,7 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
>>  
>>  	return uobj_alloc_commit(&obj->uevent.uobject, attrs);
>>  err_cb:
>> -	ib_destroy_qp(qp);
>> +	ib_destroy_qp_user(qp, uverbs_get_cleared_udata(attrs));
> 
> Blah, the more I look at this, the more wrongly it seems.
> 
> The ioctl code handles this by destroying the uobject as part of
> alloc_abort - which automatically uses the right flow.
> 
> We hacked up a special uobj_alloc_abort/rdma_alloc_abort_uobject that
> nulls the uobj->object to prevernt this.
> 
> But this now seems like a mistake
> 
> I once sketched out a patch to remove *all* of these destroys from the
> uverbs_cmd.c, so maybe we should do that as well.. Here is the old version:

Do you think you'll submit this fix to for-rc? If not, we should apply Leon's
patch (that removed the udata checks from EFA) to for-rc in order to prevent
kernel panic.

> 
> From cf37a512ad366f4634fa7a9c7358bdf91b7b5c73 Mon Sep 17 00:00:00 2001
> Date: Wed, 13 Feb 2019 19:07:05 +0200
> Subject: [PATCH] RDMA/uverbs: Rely on abort_uobject to cleanup
> 
> Make write commands more like ioctl commands and rely on the
> abort_uobject flow to clean up and destroy the HW object during error
> unwind.
> 
> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
> ---
>  drivers/infiniband/core/rdma_core.c           |  1 -
>  drivers/infiniband/core/uverbs_cmd.c          | 85 ++++++-------------
>  .../core/uverbs_std_types_counters.c          | 10 +--
>  drivers/infiniband/core/uverbs_std_types_cq.c | 10 +--
>  4 files changed, 28 insertions(+), 78 deletions(-)
> 
> diff --git a/drivers/infiniband/core/rdma_core.c b/drivers/infiniband/core/rdma_core.c
> index a260d2f8e0b771..3599b97b00b59b 100644
> --- a/drivers/infiniband/core/rdma_core.c
> +++ b/drivers/infiniband/core/rdma_core.c
> @@ -679,7 +679,6 @@ void rdma_alloc_abort_uobject(struct ib_uobject *uobj)
>  {
>  	struct ib_uverbs_file *ufile = uobj->ufile;
>  
> -	uobj->object = NULL;
>  	uverbs_destroy_uobject(uobj, RDMA_REMOVE_ABORT);
>  
>  	/* Matches the down_read in rdma_alloc_begin_uobject */
> diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
> index 5ac143f22df009..15f31c915cd1fd 100644
> --- a/drivers/infiniband/core/uverbs_cmd.c
> +++ b/drivers/infiniband/core/uverbs_cmd.c
> @@ -430,12 +430,10 @@ static int ib_uverbs_alloc_pd(struct uverbs_attr_bundle *attrs)
>  
>  	ret = uverbs_response(attrs, &resp, sizeof(resp));
>  	if (ret)
> -		goto err_copy;
> +		goto err;
>  
>  	return uobj_alloc_commit(uobj);
>  
> -err_copy:
> -	ib_dealloc_pd(pd);
>  err_alloc:
>  	kfree(pd);
>  err:
> @@ -609,20 +607,20 @@ static int ib_uverbs_open_xrcd(struct uverbs_attr_bundle *attrs)
>  	memset(&resp, 0, sizeof resp);
>  	resp.xrcd_handle = obj->uobject.id;
>  
> +	ret = uverbs_response(attrs, &resp, sizeof(resp));
> +	if (ret)
> +		goto err;
> +
>  	if (inode) {
>  		if (new_xrcd) {
>  			/* create new inode/xrcd table entry */
>  			ret = xrcd_table_insert(ibudev, inode, xrcd);
>  			if (ret)
> -				goto err_dealloc_xrcd;
> +				goto err;
>  		}
>  		atomic_inc(&xrcd->usecnt);
>  	}
>  
> -	ret = uverbs_response(attrs, &resp, sizeof(resp));
> -	if (ret)
> -		goto err_copy;
> -
>  	if (f.file)
>  		fdput(f);
>  
> @@ -630,16 +628,6 @@ static int ib_uverbs_open_xrcd(struct uverbs_attr_bundle *attrs)
>  
>  	return uobj_alloc_commit(&obj->uobject);
>  
> -err_copy:
> -	if (inode) {
> -		if (new_xrcd)
> -			xrcd_table_delete(ibudev, inode);
> -		atomic_dec(&xrcd->usecnt);
> -	}
> -
> -err_dealloc_xrcd:
> -	ib_dealloc_xrcd(xrcd);
> -
>  err:
>  	uobj_alloc_abort(&obj->uobject);
>  
> @@ -754,15 +742,12 @@ static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs)
>  
>  	ret = uverbs_response(attrs, &resp, sizeof(resp));
>  	if (ret)
> -		goto err_copy;
> +		goto err_put;
>  
>  	uobj_put_obj_read(pd);
>  
>  	return uobj_alloc_commit(uobj);
>  
> -err_copy:
> -	ib_dereg_mr(mr);
> -
>  err_put:
>  	uobj_put_obj_read(pd);
>  
> @@ -905,13 +890,11 @@ static int ib_uverbs_alloc_mw(struct uverbs_attr_bundle *attrs)
>  
>  	ret = uverbs_response(attrs, &resp, sizeof(resp));
>  	if (ret)
> -		goto err_copy;
> +		goto err_put;
>  
>  	uobj_put_obj_read(pd);
>  	return uobj_alloc_commit(uobj);
>  
> -err_copy:
> -	uverbs_dealloc_mw(mw);
>  err_put:
>  	uobj_put_obj_read(pd);
>  err_free:
> @@ -1025,16 +1008,13 @@ static struct ib_ucq_object *create_cq(struct uverbs_attr_bundle *attrs,
>  
>  	ret = uverbs_response(attrs, &resp, sizeof(resp));
>  	if (ret)
> -		goto err_cb;
> +		goto err;
>  
>  	ret = uobj_alloc_commit(&obj->uobject);
>  	if (ret)
>  		return ERR_PTR(ret);
>  	return obj;
>  
> -err_cb:
> -	ib_destroy_cq(cq);
> -
>  err_file:
>  	if (ev_file)
>  		ib_uverbs_release_ucq(attrs->ufile, ev_file, obj);
> @@ -1404,12 +1384,9 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
>  		ret = PTR_ERR(qp);
>  		goto err_put;
>  	}
> +	obj->uevent.uobject.object = qp;
>  
>  	if (cmd->qp_type != IB_QPT_XRC_TGT) {
> -		ret = ib_create_qp_security(qp, device);
> -		if (ret)
> -			goto err_cb;
> -
>  		qp->real_qp	  = qp;
>  		qp->pd		  = pd;
>  		qp->send_cq	  = attr.send_cq;
> @@ -1430,13 +1407,15 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
>  			atomic_inc(&attr.srq->usecnt);
>  		if (ind_tbl)
>  			atomic_inc(&ind_tbl->usecnt);
> +
> +		ret = ib_create_qp_security(qp, device);
> +		if (ret)
> +			goto err_put;
>  	} else {
>  		/* It is done in _ib_create_qp for other QP types */
>  		qp->uobject = &obj->uevent.uobject;
>  	}
>  
> -	obj->uevent.uobject.object = qp;
> -
>  	memset(&resp, 0, sizeof resp);
>  	resp.base.qpn             = qp->qp_num;
>  	resp.base.qp_handle       = obj->uevent.uobject.id;
> @@ -1449,7 +1428,7 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
>  
>  	ret = uverbs_response(attrs, &resp, sizeof(resp));
>  	if (ret)
> -		goto err_cb;
> +		goto err_put;
>  
>  	if (xrcd) {
>  		obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object,
> @@ -1470,8 +1449,6 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
>  		uobj_put_obj_read(ind_tbl);
>  
>  	return uobj_alloc_commit(&obj->uevent.uobject);
> -err_cb:
> -	ib_destroy_qp(qp);
>  
>  err_put:
>  	if (!IS_ERR(xrcd_uobj))
> @@ -1594,7 +1571,7 @@ static int ib_uverbs_open_qp(struct uverbs_attr_bundle *attrs)
>  
>  	ret = uverbs_response(attrs, &resp, sizeof(resp));
>  	if (ret)
> -		goto err_destroy;
> +		goto err_xrcd;
>  
>  	obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object, uobject);
>  	atomic_inc(&obj->uxrcd->refcnt);
> @@ -1603,8 +1580,6 @@ static int ib_uverbs_open_qp(struct uverbs_attr_bundle *attrs)
>  
>  	return uobj_alloc_commit(&obj->uevent.uobject);
>  
> -err_destroy:
> -	ib_destroy_qp(qp);
>  err_xrcd:
>  	uobj_put_read(xrcd_uobj);
>  err_put:
> @@ -2440,14 +2415,11 @@ static int ib_uverbs_create_ah(struct uverbs_attr_bundle *attrs)
>  
>  	ret = uverbs_response(attrs, &resp, sizeof(resp));
>  	if (ret)
> -		goto err_copy;
> +		goto err_put;
>  
>  	uobj_put_obj_read(pd);
>  	return uobj_alloc_commit(uobj);
>  
> -err_copy:
> -	rdma_destroy_ah(ah, RDMA_DESTROY_AH_SLEEPABLE);
> -
>  err_put:
>  	uobj_put_obj_read(pd);
>  
> @@ -2950,14 +2922,12 @@ static int ib_uverbs_ex_create_wq(struct uverbs_attr_bundle *attrs)
>  	resp.response_length = uverbs_response_length(attrs, sizeof(resp));
>  	err = uverbs_response(attrs, &resp, sizeof(resp));
>  	if (err)
> -		goto err_copy;
> +		goto err_put_cq;
>  
>  	uobj_put_obj_read(pd);
>  	uobj_put_obj_read(cq);
>  	return uobj_alloc_commit(&obj->uevent.uobject);
>  
> -err_copy:
> -	ib_destroy_wq(wq);
>  err_put_cq:
>  	uobj_put_obj_read(cq);
>  err_put_pd:
> @@ -3105,6 +3075,7 @@ static int ib_uverbs_ex_create_rwq_ind_table(struct uverbs_attr_bundle *attrs)
>  		goto err_uobj;
>  	}
>  
> +	wqs = NULL;
>  	rwq_ind_tbl->ind_tbl = wqs;
>  	rwq_ind_tbl->log_ind_tbl_size = init_attr.log_ind_tbl_size;
>  	rwq_ind_tbl->uobject = uobj;
> @@ -3121,7 +3092,7 @@ static int ib_uverbs_ex_create_rwq_ind_table(struct uverbs_attr_bundle *attrs)
>  
>  	err = uverbs_response(attrs, &resp, sizeof(resp));
>  	if (err)
> -		goto err_copy;
> +		goto err_uobj;
>  
>  	kfree(wqs_handles);
>  
> @@ -3130,8 +3101,6 @@ static int ib_uverbs_ex_create_rwq_ind_table(struct uverbs_attr_bundle *attrs)
>  
>  	return uobj_alloc_commit(uobj);
>  
> -err_copy:
> -	ib_destroy_rwq_ind_table(rwq_ind_tbl);
>  err_uobj:
>  	uobj_alloc_abort(uobj);
>  put_wqs:
> @@ -3293,23 +3262,20 @@ static int ib_uverbs_ex_create_flow(struct uverbs_attr_bundle *attrs)
>  		goto err_free;
>  	}
>  
> -	ib_set_flow(uobj, flow_id, qp, qp->device, uflow_res);
> -
>  	memset(&resp, 0, sizeof(resp));
>  	resp.flow_handle = uobj->id;
>  
>  	err = uverbs_response(attrs, &resp, sizeof(resp));
>  	if (err)
> -		goto err_copy;
> +		goto err_free;
> +
> +	ib_set_flow(uobj, flow_id, qp, qp->device, uflow_res);
>  
>  	uobj_put_obj_read(qp);
>  	kfree(flow_attr);
>  	if (cmd.flow_attr.num_of_specs)
>  		kfree(kern_flow_attr);
>  	return uobj_alloc_commit(uobj);
> -err_copy:
> -	if (!qp->device->ops.destroy_flow(flow_id))
> -		atomic_dec(&qp->usecnt);
>  err_free:
>  	ib_uverbs_flow_resources_free(uflow_res);
>  err_free_flow_attr:
> @@ -3441,7 +3407,7 @@ static int __uverbs_create_xsrq(struct uverbs_attr_bundle *attrs,
>  
>  	ret = uverbs_response(attrs, &resp, sizeof(resp));
>  	if (ret)
> -		goto err_copy;
> +		goto err;
>  
>  	if (cmd->srq_type == IB_SRQT_XRC)
>  		uobj_put_read(xrcd_uobj);
> @@ -3452,9 +3418,6 @@ static int __uverbs_create_xsrq(struct uverbs_attr_bundle *attrs,
>  	uobj_put_obj_read(pd);
>  	return uobj_alloc_commit(&obj->uevent.uobject);
>  
> -err_copy:
> -	ib_destroy_srq(srq);
> -
>  err_put:
>  	uobj_put_obj_read(pd);
>  
> diff --git a/drivers/infiniband/core/uverbs_std_types_counters.c b/drivers/infiniband/core/uverbs_std_types_counters.c
> index 309c5e80988d2e..9b096d7e36cf59 100644
> --- a/drivers/infiniband/core/uverbs_std_types_counters.c
> +++ b/drivers/infiniband/core/uverbs_std_types_counters.c
> @@ -54,7 +54,6 @@ static int UVERBS_HANDLER(UVERBS_METHOD_COUNTERS_CREATE)(
>  		attrs, UVERBS_ATTR_CREATE_COUNTERS_HANDLE);
>  	struct ib_device *ib_dev = uobj->context->device;
>  	struct ib_counters *counters;
> -	int ret;
>  
>  	/*
>  	 * This check should be removed once the infrastructure
> @@ -65,10 +64,8 @@ static int UVERBS_HANDLER(UVERBS_METHOD_COUNTERS_CREATE)(
>  		return -EOPNOTSUPP;
>  
>  	counters = ib_dev->ops.create_counters(ib_dev, attrs);
> -	if (IS_ERR(counters)) {
> -		ret = PTR_ERR(counters);
> -		goto err_create_counters;
> -	}
> +	if (IS_ERR(counters))
> +		return PTR_ERR(counters);
>  
>  	counters->device = ib_dev;
>  	counters->uobject = uobj;
> @@ -76,9 +73,6 @@ static int UVERBS_HANDLER(UVERBS_METHOD_COUNTERS_CREATE)(
>  	atomic_set(&counters->usecnt, 0);
>  
>  	return 0;
> -
> -err_create_counters:
> -	return ret;
>  }
>  
>  static int UVERBS_HANDLER(UVERBS_METHOD_COUNTERS_READ)(
> diff --git a/drivers/infiniband/core/uverbs_std_types_cq.c b/drivers/infiniband/core/uverbs_std_types_cq.c
> index a59ea89e3f2b06..f9f4c1460c7a58 100644
> --- a/drivers/infiniband/core/uverbs_std_types_cq.c
> +++ b/drivers/infiniband/core/uverbs_std_types_cq.c
> @@ -128,14 +128,8 @@ static int UVERBS_HANDLER(UVERBS_METHOD_CQ_CREATE)(
>  	cq->res.type = RDMA_RESTRACK_CQ;
>  	rdma_restrack_uadd(&cq->res);
>  
> -	ret = uverbs_copy_to(attrs, UVERBS_ATTR_CREATE_CQ_RESP_CQE, &cq->cqe,
> -			     sizeof(cq->cqe));
> -	if (ret)
> -		goto err_cq;
> -
> -	return 0;
> -err_cq:
> -	ib_destroy_cq(cq);
> +	return uverbs_copy_to(attrs, UVERBS_ATTR_CREATE_CQ_RESP_CQE, &cq->cqe,
> +			      sizeof(cq->cqe));
>  
>  err_event_file:
>  	if (ev_file)
>
Jason Gunthorpe May 27, 2019, 5:39 p.m. UTC | #4
On Wed, May 22, 2019 at 11:06:43AM +0300, Gal Pressman wrote:
> When destroy_* is called as a result of uverbs create cleanup flow a
> cleared udata should be passed instead of NULL to indicate that it is
> called under user flow.
> 
> Fixes: bc38a6abdd5a ("[PATCH] IB uverbs: core implementation")
> Fixes: 67cdb40ca444 ("[IB] uverbs: Implement more commands")
> Fixes: 42849b2697c3 ("RDMA/uverbs: Export ib_open_qp() capability to user space")
> Fixes: 9ee79fce3642 ("IB/core: Add completion queue (cq) object actions")
> Signed-off-by: Gal Pressman <galpress@amazon.com>
> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
> ---
>  drivers/infiniband/core/uverbs_cmd.c          | 9 +++++----
>  drivers/infiniband/core/uverbs_std_types_cq.c | 2 +-
>  2 files changed, 6 insertions(+), 5 deletions(-)

Applied to for-rc (that last one was for-rc too, woops)

Thanks,
Jason
diff mbox series

Patch

diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index a9b32ebb9beb..63fe14c7c68f 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -1053,7 +1053,7 @@  static struct ib_ucq_object *create_cq(struct uverbs_attr_bundle *attrs,
 	return obj;
 
 err_cb:
-	ib_destroy_cq(cq);
+	ib_destroy_cq_user(cq, uverbs_get_cleared_udata(attrs));
 
 err_file:
 	if (ev_file)
@@ -1489,7 +1489,7 @@  static int create_qp(struct uverbs_attr_bundle *attrs,
 
 	return uobj_alloc_commit(&obj->uevent.uobject, attrs);
 err_cb:
-	ib_destroy_qp(qp);
+	ib_destroy_qp_user(qp, uverbs_get_cleared_udata(attrs));
 
 err_put:
 	if (!IS_ERR(xrcd_uobj))
@@ -1622,7 +1622,7 @@  static int ib_uverbs_open_qp(struct uverbs_attr_bundle *attrs)
 	return uobj_alloc_commit(&obj->uevent.uobject, attrs);
 
 err_destroy:
-	ib_destroy_qp(qp);
+	ib_destroy_qp_user(qp, uverbs_get_cleared_udata(attrs));
 err_xrcd:
 	uobj_put_read(xrcd_uobj);
 err_put:
@@ -2464,7 +2464,8 @@  static int ib_uverbs_create_ah(struct uverbs_attr_bundle *attrs)
 	return uobj_alloc_commit(uobj, attrs);
 
 err_copy:
-	rdma_destroy_ah(ah, RDMA_DESTROY_AH_SLEEPABLE);
+	rdma_destroy_ah_user(ah, RDMA_DESTROY_AH_SLEEPABLE,
+			     uverbs_get_cleared_udata(attrs));
 
 err_put:
 	uobj_put_obj_read(pd);
diff --git a/drivers/infiniband/core/uverbs_std_types_cq.c b/drivers/infiniband/core/uverbs_std_types_cq.c
index db5c46a1bb2d..07ea4e3c4566 100644
--- a/drivers/infiniband/core/uverbs_std_types_cq.c
+++ b/drivers/infiniband/core/uverbs_std_types_cq.c
@@ -135,7 +135,7 @@  static int UVERBS_HANDLER(UVERBS_METHOD_CQ_CREATE)(
 
 	return 0;
 err_cq:
-	ib_destroy_cq(cq);
+	ib_destroy_cq_user(cq, uverbs_get_cleared_udata(attrs));
 
 err_event_file:
 	if (ev_file)