mirror of
https://github.com/torvalds/linux.git
synced 2025-04-12 16:47:42 +00:00
RDMA/uverbs: Propagate errors from rdma_lookup_get_uobject()
Currently, the IB uverbs API calls uobj_get_uobj_read(), which in turn uses the rdma_lookup_get_uobject() helper to retrieve user objects. In case of failure, uobj_get_uobj_read() returns NULL, overriding the error code from rdma_lookup_get_uobject(). The IB uverbs API then translates this NULL to -EINVAL, masking the actual error and complicating debugging. For example, applications calling ibv_modify_qp that fails with EBUSY when retrieving the QP uobject will see the overridden error code EINVAL instead, masking the actual error. Furthermore, based on rdma-core commit: "2a22f1ced5f3 ("Merge pull request #1568 from jakemoroni/master")" Kernel's IB uverbs return values are either ignored and passed on as is to application or overridden with other errnos in a few cases. Thus, to improve error reporting and debuggability, propagate the original error from rdma_lookup_get_uobject() instead of replacing it with EINVAL. Signed-off-by: Maher Sanalla <msanalla@nvidia.com> Link: https://patch.msgid.link/64f9d3711b183984e939962c2f83383904f97dfb.1740577869.git.leon@kernel.org Signed-off-by: Leon Romanovsky <leon@kernel.org>
This commit is contained in:
parent
bee35b7161
commit
81f8f7454a
@ -735,8 +735,8 @@ static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs)
|
||||
goto err_free;
|
||||
|
||||
pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, attrs);
|
||||
if (!pd) {
|
||||
ret = -EINVAL;
|
||||
if (IS_ERR(pd)) {
|
||||
ret = PTR_ERR(pd);
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
@ -826,8 +826,8 @@ static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs)
|
||||
if (cmd.flags & IB_MR_REREG_PD) {
|
||||
new_pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle,
|
||||
attrs);
|
||||
if (!new_pd) {
|
||||
ret = -EINVAL;
|
||||
if (IS_ERR(new_pd)) {
|
||||
ret = PTR_ERR(new_pd);
|
||||
goto put_uobjs;
|
||||
}
|
||||
} else {
|
||||
@ -936,8 +936,8 @@ static int ib_uverbs_alloc_mw(struct uverbs_attr_bundle *attrs)
|
||||
return PTR_ERR(uobj);
|
||||
|
||||
pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, attrs);
|
||||
if (!pd) {
|
||||
ret = -EINVAL;
|
||||
if (IS_ERR(pd)) {
|
||||
ret = PTR_ERR(pd);
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
@ -1144,8 +1144,8 @@ static int ib_uverbs_resize_cq(struct uverbs_attr_bundle *attrs)
|
||||
return ret;
|
||||
|
||||
cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs);
|
||||
if (!cq)
|
||||
return -EINVAL;
|
||||
if (IS_ERR(cq))
|
||||
return PTR_ERR(cq);
|
||||
|
||||
ret = cq->device->ops.resize_cq(cq, cmd.cqe, &attrs->driver_udata);
|
||||
if (ret)
|
||||
@ -1206,8 +1206,8 @@ static int ib_uverbs_poll_cq(struct uverbs_attr_bundle *attrs)
|
||||
return ret;
|
||||
|
||||
cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs);
|
||||
if (!cq)
|
||||
return -EINVAL;
|
||||
if (IS_ERR(cq))
|
||||
return PTR_ERR(cq);
|
||||
|
||||
/* we copy a struct ib_uverbs_poll_cq_resp to user space */
|
||||
header_ptr = attrs->ucore.outbuf;
|
||||
@ -1255,8 +1255,8 @@ static int ib_uverbs_req_notify_cq(struct uverbs_attr_bundle *attrs)
|
||||
return ret;
|
||||
|
||||
cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs);
|
||||
if (!cq)
|
||||
return -EINVAL;
|
||||
if (IS_ERR(cq))
|
||||
return PTR_ERR(cq);
|
||||
|
||||
ib_req_notify_cq(cq, cmd.solicited_only ?
|
||||
IB_CQ_SOLICITED : IB_CQ_NEXT_COMP);
|
||||
@ -1338,8 +1338,8 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
|
||||
ind_tbl = uobj_get_obj_read(rwq_ind_table,
|
||||
UVERBS_OBJECT_RWQ_IND_TBL,
|
||||
cmd->rwq_ind_tbl_handle, attrs);
|
||||
if (!ind_tbl) {
|
||||
ret = -EINVAL;
|
||||
if (IS_ERR(ind_tbl)) {
|
||||
ret = PTR_ERR(ind_tbl);
|
||||
goto err_put;
|
||||
}
|
||||
|
||||
@ -1377,8 +1377,10 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
|
||||
if (cmd->is_srq) {
|
||||
srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ,
|
||||
cmd->srq_handle, attrs);
|
||||
if (!srq || srq->srq_type == IB_SRQT_XRC) {
|
||||
ret = -EINVAL;
|
||||
if (IS_ERR(srq) ||
|
||||
srq->srq_type == IB_SRQT_XRC) {
|
||||
ret = IS_ERR(srq) ? PTR_ERR(srq) :
|
||||
-EINVAL;
|
||||
goto err_put;
|
||||
}
|
||||
}
|
||||
@ -1388,23 +1390,29 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
|
||||
rcq = uobj_get_obj_read(
|
||||
cq, UVERBS_OBJECT_CQ,
|
||||
cmd->recv_cq_handle, attrs);
|
||||
if (!rcq) {
|
||||
ret = -EINVAL;
|
||||
if (IS_ERR(rcq)) {
|
||||
ret = PTR_ERR(rcq);
|
||||
goto err_put;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (has_sq)
|
||||
if (has_sq) {
|
||||
scq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ,
|
||||
cmd->send_cq_handle, attrs);
|
||||
if (IS_ERR(scq)) {
|
||||
ret = PTR_ERR(scq);
|
||||
goto err_put;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ind_tbl && cmd->qp_type != IB_QPT_XRC_INI)
|
||||
rcq = rcq ?: scq;
|
||||
pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd->pd_handle,
|
||||
attrs);
|
||||
if (!pd || (!scq && has_sq)) {
|
||||
ret = -EINVAL;
|
||||
if (IS_ERR(pd)) {
|
||||
ret = PTR_ERR(pd);
|
||||
goto err_put;
|
||||
}
|
||||
|
||||
@ -1499,18 +1507,18 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
|
||||
err_put:
|
||||
if (!IS_ERR(xrcd_uobj))
|
||||
uobj_put_read(xrcd_uobj);
|
||||
if (pd)
|
||||
if (!IS_ERR_OR_NULL(pd))
|
||||
uobj_put_obj_read(pd);
|
||||
if (scq)
|
||||
if (!IS_ERR_OR_NULL(scq))
|
||||
rdma_lookup_put_uobject(&scq->uobject->uevent.uobject,
|
||||
UVERBS_LOOKUP_READ);
|
||||
if (rcq && rcq != scq)
|
||||
if (!IS_ERR_OR_NULL(rcq) && rcq != scq)
|
||||
rdma_lookup_put_uobject(&rcq->uobject->uevent.uobject,
|
||||
UVERBS_LOOKUP_READ);
|
||||
if (srq)
|
||||
if (!IS_ERR_OR_NULL(srq))
|
||||
rdma_lookup_put_uobject(&srq->uobject->uevent.uobject,
|
||||
UVERBS_LOOKUP_READ);
|
||||
if (ind_tbl)
|
||||
if (!IS_ERR_OR_NULL(ind_tbl))
|
||||
uobj_put_obj_read(ind_tbl);
|
||||
|
||||
uobj_alloc_abort(&obj->uevent.uobject, attrs);
|
||||
@ -1672,8 +1680,8 @@ static int ib_uverbs_query_qp(struct uverbs_attr_bundle *attrs)
|
||||
}
|
||||
|
||||
qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
|
||||
if (!qp) {
|
||||
ret = -EINVAL;
|
||||
if (IS_ERR(qp)) {
|
||||
ret = PTR_ERR(qp);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -1778,8 +1786,8 @@ static int modify_qp(struct uverbs_attr_bundle *attrs,
|
||||
|
||||
qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd->base.qp_handle,
|
||||
attrs);
|
||||
if (!qp) {
|
||||
ret = -EINVAL;
|
||||
if (IS_ERR(qp)) {
|
||||
ret = PTR_ERR(qp);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -2045,8 +2053,8 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs)
|
||||
return -ENOMEM;
|
||||
|
||||
qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
|
||||
if (!qp) {
|
||||
ret = -EINVAL;
|
||||
if (IS_ERR(qp)) {
|
||||
ret = PTR_ERR(qp);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -2083,9 +2091,9 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs)
|
||||
|
||||
ud->ah = uobj_get_obj_read(ah, UVERBS_OBJECT_AH,
|
||||
user_wr->wr.ud.ah, attrs);
|
||||
if (!ud->ah) {
|
||||
if (IS_ERR(ud->ah)) {
|
||||
ret = PTR_ERR(ud->ah);
|
||||
kfree(ud);
|
||||
ret = -EINVAL;
|
||||
goto out_put;
|
||||
}
|
||||
ud->remote_qpn = user_wr->wr.ud.remote_qpn;
|
||||
@ -2322,8 +2330,8 @@ static int ib_uverbs_post_recv(struct uverbs_attr_bundle *attrs)
|
||||
return PTR_ERR(wr);
|
||||
|
||||
qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
|
||||
if (!qp) {
|
||||
ret = -EINVAL;
|
||||
if (IS_ERR(qp)) {
|
||||
ret = PTR_ERR(qp);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -2373,8 +2381,8 @@ static int ib_uverbs_post_srq_recv(struct uverbs_attr_bundle *attrs)
|
||||
return PTR_ERR(wr);
|
||||
|
||||
srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ, cmd.srq_handle, attrs);
|
||||
if (!srq) {
|
||||
ret = -EINVAL;
|
||||
if (IS_ERR(srq)) {
|
||||
ret = PTR_ERR(srq);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -2430,8 +2438,8 @@ static int ib_uverbs_create_ah(struct uverbs_attr_bundle *attrs)
|
||||
}
|
||||
|
||||
pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, attrs);
|
||||
if (!pd) {
|
||||
ret = -EINVAL;
|
||||
if (IS_ERR(pd)) {
|
||||
ret = PTR_ERR(pd);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -2500,8 +2508,8 @@ static int ib_uverbs_attach_mcast(struct uverbs_attr_bundle *attrs)
|
||||
return ret;
|
||||
|
||||
qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
|
||||
if (!qp)
|
||||
return -EINVAL;
|
||||
if (IS_ERR(qp))
|
||||
return PTR_ERR(qp);
|
||||
|
||||
obj = qp->uobject;
|
||||
|
||||
@ -2550,8 +2558,8 @@ static int ib_uverbs_detach_mcast(struct uverbs_attr_bundle *attrs)
|
||||
return ret;
|
||||
|
||||
qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
|
||||
if (!qp)
|
||||
return -EINVAL;
|
||||
if (IS_ERR(qp))
|
||||
return PTR_ERR(qp);
|
||||
|
||||
obj = qp->uobject;
|
||||
mutex_lock(&obj->mcast_lock);
|
||||
@ -2685,8 +2693,8 @@ static int kern_spec_to_ib_spec_action(struct uverbs_attr_bundle *attrs,
|
||||
UVERBS_OBJECT_FLOW_ACTION,
|
||||
kern_spec->action.handle,
|
||||
attrs);
|
||||
if (!ib_spec->action.act)
|
||||
return -EINVAL;
|
||||
if (IS_ERR(ib_spec->action.act))
|
||||
return PTR_ERR(ib_spec->action.act);
|
||||
ib_spec->action.size =
|
||||
sizeof(struct ib_flow_spec_action_handle);
|
||||
flow_resources_add(uflow_res,
|
||||
@ -2703,8 +2711,8 @@ static int kern_spec_to_ib_spec_action(struct uverbs_attr_bundle *attrs,
|
||||
UVERBS_OBJECT_COUNTERS,
|
||||
kern_spec->flow_count.handle,
|
||||
attrs);
|
||||
if (!ib_spec->flow_count.counters)
|
||||
return -EINVAL;
|
||||
if (IS_ERR(ib_spec->flow_count.counters))
|
||||
return PTR_ERR(ib_spec->flow_count.counters);
|
||||
ib_spec->flow_count.size =
|
||||
sizeof(struct ib_flow_spec_action_count);
|
||||
flow_resources_add(uflow_res,
|
||||
@ -2922,14 +2930,14 @@ static int ib_uverbs_ex_create_wq(struct uverbs_attr_bundle *attrs)
|
||||
return PTR_ERR(obj);
|
||||
|
||||
pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, attrs);
|
||||
if (!pd) {
|
||||
err = -EINVAL;
|
||||
if (IS_ERR(pd)) {
|
||||
err = PTR_ERR(pd);
|
||||
goto err_uobj;
|
||||
}
|
||||
|
||||
cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs);
|
||||
if (!cq) {
|
||||
err = -EINVAL;
|
||||
if (IS_ERR(cq)) {
|
||||
err = PTR_ERR(cq);
|
||||
goto err_put_pd;
|
||||
}
|
||||
|
||||
@ -3030,8 +3038,8 @@ static int ib_uverbs_ex_modify_wq(struct uverbs_attr_bundle *attrs)
|
||||
return -EINVAL;
|
||||
|
||||
wq = uobj_get_obj_read(wq, UVERBS_OBJECT_WQ, cmd.wq_handle, attrs);
|
||||
if (!wq)
|
||||
return -EINVAL;
|
||||
if (IS_ERR(wq))
|
||||
return PTR_ERR(wq);
|
||||
|
||||
if (cmd.attr_mask & IB_WQ_FLAGS) {
|
||||
wq_attr.flags = cmd.flags;
|
||||
@ -3114,8 +3122,8 @@ static int ib_uverbs_ex_create_rwq_ind_table(struct uverbs_attr_bundle *attrs)
|
||||
num_read_wqs++) {
|
||||
wq = uobj_get_obj_read(wq, UVERBS_OBJECT_WQ,
|
||||
wqs_handles[num_read_wqs], attrs);
|
||||
if (!wq) {
|
||||
err = -EINVAL;
|
||||
if (IS_ERR(wq)) {
|
||||
err = PTR_ERR(wq);
|
||||
goto put_wqs;
|
||||
}
|
||||
|
||||
@ -3270,8 +3278,8 @@ static int ib_uverbs_ex_create_flow(struct uverbs_attr_bundle *attrs)
|
||||
}
|
||||
|
||||
qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
|
||||
if (!qp) {
|
||||
err = -EINVAL;
|
||||
if (IS_ERR(qp)) {
|
||||
err = PTR_ERR(qp);
|
||||
goto err_uobj;
|
||||
}
|
||||
|
||||
@ -3417,15 +3425,15 @@ static int __uverbs_create_xsrq(struct uverbs_attr_bundle *attrs,
|
||||
if (ib_srq_has_cq(cmd->srq_type)) {
|
||||
attr.ext.cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ,
|
||||
cmd->cq_handle, attrs);
|
||||
if (!attr.ext.cq) {
|
||||
ret = -EINVAL;
|
||||
if (IS_ERR(attr.ext.cq)) {
|
||||
ret = PTR_ERR(attr.ext.cq);
|
||||
goto err_put_xrcd;
|
||||
}
|
||||
}
|
||||
|
||||
pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd->pd_handle, attrs);
|
||||
if (!pd) {
|
||||
ret = -EINVAL;
|
||||
if (IS_ERR(pd)) {
|
||||
ret = PTR_ERR(pd);
|
||||
goto err_put_cq;
|
||||
}
|
||||
|
||||
@ -3532,8 +3540,8 @@ static int ib_uverbs_modify_srq(struct uverbs_attr_bundle *attrs)
|
||||
return ret;
|
||||
|
||||
srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ, cmd.srq_handle, attrs);
|
||||
if (!srq)
|
||||
return -EINVAL;
|
||||
if (IS_ERR(srq))
|
||||
return PTR_ERR(srq);
|
||||
|
||||
attr.max_wr = cmd.max_wr;
|
||||
attr.srq_limit = cmd.srq_limit;
|
||||
@ -3560,8 +3568,8 @@ static int ib_uverbs_query_srq(struct uverbs_attr_bundle *attrs)
|
||||
return ret;
|
||||
|
||||
srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ, cmd.srq_handle, attrs);
|
||||
if (!srq)
|
||||
return -EINVAL;
|
||||
if (IS_ERR(srq))
|
||||
return PTR_ERR(srq);
|
||||
|
||||
ret = ib_query_srq(srq, &attr);
|
||||
|
||||
@ -3686,8 +3694,8 @@ static int ib_uverbs_ex_modify_cq(struct uverbs_attr_bundle *attrs)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs);
|
||||
if (!cq)
|
||||
return -EINVAL;
|
||||
if (IS_ERR(cq))
|
||||
return PTR_ERR(cq);
|
||||
|
||||
ret = rdma_set_cq_moderation(cq, cmd.attr.cq_count, cmd.attr.cq_period);
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
static inline void *_uobj_get_obj_read(struct ib_uobject *uobj)
|
||||
{
|
||||
if (IS_ERR(uobj))
|
||||
return NULL;
|
||||
return ERR_CAST(uobj);
|
||||
return uobj->object;
|
||||
}
|
||||
#define uobj_get_obj_read(_object, _type, _id, _attrs) \
|
||||
|
Loading…
x
Reference in New Issue
Block a user