All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Vetter <daniel.vetter@ffwll.ch>
To: John Hubbard <jhubbard@nvidia.com>
Cc: "DRI Development" <dri-devel@lists.freedesktop.org>,
	LKML <linux-kernel@vger.kernel.org>,
	"KVM list" <kvm@vger.kernel.org>, "Linux MM" <linux-mm@kvack.org>,
	"Linux ARM" <linux-arm-kernel@lists.infradead.org>,
	linux-samsung-soc <linux-samsung-soc@vger.kernel.org>,
	"open list:DMA BUFFER SHARING FRAMEWORK"
	<linux-media@vger.kernel.org>,
	"Daniel Vetter" <daniel.vetter@intel.com>,
	"Jason Gunthorpe" <jgg@ziepe.ca>,
	"Pawel Osciak" <pawel@osciak.com>,
	"Marek Szyprowski" <m.szyprowski@samsung.com>,
	"Kyungmin Park" <kyungmin.park@samsung.com>,
	"Tomasz Figa" <tfiga@chromium.org>,
	"Mauro Carvalho Chehab" <mchehab@kernel.org>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"Jérôme Glisse" <jglisse@redhat.com>, "Jan Kara" <jack@suse.cz>,
	"Dan Williams" <dan.j.williams@intel.com>
Subject: Re: [PATCH v5 05/15] mm/frame-vector: Use FOLL_LONGTERM
Date: Sat, 31 Oct 2020 15:45:41 +0100	[thread overview]
Message-ID: <CAKMK7uGDW2f0oOvwgryCHxQFHyh3Tsk6ENsMGmtZ-EnH57tMSA@mail.gmail.com> (raw)
In-Reply-To: <446b2d5b-a1a1-a408-f884-f17a04b72c18@nvidia.com>

On Sat, Oct 31, 2020 at 3:55 AM John Hubbard <jhubbard@nvidia.com> wrote:
>
> On 10/30/20 3:08 AM, Daniel Vetter wrote:
> > This is used by media/videbuf2 for persistent dma mappings, not just
> > for a single dma operation and then freed again, so needs
> > FOLL_LONGTERM.
> >
> > Unfortunately current pup_locked doesn't support FOLL_LONGTERM due to
> > locking issues. Rework the code to pull the pup path out from the
> > mmap_sem critical section as suggested by Jason.
> >
> > By relying entirely on the vma checks in pin_user_pages and follow_pfn
>
> There are vma checks in pin_user_pages(), but this patch changes things
> to call pin_user_pages_fast(). And that does not have the vma checks.
> More below about this:
>
> > (for vm_flags and vma_is_fsdax) we can also streamline the code a lot.
> >
> > Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> > Cc: Jason Gunthorpe <jgg@ziepe.ca>
> > Cc: Pawel Osciak <pawel@osciak.com>
> > Cc: Marek Szyprowski <m.szyprowski@samsung.com>
> > Cc: Kyungmin Park <kyungmin.park@samsung.com>
> > Cc: Tomasz Figa <tfiga@chromium.org>
> > Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
> > Cc: Andrew Morton <akpm@linux-foundation.org>
> > Cc: John Hubbard <jhubbard@nvidia.com>
> > Cc: Jérôme Glisse <jglisse@redhat.com>
> > Cc: Jan Kara <jack@suse.cz>
> > Cc: Dan Williams <dan.j.williams@intel.com>
> > Cc: linux-mm@kvack.org
> > Cc: linux-arm-kernel@lists.infradead.org
> > Cc: linux-samsung-soc@vger.kernel.org
> > Cc: linux-media@vger.kernel.org
> > Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> > --
> > v2: Streamline the code and further simplify the loop checks (Jason)
> >
> > v5: Review from Tomasz:
> > - fix page counting for the follow_pfn case by resetting ret
> > - drop gup_flags paramater, now unused
> > ---
> >   .../media/common/videobuf2/videobuf2-memops.c |  3 +-
> >   include/linux/mm.h                            |  2 +-
> >   mm/frame_vector.c                             | 53 ++++++-------------
> >   3 files changed, 19 insertions(+), 39 deletions(-)
> >
> > diff --git a/drivers/media/common/videobuf2/videobuf2-memops.c b/drivers/media/common/videobuf2/videobuf2-memops.c
> > index 6e9e05153f4e..9dd6c27162f4 100644
> > --- a/drivers/media/common/videobuf2/videobuf2-memops.c
> > +++ b/drivers/media/common/videobuf2/videobuf2-memops.c
> > @@ -40,7 +40,6 @@ struct frame_vector *vb2_create_framevec(unsigned long start,
> >       unsigned long first, last;
> >       unsigned long nr;
> >       struct frame_vector *vec;
> > -     unsigned int flags = FOLL_FORCE | FOLL_WRITE;
> >
> >       first = start >> PAGE_SHIFT;
> >       last = (start + length - 1) >> PAGE_SHIFT;
> > @@ -48,7 +47,7 @@ struct frame_vector *vb2_create_framevec(unsigned long start,
> >       vec = frame_vector_create(nr);
> >       if (!vec)
> >               return ERR_PTR(-ENOMEM);
> > -     ret = get_vaddr_frames(start & PAGE_MASK, nr, flags, vec);
> > +     ret = get_vaddr_frames(start & PAGE_MASK, nr, vec);
> >       if (ret < 0)
> >               goto out_destroy;
> >       /* We accept only complete set of PFNs */
> > diff --git a/include/linux/mm.h b/include/linux/mm.h
> > index ef360fe70aaf..d6b8e30dce2e 100644
> > --- a/include/linux/mm.h
> > +++ b/include/linux/mm.h
> > @@ -1765,7 +1765,7 @@ struct frame_vector {
> >   struct frame_vector *frame_vector_create(unsigned int nr_frames);
> >   void frame_vector_destroy(struct frame_vector *vec);
> >   int get_vaddr_frames(unsigned long start, unsigned int nr_pfns,
> > -                  unsigned int gup_flags, struct frame_vector *vec);
> > +                  struct frame_vector *vec);
> >   void put_vaddr_frames(struct frame_vector *vec);
> >   int frame_vector_to_pages(struct frame_vector *vec);
> >   void frame_vector_to_pfns(struct frame_vector *vec);
> > diff --git a/mm/frame_vector.c b/mm/frame_vector.c
> > index 10f82d5643b6..f8c34b895c76 100644
> > --- a/mm/frame_vector.c
> > +++ b/mm/frame_vector.c
> > @@ -32,13 +32,12 @@
> >    * This function takes care of grabbing mmap_lock as necessary.
> >    */
> >   int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
> > -                  unsigned int gup_flags, struct frame_vector *vec)
> > +                  struct frame_vector *vec)
> >   {
> >       struct mm_struct *mm = current->mm;
> >       struct vm_area_struct *vma;
> >       int ret = 0;
> >       int err;
> > -     int locked;
> >
> >       if (nr_frames == 0)
> >               return 0;
> > @@ -48,40 +47,26 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
> >
> >       start = untagged_addr(start);
> >
> > -     mmap_read_lock(mm);
> > -     locked = 1;
> > -     vma = find_vma_intersection(mm, start, start + 1);
> > -     if (!vma) {
> > -             ret = -EFAULT;
> > -             goto out;
> > -     }
> > -
> > -     /*
> > -      * While get_vaddr_frames() could be used for transient (kernel
> > -      * controlled lifetime) pinning of memory pages all current
> > -      * users establish long term (userspace controlled lifetime)
> > -      * page pinning. Treat get_vaddr_frames() like
> > -      * get_user_pages_longterm() and disallow it for filesystem-dax
> > -      * mappings.
> > -      */
> > -     if (vma_is_fsdax(vma)) {
> > -             ret = -EOPNOTSUPP;
> > -             goto out;
> > -     }
> > -
> > -     if (!(vma->vm_flags & (VM_IO | VM_PFNMAP))) {
>
> By removing this check from this location, and changing from
> pin_user_pages_locked() to pin_user_pages_fast(), I *think* we end up
> losing the check entirely. Is that intended? If so it could use a comment
> somewhere to explain why.

Yeah this wasn't intentional. I think I needed to drop the _locked
version to prep for FOLL_LONGTERM, and figured _fast is always better.
But I didn't realize that _fast doesn't have the vma checks, gup.c got
me a bit confused.

I'll remedy this in all the patches where this applies (because a
VM_IO | VM_PFNMAP can point at struct page backed memory, and that
exact use-case is what we want to stop with the unsafe_follow_pfn work
since it wreaks things like cma or security).

Aside: I do wonder whether the lack for that check isn't a problem.
VM_IO | VM_PFNMAP generally means driver managed, which means the
driver isn't going to consult the page pin count or anything like that
(at least not necessarily) when revoking or moving that memory, since
we're assuming it's totally under driver control. So if pup_fast can
get into such a mapping, we might have a problem.
-Daniel

> thanks,
> --
> John Hubbard
> NVIDIA
>
> > +     ret = pin_user_pages_fast(start, nr_frames,
> > +                               FOLL_FORCE | FOLL_WRITE | FOLL_LONGTERM,
> > +                               (struct page **)(vec->ptrs));
> > +     if (ret > 0) {
> >               vec->got_ref = true;
> >               vec->is_pfns = false;
> > -             ret = pin_user_pages_locked(start, nr_frames,
> > -                     gup_flags, (struct page **)(vec->ptrs), &locked);
> > -             goto out;
> > +             goto out_unlocked;
> >       }
> >
> > +     mmap_read_lock(mm);
> >       vec->got_ref = false;
> >       vec->is_pfns = true;
> > +     ret = 0;
> >       do {
> >               unsigned long *nums = frame_vector_pfns(vec);
> >
> > +             vma = find_vma_intersection(mm, start, start + 1);
> > +             if (!vma)
> > +                     break;
> > +
> >               while (ret < nr_frames && start + PAGE_SIZE <= vma->vm_end) {
> >                       err = follow_pfn(vma, start, &nums[ret]);
> >                       if (err) {
> > @@ -92,17 +77,13 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
> >                       start += PAGE_SIZE;
> >                       ret++;
> >               }
> > -             /*
> > -              * We stop if we have enough pages or if VMA doesn't completely
> > -              * cover the tail page.
> > -              */
> > -             if (ret >= nr_frames || start < vma->vm_end)
> > +             /* Bail out if VMA doesn't completely cover the tail page. */
> > +             if (start < vma->vm_end)
> >                       break;
> > -             vma = find_vma_intersection(mm, start, start + 1);
> > -     } while (vma && vma->vm_flags & (VM_IO | VM_PFNMAP));
> > +     } while (ret < nr_frames);
> >   out:
> > -     if (locked)
> > -             mmap_read_unlock(mm);
> > +     mmap_read_unlock(mm);
> > +out_unlocked:
> >       if (!ret)
> >               ret = -EFAULT;
> >       if (ret > 0)
> >
>
>


-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

WARNING: multiple messages have this Message-ID (diff)
From: Daniel Vetter <daniel.vetter@ffwll.ch>
To: John Hubbard <jhubbard@nvidia.com>
Cc: "Jérôme Glisse" <jglisse@redhat.com>,
	linux-samsung-soc <linux-samsung-soc@vger.kernel.org>,
	"Jan Kara" <jack@suse.cz>, "Pawel Osciak" <pawel@osciak.com>,
	"KVM list" <kvm@vger.kernel.org>,
	"Jason Gunthorpe" <jgg@ziepe.ca>,
	"Mauro Carvalho Chehab" <mchehab@kernel.org>,
	LKML <linux-kernel@vger.kernel.org>,
	"DRI Development" <dri-devel@lists.freedesktop.org>,
	"Tomasz Figa" <tfiga@chromium.org>,
	"Linux MM" <linux-mm@kvack.org>,
	"Kyungmin Park" <kyungmin.park@samsung.com>,
	"Daniel Vetter" <daniel.vetter@intel.com>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"Marek Szyprowski" <m.szyprowski@samsung.com>,
	"Dan Williams" <dan.j.williams@intel.com>,
	"Linux ARM" <linux-arm-kernel@lists.infradead.org>,
	"open list:DMA BUFFER SHARING FRAMEWORK"
	<linux-media@vger.kernel.org>
Subject: Re: [PATCH v5 05/15] mm/frame-vector: Use FOLL_LONGTERM
Date: Sat, 31 Oct 2020 15:45:41 +0100	[thread overview]
Message-ID: <CAKMK7uGDW2f0oOvwgryCHxQFHyh3Tsk6ENsMGmtZ-EnH57tMSA@mail.gmail.com> (raw)
In-Reply-To: <446b2d5b-a1a1-a408-f884-f17a04b72c18@nvidia.com>

On Sat, Oct 31, 2020 at 3:55 AM John Hubbard <jhubbard@nvidia.com> wrote:
>
> On 10/30/20 3:08 AM, Daniel Vetter wrote:
> > This is used by media/videbuf2 for persistent dma mappings, not just
> > for a single dma operation and then freed again, so needs
> > FOLL_LONGTERM.
> >
> > Unfortunately current pup_locked doesn't support FOLL_LONGTERM due to
> > locking issues. Rework the code to pull the pup path out from the
> > mmap_sem critical section as suggested by Jason.
> >
> > By relying entirely on the vma checks in pin_user_pages and follow_pfn
>
> There are vma checks in pin_user_pages(), but this patch changes things
> to call pin_user_pages_fast(). And that does not have the vma checks.
> More below about this:
>
> > (for vm_flags and vma_is_fsdax) we can also streamline the code a lot.
> >
> > Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> > Cc: Jason Gunthorpe <jgg@ziepe.ca>
> > Cc: Pawel Osciak <pawel@osciak.com>
> > Cc: Marek Szyprowski <m.szyprowski@samsung.com>
> > Cc: Kyungmin Park <kyungmin.park@samsung.com>
> > Cc: Tomasz Figa <tfiga@chromium.org>
> > Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
> > Cc: Andrew Morton <akpm@linux-foundation.org>
> > Cc: John Hubbard <jhubbard@nvidia.com>
> > Cc: Jérôme Glisse <jglisse@redhat.com>
> > Cc: Jan Kara <jack@suse.cz>
> > Cc: Dan Williams <dan.j.williams@intel.com>
> > Cc: linux-mm@kvack.org
> > Cc: linux-arm-kernel@lists.infradead.org
> > Cc: linux-samsung-soc@vger.kernel.org
> > Cc: linux-media@vger.kernel.org
> > Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> > --
> > v2: Streamline the code and further simplify the loop checks (Jason)
> >
> > v5: Review from Tomasz:
> > - fix page counting for the follow_pfn case by resetting ret
> > - drop gup_flags paramater, now unused
> > ---
> >   .../media/common/videobuf2/videobuf2-memops.c |  3 +-
> >   include/linux/mm.h                            |  2 +-
> >   mm/frame_vector.c                             | 53 ++++++-------------
> >   3 files changed, 19 insertions(+), 39 deletions(-)
> >
> > diff --git a/drivers/media/common/videobuf2/videobuf2-memops.c b/drivers/media/common/videobuf2/videobuf2-memops.c
> > index 6e9e05153f4e..9dd6c27162f4 100644
> > --- a/drivers/media/common/videobuf2/videobuf2-memops.c
> > +++ b/drivers/media/common/videobuf2/videobuf2-memops.c
> > @@ -40,7 +40,6 @@ struct frame_vector *vb2_create_framevec(unsigned long start,
> >       unsigned long first, last;
> >       unsigned long nr;
> >       struct frame_vector *vec;
> > -     unsigned int flags = FOLL_FORCE | FOLL_WRITE;
> >
> >       first = start >> PAGE_SHIFT;
> >       last = (start + length - 1) >> PAGE_SHIFT;
> > @@ -48,7 +47,7 @@ struct frame_vector *vb2_create_framevec(unsigned long start,
> >       vec = frame_vector_create(nr);
> >       if (!vec)
> >               return ERR_PTR(-ENOMEM);
> > -     ret = get_vaddr_frames(start & PAGE_MASK, nr, flags, vec);
> > +     ret = get_vaddr_frames(start & PAGE_MASK, nr, vec);
> >       if (ret < 0)
> >               goto out_destroy;
> >       /* We accept only complete set of PFNs */
> > diff --git a/include/linux/mm.h b/include/linux/mm.h
> > index ef360fe70aaf..d6b8e30dce2e 100644
> > --- a/include/linux/mm.h
> > +++ b/include/linux/mm.h
> > @@ -1765,7 +1765,7 @@ struct frame_vector {
> >   struct frame_vector *frame_vector_create(unsigned int nr_frames);
> >   void frame_vector_destroy(struct frame_vector *vec);
> >   int get_vaddr_frames(unsigned long start, unsigned int nr_pfns,
> > -                  unsigned int gup_flags, struct frame_vector *vec);
> > +                  struct frame_vector *vec);
> >   void put_vaddr_frames(struct frame_vector *vec);
> >   int frame_vector_to_pages(struct frame_vector *vec);
> >   void frame_vector_to_pfns(struct frame_vector *vec);
> > diff --git a/mm/frame_vector.c b/mm/frame_vector.c
> > index 10f82d5643b6..f8c34b895c76 100644
> > --- a/mm/frame_vector.c
> > +++ b/mm/frame_vector.c
> > @@ -32,13 +32,12 @@
> >    * This function takes care of grabbing mmap_lock as necessary.
> >    */
> >   int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
> > -                  unsigned int gup_flags, struct frame_vector *vec)
> > +                  struct frame_vector *vec)
> >   {
> >       struct mm_struct *mm = current->mm;
> >       struct vm_area_struct *vma;
> >       int ret = 0;
> >       int err;
> > -     int locked;
> >
> >       if (nr_frames == 0)
> >               return 0;
> > @@ -48,40 +47,26 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
> >
> >       start = untagged_addr(start);
> >
> > -     mmap_read_lock(mm);
> > -     locked = 1;
> > -     vma = find_vma_intersection(mm, start, start + 1);
> > -     if (!vma) {
> > -             ret = -EFAULT;
> > -             goto out;
> > -     }
> > -
> > -     /*
> > -      * While get_vaddr_frames() could be used for transient (kernel
> > -      * controlled lifetime) pinning of memory pages all current
> > -      * users establish long term (userspace controlled lifetime)
> > -      * page pinning. Treat get_vaddr_frames() like
> > -      * get_user_pages_longterm() and disallow it for filesystem-dax
> > -      * mappings.
> > -      */
> > -     if (vma_is_fsdax(vma)) {
> > -             ret = -EOPNOTSUPP;
> > -             goto out;
> > -     }
> > -
> > -     if (!(vma->vm_flags & (VM_IO | VM_PFNMAP))) {
>
> By removing this check from this location, and changing from
> pin_user_pages_locked() to pin_user_pages_fast(), I *think* we end up
> losing the check entirely. Is that intended? If so it could use a comment
> somewhere to explain why.

Yeah this wasn't intentional. I think I needed to drop the _locked
version to prep for FOLL_LONGTERM, and figured _fast is always better.
But I didn't realize that _fast doesn't have the vma checks, gup.c got
me a bit confused.

I'll remedy this in all the patches where this applies (because a
VM_IO | VM_PFNMAP can point at struct page backed memory, and that
exact use-case is what we want to stop with the unsafe_follow_pfn work
since it wreaks things like cma or security).

Aside: I do wonder whether the lack for that check isn't a problem.
VM_IO | VM_PFNMAP generally means driver managed, which means the
driver isn't going to consult the page pin count or anything like that
(at least not necessarily) when revoking or moving that memory, since
we're assuming it's totally under driver control. So if pup_fast can
get into such a mapping, we might have a problem.
-Daniel

> thanks,
> --
> John Hubbard
> NVIDIA
>
> > +     ret = pin_user_pages_fast(start, nr_frames,
> > +                               FOLL_FORCE | FOLL_WRITE | FOLL_LONGTERM,
> > +                               (struct page **)(vec->ptrs));
> > +     if (ret > 0) {
> >               vec->got_ref = true;
> >               vec->is_pfns = false;
> > -             ret = pin_user_pages_locked(start, nr_frames,
> > -                     gup_flags, (struct page **)(vec->ptrs), &locked);
> > -             goto out;
> > +             goto out_unlocked;
> >       }
> >
> > +     mmap_read_lock(mm);
> >       vec->got_ref = false;
> >       vec->is_pfns = true;
> > +     ret = 0;
> >       do {
> >               unsigned long *nums = frame_vector_pfns(vec);
> >
> > +             vma = find_vma_intersection(mm, start, start + 1);
> > +             if (!vma)
> > +                     break;
> > +
> >               while (ret < nr_frames && start + PAGE_SIZE <= vma->vm_end) {
> >                       err = follow_pfn(vma, start, &nums[ret]);
> >                       if (err) {
> > @@ -92,17 +77,13 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
> >                       start += PAGE_SIZE;
> >                       ret++;
> >               }
> > -             /*
> > -              * We stop if we have enough pages or if VMA doesn't completely
> > -              * cover the tail page.
> > -              */
> > -             if (ret >= nr_frames || start < vma->vm_end)
> > +             /* Bail out if VMA doesn't completely cover the tail page. */
> > +             if (start < vma->vm_end)
> >                       break;
> > -             vma = find_vma_intersection(mm, start, start + 1);
> > -     } while (vma && vma->vm_flags & (VM_IO | VM_PFNMAP));
> > +     } while (ret < nr_frames);
> >   out:
> > -     if (locked)
> > -             mmap_read_unlock(mm);
> > +     mmap_read_unlock(mm);
> > +out_unlocked:
> >       if (!ret)
> >               ret = -EFAULT;
> >       if (ret > 0)
> >
>
>


-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

WARNING: multiple messages have this Message-ID (diff)
From: Daniel Vetter <daniel.vetter@ffwll.ch>
To: John Hubbard <jhubbard@nvidia.com>
Cc: "Jérôme Glisse" <jglisse@redhat.com>,
	linux-samsung-soc <linux-samsung-soc@vger.kernel.org>,
	"Jan Kara" <jack@suse.cz>, "Pawel Osciak" <pawel@osciak.com>,
	"KVM list" <kvm@vger.kernel.org>,
	"Jason Gunthorpe" <jgg@ziepe.ca>,
	"Mauro Carvalho Chehab" <mchehab@kernel.org>,
	LKML <linux-kernel@vger.kernel.org>,
	"DRI Development" <dri-devel@lists.freedesktop.org>,
	"Tomasz Figa" <tfiga@chromium.org>,
	"Linux MM" <linux-mm@kvack.org>,
	"Kyungmin Park" <kyungmin.park@samsung.com>,
	"Daniel Vetter" <daniel.vetter@intel.com>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"Marek Szyprowski" <m.szyprowski@samsung.com>,
	"Dan Williams" <dan.j.williams@intel.com>,
	"Linux ARM" <linux-arm-kernel@lists.infradead.org>,
	"open list:DMA BUFFER SHARING FRAMEWORK"
	<linux-media@vger.kernel.org>
Subject: Re: [PATCH v5 05/15] mm/frame-vector: Use FOLL_LONGTERM
Date: Sat, 31 Oct 2020 15:45:41 +0100	[thread overview]
Message-ID: <CAKMK7uGDW2f0oOvwgryCHxQFHyh3Tsk6ENsMGmtZ-EnH57tMSA@mail.gmail.com> (raw)
In-Reply-To: <446b2d5b-a1a1-a408-f884-f17a04b72c18@nvidia.com>

On Sat, Oct 31, 2020 at 3:55 AM John Hubbard <jhubbard@nvidia.com> wrote:
>
> On 10/30/20 3:08 AM, Daniel Vetter wrote:
> > This is used by media/videbuf2 for persistent dma mappings, not just
> > for a single dma operation and then freed again, so needs
> > FOLL_LONGTERM.
> >
> > Unfortunately current pup_locked doesn't support FOLL_LONGTERM due to
> > locking issues. Rework the code to pull the pup path out from the
> > mmap_sem critical section as suggested by Jason.
> >
> > By relying entirely on the vma checks in pin_user_pages and follow_pfn
>
> There are vma checks in pin_user_pages(), but this patch changes things
> to call pin_user_pages_fast(). And that does not have the vma checks.
> More below about this:
>
> > (for vm_flags and vma_is_fsdax) we can also streamline the code a lot.
> >
> > Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> > Cc: Jason Gunthorpe <jgg@ziepe.ca>
> > Cc: Pawel Osciak <pawel@osciak.com>
> > Cc: Marek Szyprowski <m.szyprowski@samsung.com>
> > Cc: Kyungmin Park <kyungmin.park@samsung.com>
> > Cc: Tomasz Figa <tfiga@chromium.org>
> > Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
> > Cc: Andrew Morton <akpm@linux-foundation.org>
> > Cc: John Hubbard <jhubbard@nvidia.com>
> > Cc: Jérôme Glisse <jglisse@redhat.com>
> > Cc: Jan Kara <jack@suse.cz>
> > Cc: Dan Williams <dan.j.williams@intel.com>
> > Cc: linux-mm@kvack.org
> > Cc: linux-arm-kernel@lists.infradead.org
> > Cc: linux-samsung-soc@vger.kernel.org
> > Cc: linux-media@vger.kernel.org
> > Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> > --
> > v2: Streamline the code and further simplify the loop checks (Jason)
> >
> > v5: Review from Tomasz:
> > - fix page counting for the follow_pfn case by resetting ret
> > - drop gup_flags paramater, now unused
> > ---
> >   .../media/common/videobuf2/videobuf2-memops.c |  3 +-
> >   include/linux/mm.h                            |  2 +-
> >   mm/frame_vector.c                             | 53 ++++++-------------
> >   3 files changed, 19 insertions(+), 39 deletions(-)
> >
> > diff --git a/drivers/media/common/videobuf2/videobuf2-memops.c b/drivers/media/common/videobuf2/videobuf2-memops.c
> > index 6e9e05153f4e..9dd6c27162f4 100644
> > --- a/drivers/media/common/videobuf2/videobuf2-memops.c
> > +++ b/drivers/media/common/videobuf2/videobuf2-memops.c
> > @@ -40,7 +40,6 @@ struct frame_vector *vb2_create_framevec(unsigned long start,
> >       unsigned long first, last;
> >       unsigned long nr;
> >       struct frame_vector *vec;
> > -     unsigned int flags = FOLL_FORCE | FOLL_WRITE;
> >
> >       first = start >> PAGE_SHIFT;
> >       last = (start + length - 1) >> PAGE_SHIFT;
> > @@ -48,7 +47,7 @@ struct frame_vector *vb2_create_framevec(unsigned long start,
> >       vec = frame_vector_create(nr);
> >       if (!vec)
> >               return ERR_PTR(-ENOMEM);
> > -     ret = get_vaddr_frames(start & PAGE_MASK, nr, flags, vec);
> > +     ret = get_vaddr_frames(start & PAGE_MASK, nr, vec);
> >       if (ret < 0)
> >               goto out_destroy;
> >       /* We accept only complete set of PFNs */
> > diff --git a/include/linux/mm.h b/include/linux/mm.h
> > index ef360fe70aaf..d6b8e30dce2e 100644
> > --- a/include/linux/mm.h
> > +++ b/include/linux/mm.h
> > @@ -1765,7 +1765,7 @@ struct frame_vector {
> >   struct frame_vector *frame_vector_create(unsigned int nr_frames);
> >   void frame_vector_destroy(struct frame_vector *vec);
> >   int get_vaddr_frames(unsigned long start, unsigned int nr_pfns,
> > -                  unsigned int gup_flags, struct frame_vector *vec);
> > +                  struct frame_vector *vec);
> >   void put_vaddr_frames(struct frame_vector *vec);
> >   int frame_vector_to_pages(struct frame_vector *vec);
> >   void frame_vector_to_pfns(struct frame_vector *vec);
> > diff --git a/mm/frame_vector.c b/mm/frame_vector.c
> > index 10f82d5643b6..f8c34b895c76 100644
> > --- a/mm/frame_vector.c
> > +++ b/mm/frame_vector.c
> > @@ -32,13 +32,12 @@
> >    * This function takes care of grabbing mmap_lock as necessary.
> >    */
> >   int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
> > -                  unsigned int gup_flags, struct frame_vector *vec)
> > +                  struct frame_vector *vec)
> >   {
> >       struct mm_struct *mm = current->mm;
> >       struct vm_area_struct *vma;
> >       int ret = 0;
> >       int err;
> > -     int locked;
> >
> >       if (nr_frames == 0)
> >               return 0;
> > @@ -48,40 +47,26 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
> >
> >       start = untagged_addr(start);
> >
> > -     mmap_read_lock(mm);
> > -     locked = 1;
> > -     vma = find_vma_intersection(mm, start, start + 1);
> > -     if (!vma) {
> > -             ret = -EFAULT;
> > -             goto out;
> > -     }
> > -
> > -     /*
> > -      * While get_vaddr_frames() could be used for transient (kernel
> > -      * controlled lifetime) pinning of memory pages all current
> > -      * users establish long term (userspace controlled lifetime)
> > -      * page pinning. Treat get_vaddr_frames() like
> > -      * get_user_pages_longterm() and disallow it for filesystem-dax
> > -      * mappings.
> > -      */
> > -     if (vma_is_fsdax(vma)) {
> > -             ret = -EOPNOTSUPP;
> > -             goto out;
> > -     }
> > -
> > -     if (!(vma->vm_flags & (VM_IO | VM_PFNMAP))) {
>
> By removing this check from this location, and changing from
> pin_user_pages_locked() to pin_user_pages_fast(), I *think* we end up
> losing the check entirely. Is that intended? If so it could use a comment
> somewhere to explain why.

Yeah this wasn't intentional. I think I needed to drop the _locked
version to prep for FOLL_LONGTERM, and figured _fast is always better.
But I didn't realize that _fast doesn't have the vma checks, gup.c got
me a bit confused.

I'll remedy this in all the patches where this applies (because a
VM_IO | VM_PFNMAP can point at struct page backed memory, and that
exact use-case is what we want to stop with the unsafe_follow_pfn work
since it wreaks things like cma or security).

Aside: I do wonder whether the lack for that check isn't a problem.
VM_IO | VM_PFNMAP generally means driver managed, which means the
driver isn't going to consult the page pin count or anything like that
(at least not necessarily) when revoking or moving that memory, since
we're assuming it's totally under driver control. So if pup_fast can
get into such a mapping, we might have a problem.
-Daniel

> thanks,
> --
> John Hubbard
> NVIDIA
>
> > +     ret = pin_user_pages_fast(start, nr_frames,
> > +                               FOLL_FORCE | FOLL_WRITE | FOLL_LONGTERM,
> > +                               (struct page **)(vec->ptrs));
> > +     if (ret > 0) {
> >               vec->got_ref = true;
> >               vec->is_pfns = false;
> > -             ret = pin_user_pages_locked(start, nr_frames,
> > -                     gup_flags, (struct page **)(vec->ptrs), &locked);
> > -             goto out;
> > +             goto out_unlocked;
> >       }
> >
> > +     mmap_read_lock(mm);
> >       vec->got_ref = false;
> >       vec->is_pfns = true;
> > +     ret = 0;
> >       do {
> >               unsigned long *nums = frame_vector_pfns(vec);
> >
> > +             vma = find_vma_intersection(mm, start, start + 1);
> > +             if (!vma)
> > +                     break;
> > +
> >               while (ret < nr_frames && start + PAGE_SIZE <= vma->vm_end) {
> >                       err = follow_pfn(vma, start, &nums[ret]);
> >                       if (err) {
> > @@ -92,17 +77,13 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
> >                       start += PAGE_SIZE;
> >                       ret++;
> >               }
> > -             /*
> > -              * We stop if we have enough pages or if VMA doesn't completely
> > -              * cover the tail page.
> > -              */
> > -             if (ret >= nr_frames || start < vma->vm_end)
> > +             /* Bail out if VMA doesn't completely cover the tail page. */
> > +             if (start < vma->vm_end)
> >                       break;
> > -             vma = find_vma_intersection(mm, start, start + 1);
> > -     } while (vma && vma->vm_flags & (VM_IO | VM_PFNMAP));
> > +     } while (ret < nr_frames);
> >   out:
> > -     if (locked)
> > -             mmap_read_unlock(mm);
> > +     mmap_read_unlock(mm);
> > +out_unlocked:
> >       if (!ret)
> >               ret = -EFAULT;
> >       if (ret > 0)
> >
>
>


-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

  reply	other threads:[~2020-10-31 14:45 UTC|newest]

Thread overview: 212+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-30 10:08 [PATCH v5 00/15] follow_pfn and other iomap races Daniel Vetter
2020-10-30 10:08 ` Daniel Vetter
2020-10-30 10:08 ` Daniel Vetter
2020-10-30 10:08 ` [PATCH v5 01/15] drm/exynos: Stop using frame_vector helpers Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08 ` [PATCH v5 02/15] drm/exynos: Use FOLL_LONGTERM for g2d cmdlists Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08 ` [PATCH v5 03/15] misc/habana: Stop using frame_vector helpers Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08 ` [PATCH v5 04/15] misc/habana: Use FOLL_LONGTERM for userptr Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08 ` [PATCH v5 05/15] mm/frame-vector: Use FOLL_LONGTERM Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 14:11   ` Tomasz Figa
2020-10-30 14:11     ` Tomasz Figa
2020-10-30 14:11     ` Tomasz Figa
2020-10-30 14:37     ` Daniel Vetter
2020-10-30 14:37       ` Daniel Vetter
2020-10-30 14:37       ` Daniel Vetter
2020-11-02 18:19       ` Tomasz Figa
2020-11-02 18:19         ` Tomasz Figa
2020-11-02 18:19         ` Tomasz Figa
2020-10-31  2:55   ` John Hubbard
2020-10-31  2:55     ` John Hubbard
2020-10-31  2:55     ` John Hubbard
2020-10-31 14:45     ` Daniel Vetter [this message]
2020-10-31 14:45       ` Daniel Vetter
2020-10-31 14:45       ` Daniel Vetter
2020-11-01  5:22       ` John Hubbard
2020-11-01  5:22         ` John Hubbard
2020-11-01  5:22         ` John Hubbard
2020-11-01 10:30         ` Daniel Vetter
2020-11-01 10:30           ` Daniel Vetter
2020-11-01 10:30           ` Daniel Vetter
2020-11-01 21:13           ` John Hubbard
2020-11-01 21:13             ` John Hubbard
2020-11-01 21:13             ` John Hubbard
2020-11-01 22:50             ` Daniel Vetter
2020-11-01 22:50               ` Daniel Vetter
2020-11-01 22:50               ` Daniel Vetter
2020-11-04 14:00               ` Jason Gunthorpe
2020-11-04 14:00                 ` Jason Gunthorpe
2020-11-04 14:00                 ` Jason Gunthorpe
2020-11-04 15:54                 ` Daniel Vetter
2020-11-04 15:54                   ` Daniel Vetter
2020-11-04 15:54                   ` Daniel Vetter
2020-11-04 16:21                   ` Christoph Hellwig
2020-11-04 16:21                     ` Christoph Hellwig
2020-11-04 16:21                     ` Christoph Hellwig
2020-11-04 16:26                     ` Daniel Vetter
2020-11-04 16:26                       ` Daniel Vetter
2020-11-04 16:26                       ` Daniel Vetter
2020-11-04 16:26                       ` Daniel Vetter
2020-11-04 16:37                       ` Christoph Hellwig
2020-11-04 16:37                         ` Christoph Hellwig
2020-11-04 16:37                         ` Christoph Hellwig
2020-11-04 16:41                         ` Christoph Hellwig
2020-11-04 16:41                           ` Christoph Hellwig
2020-11-04 16:41                           ` Christoph Hellwig
2020-11-04 18:17                           ` Jason Gunthorpe
2020-11-04 18:17                             ` Jason Gunthorpe
2020-11-04 18:17                             ` Jason Gunthorpe
2020-11-04 18:17                             ` Jason Gunthorpe
2020-11-04 18:44                             ` John Hubbard
2020-11-04 18:44                               ` John Hubbard
2020-11-04 18:44                               ` John Hubbard
2020-11-04 18:44                               ` John Hubbard
2020-11-04 19:02                               ` Jason Gunthorpe
2020-11-04 19:02                                 ` Jason Gunthorpe
2020-11-04 19:02                                 ` Jason Gunthorpe
2020-11-04 19:02                                 ` Jason Gunthorpe
2020-11-04 19:11                                 ` Christoph Hellwig
2020-11-04 19:11                                   ` Christoph Hellwig
2020-11-04 19:11                                   ` Christoph Hellwig
2020-11-05  9:25                               ` Daniel Vetter
2020-11-05  9:25                                 ` Daniel Vetter
2020-11-05  9:25                                 ` Daniel Vetter
2020-11-05  9:25                                 ` Daniel Vetter
2020-11-05 12:49                                 ` Jason Gunthorpe
2020-11-05 12:49                                   ` Jason Gunthorpe
2020-11-05 12:49                                   ` Jason Gunthorpe
2020-11-05 12:49                                   ` Jason Gunthorpe
2020-11-06  4:08                                   ` John Hubbard
2020-11-06  4:08                                     ` John Hubbard
2020-11-06  4:08                                     ` John Hubbard
2020-11-06  4:08                                     ` John Hubbard
2020-11-06 10:01                                     ` Daniel Vetter
2020-11-06 10:01                                       ` Daniel Vetter
2020-11-06 10:01                                       ` Daniel Vetter
2020-11-06 10:01                                       ` Daniel Vetter
2020-11-06 10:27                                       ` Daniel Vetter
2020-11-06 10:27                                         ` Daniel Vetter
2020-11-06 10:27                                         ` Daniel Vetter
2020-11-06 10:27                                         ` Daniel Vetter
2020-11-06 12:55                                         ` Jason Gunthorpe
2020-11-06 12:55                                           ` Jason Gunthorpe
2020-11-06 12:55                                           ` Jason Gunthorpe
2020-11-06 12:55                                           ` Jason Gunthorpe
2020-11-09  8:44                                           ` Thomas Hellström
2020-11-09  8:44                                             ` Thomas Hellström
2020-11-09  8:44                                             ` Thomas Hellström
2020-11-09  8:44                                             ` Thomas Hellström
2020-11-09 20:19                                             ` Jason Gunthorpe
2020-11-09 20:19                                               ` Jason Gunthorpe
2020-11-09 20:19                                               ` Jason Gunthorpe
2020-11-09 20:19                                               ` Jason Gunthorpe
2020-11-06 12:58                                       ` Jason Gunthorpe
2020-11-06 12:58                                         ` Jason Gunthorpe
2020-11-06 12:58                                         ` Jason Gunthorpe
2020-11-06 12:58                                         ` Jason Gunthorpe
2020-10-30 10:08 ` [PATCH v5 06/15] media: videobuf2: Move frame_vector into media subsystem Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08 ` [PATCH v5 07/15] mm: Close race in generic_access_phys Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08 ` [PATCH v5 08/15] mm: Add unsafe_follow_pfn Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-11-02  7:29   ` Christoph Hellwig
2020-11-02  7:29     ` Christoph Hellwig
2020-11-02 12:56     ` Daniel Vetter
2020-11-02 12:56       ` Daniel Vetter
2020-11-02 12:56       ` Daniel Vetter
2020-11-02 12:56       ` Daniel Vetter
2020-11-02 13:01       ` Jason Gunthorpe
2020-11-02 13:01         ` Jason Gunthorpe
2020-11-02 13:01         ` Jason Gunthorpe
2020-11-02 13:01         ` Jason Gunthorpe
2020-11-02 13:23         ` Daniel Vetter
2020-11-02 13:23           ` Daniel Vetter
2020-11-02 13:23           ` Daniel Vetter
2020-11-02 13:23           ` Daniel Vetter
2020-11-02 15:52           ` Jason Gunthorpe
2020-11-02 15:52             ` Jason Gunthorpe
2020-11-02 15:52             ` Jason Gunthorpe
2020-11-02 15:52             ` Jason Gunthorpe
2020-11-02 16:41             ` Christoph Hellwig
2020-11-02 16:41               ` Christoph Hellwig
2020-11-02 16:41               ` Christoph Hellwig
2020-11-02 16:42             ` Daniel Vetter
2020-11-02 16:42               ` Daniel Vetter
2020-11-02 16:42               ` Daniel Vetter
2020-11-02 16:42               ` Daniel Vetter
2020-11-02 17:16               ` Jason Gunthorpe
2020-11-02 17:16                 ` Jason Gunthorpe
2020-11-02 17:16                 ` Jason Gunthorpe
2020-11-02 17:16                 ` Jason Gunthorpe
2020-10-30 10:08 ` [PATCH v5 09/15] media/videbuf1|2: Mark follow_pfn usage as unsafe Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08 ` [PATCH v5 10/15] vfio/type1: Mark follow_pfn " Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08 ` [PATCH v5 11/15] PCI: Obey iomem restrictions for procfs mmap Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-11-03 21:28   ` Bjorn Helgaas
2020-11-03 21:28     ` Bjorn Helgaas
2020-11-03 21:28     ` Bjorn Helgaas
2020-11-03 22:09     ` Dan Williams
2020-11-03 22:09       ` Dan Williams
2020-11-03 22:09       ` Dan Williams
2020-11-04  8:44       ` Daniel Vetter
2020-11-04  8:44         ` Daniel Vetter
2020-11-04  8:44         ` Daniel Vetter
2020-11-04 16:50         ` Bjorn Helgaas
2020-11-04 16:50           ` Bjorn Helgaas
2020-11-04 16:50           ` Bjorn Helgaas
2020-11-04 20:12           ` Dan Williams
2020-11-04 20:12             ` Dan Williams
2020-11-04 20:12             ` Dan Williams
2020-11-05  9:34             ` Daniel Vetter
2020-11-05  9:34               ` Daniel Vetter
2020-11-05  9:34               ` Daniel Vetter
2020-10-30 10:08 ` [PATCH v5 12/15] /dev/mem: Only set filp->f_mapping Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08 ` [PATCH v5 13/15] resource: Move devmem revoke code to resource framework Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-31  6:36   ` John Hubbard
2020-10-31  6:36     ` John Hubbard
2020-10-31  6:36     ` John Hubbard
2020-10-31 14:40     ` Daniel Vetter
2020-10-31 14:40       ` Daniel Vetter
2020-10-31 14:40       ` Daniel Vetter
2020-11-03  6:06   ` [resource] 22b17dc667: Kernel panic - not syncing: Fatal exception lkp
2020-11-03  6:06     ` lkp
2020-11-03  6:15     ` John Hubbard
2020-11-03  6:15       ` John Hubbard
2020-11-03  6:15       ` John Hubbard
2020-11-03 10:10       ` Daniel Vetter
2020-11-03 10:10         ` Daniel Vetter
2020-11-03 10:10         ` Daniel Vetter
2020-10-30 10:08 ` [PATCH v5 14/15] sysfs: Support zapping of binary attr mmaps Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08 ` [PATCH v5 15/15] PCI: Revoke mappings like devmem Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 10:08   ` Daniel Vetter
2020-10-30 19:22   ` Dan Williams
2020-10-30 19:22     ` Dan Williams
2020-10-30 19:22     ` Dan Williams
2020-11-03 21:30   ` Bjorn Helgaas
2020-11-03 21:30     ` Bjorn Helgaas
2020-11-03 21:30     ` Bjorn Helgaas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAKMK7uGDW2f0oOvwgryCHxQFHyh3Tsk6ENsMGmtZ-EnH57tMSA@mail.gmail.com \
    --to=daniel.vetter@ffwll.ch \
    --cc=akpm@linux-foundation.org \
    --cc=dan.j.williams@intel.com \
    --cc=daniel.vetter@intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=jack@suse.cz \
    --cc=jgg@ziepe.ca \
    --cc=jglisse@redhat.com \
    --cc=jhubbard@nvidia.com \
    --cc=kvm@vger.kernel.org \
    --cc=kyungmin.park@samsung.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=linux-samsung-soc@vger.kernel.org \
    --cc=m.szyprowski@samsung.com \
    --cc=mchehab@kernel.org \
    --cc=pawel@osciak.com \
    --cc=tfiga@chromium.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.