lkml.org 
[lkml]   [2022]   [Feb]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 1/6] mm/gup: introduce pin_user_page()
    Date
    From: John Hubbard <jhubbard@nvidia.com>

    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@nvidia.com>
    ---
    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 c9bada4096ac..367d7fd28fd0 100644
    --- a/include/linux/mm.h
    +++ b/include/linux/mm.h
    @@ -1946,6 +1946,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 428c587acfa2..13c0dced2aee 100644
    --- a/mm/gup.c
    +++ b/mm/gup.c
    @@ -3035,6 +3035,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
    --
    2.35.1
    \
     
     \ /
      Last update: 2022-02-27 10:35    [W:2.330 / U:1.152 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site