linuxmemorylinux-kernelreference-countinglru

Can the pages obtained by get_user_pages() be directly recycled or swapped out without using put_user_pages()?


get_user_pages() increments the page reference count. And that is why it can pin the page in memory.

So I wonder whether the pages obtained by get_user_pages() can be directly recycled or swapped out without using put_user_pages()? Because the operating system's LRU mechanism automatically maintains page reference counts.

If can't, does that mean that pages allocated by get_user_pages() have to be reduced in reference count by put_user_pages() before they can be reclaimed or swapped out by a series of LRU operations?


Solution

  • NOTE: it seems like since v5.6 get_user_pages() and put_user_pages() were replaced with pin_user_pages() and unpin_user_pages(). You should probably use those instead.


    After get_user_pages(), pages definitely cannot be swapped out. They are pinned in memory and mapped into kernel virtual memory for kernel code to be able to access them. Swapping can only happen after put_user_pages().

    However, they can be unmapped from the original task that was holding them and re-used for something else (I assume this is what you mean by "reclaimed"). This is also stated in the docstring for get_user_pages_remote() here:

    /**
     * get_user_pages_remote() - pin user pages in memory
     * [...]
     *
     * This does not guarantee that the page exists in the user mappings when
     * get_user_pages_remote 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.
     *
     * [...]
     */