From: Jason Gunthorpe <jgg@xxxxxxxxxxxx> Now that we have metadata describing the command format the core code can directly compute the udata pointers and all the really ugly ib_uverbs_init_udata() calls can be removed from the handlers. This means all the write() handlers are no longer sensitive to the layout of the command buffer. Signed-off-by: Jason Gunthorpe <jgg@xxxxxxxxxxxx> Signed-off-by: Leon Romanovsky <leonro@xxxxxxxxxxxx> --- drivers/infiniband/core/uverbs_cmd.c | 71 --------------------------- drivers/infiniband/core/uverbs_main.c | 48 +++++++++++++++++- 2 files changed, 46 insertions(+), 73 deletions(-) diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 3ee827047cb1..8ee9e94e25fe 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -97,11 +97,6 @@ static int ib_uverbs_get_context(struct uverbs_attr_bundle *attrs, goto err; } - ib_uverbs_init_udata(&attrs->driver_udata, buf + sizeof(cmd), - u64_to_user_ptr(cmd.response) + sizeof(resp), - in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr), - out_len - sizeof(resp)); - ret = ib_rdmacg_try_charge(&cg_obj, ib_dev, RDMACG_RESOURCE_HCA_HANDLE); if (ret) goto err; @@ -352,11 +347,6 @@ static int ib_uverbs_alloc_pd(struct uverbs_attr_bundle *attrs, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - ib_uverbs_init_udata(&attrs->driver_udata, buf + sizeof(cmd), - u64_to_user_ptr(cmd.response) + sizeof(resp), - in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr), - out_len - sizeof(resp)); - uobj = uobj_alloc(UVERBS_OBJECT_PD, attrs, &ib_dev); if (IS_ERR(uobj)) return PTR_ERR(uobj); @@ -509,11 +499,6 @@ static int ib_uverbs_open_xrcd(struct uverbs_attr_bundle *attrs, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - ib_uverbs_init_udata(&attrs->driver_udata, buf + sizeof(cmd), - u64_to_user_ptr(cmd.response) + sizeof(resp), - in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr), - out_len - sizeof(resp)); - mutex_lock(&ibudev->xrcd_tree_mutex); if (cmd.fd != -1) { @@ -663,11 +648,6 @@ static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - ib_uverbs_init_udata(&attrs->driver_udata, buf + sizeof(cmd), - u64_to_user_ptr(cmd.response) + sizeof(resp), - in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr), - out_len - sizeof(resp)); - if ((cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK)) return -EINVAL; @@ -753,11 +733,6 @@ static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs, if (copy_from_user(&cmd, buf, sizeof(cmd))) return -EFAULT; - ib_uverbs_init_udata(&attrs->driver_udata, buf + sizeof(cmd), - u64_to_user_ptr(cmd.response) + sizeof(resp), - in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr), - out_len - sizeof(resp)); - if (cmd.flags & ~IB_MR_REREG_SUPPORTED || !cmd.flags) return -EINVAL; @@ -863,11 +838,6 @@ static int ib_uverbs_alloc_mw(struct uverbs_attr_bundle *attrs, goto err_free; } - ib_uverbs_init_udata(&attrs->driver_udata, buf + sizeof(cmd), - u64_to_user_ptr(cmd.response) + sizeof(resp), - in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr), - out_len - sizeof(resp)); - mw = pd->device->alloc_mw(pd, cmd.mw_type, &attrs->driver_udata); if (IS_ERR(mw)) { ret = PTR_ERR(mw); @@ -1070,11 +1040,6 @@ static int ib_uverbs_create_cq(struct uverbs_attr_bundle *attrs, ib_uverbs_init_udata(&ucore, buf, u64_to_user_ptr(cmd.response), sizeof(cmd), sizeof(resp)); - ib_uverbs_init_udata(&attrs->driver_udata, buf + sizeof(cmd), - u64_to_user_ptr(cmd.response) + sizeof(resp), - in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr), - out_len - sizeof(resp)); - memset(&cmd_ex, 0, sizeof(cmd_ex)); cmd_ex.user_handle = cmd.user_handle; cmd_ex.cqe = cmd.cqe; @@ -1145,11 +1110,6 @@ static int ib_uverbs_resize_cq(struct uverbs_attr_bundle *attrs, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - ib_uverbs_init_udata(&attrs->driver_udata, buf + sizeof(cmd), - u64_to_user_ptr(cmd.response) + sizeof(resp), - in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr), - out_len - sizeof(resp)); - cq = uobj_get_obj_read(cq, UVERBS_OBJECT_CQ, cmd.cq_handle, attrs); if (!cq) return -EINVAL; @@ -1601,10 +1561,6 @@ static int ib_uverbs_create_qp(struct uverbs_attr_bundle *attrs, ib_uverbs_init_udata(&ucore, buf, u64_to_user_ptr(cmd.response), sizeof(cmd), resp_size); - ib_uverbs_init_udata(&attrs->driver_udata, buf + sizeof(cmd), - u64_to_user_ptr(cmd.response) + resp_size, - in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr), - out_len - resp_size); memset(&cmd_ex, 0, sizeof(cmd_ex)); cmd_ex.user_handle = cmd.user_handle; @@ -1695,11 +1651,6 @@ static int ib_uverbs_open_qp(struct uverbs_attr_bundle *attrs, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - ib_uverbs_init_udata(&attrs->driver_udata, buf + sizeof(cmd), - u64_to_user_ptr(cmd.response) + sizeof(resp), - in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr), - out_len - sizeof(resp)); - obj = (struct ib_uqp_object *)uobj_alloc(UVERBS_OBJECT_QP, attrs, &ib_dev); if (IS_ERR(obj)) @@ -2067,10 +2018,6 @@ static int ib_uverbs_modify_qp(struct uverbs_attr_bundle *attrs, ~((IB_USER_LEGACY_LAST_QP_ATTR_MASK << 1) - 1)) return -EOPNOTSUPP; - ib_uverbs_init_udata(&attrs->driver_udata, buf + sizeof(cmd.base), NULL, - in_len - sizeof(cmd.base) - sizeof(struct ib_uverbs_cmd_hdr), - out_len); - return modify_qp(attrs, &cmd); } @@ -2539,11 +2486,6 @@ static int ib_uverbs_create_ah(struct uverbs_attr_bundle *attrs, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - ib_uverbs_init_udata(&attrs->driver_udata, buf + sizeof(cmd), - u64_to_user_ptr(cmd.response) + sizeof(resp), - in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr), - out_len - sizeof(resp)); - uobj = uobj_alloc(UVERBS_OBJECT_AH, attrs, &ib_dev); if (IS_ERR(uobj)) return PTR_ERR(uobj); @@ -3746,11 +3688,6 @@ static int ib_uverbs_create_srq(struct uverbs_attr_bundle *attrs, xcmd.max_sge = cmd.max_sge; xcmd.srq_limit = cmd.srq_limit; - ib_uverbs_init_udata(&attrs->driver_udata, buf + sizeof(cmd), - u64_to_user_ptr(cmd.response) + sizeof(resp), - in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr), - out_len - sizeof(resp)); - return __uverbs_create_xsrq(attrs, &xcmd, &attrs->driver_udata); } @@ -3767,11 +3704,6 @@ static int ib_uverbs_create_xsrq(struct uverbs_attr_bundle *attrs, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - ib_uverbs_init_udata(&attrs->driver_udata, buf + sizeof(cmd), - u64_to_user_ptr(cmd.response) + sizeof(resp), - in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr), - out_len - sizeof(resp)); - return __uverbs_create_xsrq(attrs, &cmd, &attrs->driver_udata); } @@ -3786,9 +3718,6 @@ static int ib_uverbs_modify_srq(struct uverbs_attr_bundle *attrs, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - ib_uverbs_init_udata(&attrs->driver_udata, buf + sizeof cmd, NULL, - in_len - sizeof cmd, out_len); - srq = uobj_get_obj_read(srq, UVERBS_OBJECT_SRQ, cmd.srq_handle, attrs); if (!srq) return -EINVAL; diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index fc8d3d1c7048..be049546cee2 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -693,8 +693,51 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, bundle.ufile = file; if (!method_elm->is_ex) { - ret = method_elm->handler(&bundle, buf, hdr.in_words * 4, - hdr.out_words * 4); + size_t in_len = hdr.in_words * 4 - sizeof(hdr); + size_t out_len = hdr.out_words * 4; + + if (method_elm->has_udata) { + bundle.driver_udata.inlen = + in_len - method_elm->req_size; + in_len = method_elm->req_size; + if (bundle.driver_udata.inlen) + bundle.driver_udata.inbuf = buf + in_len; + else + bundle.driver_udata.inbuf = NULL; + } else { + memset(&bundle.driver_udata, 0, + sizeof(bundle.driver_udata)); + } + + if (method_elm->has_resp) { + u64 response; + + /* + * The macros check that if has_resp is set + * then the command request structure starts + * with a '__aligned u64 response' member. + */ + ret = get_user(response, (const u64 *)buf); + if (ret) + goto out_unlock; + + if (method_elm->has_udata) { + bundle.driver_udata.outlen = + out_len - method_elm->resp_size; + out_len = method_elm->resp_size; + if (bundle.driver_udata.outlen) + bundle.driver_udata.outbuf = + u64_to_user_ptr(response + + out_len); + else + bundle.driver_udata.outbuf = NULL; + } + } else { + bundle.driver_udata.outlen = 0; + bundle.driver_udata.outbuf = NULL; + } + + ret = method_elm->handler(&bundle, buf, in_len, out_len); } else { struct ib_udata ucore; @@ -713,6 +756,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, ret = method_elm->handler_ex(&bundle, &ucore); } +out_unlock: srcu_read_unlock(&file->device->disassociate_srcu, srcu_key); return (ret) ? : count; } -- 2.19.1