From patchwork Fri Aug 10 02:14:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Gunthorpe X-Patchwork-Id: 10562181 X-Patchwork-Delegate: jgg@ziepe.ca Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A11D51057 for ; Fri, 10 Aug 2018 02:14:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 913EF2BB93 for ; Fri, 10 Aug 2018 02:14:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 851E62BBAF; Fri, 10 Aug 2018 02:14:56 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D8BBF2BB93 for ; Fri, 10 Aug 2018 02:14:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725917AbeHJEmf (ORCPT ); Fri, 10 Aug 2018 00:42:35 -0400 Received: from mail-pl0-f65.google.com ([209.85.160.65]:39365 "EHLO mail-pl0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727087AbeHJEme (ORCPT ); Fri, 10 Aug 2018 00:42:34 -0400 Received: by mail-pl0-f65.google.com with SMTP id w14-v6so3361305plp.6 for ; Thu, 09 Aug 2018 19:14:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ziepe.ca; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=xFom53/xfiAGgTrlrijS1PZFRbE74GFo0tpmjlnUaOU=; b=I5CuSUEQ3Wd4SatJgx0hoW9vZxIdTS4EGE6qpEqVn+c82UYNZv5mDkicNvrLyiX4wo tNgyx4gvUUwvXnjbWD31qRjId2yiQN4kimtLWxMHZ2lekPbWuit65CkP4Wxz/EQmNPH0 18CnBBR/MxQcT+IOHsP+MQta0phFHEQLZbj7lv0t4DAS5Iy3gnhzoFt4DYo9wHn5rFLa t6XuWVcFhy/qml43JEiTRO5NIW7YyqJE9pLEnihdX7RAcikxzoWNaVU/nx7Eh011/uO/ cr/kmJw2x+VLL+1dNk04Wr8ambqmxijwVuKjCagmoZWLNLFN8uzG+zlgHEarieMPq/wC /nUg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=xFom53/xfiAGgTrlrijS1PZFRbE74GFo0tpmjlnUaOU=; b=UM2WJyCIFpe6xkqB4zYJRSbXf2UeudHxbzXI/EV1TXA8FyDpcax/74DkxTUQN64hTo VKvmbAU7JK1FO0O2TDdjFymdk+o3y1ttLdNbcdT550odwqXC7CDN3kRk2C3IntqraQor yEbB/cFv/Qrha+fa10HBR/AmUxQC5sh2prPu/rQSs/Bl7CCC+NX2qe1zyo4jzVsv/0ZG YwmQgsMcpq1rarDJIaDHU3T0lsXB6w73/R6YUiWp2kHz516ET36MACCZjHYvu9B4rh+i KYFUQqmcltXluLLMazk/LRCBiTMTLIoREss+85utrwz0Asot2RWkg9F8JORGtUdym+eK WZhw== X-Gm-Message-State: AOUpUlHHL8y5rTrJ8DYtYNgj0pzlubPoEnUny0vBiD9GjLoE1fwfzkSp Y1vCfjveTCcoSP6b9vOf1ee2GSOigwI= X-Google-Smtp-Source: AA+uWPxfqQ9Lq65HH2tpE0iTISyFij6reo8WSpL1f8vgigTb2z3E/vCMd3AyDORLldcXpf2nhXLMHQ== X-Received: by 2002:a17:902:9f90:: with SMTP id g16-v6mr4223303plq.304.1533867294069; Thu, 09 Aug 2018 19:14:54 -0700 (PDT) Received: from ziepe.ca (S010614cc2056d97f.ed.shawcable.net. [174.3.196.123]) by smtp.gmail.com with ESMTPSA id b20-v6sm18562768pfc.178.2018.08.09.19.14.51 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 09 Aug 2018 19:14:52 -0700 (PDT) Received: from jgg by mlx with local (Exim 4.90_1) (envelope-from ) id 1fnwx1-0003gZ-EA; Thu, 09 Aug 2018 20:14:51 -0600 From: Jason Gunthorpe To: linux-rdma@vger.kernel.org, Leon Romanovsky , "Guy Levi(SW)" , Yishai Hadas , "Ruhl, Michael J" Cc: Jason Gunthorpe Subject: [PATCH v1 05/10] IB/uverbs: Remove the ib_uverbs_attr pointer from each attr Date: Thu, 9 Aug 2018 20:14:39 -0600 Message-Id: <20180810021444.14014-6-jgg@ziepe.ca> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180810021444.14014-1-jgg@ziepe.ca> References: <20180810021444.14014-1-jgg@ziepe.ca> Sender: linux-rdma-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rdma@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Jason Gunthorpe Memory in the bundle is valuable, do not waste it holding an 8 byte pointer for the rare case of writing to a PTR_OUT. We can compute the pointer by storing a small 1 byte array offset and the base address of the uattr memory in the bundle private memory. This also means we can access the kernel's copy of the ib_uverbs_attr, so drop the copy of flags as well. Since the uattr base should be private bundle information this also de-inlines the already too big uverbs_copy_to inline and moves create_udata into uverbs_ioctl.c so they can see the private struct definition. Signed-off-by: Jason Gunthorpe Reviewed-by: Leon Romanovsky --- drivers/infiniband/core/uverbs_ioctl.c | 67 +++++++++++++++++++++- drivers/infiniband/core/uverbs_std_types.c | 32 ----------- include/rdma/uverbs_ioctl.h | 36 +++--------- 3 files changed, 72 insertions(+), 63 deletions(-) diff --git a/drivers/infiniband/core/uverbs_ioctl.c b/drivers/infiniband/core/uverbs_ioctl.c index 74b0a40aaa36ea..c5aa64ee099efe 100644 --- a/drivers/infiniband/core/uverbs_ioctl.c +++ b/drivers/infiniband/core/uverbs_ioctl.c @@ -84,7 +84,6 @@ static int uverbs_process_attr(struct bundle_priv *pbundle, spec = &attr_spec_bucket->attrs[attr_id]; val_spec = spec; e = &elements[attr_id]; - e->uattr = uattr_ptr; switch (spec->type) { case UVERBS_ATTR_TYPE_ENUM_IN: @@ -124,8 +123,8 @@ static int uverbs_process_attr(struct bundle_priv *pbundle, uattr->attr_data.reserved) return -EINVAL; + e->ptr_attr.uattr_idx = uattr - pbundle->uattrs; e->ptr_attr.len = uattr->len; - e->ptr_attr.flags = uattr->flags; if (val_spec->alloc_and_copy && !uverbs_attr_ptr_is_inline(e)) { void *p; @@ -181,7 +180,7 @@ static int uverbs_process_attr(struct bundle_priv *pbundle, s64 id = o_attr->uobject->id; /* Copy the allocated id to the user-space */ - if (put_user(id, &e->uattr->data)) { + if (put_user(id, &uattr_ptr->data)) { uverbs_finalize_object(o_attr->uobject, UVERBS_ACCESS_NEW, false); @@ -562,3 +561,65 @@ int uverbs_get_flags32(u32 *to, const struct uverbs_attr_bundle *attrs_bundle, return 0; } EXPORT_SYMBOL(uverbs_get_flags32); + +/* + * This is for ease of conversion. The purpose is to convert all drivers to + * use uverbs_attr_bundle instead of ib_udata. Assume attr == 0 is input and + * attr == 1 is output. + */ +void create_udata(struct uverbs_attr_bundle *bundle, struct ib_udata *udata) +{ + struct bundle_priv *pbundle = + container_of(bundle, struct bundle_priv, bundle); + const struct uverbs_attr *uhw_in = + uverbs_attr_get(bundle, UVERBS_ATTR_UHW_IN); + const struct uverbs_attr *uhw_out = + uverbs_attr_get(bundle, UVERBS_ATTR_UHW_OUT); + + if (!IS_ERR(uhw_in)) { + udata->inlen = uhw_in->ptr_attr.len; + if (uverbs_attr_ptr_is_inline(uhw_in)) + udata->inbuf = + &pbundle->user_attrs[uhw_in->ptr_attr.uattr_idx] + .data; + else + udata->inbuf = u64_to_user_ptr(uhw_in->ptr_attr.data); + } else { + udata->inbuf = NULL; + udata->inlen = 0; + } + + if (!IS_ERR(uhw_out)) { + udata->outbuf = u64_to_user_ptr(uhw_out->ptr_attr.data); + udata->outlen = uhw_out->ptr_attr.len; + } else { + udata->outbuf = NULL; + udata->outlen = 0; + } +} + +int uverbs_copy_to(const struct uverbs_attr_bundle *bundle, size_t idx, + const void *from, size_t size) +{ + struct bundle_priv *pbundle = + container_of(bundle, struct bundle_priv, bundle); + const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx); + u16 flags; + size_t min_size; + + if (IS_ERR(attr)) + return PTR_ERR(attr); + + min_size = min_t(size_t, attr->ptr_attr.len, size); + if (copy_to_user(u64_to_user_ptr(attr->ptr_attr.data), from, min_size)) + return -EFAULT; + + flags = pbundle->uattrs[attr->ptr_attr.uattr_idx].flags | + UVERBS_ATTR_F_VALID_OUTPUT; + if (put_user(flags, + &pbundle->user_attrs[attr->ptr_attr.uattr_idx].flags)) + return -EFAULT; + + return 0; +} +EXPORT_SYMBOL(uverbs_copy_to); diff --git a/drivers/infiniband/core/uverbs_std_types.c b/drivers/infiniband/core/uverbs_std_types.c index 7f22b820a21ba0..203cc96ac6f508 100644 --- a/drivers/infiniband/core/uverbs_std_types.c +++ b/drivers/infiniband/core/uverbs_std_types.c @@ -217,38 +217,6 @@ int uverbs_destroy_def_handler(struct ib_uverbs_file *file, } EXPORT_SYMBOL(uverbs_destroy_def_handler); -void create_udata(struct uverbs_attr_bundle *ctx, struct ib_udata *udata) -{ - /* - * This is for ease of conversion. The purpose is to convert all drivers - * to use uverbs_attr_bundle instead of ib_udata. - * Assume attr == 0 is input and attr == 1 is output. - */ - const struct uverbs_attr *uhw_in = - uverbs_attr_get(ctx, UVERBS_ATTR_UHW_IN); - const struct uverbs_attr *uhw_out = - uverbs_attr_get(ctx, UVERBS_ATTR_UHW_OUT); - - if (!IS_ERR(uhw_in)) { - udata->inlen = uhw_in->ptr_attr.len; - if (uverbs_attr_ptr_is_inline(uhw_in)) - udata->inbuf = &uhw_in->uattr->data; - else - udata->inbuf = u64_to_user_ptr(uhw_in->ptr_attr.data); - } else { - udata->inbuf = NULL; - udata->inlen = 0; - } - - if (!IS_ERR(uhw_out)) { - udata->outbuf = u64_to_user_ptr(uhw_out->ptr_attr.data); - udata->outlen = uhw_out->ptr_attr.len; - } else { - udata->outbuf = NULL; - udata->outlen = 0; - } -} - DECLARE_UVERBS_NAMED_OBJECT( UVERBS_OBJECT_COMP_CHANNEL, UVERBS_TYPE_ALLOC_FD(sizeof(struct ib_uverbs_completion_event_file), diff --git a/include/rdma/uverbs_ioctl.h b/include/rdma/uverbs_ioctl.h index 3b497d9ed39592..ecf028446cdf53 100644 --- a/include/rdma/uverbs_ioctl.h +++ b/include/rdma/uverbs_ioctl.h @@ -461,8 +461,7 @@ struct uverbs_ptr_attr { u64 data; }; u16 len; - /* Combination of bits from enum UVERBS_ATTR_F_XXXX */ - u16 flags; + u16 uattr_idx; u8 enum_id; }; @@ -471,11 +470,6 @@ struct uverbs_obj_attr { }; struct uverbs_attr { - /* - * pointer to the user-space given attribute, in order to write the - * new uobject's id or update flags. - */ - struct ib_uverbs_attr __user *uattr; union { struct uverbs_ptr_attr ptr_attr; struct uverbs_obj_attr obj_attr; @@ -575,27 +569,6 @@ uverbs_attr_get_len(const struct uverbs_attr_bundle *attrs_bundle, u16 idx) return attr->ptr_attr.len; } -static inline int uverbs_copy_to(const struct uverbs_attr_bundle *attrs_bundle, - size_t idx, const void *from, size_t size) -{ - const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx); - u16 flags; - size_t min_size; - - if (IS_ERR(attr)) - return PTR_ERR(attr); - - min_size = min_t(size_t, attr->ptr_attr.len, size); - if (copy_to_user(u64_to_user_ptr(attr->ptr_attr.data), from, min_size)) - return -EFAULT; - - flags = attr->ptr_attr.flags | UVERBS_ATTR_F_VALID_OUTPUT; - if (put_user(flags, &attr->uattr->flags)) - return -EFAULT; - - return 0; -} - static inline bool uverbs_attr_ptr_is_inline(const struct uverbs_attr *attr) { return attr->ptr_attr.len <= sizeof(attr->ptr_attr.data); @@ -676,6 +649,8 @@ int uverbs_get_flags64(u64 *to, const struct uverbs_attr_bundle *attrs_bundle, size_t idx, u64 allowed_bits); int uverbs_get_flags32(u32 *to, const struct uverbs_attr_bundle *attrs_bundle, size_t idx, u64 allowed_bits); +int uverbs_copy_to(const struct uverbs_attr_bundle *attrs_bundle, size_t idx, + const void *from, size_t size); #else static inline int uverbs_get_flags64(u64 *to, const struct uverbs_attr_bundle *attrs_bundle, @@ -689,6 +664,11 @@ uverbs_get_flags32(u32 *to, const struct uverbs_attr_bundle *attrs_bundle, { return -EINVAL; } +static inline int uverbs_copy_to(const struct uverbs_attr_bundle *attrs_bundle, + size_t idx, const void *from, size_t size) +{ + return -EINVAL; +} #endif /* =================================================