Re: [PATCH rdma-next 4/5] RDMA/umem: Don't hold mmap_sem for too long

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

 



On Fri, Jun 29, 2018 at 11:10:56AM -0600, Jason Gunthorpe wrote:
> On Wed, Jun 27, 2018 at 10:44:27AM +0300, Leon Romanovsky wrote:
> > From: Leon Romanovsky <leonro@xxxxxxxxxxxx>
> >
> > DMA mapping is time consuming operation and doesn't need to be
> > performed with mmap_sem semaphore is held on. Limit the scope of
> > that semaphore for accounting part only.
> >
> > Signed-off-by: Huy Nguyen <huyn@xxxxxxxxxxxx>
> > Signed-off-by: Leon Romanovsky <leonro@xxxxxxxxxxxx>
> >  drivers/infiniband/core/umem.c | 17 +++++++++--------
> >  1 file changed, 9 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
> > index 498f59bb4989..626f3f3b8f44 100644
> > +++ b/drivers/infiniband/core/umem.c
> > @@ -84,7 +84,6 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
> >  	struct ib_umem *umem;
> >  	struct page **page_list;
> >  	struct vm_area_struct **vma_list;
> > -	unsigned long locked;
> >  	unsigned long lock_limit;
> >  	unsigned long cur_base;
> >  	unsigned long npages;
> > @@ -149,15 +148,16 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
> >
> >  	npages = ib_umem_num_pages(umem);
> >
> > -	down_write(&current->mm->mmap_sem);
> > -
> > -	locked     = npages + current->mm->pinned_vm;
> >  	lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
> >
> > -	if ((locked > lock_limit) && !capable(CAP_IPC_LOCK)) {
> > +	down_write(&current->mm->mmap_sem);
> > +	current->mm->pinned_vm += npages;
> > +	if ((current->mm->pinned_vm > lock_limit) && !capable(CAP_IPC_LOCK)) {
> > +		up_write(&current->mm->mmap_sem);
> >  		ret = -ENOMEM;
> >  		goto out;
> >  	}
> > +	up_write(&current->mm->mmap_sem);
>
> This change removes the lock around get_user_pages_longterm(), and we
> have this calltree:
>
>  get_user_pages_longterm()
>    get_user_pages()
>      __get_user_pages_locked()
>        __get_user_pages()
>
> And the comment for __get_user_pages() says:
>
>  * Must be called with mmap_sem held.  It may be released.  See below.
> [..]
>  * A caller using such a combination of @nonblocking and @gup_flags
>  * must therefore hold the mmap_sem for reading only, and recognize
>  * when it's been released.  Otherwise, it must be held for either
>  * reading or writing and will not be released.
>
> Though, confusingly, I checked a random selection of get_user_pages()
> callers and couldn't obviously find a current->mm->mmap_sem in a few
> cases. I think those are bugs. Will try to find out..
>
> If this is safe without a lock for some tricky reason then please
> respin with a comment explaining why

It was unclear to me too, now looking more deeply, I think that at least
read sem is needed to find VMAs (performed internally in gup). It means
that radeon is wrong:
https://elixir.bootlin.com/linux/latest/source/drivers/gpu/drm/radeon/radeon_ttm.c#L561
and i40w too:
https://elixir.bootlin.com/linux/latest/source/drivers/infiniband/hw/i40iw/i40iw_verbs.c#L1412

>
> Otherwise respin to hold the lock across get_user_pages_longterm, as
> it was before..
>
> Jason

Attachment: signature.asc
Description: PGP signature


[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