On 25.02.22 09:50, John Hubbard wrote: > pin_user_page() is an externally-usable version of try_grab_page(), but > with semantics that match get_page(), so that it can act as a drop-in > replacement for get_page(). Specifically, pin_user_page() has a void > return type. > > pin_user_page() elevates a page's refcount is using FOLL_PIN rules. This > means that the caller must release the page via unpin_user_page(). > > Signed-off-by: John Hubbard <jhubbard@xxxxxxxxxx> > --- > include/linux/mm.h | 1 + > mm/gup.c | 34 ++++++++++++++++++++++++++++++++++ > 2 files changed, 35 insertions(+) > > diff --git a/include/linux/mm.h b/include/linux/mm.h > index 929488a47181..bb51f5487aef 100644 > --- a/include/linux/mm.h > +++ b/include/linux/mm.h > @@ -1914,6 +1914,7 @@ long pin_user_pages_remote(struct mm_struct *mm, > long get_user_pages(unsigned long start, unsigned long nr_pages, > unsigned int gup_flags, struct page **pages, > struct vm_area_struct **vmas); > +void pin_user_page(struct page *page); > long pin_user_pages(unsigned long start, unsigned long nr_pages, > unsigned int gup_flags, struct page **pages, > struct vm_area_struct **vmas); > diff --git a/mm/gup.c b/mm/gup.c > index 5c3f6ede17eb..44446241c3a9 100644 > --- a/mm/gup.c > +++ b/mm/gup.c > @@ -3034,6 +3034,40 @@ long pin_user_pages(unsigned long start, unsigned long nr_pages, > } > EXPORT_SYMBOL(pin_user_pages); > > +/** > + * pin_user_page() - apply a FOLL_PIN reference to a page () > + * > + * @page: the page to be pinned. > + * > + * Similar to get_user_pages(), in that the page's refcount is elevated using > + * FOLL_PIN rules. > + * > + * IMPORTANT: That means that the caller must release the page via > + * unpin_user_page(). > + * > + */ > +void pin_user_page(struct page *page) > +{ > + struct folio *folio = page_folio(page); > + > + WARN_ON_ONCE(folio_ref_count(folio) <= 0); > + > + /* > + * Similar to try_grab_page(): be sure to *also* > + * increment the normal page refcount field at least once, > + * so that the page really is pinned. > + */ > + if (folio_test_large(folio)) { > + folio_ref_add(folio, 1); > + atomic_add(1, folio_pincount_ptr(folio)); > + } else { > + folio_ref_add(folio, GUP_PIN_COUNTING_BIAS); > + } > + > + node_stat_mod_folio(folio, NR_FOLL_PIN_ACQUIRED, 1); > +} > +EXPORT_SYMBOL(pin_user_page); > + > /* > * pin_user_pages_unlocked() is the FOLL_PIN variant of > * get_user_pages_unlocked(). Behavior is the same, except that this one sets I assume that function will only get called on a page that has been obtained by a previous pin_user_pages_fast(), correct? -- Thanks, David / dhildenb