The patch titled Subject: mm/gup: introduce pin_user_page() has been added to the -mm mm-unstable branch. Its filename is mm-gup-introduce-pin_user_page.patch This patch will shortly appear at https://git.kernel.org/pub/scm/linux/kernel/git/akpm/25-new.git/tree/patches/mm-gup-introduce-pin_user_page.patch This patch will later appear in the mm-unstable branch at git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm Before you just go and hit "reply", please: a) Consider who else should be cc'ed b) Prefer to cc a suitable mailing list as well c) Ideally: find the original patch on the mailing list and do a reply-to-all to that, adding suitable additional cc's *** Remember to use Documentation/process/submit-checklist.rst when testing your code *** The -mm tree is included into linux-next via the mm-everything branch at git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm and is updated there every 2-3 working days ------------------------------------------------------ From: John Hubbard <jhubbard@xxxxxxxxxx> Subject: mm/gup: introduce pin_user_page() Date: Tue, 30 Aug 2022 21:18:38 -0700 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 using FOLL_PIN rules. This means that the caller must release the page via unpin_user_page(). Link: https://lkml.kernel.org/r/20220831041843.973026-3-jhubbard@xxxxxxxxxx Signed-off-by: John Hubbard <jhubbard@xxxxxxxxxx> Cc: Alexander Viro <viro@xxxxxxxxxxxxxxxxxx> Cc: Anna Schumaker <anna@xxxxxxxxxx> Cc: Christoph Hellwig <hch@xxxxxxxxxxxxx> Cc: Darrick J. Wong <djwong@xxxxxxxxxx> Cc: David Hildenbrand <david@xxxxxxxxxx> Cc: Jan Kara <jack@xxxxxxx> Cc: Jens Axboe <axboe@xxxxxxxxx> Cc: Logan Gunthorpe <logang@xxxxxxxxxxxx> Cc: Miklos Szeredi <miklos@xxxxxxxxxx> Cc: Trond Myklebust <trond.myklebust@xxxxxxxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- include/linux/mm.h | 1 mm/gup.c | 50 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) --- a/include/linux/mm.h~mm-gup-introduce-pin_user_page +++ a/include/linux/mm.h @@ -1943,6 +1943,7 @@ long pin_user_pages_remote(struct mm_str 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); --- a/mm/gup.c~mm-gup-introduce-pin_user_page +++ a/mm/gup.c @@ -3240,6 +3240,56 @@ long pin_user_pages(unsigned long start, } EXPORT_SYMBOL(pin_user_pages); +/** + * pin_user_page() - apply a FOLL_PIN reference to a file-backed page that the + * caller already owns. + * + * @page: the page to be pinned. + * + * pin_user_page() elevates a page's refcount using FOLL_PIN rules. This means + * that the caller must release the page via unpin_user_page(). + * + * pin_user_page() is intended as a drop-in replacement for get_page(). This + * provides a way for callers to do a subsequent unpin_user_page() on the + * affected page. However, it is only intended for use by callers (file systems, + * block/bio) that have a file-backed page. Anonymous pages are not expected nor + * supported, and will generate a warning. + * + * pin_user_page() may also be thought of as 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(). + * + * IMPORTANT: 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); + + /* + * This function is only intended for file-backed callers, who already + * have a page reference. + */ + WARN_ON_ONCE(PageAnon(page)); + + /* + * 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 _ Patches currently in -mm which might be from jhubbard@xxxxxxxxxx are mm-change-release_pages-to-use-unsigned-long-for-npages.patch mm-gup-introduce-pin_user_page.patch block-add-dio_w_-wrappers-for-pin-unpin-user-pages.patch iov_iter-new-iov_iter_pin_pages-routines.patch block-bio-fs-convert-most-filesystems-to-pin_user_pages_fast.patch nfs-direct-io-convert-to-foll_pin-pages.patch fuse-convert-direct-io-paths-to-use-foll_pin.patch