From: Jason Gunthorpe <jgg@mellanox.com>
Date: Tue, 10 Jul 2018 20:55:20 -0600
Subject: IB/uverbs: Always propagate errors from rdma_alloc_commit_uobject()
Patch-mainline: v4.19-rc1
Git-commit: 2c96eb7d62de5048aa08e9ee4fbb607f29e2638c
References: bsc#1103992 FATE#326009
The ioctl framework already does this correctly, but the write path did
not. This is trivially fixed by simply using a standard pattern to return
uobj_alloc_commit() as the last statement in every function.
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Acked-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
---
drivers/infiniband/core/rdma_core.c | 5 ++-
drivers/infiniband/core/uverbs_cmd.c | 49 ++++++++++-------------------------
include/rdma/uverbs_std_types.h | 9 +++++-
include/rdma/uverbs_types.h | 2 -
4 files changed, 26 insertions(+), 39 deletions(-)
--- a/drivers/infiniband/core/rdma_core.c
+++ b/drivers/infiniband/core/rdma_core.c
@@ -532,9 +532,10 @@ static void alloc_commit_fd_uobject(stru
/*
* In all cases rdma_alloc_commit_uobject() consumes the kref to uobj and the
- * caller can no longer assume uobj is valid.
+ * caller can no longer assume uobj is valid. If this function fails it
+ * destroys the uboject, including the attached HW object.
*/
-int rdma_alloc_commit_uobject(struct ib_uobject *uobj)
+int __must_check rdma_alloc_commit_uobject(struct ib_uobject *uobj)
{
struct ib_uverbs_file *ufile = uobj->ufile;
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -372,9 +372,7 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uve
goto err_copy;
}
- uobj_alloc_commit(uobj);
-
- return in_len;
+ return uobj_alloc_commit(uobj, in_len);
err_copy:
ib_dealloc_pd(pd);
@@ -579,9 +577,7 @@ ssize_t ib_uverbs_open_xrcd(struct ib_uv
mutex_unlock(&file->device->xrcd_tree_mutex);
- uobj_alloc_commit(&obj->uobject);
-
- return in_len;
+ return uobj_alloc_commit(&obj->uobject, in_len);
err_copy:
if (inode) {
@@ -723,9 +719,7 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverb
uobj_put_obj_read(pd);
- uobj_alloc_commit(uobj);
-
- return in_len;
+ return uobj_alloc_commit(uobj, in_len);
err_copy:
ib_dereg_mr(mr);
@@ -901,9 +895,7 @@ ssize_t ib_uverbs_alloc_mw(struct ib_uve
}
uobj_put_obj_read(pd);
- uobj_alloc_commit(uobj);
-
- return in_len;
+ return uobj_alloc_commit(uobj, in_len);
err_copy:
uverbs_dealloc_mw(mw);
@@ -959,8 +951,7 @@ ssize_t ib_uverbs_create_comp_channel(st
return -EFAULT;
}
- uobj_alloc_commit(uobj);
- return in_len;
+ return uobj_alloc_commit(uobj, in_len);
}
static struct ib_ucq_object *create_cq(struct ib_uverbs_file *file,
@@ -1041,7 +1032,9 @@ static struct ib_ucq_object *create_cq(s
if (ret)
goto err_cb;
- uobj_alloc_commit(&obj->uobject);
+ ret = uobj_alloc_commit(&obj->uobject, 0);
+ if (ret)
+ return ERR_PTR(ret);
return obj;
err_cb:
@@ -1596,9 +1589,7 @@ static int create_qp(struct ib_uverbs_fi
if (ind_tbl)
uobj_put_obj_read(ind_tbl);
- uobj_alloc_commit(&obj->uevent.uobject);
-
- return 0;
+ return uobj_alloc_commit(&obj->uevent.uobject, 0);
err_cb:
ib_destroy_qp(qp);
@@ -1801,10 +1792,7 @@ ssize_t ib_uverbs_open_qp(struct ib_uver
qp->uobject = &obj->uevent.uobject;
uobj_put_read(xrcd_uobj);
-
- uobj_alloc_commit(&obj->uevent.uobject);
-
- return in_len;
+ return uobj_alloc_commit(&obj->uevent.uobject, in_len);
err_destroy:
ib_destroy_qp(qp);
@@ -2656,9 +2644,7 @@ ssize_t ib_uverbs_create_ah(struct ib_uv
}
uobj_put_obj_read(pd);
- uobj_alloc_commit(uobj);
-
- return in_len;
+ return uobj_alloc_commit(uobj, in_len);
err_copy:
rdma_destroy_ah(ah);
@@ -3204,8 +3190,7 @@ int ib_uverbs_ex_create_wq(struct ib_uve
uobj_put_obj_read(pd);
uobj_put_obj_read(cq);
- uobj_alloc_commit(&obj->uevent.uobject);
- return 0;
+ return uobj_alloc_commit(&obj->uevent.uobject, 0);
err_copy:
ib_destroy_wq(wq);
@@ -3452,8 +3437,7 @@ int ib_uverbs_ex_create_rwq_ind_table(st
for (j = 0; j < num_read_wqs; j++)
uobj_put_obj_read(wqs[j]);
- uobj_alloc_commit(uobj);
- return 0;
+ return uobj_alloc_commit(uobj, 0);
err_copy:
ib_destroy_rwq_ind_table(rwq_ind_tbl);
@@ -3661,11 +3645,10 @@ int ib_uverbs_ex_create_flow(struct ib_u
goto err_copy;
uobj_put_obj_read(qp);
- uobj_alloc_commit(uobj);
kfree(flow_attr);
if (cmd.flow_attr.num_of_specs)
kfree(kern_flow_attr);
- return 0;
+ return uobj_alloc_commit(uobj, 0);
err_copy:
if (!qp->device->destroy_flow(flow_id))
atomic_dec(&qp->usecnt);
@@ -3817,9 +3800,7 @@ static int __uverbs_create_xsrq(struct i
uobj_put_obj_read(attr.ext.cq);
uobj_put_obj_read(pd);
- uobj_alloc_commit(&obj->uevent.uobject);
-
- return 0;
+ return uobj_alloc_commit(&obj->uevent.uobject, 0);
err_copy:
ib_destroy_srq(srq);
--- a/include/rdma/uverbs_std_types.h
+++ b/include/rdma/uverbs_std_types.h
@@ -102,9 +102,14 @@ static inline int __must_check uobj_remo
return rdma_remove_commit_uobject(uobj);
}
-static inline void uobj_alloc_commit(struct ib_uobject *uobj)
+static inline int __must_check uobj_alloc_commit(struct ib_uobject *uobj,
+ int success_res)
{
- rdma_alloc_commit_uobject(uobj);
+ int ret = rdma_alloc_commit_uobject(uobj);
+
+ if (ret)
+ return ret;
+ return success_res;
}
static inline void uobj_alloc_abort(struct ib_uobject *uobj)
--- a/include/rdma/uverbs_types.h
+++ b/include/rdma/uverbs_types.h
@@ -127,7 +127,7 @@ struct ib_uobject *rdma_alloc_begin_uobj
struct ib_uverbs_file *ufile);
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 __must_check rdma_alloc_commit_uobject(struct ib_uobject *uobj);
int rdma_explicit_destroy(struct ib_uobject *uobject);
struct uverbs_obj_fd_type {