On 2/10/21 11:19 PM, John Hubbard wrote: > On 2/5/21 12:41 PM, Joao Martins wrote: >> Add a unpin_user_page_range_dirty_lock() API which takes a starting page >> and how many consecutive pages we want to unpin and optionally dirty. >> >> To that end, define another iterator for_each_compound_range() >> that operates in page ranges as opposed to page array. >> >> For users (like RDMA mr_dereg) where each sg represents a >> contiguous set of pages, we're able to more efficiently unpin >> pages without having to supply an array of pages much of what >> happens today with unpin_user_pages(). >> >> Suggested-by: Jason Gunthorpe <jgg@xxxxxxxxxx> >> Signed-off-by: Joao Martins <joao.m.martins@xxxxxxxxxx> >> --- >> include/linux/mm.h | 2 ++ >> mm/gup.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++ >> 2 files changed, 64 insertions(+) >> >> diff --git a/include/linux/mm.h b/include/linux/mm.h >> index a608feb0d42e..b76063f7f18a 100644 >> --- a/include/linux/mm.h >> +++ b/include/linux/mm.h >> @@ -1265,6 +1265,8 @@ static inline void put_page(struct page *page) >> void unpin_user_page(struct page *page); >> void unpin_user_pages_dirty_lock(struct page **pages, unsigned long npages, >> bool make_dirty); >> +void unpin_user_page_range_dirty_lock(struct page *page, unsigned long npages, >> + bool make_dirty); >> void unpin_user_pages(struct page **pages, unsigned long npages); >> >> /** >> diff --git a/mm/gup.c b/mm/gup.c >> index 467a11df216d..938964d31494 100644 >> --- a/mm/gup.c >> +++ b/mm/gup.c >> @@ -215,6 +215,32 @@ void unpin_user_page(struct page *page) >> } >> EXPORT_SYMBOL(unpin_user_page); >> >> +static inline void compound_range_next(unsigned long i, unsigned long npages, >> + struct page **list, struct page **head, >> + unsigned int *ntails) > > Yes, the new names look good, and I have failed to find any logic errors, so: > > Reviewed-by: John Hubbard <jhubbard@xxxxxxxxxx> > Thanks again for all the input!