On 8/8/19 8:21 AM, Michal Hocko wrote: > On Wed 07-08-19 16:32:08, John Hubbard wrote: >> On 8/7/19 4:01 AM, Michal Hocko wrote: >>> On Mon 05-08-19 15:20:17, john.hubbard@xxxxxxxxx wrote: >>>> From: John Hubbard <jhubbard@xxxxxxxxxx> >>>> >>>> For pages that were retained via get_user_pages*(), release those pages >>>> via the new put_user_page*() routines, instead of via put_page() or >>>> release_pages(). >>> >>> Hmm, this is an interesting code path. There seems to be a mix of pages >>> in the game. We get one page via follow_page_mask but then other pages >>> in the range are filled by __munlock_pagevec_fill and that does a direct >>> pte walk. Is using put_user_page correct in this case? Could you explain >>> why in the changelog? >>> >> >> Actually, I think follow_page_mask() gets all the pages, right? And the >> get_page() in __munlock_pagevec_fill() is there to allow a pagevec_release() >> later. > > Maybe I am misreading the code (looking at Linus tree) but munlock_vma_pages_range > calls follow_page for the start address and then if not THP tries to > fill up the pagevec with few more pages (up to end), do the shortcut > via manual pte walk as an optimization and use generic get_page there. That's true. However, I'm not sure munlocking is where the put_user_page() machinery is intended to be used anyway? These are short-term pins for struct page manipulation, not e.g. dirtying of page contents. Reading commit fc1d8e7cca2d I don't think this case falls within the reasoning there. Perhaps not all GUP users should be converted to the planned separate GUP tracking, and instead we should have a GUP/follow_page_mask() variant that keeps using get_page/put_page?