__get_user_pages(9)
β¨ __get_user_pages β the high-key iconic guide to pinning user pages in memory β¨
okay so bestie, you found the Linux kernel API manual page for __get_user_pages(9)?? literally the main character of memory pinning fr fr. this is a #LongHeader moment, let's get into it π
πΈ NAME πΈ
__get_user_pages β pin user pages in memory (like, actually pin them, bestie π)
β¨ SYNOPSIS β¨
long __get_user_pages (struct mm_struct *mm , unsigned long start ,
unsigned long nr_pages , unsigned int gup_flags , struct page **pages ,
int *locked );
π ARGUMENTS π
mmβ themm_structof the target mm. like, whose memory are we even talking about? this is the vibes source π«Άstartβ the starting user address. where the plot begins, no cap.nr_pagesβ number of pages fromstartto pin. how many we're grabbing, periodt πgup_flagsβ flags modifying pin behaviour. the ~spice~ of how it all goes down π₯pagesβ array that receives pointers to the pages pinned. Should be at leastnr_pageslong. OrNULL, if caller only intends to ensure the pages are faulted in. (so like, the "receipts" array β fill it up, or passNULLif you're just here for the fault-in vibes π)lockedβ whether we're still with themmap_lockheld. honestly same, bestie, same.
π¦ DESCRIPTION π¦
okay so here's the tea: this function Returns either the number of pages pinned (which may be less than the number requested), or an error. Details about the return value are literally giving:
- If
nr_pagesis0, returns0. - If
nr_pagesis>0, but no pages were pinned, returns-errno. - If
nr_pagesis>0, and some pages were pinned, returns the number of pages pinned. Again, this may be less thannr_pages. 0return value is possible when the fault would need to be retried.
The caller is responsible for releasing returned pages, via put_page. yes bestie, you gotta clean up your own mess, we don't leave pins hanging π
Must be called with mmap_lock held. It may be released. See below. (the plot thickens π)
__get_user_pages walks a process's page tables and takes a reference to each struct page that each user address corresponds to at a given instant. That is, it takes the page that would be accessed if a user thread accesses the given user virtual address at that instant. (so like, it's a little snapshot moment in time, iykyk β)
This does not guarantee that the page exists in the user mappings when __get_user_pages returns, and there may even be a completely different page there in some cases (eg. if mmapped pagecache has been invalidated and subsequently re-faulted). However it does guarantee that the page won't be freed completely. And mostly callers simply care that the page contains data that was valid at some point in time. Typically, an IO or similar operation cannot guarantee anything stronger anyway because locks can't be held over the syscall boundary. (so like, it's giving "best effort", not "lifetime guarantee" π)
If gup_flags & FOLL_WRITE == 0, the page must not be written to. If the page is written to, set_page_dirty (or set_page_dirty_lock, as appropriate) must be called after the page is finished with, and before put_page is called. (read-only pin gang, stay in your lane, or like, call the right dirty function π«Ά)
If FOLL_UNLOCKABLE is set without FOLL_NOWAIT then the mmap_lock may be released. If this happens *locked will be set to 0 on return. (the lock said "bye" and you gotta recognize π)
A caller using such a combination of gup_flags must therefore hold the mmap_lock for reading only, and recognize when it's been released. Otherwise, it must be held for either reading or writing and will not be released. (like, either you're in the "might release" club or the "definitely holding" club β no in-between β¨)
In most cases, get_user_pages or get_user_pages_fast should be used instead of __get_user_pages. __get_user_pages should be used only if you need some special gup_flags. (ngl unless you're doing something β¨spicyβ¨, use the other ones, they're giving convenience π)
π SEE ALSO π
okay so if you liked this one (you didn't, but like, slay for reading it π«Ά), here's the whole friend group you should also check out:
- Kernel file
./mm/gup.c try_grab_folio(9)β my belovedunpin_user_page(9)β the cleanup crewunpin_folio(9)β its folio-sized siblingfolio_add_pin(9)β +1 pin, literallyunpin_user_pages_dirty_lock(9)β the dramatic exit with dirty lockunpin_user_page_range_dirty_lock(9)β the range version, extraunpin_user_pages(9)β plural slayunpin_user_folio(9)β singular folio slayunpin_folios(9)β folio army, periodttry_grab_folio_fast(9)β the fast lane, no capfollow_page_mask(9)β the ogfixup_user_fault(9)β the fixerpopulate_vma_page_range(9)β the populatorfault_in_writeable(9)β writeable fault-in, yesfault_in_subpage_writeable(9)β subpage version, sneakierfault_in_readable(9)β readable fault-inget_dump_page(9)β for the dumping momentsget_user_pages_remote(9)β remote vibesget_user_pages(9)β the classicget_user_pages_fast_only(9)β fast but ONLY fastget_user_pages_fast(9)β fast & furiouspin_user_pages_fast(9)β pin + fast, double threatpin_user_pages_remote(9)β pin + remotepin_user_pages(9)β pin, classicmemfd_pin_folios(9)β the memfd onefolio_add_pins(9)β pins, plural, go off
bestie if you're still here, you're a real one. this manpage is part of the Kernel API Manual and comes from the ./mm source, dated October 2026. go touch some pages (safely, with mmap_lock held π«Ά). stay slay, stay pinned. π
β written by your unix-obsessed bestie, for the group chat π©·
π¦ where this page comes from
- nixpkgs unstable: linux-manual 7.3.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms