Re: [PATCH for-next v2 2/3] IB/verbs: add helper function rdma_udata_to_drv_context

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

 



On Mon, Jan 28, 2019 at 11:45:35PM -0800, Christoph Hellwig wrote:
> On Mon, Jan 28, 2019 at 12:01:06PM -0700, Jason Gunthorpe wrote:
> >  * If udata is not NULL this cannot fail. Otherwise a NULL udata will result
> >  * in a NULL ucontext pointer. Callers can rely on !NULL ucontext to show the
> >  * op is being called as part of a user system call.
> >  */
> > #define rdma_udata_to_drv_context(udata, drv_dev_struct, member)	\
> > 	(udata ? container_of(container_of(udata, struct uverbs_attr_bundle,   \
> > 					   driver_udata)                       \
> > 				      ->context,                               \
> > 			      drv_dev_struct, member) :                        \
> > 		 (drv_dev_struct *)NULL)
> > 
> > And get rid of the rdma_get_ucontext helper function, umem can just
> > inspect udata->context itself and fail with EIO if NULL.
> 
> And what exactly is the benefit over opencoding it?  Yes, it'll save
> about 2 lines of source per caller, but it will also make the code
> basically unreadable without looking at the defintion of
> rdma_udata_to_drv_context.

You are talking about the ternary expression, right? I think the
benefit of hiding the ugly container_of stuff is obvious..  (and why
the container_of is like that is a whole other email, I'm going to
work on that too someday)

The background here is that all driver callbacks can run in kernel
mode, or user mode. Shamir has been cleaning things so that the
drivers generally now inspect udata != NULL to determine if they are
in user mode (instead of the crazy mis-match before).

Only in user mode does a ucontext pointer exist.

Without the ternary expression, calling the macro will oops if done
unprotected in kernel mode.

Shamir converted some of the users in all the drivers:

https://patchwork.kernel.org/patch/10783539/

.. and if we drop the ternary then all those sites have to be much
more carefully reworked to ensure that the rdma_udata_to_drv_context
is only ever called under a 'if (udata)' block..

.. and that makes a big mess of a typical driver control flow pattern
of:

struct drv_uctx *uctx = rdma_udata_to_drv_context(udata, drv_uctx, ib_uctx);

if (uctx) {
   uctx->blah
}

[..]

if (udata) {
   if (copy_to_user(udata->outbuf))
       goto err_copy;
}

err_copy:
  if (uctx)
     undo uctx->blah

In other words adding the ternary is done to make reworking the
drivers easier and the result less likely to be wrong.

I think you are right though - the cases that do not have a
complicated control flow should be remain-as/be-changed-to:

   if (udata) {
         struct drv_uctx *uctx = rdma_udata_to_drv_context(..);

         uctx->blah
         if (copy_to_user())
              [..]
   }

To make the relation clear, and keep udata at the center for
determining user/kernel mode.

Jason



[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