Re: [PATCH RFC] RDMA: Change ib_umem_get to accept an ib_udata

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Dec 19, 2018 at 05:08:54AM +0000, Jason Gunthorpe wrote:
> ib_umem_get can only be called in a method callback, which always has a
> udata parameter. This allows ib_umem_get() to derive the ucontext pointer
> directly from the udata without requiring the drivers to find it in some
> way or another.
> 
> Signed-off-by: Jason Gunthorpe <jgg@xxxxxxxxxxxx>
> ---
>  drivers/infiniband/core/umem.c                | 31 +++++++++++++++++--
>  drivers/infiniband/hw/bnxt_re/ib_verbs.c      | 11 +++----
>  drivers/infiniband/hw/cxgb3/iwch_provider.c   |  2 +-
>  drivers/infiniband/hw/cxgb4/mem.c             |  2 +-
>  drivers/infiniband/hw/hns/hns_roce_cq.c       |  9 +++---
>  drivers/infiniband/hw/hns/hns_roce_db.c       |  6 ++--
>  drivers/infiniband/hw/hns/hns_roce_device.h   |  3 +-
>  drivers/infiniband/hw/hns/hns_roce_mr.c       |  7 ++---
>  drivers/infiniband/hw/hns/hns_roce_qp.c       | 13 ++++----
>  drivers/infiniband/hw/hns/hns_roce_srq.c      |  7 ++---
>  drivers/infiniband/hw/i40iw/i40iw_verbs.c     |  2 +-
>  drivers/infiniband/hw/mlx4/cq.c               | 16 +++++-----
>  drivers/infiniband/hw/mlx4/doorbell.c         |  6 ++--
>  drivers/infiniband/hw/mlx4/mlx4_ib.h          |  3 +-
>  drivers/infiniband/hw/mlx4/mr.c               | 13 ++++----
>  drivers/infiniband/hw/mlx4/qp.c               |  8 +++--
>  drivers/infiniband/hw/mlx4/srq.c              |  5 ++-
>  drivers/infiniband/hw/mlx5/cq.c               |  7 ++---
>  drivers/infiniband/hw/mlx5/devx.c             |  2 +-
>  drivers/infiniband/hw/mlx5/doorbell.c         |  6 ++--
>  drivers/infiniband/hw/mlx5/mlx5_ib.h          |  4 ++-
>  drivers/infiniband/hw/mlx5/mr.c               | 22 ++++++-------
>  drivers/infiniband/hw/mlx5/odp.c              |  4 +--
>  drivers/infiniband/hw/mlx5/qp.c               | 25 +++++++--------
>  drivers/infiniband/hw/mlx5/srq.c              |  5 ++-
>  drivers/infiniband/hw/mthca/mthca_provider.c  |  2 +-
>  drivers/infiniband/hw/nes/nes_verbs.c         |  4 +--
>  drivers/infiniband/hw/ocrdma/ocrdma_verbs.c   |  2 +-
>  drivers/infiniband/hw/qedr/verbs.c            | 28 ++++++++---------
>  drivers/infiniband/hw/vmw_pvrdma/pvrdma_cq.c  |  2 +-
>  drivers/infiniband/hw/vmw_pvrdma/pvrdma_mr.c  |  3 +-
>  drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c  |  6 ++--
>  drivers/infiniband/hw/vmw_pvrdma/pvrdma_srq.c |  4 +--
>  drivers/infiniband/sw/rdmavt/mr.c             |  3 +-
>  drivers/infiniband/sw/rxe/rxe_mr.c            |  2 +-
>  include/rdma/ib_umem.h                        |  5 +--
>  36 files changed, 150 insertions(+), 130 deletions(-)
> 
> Shamir, this is the next step I see in your series - this alone chops
> out another 30 cases. Nearly all core APIs toward the driver should be
> adjusted similarly in patches like this (ie rdma_user_mmap_page() and
> so forth)

Great!

> 
> The immediate step beyond this is to make rdma_get_ucontext into a
> driver exported function and replace all *->uobject->context with
> it. Maybe also adjust things so it can't fail, hard to say right now
> if failure will be inconvenient.
> 

I did something like this based on your recent work to unify the uverbs
& ioctl code path. Will add the patches to this email and if they are
fine with you we could use them to fill the ucontext in the udata from
uverbs & ioctl.

> Then we can see what is left and make a decision how to handle it.
> 
> I made this patch pretty fast, you should check it, test it, make the
> other similarly related ones, etc.
> 
> diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
> index c6144df47ea47e..37aa3fbda56fc3 100644
> --- a/drivers/infiniband/core/umem.c
> +++ b/drivers/infiniband/core/umem.c
> @@ -43,6 +43,28 @@
>  
>  #include "uverbs.h"
>  
> +/* rdma_get_ucontext - Return the ucontext from a udata
> + * @udata: The udata to get the context from
> + *
> + * This can only be called from within a uapi method that was passed ib_udata
> + * as a parameter. It returns the ucontext associated with the udata, or ERR_PTR
> + * if the udata is NULL or the ucontext has been disassociated.
> + */
> +static struct ib_ucontext *rdma_get_ucontext(struct ib_udata *udata)
> +{
> +	if (!udata)
> +		return ERR_PTR(-EIO);
> +
> +	/*
> +	 * FIXME: Really all cases that get here with a udata will have
> +	 * already called ib_uverbs_get_ucontext_file, or located a uobject
> +	 * that points to a ucontext. We could store that result in the udata
> +	 * so this function can't fail.
> +	 */
> +	return ib_uverbs_get_ucontext_file(
> +		container_of(udata, struct uverbs_attr_bundle, driver_udata)
> +			->ufile);

I think the patches I attached here solve this so if you are OK with
them I think there is no need for this function unless I missed
something.

> +}
>  

Thanks
>From dc6f3a023c627832a93aaede5cfea052f3973fc4 Mon Sep 17 00:00:00 2001
From: Shamir Rabinovitch <shamir.rabinovitch@xxxxxxxxxx>
Date: Sun, 14 Oct 2018 09:11:12 +0300
Subject: [PATCH 1/2] IB/verbs: add ib_ucontext to ib_udata

ib_udata is used in (almost) all the places in the code that require
ib_ucontext and can convey this information to the ib core and driver
layers.

Signed-off-by: Shamir Rabinovitch <shamir.rabinovitch@xxxxxxxxxx>
---
 include/rdma/ib_verbs.h | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index b8ddb2d82372..b7ec9da0b22b 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -1533,8 +1533,36 @@ struct ib_udata {
 	void __user *outbuf;
 	size_t       inlen;
 	size_t       outlen;
+	struct ib_ucontext     *context;        /* associated user context */
 };
 
+/**
+ * _rdma_udata_context - Get ucontext from udata
+ * @udata: The udata object
+ * @warn: Warn true/false if ucontext is NULL
+ *
+ * NOTE:
+ * Most of the code should use rdma_udata_context which turn
+ * the NULL ucontext warning on. Use this function if you need
+ * to *test* if udata has ucontext and want to turn the warning
+ * off.
+ */
+static inline struct ib_ucontext *_rdma_udata_context(struct ib_udata *udata,
+						      bool warn)
+{
+	WARN_ON(warn && !udata->context);
+	return udata->context;
+}
+
+/**
+ * rdma_udata_context - Get ucontext from udata
+ * @udata: The udata object
+ *
+ * NOTE: Assume valid ucontext & warn if ucontext is NULL!
+ */
+#define rdma_udata_context(udata) \
+	_rdma_udata_context(udata, true)
+
 struct ib_pd {
 	u32			local_dma_lkey;
 	u32			flags;
-- 
2.17.2

>From 033dc509ba8ec9d5521c0b04cbffba203273324d Mon Sep 17 00:00:00 2001
From: Shamir Rabinovitch <shamir.rabinovitch@xxxxxxxxxx>
Date: Tue, 18 Dec 2018 17:13:53 +0200
Subject: [PATCH 2/2] IB/uverbs: initialize context field in ib_udata

initialize the context field in ib_udata created from uverbs commands
and extended commands path.

NOTE:
follow this change, any code path that call uobj_get_[read|write]
directly/indirectly can no longer define the uverbs_attr_bundle as
'const'.

Signed-off-by: Shamir Rabinovitch <shamir.rabinovitch@xxxxxxxxxx>
---
 drivers/infiniband/core/uverbs.h      |  1 +
 drivers/infiniband/core/uverbs_cmd.c  |  2 +-
 drivers/infiniband/core/uverbs_main.c |  1 +
 include/rdma/uverbs_std_types.h       | 20 ++++++++++++++++----
 4 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index 8b41c95300c6..ce0800de1145 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -61,6 +61,7 @@ ib_uverbs_init_udata(struct ib_udata *udata,
 	udata->outbuf = obuf;
 	udata->inlen  = ilen;
 	udata->outlen = olen;
+	udata->context = NULL;
 }
 
 static inline void
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index f68d234b09f2..d37bc7401064 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -2670,7 +2670,7 @@ void flow_resources_add(struct ib_uflow_resources *uflow_res,
 }
 EXPORT_SYMBOL(flow_resources_add);
 
-static int kern_spec_to_ib_spec_action(const struct uverbs_attr_bundle *attrs,
+static int kern_spec_to_ib_spec_action(struct uverbs_attr_bundle *attrs,
 				       struct ib_uverbs_flow_spec *kern_spec,
 				       union ib_flow_spec *ib_spec,
 				       struct ib_uflow_resources *uflow_res)
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 96a5f89bbb75..084c1cd06b2f 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -705,6 +705,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
 				bundle.driver_udata.inbuf = buf + in_len;
 			else
 				bundle.driver_udata.inbuf = NULL;
+			bundle.driver_udata.context = NULL;
 		} else {
 			memset(&bundle.driver_udata, 0,
 			       sizeof(bundle.driver_udata));
diff --git a/include/rdma/uverbs_std_types.h b/include/rdma/uverbs_std_types.h
index 883abcf6d36e..a0fcd5818c0f 100644
--- a/include/rdma/uverbs_std_types.h
+++ b/include/rdma/uverbs_std_types.h
@@ -48,9 +48,20 @@
 #define uobj_get_type(_attrs, _object)                                         \
 	uapi_get_object((_attrs)->ufile->device->uapi, _object)
 
+static inline struct ib_uobject *
+uobj_attrs_set_context(struct ib_uobject *uobj,
+		      struct uverbs_attr_bundle *attrs)
+{
+	if (IS_ERR(uobj))
+		return uobj;
+	attrs->driver_udata.context = uobj->context;
+	return uobj;
+}
+
 #define uobj_get_read(_type, _id, _attrs)                                      \
-	rdma_lookup_get_uobject(uobj_get_type(_attrs, _type), (_attrs)->ufile, \
-				_uobj_check_id(_id), UVERBS_LOOKUP_READ)
+	uobj_attrs_set_context(rdma_lookup_get_uobject(                        \
+		uobj_get_type(_attrs, _type), (_attrs)->ufile,                 \
+			_uobj_check_id(_id), UVERBS_LOOKUP_READ), _attrs)
 
 #define ufd_get_read(_type, _fdnum, _attrs)                                    \
 	rdma_lookup_get_uobject(uobj_get_type(_attrs, _type), (_attrs)->ufile, \
@@ -68,8 +79,9 @@ static inline void *_uobj_get_obj_read(struct ib_uobject *uobj)
 		uobj_get_read(_type, _id, _attrs)))
 
 #define uobj_get_write(_type, _id, _attrs)                                     \
-	rdma_lookup_get_uobject(uobj_get_type(_attrs, _type), (_attrs)->ufile, \
-				_uobj_check_id(_id), UVERBS_LOOKUP_WRITE)
+	uobj_attrs_set_context(rdma_lookup_get_uobject(                        \
+		uobj_get_type(_attrs, _type), (_attrs)->ufile,                 \
+			_uobj_check_id(_id), UVERBS_LOOKUP_WRITE), _attrs)
 
 int __uobj_perform_destroy(const struct uverbs_api_object *obj, u32 id,
 			   const struct uverbs_attr_bundle *attrs);
-- 
2.17.2


[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux