€•Œsphinx.addnodes”Œdocument”“”)�”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)�”}”(hhh]”(hŒ pending_xref”“”)�”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…”�”}”Œparent”hsbaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ$/translations/zh_CN/mm/process_addrs”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)�”}”(hhh]”hŒChinese (Traditional)”…”�”}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ$/translations/zh_TW/mm/process_addrs”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒItalian”…”�”}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ$/translations/it_IT/mm/process_addrs”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒJapanese”…”�”}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ$/translations/ja_JP/mm/process_addrs”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒKorean”…”�”}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ$/translations/ko_KR/mm/process_addrs”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒPortuguese (Brazilian)”…”�”}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ$/translations/pt_BR/mm/process_addrs”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)�”}”(hhh]”hŒSpanish”…”�”}”hh–sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ$/translations/sp_SP/mm/process_addrs”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒcomment”“”)�”}”(hŒ SPDX-License-Identifier: GPL-2.0”h]”hŒ SPDX-License-Identifier: GPL-2.0”…”�”}”hh·sbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1hµhhh²hh³Œ>/var/lib/git/docbuild/linux/Documentation/mm/process_addrs.rst”h´KubhŒsection”“”)�”}”(hhh]”(hŒtitle”“”)�”}”(hŒProcess Addresses”h]”hŒProcess Addresses”…”�”}”(hhÏh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhhÊh²hh³hÇh´KubhŒcompound”“”)�”}”(hhh]”hŒtoctree”“”)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”hŒmm/process_addrs”Œentries”]”Œ includefiles”]”Œmaxdepth”KŒcaption”NŒglob”‰Œhidden”‰Œ includehidden”‰Œnumbered”KŒ titlesonly”‰Œ rawentries”]”uh1hâh³hÇh´Khhßubah}”(h]”h ]”Œtoctree-wrapper”ah"]”h$]”h&]”uh1hÝhhÊh²hh³hÇh´NubhŒ paragraph”“”)�”}”(hŒUserland memory ranges are tracked by the kernel via Virtual Memory Areas or 'VMA's of type :c:struct:`!struct vm_area_struct`.”h]”(hŒ`Userland memory ranges are tracked by the kernel via Virtual Memory Areas or ‘VMA’s of type ”…”�”}”(hjh²hh³Nh´NubhŒliteral”“”)�”}”(hŒ":c:struct:`!struct vm_area_struct`”h]”hŒstruct vm_area_struct”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”(Œxref”Œc”Œc-struct”eh"]”h$]”h&]”uh1j hjubhŒ.”…”�”}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K hhÊh²hubj)�”}”(hXEach VMA describes a virtually contiguous memory range with identical attributes, each described by a :c:struct:`!struct vm_area_struct` object. Userland access outside of VMAs is invalid except in the case where an adjacent stack VMA could be extended to contain the accessed address.”h]”(hŒfEach VMA describes a virtually contiguous memory range with identical attributes, each described by a ”…”�”}”(hj)h²hh³Nh´Nubj )�”}”(hŒ":c:struct:`!struct vm_area_struct`”h]”hŒstruct vm_area_struct”…”�”}”(hj1h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-struct”eh"]”h$]”h&]”uh1j hj)ubhŒ• object. Userland access outside of VMAs is invalid except in the case where an adjacent stack VMA could be extended to contain the accessed address.”…”�”}”(hj)h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KhhÊh²hubj)�”}”(hŒýAll VMAs are contained within one and only one virtual address space, described by a :c:struct:`!struct mm_struct` object which is referenced by all tasks (that is, threads) which share the virtual address space. We refer to this as the :c:struct:`!mm`.”h]”(hŒUAll VMAs are contained within one and only one virtual address space, described by a ”…”�”}”(hjJh²hh³Nh´Nubj )�”}”(hŒ:c:struct:`!struct mm_struct`”h]”hŒstruct mm_struct”…”�”}”(hjRh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-struct”eh"]”h$]”h&]”uh1j hjJubhŒ{ object which is referenced by all tasks (that is, threads) which share the virtual address space. We refer to this as the ”…”�”}”(hjJh²hh³Nh´Nubj )�”}”(hŒ:c:struct:`!mm`”h]”hŒmm”…”�”}”(hjeh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-struct”eh"]”h$]”h&]”uh1j hjJubhŒ.”…”�”}”(hjJh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KhhÊh²hubj)�”}”(hŒnEach mm object contains a maple tree data structure which describes all VMAs within the virtual address space.”h]”hŒnEach mm object contains a maple tree data structure which describes all VMAs within the virtual address space.”…”�”}”(hj~h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KhhÊh²hubhŒnote”“”)�”}”(hŒ±An exception to this is the 'gate' VMA which is provided by architectures which use :c:struct:`!vsyscall` and is a global static object which does not belong to any specific mm.”h]”j)�”}”(hŒ±An exception to this is the 'gate' VMA which is provided by architectures which use :c:struct:`!vsyscall` and is a global static object which does not belong to any specific mm.”h]”(hŒXAn exception to this is the ‘gate’ VMA which is provided by architectures which use ”…”�”}”(hj’h²hh³Nh´Nubj )�”}”(hŒ:c:struct:`!vsyscall`”h]”hŒvsyscall”…”�”}”(hjšh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-struct”eh"]”h$]”h&]”uh1j hj’ubhŒH and is a global static object which does not belong to any specific mm.”…”�”}”(hj’h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KhjŽubah}”(h]”h ]”h"]”h$]”h&]”uh1jŒhhÊh²hh³hÇh´NubhÉ)�”}”(hhh]”(hÎ)�”}”(hŒLocking”h]”hŒLocking”…”�”}”(hj¼h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj¹h²hh³hÇh´K!ubj)�”}”(hŒºThe kernel is designed to be highly scalable against concurrent read operations on VMA **metadata** so a complicated set of locks are required to ensure memory corruption does not occur.”h]”(hŒWThe kernel is designed to be highly scalable against concurrent read operations on VMA ”…”�”}”(hjÊh²hh³Nh´NubhŒstrong”“”)�”}”(hŒ **metadata**”h]”hŒmetadata”…”�”}”(hjÔh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjÊubhŒW so a complicated set of locks are required to ensure memory corruption does not occur.”…”�”}”(hjÊh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K#hj¹h²hubj�)�”}”(hŒwLocking VMAs for their metadata does not have any impact on the memory they describe nor the page tables that map them.”h]”j)�”}”(hŒwLocking VMAs for their metadata does not have any impact on the memory they describe nor the page tables that map them.”h]”hŒwLocking VMAs for their metadata does not have any impact on the memory they describe nor the page tables that map them.”…”�”}”(hjðh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K'hjìubah}”(h]”h ]”h"]”h$]”h&]”uh1jŒhj¹h²hh³hÇh´NubhÉ)�”}”(hhh]”(hÎ)�”}”(hŒ Terminology”h]”hŒ Terminology”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjh²hh³hÇh´K+ubhŒ bullet_list”“”)�”}”(hhh]”(hŒ list_item”“”)�”}”(hŒÛ**mmap locks** - Each MM has a read/write semaphore :c:member:`!mmap_lock` which locks at a process address space granularity which can be acquired via :c:func:`!mmap_read_lock`, :c:func:`!mmap_write_lock` and variants.”h]”j)�”}”(hŒÛ**mmap locks** - Each MM has a read/write semaphore :c:member:`!mmap_lock` which locks at a process address space granularity which can be acquired via :c:func:`!mmap_read_lock`, :c:func:`!mmap_write_lock` and variants.”h]”(jÓ)�”}”(hŒ**mmap locks**”h]”hŒ mmap locks”…”�”}”(hj$h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhj ubhŒ& - Each MM has a read/write semaphore ”…”�”}”(hj h²hh³Nh´Nubj )�”}”(hŒ:c:member:`!mmap_lock`”h]”hŒ mmap_lock”…”�”}”(hj6h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hj ubhŒN which locks at a process address space granularity which can be acquired via ”…”�”}”(hj h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!mmap_read_lock`”h]”hŒmmap_read_lock()”…”�”}”(hjIh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj ubhŒ, ”…”�”}”(hj h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!mmap_write_lock`”h]”hŒmmap_write_lock()”…”�”}”(hj\h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj ubhŒ and variants.”…”�”}”(hj h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K-hjubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjh²hh³hÇh´Nubj)�”}”(hXÓ**VMA locks** - The VMA lock is at VMA granularity (of course) which behaves as a read/write semaphore in practice. A VMA read lock is obtained via :c:func:`!lock_vma_under_rcu` (and unlocked via :c:func:`!vma_end_read`) and a write lock via vma_start_write() or vma_start_write_killable() (all VMA write locks are unlocked automatically when the mmap write lock is released). To take a VMA write lock you **must** have already acquired an :c:func:`!mmap_write_lock`.”h]”j)�”}”(hXÓ**VMA locks** - The VMA lock is at VMA granularity (of course) which behaves as a read/write semaphore in practice. A VMA read lock is obtained via :c:func:`!lock_vma_under_rcu` (and unlocked via :c:func:`!vma_end_read`) and a write lock via vma_start_write() or vma_start_write_killable() (all VMA write locks are unlocked automatically when the mmap write lock is released). To take a VMA write lock you **must** have already acquired an :c:func:`!mmap_write_lock`.”h]”(jÓ)�”}”(hŒ **VMA locks**”h]”hŒ VMA locks”…”�”}”(hjƒh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjubhŒ‡ - The VMA lock is at VMA granularity (of course) which behaves as a read/write semaphore in practice. A VMA read lock is obtained via ”…”�”}”(hjh²hh³Nh´Nubj )�”}”(hŒ:c:func:`!lock_vma_under_rcu`”h]”hŒlock_vma_under_rcu()”…”�”}”(hj•h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjubhŒ (and unlocked via ”…”�”}”(hjh²hh³Nh´Nubj )�”}”(hŒ:c:func:`!vma_end_read`”h]”hŒvma_end_read()”…”�”}”(hj¨h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjubhŒ») and a write lock via vma_start_write() or vma_start_write_killable() (all VMA write locks are unlocked automatically when the mmap write lock is released). To take a VMA write lock you ”…”�”}”(hjh²hh³Nh´NubjÓ)�”}”(hŒ**must**”h]”hŒmust”…”�”}”(hj»h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjubhŒ have already acquired an ”…”�”}”(hjh²hh³Nh´Nubj )�”}”(hŒ:c:func:`!mmap_write_lock`”h]”hŒmmap_write_lock()”…”�”}”(hjÍh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjubhŒ.”…”�”}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K0hj{ubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjh²hh³hÇh´Nubj)�”}”(hX**rmap locks** - When trying to access VMAs through the reverse mapping via a :c:struct:`!struct address_space` or :c:struct:`!struct anon_vma` object (reachable from a folio via :c:member:`!folio->mapping`). VMAs must be stabilised via :c:func:`!anon_vma_[try]lock_read` or :c:func:`!anon_vma_[try]lock_write` for anonymous memory and :c:func:`!i_mmap_[try]lock_read` or :c:func:`!i_mmap_[try]lock_write` for file-backed memory. We refer to these locks as the reverse mapping locks, or 'rmap locks' for brevity. ”h]”j)�”}”(hX**rmap locks** - When trying to access VMAs through the reverse mapping via a :c:struct:`!struct address_space` or :c:struct:`!struct anon_vma` object (reachable from a folio via :c:member:`!folio->mapping`). VMAs must be stabilised via :c:func:`!anon_vma_[try]lock_read` or :c:func:`!anon_vma_[try]lock_write` for anonymous memory and :c:func:`!i_mmap_[try]lock_read` or :c:func:`!i_mmap_[try]lock_write` for file-backed memory. We refer to these locks as the reverse mapping locks, or 'rmap locks' for brevity.”h]”(jÓ)�”}”(hŒ**rmap locks**”h]”hŒ rmap locks”…”�”}”(hjôh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjðubhŒ@ - When trying to access VMAs through the reverse mapping via a ”…”�”}”(hjðh²hh³Nh´Nubj )�”}”(hŒ!:c:struct:`!struct address_space`”h]”hŒstruct address_space”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-struct”eh"]”h$]”h&]”uh1j hjðubhŒ or ”…”�”}”(hjðh²hh³Nh´Nubj )�”}”(hŒ:c:struct:`!struct anon_vma`”h]”hŒstruct anon_vma”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-struct”eh"]”h$]”h&]”uh1j hjðubhŒ$ object (reachable from a folio via ”…”�”}”(hjðh²hh³Nh´Nubj )�”}”(hŒ:c:member:`!folio->mapping`”h]”hŒfolio->mapping”…”�”}”(hj,h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hjðubhŒ). VMAs must be stabilised via ”…”�”}”(hjðh²hh³Nh´Nubj )�”}”(hŒ":c:func:`!anon_vma_[try]lock_read`”h]”hŒanon_vma_[try]lock_read()”…”�”}”(hj?h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjðubhŒ or ”…”�”}”hjðsbj )�”}”(hŒ#:c:func:`!anon_vma_[try]lock_write`”h]”hŒanon_vma_[try]lock_write()”…”�”}”(hjRh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjðubhŒ for anonymous memory and ”…”�”}”(hjðh²hh³Nh´Nubj )�”}”(hŒ :c:func:`!i_mmap_[try]lock_read`”h]”hŒi_mmap_[try]lock_read()”…”�”}”(hjeh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjðubhŒ or ”…”�”}”(hjðh²hh³Nh´Nubj )�”}”(hŒ!:c:func:`!i_mmap_[try]lock_write`”h]”hŒi_mmap_[try]lock_write()”…”�”}”(hjxh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjðubhŒo for file-backed memory. We refer to these locks as the reverse mapping locks, or ‘rmap locks’ for brevity.”…”�”}”(hjðh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K7hjìubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjh²hh³hÇh´Nubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ*”uh1jh³hÇh´K-hjh²hubj)�”}”(hŒFWe discuss page table locks separately in the dedicated section below.”h]”hŒFWe discuss page table locks separately in the dedicated section below.”…”�”}”(hjŸh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K?hjh²hubj)�”}”(hŒëThe first thing **any** of these locks achieve is to **stabilise** the VMA within the MM tree. That is, guaranteeing that the VMA object will not be deleted from under you nor modified (except for some specific fields described below).”h]”(hŒThe first thing ”…”�”}”(hj­h²hh³Nh´NubjÓ)�”}”(hŒ**any**”h]”hŒany”…”�”}”(hjµh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhj­ubhŒ of these locks achieve is to ”…”�”}”(hj­h²hh³Nh´NubjÓ)�”}”(hŒ **stabilise**”h]”hŒ stabilise”…”�”}”(hjÇh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhj­ubhŒ© the VMA within the MM tree. That is, guaranteeing that the VMA object will not be deleted from under you nor modified (except for some specific fields described below).”…”�”}”(hj­h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KAhjh²hubj)�”}”(hŒFStabilising a VMA also keeps the address space described by it around.”h]”hŒFStabilising a VMA also keeps the address space described by it around.”…”�”}”(hjßh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KFhjh²hubeh}”(h]”Œ terminology”ah ]”h"]”Œ terminology”ah$]”h&]”uh1hÈhj¹h²hh³hÇh´K+ubhÉ)�”}”(hhh]”(hÎ)�”}”(hŒ Lock usage”h]”hŒ Lock usage”…”�”}”(hjøh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjõh²hh³hÇh´KIubj)�”}”(hŒjIf you want to **read** VMA metadata fields or just keep the VMA stable, you must do one of the following:”h]”(hŒIf you want to ”…”�”}”(hjh²hh³Nh´NubjÓ)�”}”(hŒ**read**”h]”hŒread”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjubhŒS VMA metadata fields or just keep the VMA stable, you must do one of the following:”…”�”}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KKhjõh²hubj)�”}”(hhh]”(j)�”}”(hŒÂObtain an mmap read lock at the MM granularity via :c:func:`!mmap_read_lock` (or a suitable variant), unlocking it with a matching :c:func:`!mmap_read_unlock` when you're done with the VMA, *or*”h]”j)�”}”(hŒÂObtain an mmap read lock at the MM granularity via :c:func:`!mmap_read_lock` (or a suitable variant), unlocking it with a matching :c:func:`!mmap_read_unlock` when you're done with the VMA, *or*”h]”(hŒ3Obtain an mmap read lock at the MM granularity via ”…”�”}”(hj-h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!mmap_read_lock`”h]”hŒmmap_read_lock()”…”�”}”(hj5h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj-ubhŒ7 (or a suitable variant), unlocking it with a matching ”…”�”}”(hj-h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!mmap_read_unlock`”h]”hŒmmap_read_unlock()”…”�”}”(hjHh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj-ubhŒ" when you’re done with the VMA, ”…”�”}”(hj-h²hh³Nh´NubhŒemphasis”“”)�”}”(hŒ*or*”h]”hŒor”…”�”}”(hj]h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j[hj-ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KNhj)ubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj&h²hh³hÇh´Nubj)�”}”(hŒîTry to obtain a VMA read lock via :c:func:`!lock_vma_under_rcu`. This tries to acquire the lock atomically so might fail, in which case fall-back logic is required to instead obtain an mmap read lock if this returns :c:macro:`!NULL`, *or*”h]”j)�”}”(hŒîTry to obtain a VMA read lock via :c:func:`!lock_vma_under_rcu`. This tries to acquire the lock atomically so might fail, in which case fall-back logic is required to instead obtain an mmap read lock if this returns :c:macro:`!NULL`, *or*”h]”(hŒ"Try to obtain a VMA read lock via ”…”�”}”(hj{h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!lock_vma_under_rcu`”h]”hŒlock_vma_under_rcu()”…”�”}”(hjƒh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj{ubhŒ™. This tries to acquire the lock atomically so might fail, in which case fall-back logic is required to instead obtain an mmap read lock if this returns ”…”�”}”(hj{h²hh³Nh´Nubj )�”}”(hŒ:c:macro:`!NULL`”h]”hŒNULL”…”�”}”(hj–h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-macro”eh"]”h$]”h&]”uh1j hj{ubhŒ, ”…”�”}”(hj{h²hh³Nh´Nubj\)�”}”(hŒ*or*”h]”hŒor”…”�”}”(hj©h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j[hj{ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KQhjwubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj&h²hh³hÇh´Nubj)�”}”(hŒAcquire an rmap lock before traversing the locked interval tree (whether anonymous or file-backed) to obtain the required VMA. ”h]”j)�”}”(hŒ~Acquire an rmap lock before traversing the locked interval tree (whether anonymous or file-backed) to obtain the required VMA.”h]”hŒ~Acquire an rmap lock before traversing the locked interval tree (whether anonymous or file-backed) to obtain the required VMA.”…”�”}”(hjÇh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KUhjÃubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj&h²hh³hÇh´Nubeh}”(h]”h ]”h"]”h$]”h&]”j�jžuh1jh³hÇh´KNhjõh²hubj)�”}”(hŒ�If you want to **write** VMA metadata fields, then things vary depending on the field (we explore each VMA field in detail below). For the majority you must:”h]”(hŒIf you want to ”…”�”}”(hjáh²hh³Nh´NubjÓ)�”}”(hŒ **write**”h]”hŒwrite”…”�”}”(hjéh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjáubhŒ… VMA metadata fields, then things vary depending on the field (we explore each VMA field in detail below). For the majority you must:”…”�”}”(hjáh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KXhjõh²hubj)�”}”(hhh]”(j)�”}”(hŒÆObtain an mmap write lock at the MM granularity via :c:func:`!mmap_write_lock` (or a suitable variant), unlocking it with a matching :c:func:`!mmap_write_unlock` when you're done with the VMA, *and*”h]”j)�”}”(hŒÆObtain an mmap write lock at the MM granularity via :c:func:`!mmap_write_lock` (or a suitable variant), unlocking it with a matching :c:func:`!mmap_write_unlock` when you're done with the VMA, *and*”h]”(hŒ4Obtain an mmap write lock at the MM granularity via ”…”�”}”(hjh²hh³Nh´Nubj )�”}”(hŒ:c:func:`!mmap_write_lock`”h]”hŒmmap_write_lock()”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjubhŒ7 (or a suitable variant), unlocking it with a matching ”…”�”}”(hjh²hh³Nh´Nubj )�”}”(hŒ:c:func:`!mmap_write_unlock`”h]”hŒmmap_write_unlock()”…”�”}”(hj#h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjubhŒ" when you’re done with the VMA, ”…”�”}”(hjh²hh³Nh´Nubj\)�”}”(hŒ*and*”h]”hŒand”…”�”}”(hj6h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j[hjubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K[hjubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjh²hh³hÇh´Nubj)�”}”(hŒ©Obtain a VMA write lock via :c:func:`!vma_start_write` for each VMA you wish to modify, which will be released automatically when :c:func:`!mmap_write_unlock` is called.”h]”j)�”}”(hŒ©Obtain a VMA write lock via :c:func:`!vma_start_write` for each VMA you wish to modify, which will be released automatically when :c:func:`!mmap_write_unlock` is called.”h]”(hŒObtain a VMA write lock via ”…”�”}”(hjTh²hh³Nh´Nubj )�”}”(hŒ:c:func:`!vma_start_write`”h]”hŒvma_start_write()”…”�”}”(hj\h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjTubhŒL for each VMA you wish to modify, which will be released automatically when ”…”�”}”(hjTh²hh³Nh´Nubj )�”}”(hŒ:c:func:`!mmap_write_unlock`”h]”hŒmmap_write_unlock()”…”�”}”(hjoh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjTubhŒ is called.”…”�”}”(hjTh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K^hjPubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjh²hh³hÇh´Nubj)�”}”(hŒ‹If you want to be able to write to **any** field, you must also hide the VMA from the reverse mapping by obtaining an **rmap write lock**. ”h]”j)�”}”(hŒŠIf you want to be able to write to **any** field, you must also hide the VMA from the reverse mapping by obtaining an **rmap write lock**.”h]”(hŒ#If you want to be able to write to ”…”�”}”(hj’h²hh³Nh´NubjÓ)�”}”(hŒ**any**”h]”hŒany”…”�”}”(hjšh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhj’ubhŒL field, you must also hide the VMA from the reverse mapping by obtaining an ”…”�”}”(hj’h²hh³Nh´NubjÓ)�”}”(hŒ**rmap write lock**”h]”hŒrmap write lock”…”�”}”(hj¬h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhj’ubhŒ.”…”�”}”(hj’h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KahjŽubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjh²hh³hÇh´Nubeh}”(h]”h ]”h"]”h$]”h&]”j�jžuh1jh³hÇh´K[hjõh²hubj)�”}”(hXVMA locks are special in that you must obtain an mmap **write** lock **first** in order to obtain a VMA **write** lock. A VMA **read** lock however can be obtained without any other lock (:c:func:`!lock_vma_under_rcu` will acquire then release an RCU lock to lookup the VMA for you).”h]”(hŒ6VMA locks are special in that you must obtain an mmap ”…”�”}”(hjÐh²hh³Nh´NubjÓ)�”}”(hŒ **write**”h]”hŒwrite”…”�”}”(hjØh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjÐubhŒ lock ”…”�”}”(hjÐh²hh³Nh´NubjÓ)�”}”(hŒ **first**”h]”hŒfirst”…”�”}”(hjêh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjÐubhŒ in order to obtain a VMA ”…”�”}”(hjÐh²hh³Nh´NubjÓ)�”}”(hŒ **write**”h]”hŒwrite”…”�”}”(hjüh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjÐubhŒ lock. A VMA ”…”�”}”(hjÐh²hh³Nh´NubjÓ)�”}”(hŒ**read**”h]”hŒread”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjÐubhŒ6 lock however can be obtained without any other lock (”…”�”}”(hjÐh²hh³Nh´Nubj )�”}”(hŒ:c:func:`!lock_vma_under_rcu`”h]”hŒlock_vma_under_rcu()”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjÐubhŒB will acquire then release an RCU lock to lookup the VMA for you).”…”�”}”(hjÐh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kdhjõh²hubj)�”}”(hŒ�This constrains the impact of writers on readers, as a writer can interact with one VMA while a reader interacts with another simultaneously.”h]”hŒ�This constrains the impact of writers on readers, as a writer can interact with one VMA while a reader interacts with another simultaneously.”…”�”}”(hj9h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kihjõh²hubj�)�”}”(hŒ¤The primary users of VMA read locks are page fault handlers, which means that without a VMA write lock, page faults will run concurrent with whatever you are doing.”h]”j)�”}”(hŒ¤The primary users of VMA read locks are page fault handlers, which means that without a VMA write lock, page faults will run concurrent with whatever you are doing.”h]”hŒ¤The primary users of VMA read locks are page fault handlers, which means that without a VMA write lock, page faults will run concurrent with whatever you are doing.”…”�”}”(hjKh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KlhjGubah}”(h]”h ]”h"]”h$]”h&]”uh1jŒhjõh²hh³hÇh´Nubj)�”}”(hŒ Examining all valid lock states:”h]”hŒ Examining all valid lock states:”…”�”}”(hj_h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kphjõh²hubhŒtable”“”)�”}”(hhh]”hŒtgroup”“”)�”}”(hhh]”(hŒcolspec”“”)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”K uh1jwhjtubjx)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”Kuh1jwhjtubjx)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”K uh1jwhjtubjx)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”Kuh1jwhjtubjx)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”Kuh1jwhjtubjx)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”K uh1jwhjtubjx)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”K uh1jwhjtubhŒthead”“”)�”}”(hhh]”hŒrow”“”)�”}”(hhh]”(hŒentry”“”)�”}”(hhh]”j)�”}”(hŒ mmap lock”h]”hŒ mmap lock”…”�”}”(hjÎh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KuhjËubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjÆubjÊ)�”}”(hhh]”j)�”}”(hŒVMA lock”h]”hŒVMA lock”…”�”}”(hjåh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kuhjâubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjÆubjÊ)�”}”(hhh]”j)�”}”(hŒ rmap lock”h]”hŒ rmap lock”…”�”}”(hjüh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kuhjùubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjÆubjÊ)�”}”(hhh]”j)�”}”(hŒStable?”h]”hŒStable?”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kuhjubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjÆubjÊ)�”}”(hhh]”j)�”}”(hŒRead?”h]”hŒRead?”…”�”}”(hj*h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kuhj'ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjÆubjÊ)�”}”(hhh]”j)�”}”(hŒ Write most?”h]”hŒ Write most?”…”�”}”(hjAh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kuhj>ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjÆubjÊ)�”}”(hhh]”j)�”}”(hŒ Write all?”h]”hŒ Write all?”…”�”}”(hjXh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KuhjUubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjÆubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjÁubah}”(h]”h ]”h"]”h$]”h&]”uh1j¿hjtubhŒtbody”“”)�”}”(hhh]”(jÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒ\-”h]”hŒ-”…”�”}”(hjƒh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kwhj€ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj}ubjÊ)�”}”(hhh]”j)�”}”(hŒ\-”h]”hŒ-”…”�”}”(hjšh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kwhj—ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj}ubjÊ)�”}”(hhh]”j)�”}”(hŒ\-”h]”hŒ-”…”�”}”(hj±h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kwhj®ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj}ubjÊ)�”}”(hhh]”j)�”}”(hŒN”h]”hŒN”…”�”}”(hjÈh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KwhjÅubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj}ubjÊ)�”}”(hhh]”j)�”}”(hjÊh]”hŒN”…”�”}”(hjßh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KwhjÜubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj}ubjÊ)�”}”(hhh]”j)�”}”(hjÊh]”hŒN”…”�”}”(hjõh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kwhjòubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj}ubjÊ)�”}”(hhh]”j)�”}”(hjÊh]”hŒN”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kwhjubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj}ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjzubjÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒ\-”h]”hŒ-”…”�”}”(hj*h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kxhj'ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj$ubjÊ)�”}”(hhh]”j)�”}”(hŒR”h]”hŒR”…”�”}”(hjAh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kxhj>ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj$ubjÊ)�”}”(hhh]”j)�”}”(hŒ\-”h]”hŒ-”…”�”}”(hjXh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KxhjUubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj$ubjÊ)�”}”(hhh]”j)�”}”(hŒY”h]”hŒY”…”�”}”(hjoh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kxhjlubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj$ubjÊ)�”}”(hhh]”j)�”}”(hjqh]”hŒY”…”�”}”(hj†h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kxhjƒubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj$ubjÊ)�”}”(hhh]”j)�”}”(hjÊh]”hŒN”…”�”}”(hjœh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kxhj™ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj$ubjÊ)�”}”(hhh]”j)�”}”(hjÊh]”hŒN”…”�”}”(hj²h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kxhj¯ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj$ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjzubjÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒ\-”h]”hŒ-”…”�”}”(hjÑh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KyhjÎubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjËubjÊ)�”}”(hhh]”j)�”}”(hŒ\-”h]”hŒ-”…”�”}”(hjèh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kyhjåubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjËubjÊ)�”}”(hhh]”j)�”}”(hŒR/W”h]”hŒR/W”…”�”}”(hjÿh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kyhjüubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjËubjÊ)�”}”(hhh]”j)�”}”(hjqh]”hŒY”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kyhj ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjËubjÊ)�”}”(hhh]”j)�”}”(hjqh]”hŒY”…”�”}”(hj, h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kyhj) ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjËubjÊ)�”}”(hhh]”j)�”}”(hjÊh]”hŒN”…”�”}”(hjB h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kyhj? ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjËubjÊ)�”}”(hhh]”j)�”}”(hjÊh]”hŒN”…”�”}”(hjX h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KyhjU ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjËubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjzubjÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒR/W”h]”hŒR/W”…”�”}”(hjw h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kzhjt ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjq ubjÊ)�”}”(hhh]”j)�”}”(hŒ\-/R”h]”hŒ-/R”…”�”}”(hjŽ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kzhj‹ ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjq ubjÊ)�”}”(hhh]”j)�”}”(hŒ\-/R/W”h]”hŒ-/R/W”…”�”}”(hj¥ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kzhj¢ ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjq ubjÊ)�”}”(hhh]”j)�”}”(hjqh]”hŒY”…”�”}”(hj¼ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kzhj¹ ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjq ubjÊ)�”}”(hhh]”j)�”}”(hjqh]”hŒY”…”�”}”(hjÒ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KzhjÏ ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjq ubjÊ)�”}”(hhh]”j)�”}”(hjÊh]”hŒN”…”�”}”(hjè h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kzhjå ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjq ubjÊ)�”}”(hhh]”j)�”}”(hjÊh]”hŒN”…”�”}”(hjþ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kzhjû ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjq ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjzubjÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒW”h]”hŒW”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K{hj ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj ubjÊ)�”}”(hhh]”j)�”}”(hj h]”hŒW”…”�”}”(hj4 h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K{hj1 ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj ubjÊ)�”}”(hhh]”j)�”}”(hŒ\-/R”h]”hŒ-/R”…”�”}”(hjJ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K{hjG ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj ubjÊ)�”}”(hhh]”j)�”}”(hjqh]”hŒY”…”�”}”(hja h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K{hj^ ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj ubjÊ)�”}”(hhh]”j)�”}”(hjqh]”hŒY”…”�”}”(hjw h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K{hjt ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj ubjÊ)�”}”(hhh]”j)�”}”(hjqh]”hŒY”…”�”}”(hj� h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K{hjŠ ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj ubjÊ)�”}”(hhh]”j)�”}”(hjÊh]”hŒN”…”�”}”(hj£ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K{hj  ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjzubjÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hj h]”hŒW”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K|hj¿ ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj¼ ubjÊ)�”}”(hhh]”j)�”}”(hj h]”hŒW”…”�”}”(hjØ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K|hjÕ ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj¼ ubjÊ)�”}”(hhh]”j)�”}”(hj h]”hŒW”…”�”}”(hjî h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K|hjë ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj¼ ubjÊ)�”}”(hhh]”j)�”}”(hjqh]”hŒY”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K|hj ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj¼ ubjÊ)�”}”(hhh]”j)�”}”(hjqh]”hŒY”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K|hj ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj¼ ubjÊ)�”}”(hhh]”j)�”}”(hjqh]”hŒY”…”�”}”(hj0 h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K|hj- ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj¼ ubjÊ)�”}”(hhh]”j)�”}”(hjqh]”hŒY”…”�”}”(hjF h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K|hjC ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj¼ ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjzubeh}”(h]”h ]”h"]”h$]”h&]”uh1jxhjtubeh}”(h]”h ]”h"]”h$]”h&]”Œcols”Kuh1jrhjoubah}”(h]”h ]”h"]”h$]”h&]”uh1jmhjõh²hh³hÇh´NubhŒwarning”“”)�”}”(hXWhile it's possible to obtain a VMA lock while holding an mmap read lock, attempting to do the reverse is invalid as it can result in deadlock - if another task already holds an mmap write lock and attempts to acquire a VMA write lock that will deadlock on the VMA read lock.”h]”j)�”}”(hXWhile it's possible to obtain a VMA lock while holding an mmap read lock, attempting to do the reverse is invalid as it can result in deadlock - if another task already holds an mmap write lock and attempts to acquire a VMA write lock that will deadlock on the VMA read lock.”h]”hXWhile it’s possible to obtain a VMA lock while holding an mmap read lock, attempting to do the reverse is invalid as it can result in deadlock - if another task already holds an mmap write lock and attempts to acquire a VMA write lock that will deadlock on the VMA read lock.”…”�”}”(hjx h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Khjt ubah}”(h]”h ]”h"]”h$]”h&]”uh1jr hjõh²hh³hÇh´Nubj)�”}”(hŒ‚All of these locks behave as read/write semaphores in practice, so you can obtain either a read or a write lock for each of these.”h]”hŒ‚All of these locks behave as read/write semaphores in practice, so you can obtain either a read or a write lock for each of these.”…”�”}”(hjŒ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K„hjõh²hubj�)�”}”(hXqGenerally speaking, a read/write semaphore is a class of lock which permits concurrent readers. However a write lock can only be obtained once all readers have left the critical region (and pending readers made to wait). This renders read locks on a read/write semaphore concurrent with other readers and write locks exclusive against all others holding the semaphore.”h]”(j)�”}”(hŒÜGenerally speaking, a read/write semaphore is a class of lock which permits concurrent readers. However a write lock can only be obtained once all readers have left the critical region (and pending readers made to wait).”h]”hŒÜGenerally speaking, a read/write semaphore is a class of lock which permits concurrent readers. However a write lock can only be obtained once all readers have left the critical region (and pending readers made to wait).”…”�”}”(hjž h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K‡hjš ubj)�”}”(hŒ“This renders read locks on a read/write semaphore concurrent with other readers and write locks exclusive against all others holding the semaphore.”h]”hŒ“This renders read locks on a read/write semaphore concurrent with other readers and write locks exclusive against all others holding the semaphore.”…”�”}”(hj¬ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KŒhjš ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jŒhjõh²hh³hÇh´NubhÉ)�”}”(hhh]”(hÎ)�”}”(hŒ VMA fields”h]”hŒ VMA fields”…”�”}”(hjà h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjÀ h²hh³hÇh´K�ubj)�”}”(hŒŒWe can subdivide :c:struct:`!struct vm_area_struct` fields by their purpose, which makes it easier to explore their locking characteristics:”h]”(hŒWe can subdivide ”…”�”}”(hjÑ h²hh³Nh´Nubj )�”}”(hŒ":c:struct:`!struct vm_area_struct`”h]”hŒstruct vm_area_struct”…”�”}”(hjÙ h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-struct”eh"]”h$]”h&]”uh1j hjÑ ubhŒY fields by their purpose, which makes it easier to explore their locking characteristics:”…”�”}”(hjÑ h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K’hjÀ h²hubj�)�”}”(hŒvWe exclude VMA lock-specific fields here to avoid confusion, as these are in effect an internal implementation detail.”h]”j)�”}”(hŒvWe exclude VMA lock-specific fields here to avoid confusion, as these are in effect an internal implementation detail.”h]”hŒvWe exclude VMA lock-specific fields here to avoid confusion, as these are in effect an internal implementation detail.”…”�”}”(hjö h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K•hjò ubah}”(h]”h ]”h"]”h$]”h&]”uh1jŒhjÀ h²hh³hÇh´Nubjn)�”}”(hhh]”(hÎ)�”}”(hŒVirtual layout fields”h]”hŒVirtual layout fields”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍh³hÇh´K˜hj ubjs)�”}”(hhh]”(jx)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”Kuh1jwhj ubjx)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”K(uh1jwhj ubjx)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”K uh1jwhj ubjÀ)�”}”(hhh]”jÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒField”h]”hŒField”…”�”}”(hjE h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K›hjB ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj? ubjÊ)�”}”(hhh]”j)�”}”(hŒ Description”h]”hŒ Description”…”�”}”(hj\ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K›hjY ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj? ubjÊ)�”}”(hhh]”j)�”}”(hŒ Write lock”h]”hŒ Write lock”…”�”}”(hjs h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K›hjp ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj? ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhj< ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¿hj ubjy)�”}”(hhh]”(jÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒ:c:member:`!vm_start`”h]”j )�”}”(hjž h]”hŒvm_start”…”�”}”(hj  h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hjœ ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K�hj™ ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj– ubjÊ)�”}”(hhh]”j)�”}”(hŒ7Inclusive start virtual address of range VMA describes.”h]”hŒ7Inclusive start virtual address of range VMA describes.”…”�”}”(hj½ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K�hjº ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj– ubjÊ)�”}”(hhh]”j)�”}”(hŒ"mmap write, VMA write, rmap write.”h]”hŒ"mmap write, VMA write, rmap write.”…”�”}”(hjÔ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K�hjÑ ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj– ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhj“ ubjÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒ:c:member:`!vm_end`”h]”j )�”}”(hjö h]”hŒvm_end”…”�”}”(hjø h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hjô ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K hjñ ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjî ubjÊ)�”}”(hhh]”j)�”}”(hŒ5Exclusive end virtual address of range VMA describes.”h]”hŒ5Exclusive end virtual address of range VMA describes.”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K hj ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjî ubjÊ)�”}”(hhh]”j)�”}”(hŒ"mmap write, VMA write, rmap write.”h]”hŒ"mmap write, VMA write, rmap write.”…”�”}”(hj, h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K hj) ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjî ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhj“ ubjÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒ:c:member:`!vm_pgoff`”h]”j )�”}”(hjN h]”hŒvm_pgoff”…”�”}”(hjP h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hjL ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K£hjI ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjF ubjÊ)�”}”(hhh]”j)�”}”(hŒçDescribes the page offset into the file, the original page offset within the virtual address space (prior to any :c:func:`!mremap`), or PFN if a PFN map and the architecture does not support :c:macro:`!CONFIG_ARCH_HAS_PTE_SPECIAL`.”h]”(hŒqDescribes the page offset into the file, the original page offset within the virtual address space (prior to any ”…”�”}”(hjm h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!mremap`”h]”hŒmremap()”…”�”}”(hju h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjm ubhŒ=), or PFN if a PFN map and the architecture does not support ”…”�”}”(hjm h²hh³Nh´Nubj )�”}”(hŒ':c:macro:`!CONFIG_ARCH_HAS_PTE_SPECIAL`”h]”hŒCONFIG_ARCH_HAS_PTE_SPECIAL”…”�”}”(hjˆ h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-macro”eh"]”h$]”h&]”uh1j hjm ubhŒ.”…”�”}”(hjm h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K£hjj ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjF ubjÊ)�”}”(hhh]”j)�”}”(hŒ"mmap write, VMA write, rmap write.”h]”hŒ"mmap write, VMA write, rmap write.”…”�”}”(hjª h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K£hj§ ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjF ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhj“ ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jxhj ubeh}”(h]”h ]”h"]”h$]”h&]”Œcols”Kuh1jrhj ubeh}”(h]”Œid1”ah ]”h"]”h$]”h&]”uh1jmhjÀ h²hh³hÇh´Nubj)�”}”(hŒãThese fields describes the size, start and end of the VMA, and as such cannot be modified without first being hidden from the reverse mapping since these fields are used to locate VMAs within the reverse mapping interval trees.”h]”hŒãThese fields describes the size, start and end of the VMA, and as such cannot be modified without first being hidden from the reverse mapping since these fields are used to locate VMAs within the reverse mapping interval trees.”…”�”}”(hjØ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K«hjÀ h²hubjn)�”}”(hhh]”(hÎ)�”}”(hŒ Core fields”h]”hŒ Core fields”…”�”}”(hjé h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍh³hÇh´K¯hjæ ubjs)�”}”(hhh]”(jx)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”Kuh1jwhj÷ ubjx)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”K(uh1jwhj÷ ubjx)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”Kuh1jwhj÷ ubjÀ)�”}”(hhh]”jÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒField”h]”hŒField”…”�”}”(hj!h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K²hjubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjubjÊ)�”}”(hhh]”j)�”}”(hŒ Description”h]”hŒ Description”…”�”}”(hj8h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K²hj5ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjubjÊ)�”}”(hhh]”j)�”}”(hŒ Write lock”h]”hŒ Write lock”…”�”}”(hjOh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K²hjLubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjubah}”(h]”h ]”h"]”h$]”h&]”uh1j¿hj÷ ubjy)�”}”(hhh]”(jÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒ:c:member:`!vm_mm`”h]”j )�”}”(hjzh]”hŒvm_mm”…”�”}”(hj|h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hjxubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K´hjuubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjrubjÊ)�”}”(hhh]”j)�”}”(hŒContaining mm_struct.”h]”hŒContaining mm_struct.”…”�”}”(hj™h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K´hj–ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjrubjÊ)�”}”(hhh]”j)�”}”(hŒ#None - written once on initial map.”h]”hŒ#None - written once on initial map.”…”�”}”(hj°h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K´hj­ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjrubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjoubjÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒ:c:member:`!vm_page_prot`”h]”j )�”}”(hjÒh]”hŒ vm_page_prot”…”�”}”(hjÔh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hjÐubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K¶hjÍubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjÊubjÊ)�”}”(hhh]”j)�”}”(hŒKArchitecture-specific page table protection bits determined from VMA flags.”h]”hŒKArchitecture-specific page table protection bits determined from VMA flags.”…”�”}”(hjñh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K¶hjîubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjÊubjÊ)�”}”(hhh]”j)�”}”(hŒmmap write, VMA write.”h]”hŒmmap write, VMA write.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K¶hjubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjÊubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjoubjÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒ:c:member:`!vm_flags`”h]”j )�”}”(hj*h]”hŒvm_flags”…”�”}”(hj,h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hj(ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K¹hj%ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj"ubjÊ)�”}”(hhh]”j)�”}”(hŒwRead-only access to VMA flags describing attributes of the VMA, in union with private writable :c:member:`!__vm_flags`.”h]”(hŒ_Read-only access to VMA flags describing attributes of the VMA, in union with private writable ”…”�”}”(hjIh²hh³Nh´Nubj )�”}”(hŒ:c:member:`!__vm_flags`”h]”hŒ __vm_flags”…”�”}”(hjQh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hjIubhŒ.”…”�”}”(hjIh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K¹hjFubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj"ubjÊ)�”}”(hhh]”j)�”}”(hŒN/A”h]”hŒN/A”…”�”}”(hjsh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K¹hjpubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj"ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjoubjÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒ:c:member:`!__vm_flags`”h]”j )�”}”(hj•h]”hŒ __vm_flags”…”�”}”(hj—h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hj“ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K½hj�ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj�ubjÊ)�”}”(hhh]”j)�”}”(hŒXPrivate, writable access to VMA flags field, updated by :c:func:`!vm_flags_*` functions.”h]”(hŒ8Private, writable access to VMA flags field, updated by ”…”�”}”(hj´h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!vm_flags_*`”h]”hŒ vm_flags_*()”…”�”}”(hj¼h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj´ubhŒ functions.”…”�”}”(hj´h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K½hj±ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj�ubjÊ)�”}”(hhh]”j)�”}”(hŒmmap write, VMA write.”h]”hŒmmap write, VMA write.”…”�”}”(hjÞh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K½hjÛubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj�ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjoubjÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒ:c:member:`!vm_file`”h]”j )�”}”(hjh]”hŒvm_file”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hjþubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KÀhjûubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjøubjÊ)�”}”(hhh]”j)�”}”(hŒ}If the VMA is file-backed, points to a struct file object describing the underlying file, if anonymous then :c:macro:`!NULL`.”h]”(hŒlIf the VMA is file-backed, points to a struct file object describing the underlying file, if anonymous then ”…”�”}”(hjh²hh³Nh´Nubj )�”}”(hŒ:c:macro:`!NULL`”h]”hŒNULL”…”�”}”(hj'h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-macro”eh"]”h$]”h&]”uh1j hjubhŒ.”…”�”}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KÀhjubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjøubjÊ)�”}”(hhh]”j)�”}”(hŒ#None - written once on initial map.”h]”hŒ#None - written once on initial map.”…”�”}”(hjIh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KÀhjFubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjøubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjoubjÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒ:c:member:`!vm_ops`”h]”j )�”}”(hjkh]”hŒvm_ops”…”�”}”(hjmh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hjiubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KÄhjfubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjcubjÊ)�”}”(hhh]”j)�”}”(hŒ¶If the VMA is file-backed, then either the driver or file-system provides a :c:struct:`!struct vm_operations_struct` object describing callbacks to be invoked on VMA lifetime events.”h]”(hŒLIf the VMA is file-backed, then either the driver or file-system provides a ”…”�”}”(hjŠh²hh³Nh´Nubj )�”}”(hŒ(:c:struct:`!struct vm_operations_struct`”h]”hŒstruct vm_operations_struct”…”�”}”(hj’h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-struct”eh"]”h$]”h&]”uh1j hjŠubhŒB object describing callbacks to be invoked on VMA lifetime events.”…”�”}”(hjŠh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KÄhj‡ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjcubjÊ)�”}”(hhh]”j)�”}”(hŒ?None - Written once on initial map by :c:func:`!f_ops->mmap()`.”h]”(hŒ&None - Written once on initial map by ”…”�”}”(hj´h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!f_ops->mmap()`”h]”hŒ f_ops->mmap()”…”�”}”(hj¼h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj´ubhŒ.”…”�”}”(hj´h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KÄhj±ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjcubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjoubjÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒ:c:member:`!vm_private_data`”h]”j )�”}”(hjéh]”hŒvm_private_data”…”�”}”(hjëh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hjçubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KÉhjäubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjáubjÊ)�”}”(hhh]”j)�”}”(hŒ9A :c:member:`!void *` field for driver-specific metadata.”h]”(hŒA ”…”�”}”(hjh²hh³Nh´Nubj )�”}”(hŒ:c:member:`!void *`”h]”hŒvoid *”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hjubhŒ$ field for driver-specific metadata.”…”�”}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KÉhjubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjáubjÊ)�”}”(hhh]”j)�”}”(hŒHandled by driver.”h]”hŒHandled by driver.”…”�”}”(hj2h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KÉhj/ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjáubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjoubeh}”(h]”h ]”h"]”h$]”h&]”uh1jxhj÷ ubeh}”(h]”h ]”h"]”h$]”h&]”Œcols”Kuh1jrhjæ ubeh}”(h]”Œid2”ah ]”h"]”h$]”h&]”uh1jmhjÀ h²hh³hÇh´Nubj)�”}”(hŒVThese are the core fields which describe the MM the VMA belongs to and its attributes.”h]”hŒVThese are the core fields which describe the MM the VMA belongs to and its attributes.”…”�”}”(hj`h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KÍhjÀ h²hubjn)�”}”(hhh]”(hÎ)�”}”(hŒConfig-specific fields”h]”hŒConfig-specific fields”…”�”}”(hjqh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍh³hÇh´KÏhjnubjs)�”}”(hhh]”(jx)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”K!uh1jwhjubjx)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”Kuh1jwhjubjx)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”K(uh1jwhjubjx)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”Kuh1jwhjubjÀ)�”}”(hhh]”jÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒField”h]”hŒField”…”�”}”(hj³h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KÒhj°ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj­ubjÊ)�”}”(hhh]”j)�”}”(hŒConfiguration option”h]”hŒConfiguration option”…”�”}”(hjÊh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KÒhjÇubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj­ubjÊ)�”}”(hhh]”j)�”}”(hŒ Description”h]”hŒ Description”…”�”}”(hjáh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KÒhjÞubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj­ubjÊ)�”}”(hhh]”j)�”}”(hŒ Write lock”h]”hŒ Write lock”…”�”}”(hjøh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KÒhjõubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj­ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjªubah}”(h]”h ]”h"]”h$]”h&]”uh1j¿hjubjy)�”}”(hhh]”(jÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒ:c:member:`!anon_name`”h]”j )�”}”(hj#h]”hŒ anon_name”…”�”}”(hj%h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hj!ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KÔhjubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjubjÊ)�”}”(hhh]”j)�”}”(hŒCONFIG_ANON_VMA_NAME”h]”hŒCONFIG_ANON_VMA_NAME”…”�”}”(hjBh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KÔhj?ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjubjÊ)�”}”(hhh]”j)�”}”(hXA field for storing a :c:struct:`!struct anon_vma_name` object providing a name for anonymous mappings, or :c:macro:`!NULL` if none is set or the VMA is file-backed. The underlying object is reference counted and can be shared across multiple VMAs for scalability.”h]”(hŒA field for storing a ”…”�”}”(hjYh²hh³Nh´Nubj )�”}”(hŒ!:c:struct:`!struct anon_vma_name`”h]”hŒstruct anon_vma_name”…”�”}”(hjah²hh³Nh´Nubah}”(h]”h ]”(jjŒc-struct”eh"]”h$]”h&]”uh1j hjYubhŒ4 object providing a name for anonymous mappings, or ”…”�”}”(hjYh²hh³Nh´Nubj )�”}”(hŒ:c:macro:`!NULL`”h]”hŒNULL”…”�”}”(hjth²hh³Nh´Nubah}”(h]”h ]”(jjŒc-macro”eh"]”h$]”h&]”uh1j hjYubhŒ� if none is set or the VMA is file-backed. The underlying object is reference counted and can be shared across multiple VMAs for scalability.”…”�”}”(hjYh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KÔhjVubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjubjÊ)�”}”(hhh]”j)�”}”(hŒmmap write, VMA write.”h]”hŒmmap write, VMA write.”…”�”}”(hj–h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KÔhj“ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjubjÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒ :c:member:`!swap_readahead_info`”h]”j )�”}”(hj¸h]”hŒswap_readahead_info”…”�”}”(hjºh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hj¶ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KÜhj³ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj°ubjÊ)�”}”(hhh]”j)�”}”(hŒ CONFIG_SWAP”h]”hŒ CONFIG_SWAP”…”�”}”(hj×h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KÜhjÔubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj°ubjÊ)�”}”(hhh]”j)�”}”(hŒ\Metadata used by the swap mechanism to perform readahead. This field is accessed atomically.”h]”hŒ\Metadata used by the swap mechanism to perform readahead. This field is accessed atomically.”…”�”}”(hjîh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KÜhjëubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj°ubjÊ)�”}”(hhh]”j)�”}”(hŒmmap read, swap-specific lock.”h]”hŒmmap read, swap-specific lock.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KÜhjubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj°ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjubjÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒ:c:member:`!vm_policy`”h]”j )�”}”(hj'h]”hŒ vm_policy”…”�”}”(hj)h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hj%ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kßhj"ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjubjÊ)�”}”(hhh]”j)�”}”(hŒ CONFIG_NUMA”h]”hŒ CONFIG_NUMA”…”�”}”(hjFh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KßhjCubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjubjÊ)�”}”(hhh]”j)�”}”(hŒv:c:type:`!mempolicy` object which describes the NUMA behaviour of the VMA. The underlying object is reference counted.”h]”(j )�”}”(hŒ:c:type:`!mempolicy`”h]”hŒ mempolicy”…”�”}”(hjah²hh³Nh´Nubah}”(h]”h ]”(jjŒc-type”eh"]”h$]”h&]”uh1j hj]ubhŒb object which describes the NUMA behaviour of the VMA. The underlying object is reference counted.”…”�”}”(hj]h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KßhjZubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjubjÊ)�”}”(hhh]”j)�”}”(hŒmmap write, VMA write.”h]”hŒmmap write, VMA write.”…”�”}”(hjƒh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kßhj€ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjubjÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒ:c:member:`!numab_state`”h]”j )�”}”(hj¥h]”hŒ numab_state”…”�”}”(hj§h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hj£ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kãhj ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj�ubjÊ)�”}”(hhh]”j)�”}”(hŒCONFIG_NUMA_BALANCING”h]”hŒCONFIG_NUMA_BALANCING”…”�”}”(hjÄh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KãhjÁubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj�ubjÊ)�”}”(hhh]”j)�”}”(hŒ©:c:type:`!vma_numab_state` object which describes the current state of NUMA balancing in relation to this VMA. Updated under mmap read lock by :c:func:`!task_numa_work`.”h]”(j )�”}”(hŒ:c:type:`!vma_numab_state`”h]”hŒvma_numab_state”…”�”}”(hjßh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-type”eh"]”h$]”h&]”uh1j hjÛubhŒu object which describes the current state of NUMA balancing in relation to this VMA. Updated under mmap read lock by ”…”�”}”(hjÛh²hh³Nh´Nubj )�”}”(hŒ:c:func:`!task_numa_work`”h]”hŒtask_numa_work()”…”�”}”(hjòh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjÛubhŒ.”…”�”}”(hjÛh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KãhjØubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj�ubjÊ)�”}”(hhh]”j)�”}”(hŒmmap read, numab-specific lock.”h]”hŒmmap read, numab-specific lock.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kãhjubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj�ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjubjÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒ:c:member:`!vm_userfaultfd_ctx`”h]”j )�”}”(hj6h]”hŒvm_userfaultfd_ctx”…”�”}”(hj8h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hj4ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kèhj1ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj.ubjÊ)�”}”(hhh]”j)�”}”(hŒCONFIG_USERFAULTFD”h]”hŒCONFIG_USERFAULTFD”…”�”}”(hjUh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KèhjRubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj.ubjÊ)�”}”(hhh]”j)�”}”(hŒêUserfaultfd context wrapper object of type :c:type:`!vm_userfaultfd_ctx`, either of zero size if userfaultfd is disabled, or containing a pointer to an underlying :c:type:`!userfaultfd_ctx` object which describes userfaultfd metadata.”h]”(hŒ+Userfaultfd context wrapper object of type ”…”�”}”(hjlh²hh³Nh´Nubj )�”}”(hŒ:c:type:`!vm_userfaultfd_ctx`”h]”hŒvm_userfaultfd_ctx”…”�”}”(hjth²hh³Nh´Nubah}”(h]”h ]”(jjŒc-type”eh"]”h$]”h&]”uh1j hjlubhŒ[, either of zero size if userfaultfd is disabled, or containing a pointer to an underlying ”…”�”}”(hjlh²hh³Nh´Nubj )�”}”(hŒ:c:type:`!userfaultfd_ctx`”h]”hŒuserfaultfd_ctx”…”�”}”(hj‡h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-type”eh"]”h$]”h&]”uh1j hjlubhŒ- object which describes userfaultfd metadata.”…”�”}”(hjlh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kèhjiubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj.ubjÊ)�”}”(hhh]”j)�”}”(hŒmmap write, VMA write.”h]”hŒmmap write, VMA write.”…”�”}”(hj©h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kèhj¦ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj.ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjubeh}”(h]”h ]”h"]”h$]”h&]”uh1jxhjubeh}”(h]”h ]”h"]”h$]”h&]”Œcols”Kuh1jrhjnubeh}”(h]”Œid3”ah ]”h"]”h$]”h&]”uh1jmhjÀ h²hh³hÇh´Nubj)�”}”(hŒeThese fields are present or not depending on whether the relevant kernel configuration option is set.”h]”hŒeThese fields are present or not depending on whether the relevant kernel configuration option is set.”…”�”}”(hj×h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´KñhjÀ h²hubjn)�”}”(hhh]”(hÎ)�”}”(hŒReverse mapping fields”h]”hŒReverse mapping fields”…”�”}”(hjèh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍh³hÇh´Kôhjåubjs)�”}”(hhh]”(jx)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”K#uh1jwhjöubjx)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”K)uh1jwhjöubjx)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”Kuh1jwhjöubjÀ)�”}”(hhh]”jÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒField”h]”hŒField”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K÷hjubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjubjÊ)�”}”(hhh]”j)�”}”(hŒ Description”h]”hŒ Description”…”�”}”(hj7h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K÷hj4ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjubjÊ)�”}”(hhh]”j)�”}”(hŒ Write lock”h]”hŒ Write lock”…”�”}”(hjNh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´K÷hjKubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjubah}”(h]”h ]”h"]”h$]”h&]”uh1j¿hjöubjy)�”}”(hhh]”(jÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒ:c:member:`!shared.rb`”h]”j )�”}”(hjyh]”hŒ shared.rb”…”�”}”(hj{h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hjwubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kùhjtubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjqubjÊ)�”}”(hhh]”j)�”}”(hŒ•A red/black tree node used, if the mapping is file-backed, to place the VMA in the :c:member:`!struct address_space->i_mmap` red/black interval tree.”h]”(hŒSA red/black tree node used, if the mapping is file-backed, to place the VMA in the ”…”�”}”(hj˜h²hh³Nh´Nubj )�”}”(hŒ):c:member:`!struct address_space->i_mmap`”h]”hŒstruct address_space->i_mmap”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hj˜ubhŒ red/black interval tree.”…”�”}”(hj˜h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kùhj•ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjqubjÊ)�”}”(hhh]”j)�”}”(hŒ$mmap write, VMA write, i_mmap write.”h]”hŒ$mmap write, VMA write, i_mmap write.”…”�”}”(hjÂh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kùhj¿ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjqubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjnubjÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒ#:c:member:`!shared.rb_subtree_last`”h]”j )�”}”(hjäh]”hŒshared.rb_subtree_last”…”�”}”(hjæh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hjâubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kþhjßubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjÜubjÊ)�”}”(hhh]”j)�”}”(hŒLMetadata used for management of the interval tree if the VMA is file-backed.”h]”hŒLMetadata used for management of the interval tree if the VMA is file-backed.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kþhjubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjÜubjÊ)�”}”(hhh]”j)�”}”(hŒ$mmap write, VMA write, i_mmap write.”h]”hŒ$mmap write, VMA write, i_mmap write.”…”�”•ˆ}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Kþhjubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjÜubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjnubjÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒ:c:member:`!anon_vma_chain`”h]”j )�”}”(hj<h]”hŒanon_vma_chain”…”�”}”(hj>h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hj:ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mhj7ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj4ubjÊ)�”}”(hhh]”j)�”}”(hŒ�List of pointers to both forked/CoW’d :c:type:`!anon_vma` objects and :c:member:`!vma->anon_vma` if it is non-:c:macro:`!NULL`.”h]”(hŒ(List of pointers to both forked/CoW’d ”…”�”}”(hj[h²hh³Nh´Nubj )�”}”(hŒ:c:type:`!anon_vma`”h]”hŒanon_vma”…”�”}”(hjch²hh³Nh´Nubah}”(h]”h ]”(jjŒc-type”eh"]”h$]”h&]”uh1j hj[ubhŒ objects and ”…”�”}”(hj[h²hh³Nh´Nubj )�”}”(hŒ:c:member:`!vma->anon_vma`”h]”hŒ vma->anon_vma”…”�”}”(hjvh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hj[ubhŒ if it is non-”…”�”}”(hj[h²hh³Nh´Nubj )�”}”(hŒ:c:macro:`!NULL`”h]”hŒNULL”…”�”}”(hj‰h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-macro”eh"]”h$]”h&]”uh1j hj[ubhŒ.”…”�”}”(hj[h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MhjXubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj4ubjÊ)�”}”(hhh]”j)�”}”(hŒmmap read, anon_vma write.”h]”hŒmmap read, anon_vma write.”…”�”}”(hj«h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mhj¨ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj4ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjnubjÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hŒ:c:member:`!anon_vma`”h]”j )�”}”(hjÍh]”hŒanon_vma”…”�”}”(hjÏh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hjËubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MhjÈubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjÅubjÊ)�”}”(hhh]”j)�”}”(hŒÞ:c:type:`!anon_vma` object used by anonymous folios mapped exclusively to this VMA. Initially set by :c:func:`!anon_vma_prepare` serialised by the :c:macro:`!page_table_lock`. This is set as soon as any page is faulted in.”h]”(j )�”}”(hŒ:c:type:`!anon_vma`”h]”hŒanon_vma”…”�”}”(hjðh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-type”eh"]”h$]”h&]”uh1j hjìubhŒR object used by anonymous folios mapped exclusively to this VMA. Initially set by ”…”�”}”(hjìh²hh³Nh´Nubj )�”}”(hŒ:c:func:`!anon_vma_prepare`”h]”hŒanon_vma_prepare()”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjìubhŒ serialised by the ”…”�”}”(hjìh²hh³Nh´Nubj )�”}”(hŒ:c:macro:`!page_table_lock`”h]”hŒpage_table_lock”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-macro”eh"]”h$]”h&]”uh1j hjìubhŒ0. This is set as soon as any page is faulted in.”…”�”}”(hjìh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mhjéubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjÅubjÊ)�”}”(hhh]”(j)�”}”(hŒQWhen :c:macro:`NULL` and setting non-:c:macro:`NULL`: mmap read, page_table_lock.”h]”(hŒWhen ”…”�”}”(hj8h²hh³Nh´Nubh)�”}”(hŒ:c:macro:`NULL`”h]”j )�”}”(hjBh]”hŒNULL”…”�”}”(hjDh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-macro”eh"]”h$]”h&]”uh1j hj@ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”híŒ refdomain”jŒreftype”Œmacro”Œ refexplicit”‰Œrefwarn”‰Œ reftarget”ŒNULL”uh1hh³hÇh´Mhj8ubhŒ and setting non-”…”�”}”(hj8h²hh³Nh´Nubh)�”}”(hŒ:c:macro:`NULL`”h]”j )�”}”(hjfh]”hŒNULL”…”�”}”(hjhh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-macro”eh"]”h$]”h&]”uh1j hjdubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”híŒ refdomain”jŒreftype”Œmacro”Œ refexplicit”‰Œrefwarn”‰j^ŒNULL”uh1hh³hÇh´Mhj8ubhŒ: mmap read, page_table_lock.”…”�”}”(hj8h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mhj5ubj)�”}”(hŒ\When non-:c:macro:`NULL` and setting :c:macro:`NULL`: mmap write, VMA write, anon_vma write.”h]”(hŒ When non-”…”�”}”(hj�h²hh³Nh´Nubh)�”}”(hŒ:c:macro:`NULL`”h]”j )�”}”(hj—h]”hŒNULL”…”�”}”(hj™h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-macro”eh"]”h$]”h&]”uh1j hj•ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”híŒ refdomain”jŒreftype”Œmacro”Œ refexplicit”‰Œrefwarn”‰j^ŒNULL”uh1hh³hÇh´M hj�ubhŒ and setting ”…”�”}”(hj�h²hh³Nh´Nubh)�”}”(hŒ:c:macro:`NULL`”h]”j )�”}”(hjºh]”hŒNULL”…”�”}”(hj¼h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-macro”eh"]”h$]”h&]”uh1j hj¸ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”híŒ refdomain”jŒreftype”Œmacro”Œ refexplicit”‰Œrefwarn”‰j^ŒNULL”uh1hh³hÇh´M hj�ubhŒ(: mmap write, VMA write, anon_vma write.”…”�”}”(hj�h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mhj5ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjÅubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhjnubeh}”(h]”h ]”h"]”h$]”h&]”uh1jxhjöubeh}”(h]”h ]”h"]”h$]”h&]”Œcols”Kuh1jrhjåubeh}”(h]”Œid4”ah ]”h"]”h$]”h&]”uh1jmhjÀ h²hh³hÇh´Nubj)�”}”(hX These fields are used to both place the VMA within the reverse mapping, and for anonymous mappings, to be able to access both related :c:struct:`!struct anon_vma` objects and the :c:struct:`!struct anon_vma` in which folios mapped exclusively to this VMA should reside.”h]”(hŒ†These fields are used to both place the VMA within the reverse mapping, and for anonymous mappings, to be able to access both related ”…”�”}”(hjh²hh³Nh´Nubj )�”}”(hŒ:c:struct:`!struct anon_vma`”h]”hŒstruct anon_vma”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-struct”eh"]”h$]”h&]”uh1j hjubhŒ objects and the ”…”�”}”(hjh²hh³Nh´Nubj )�”}”(hŒ:c:struct:`!struct anon_vma`”h]”hŒstruct anon_vma”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-struct”eh"]”h$]”h&]”uh1j hjubhŒ> in which folios mapped exclusively to this VMA should reside.”…”�”}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MhjÀ h²hubj�)�”}”(hŒÒIf a file-backed mapping is mapped with :c:macro:`!MAP_PRIVATE` set then it can be in both the :c:type:`!anon_vma` and :c:type:`!i_mmap` trees at the same time, so all of these fields might be utilised at once.”h]”j)�”}”(hŒÒIf a file-backed mapping is mapped with :c:macro:`!MAP_PRIVATE` set then it can be in both the :c:type:`!anon_vma` and :c:type:`!i_mmap` trees at the same time, so all of these fields might be utilised at once.”h]”(hŒ(If a file-backed mapping is mapped with ”…”�”}”(hj9h²hh³Nh´Nubj )�”}”(hŒ:c:macro:`!MAP_PRIVATE`”h]”hŒ MAP_PRIVATE”…”�”}”(hjAh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-macro”eh"]”h$]”h&]”uh1j hj9ubhŒ set then it can be in both the ”…”�”}”(hj9h²hh³Nh´Nubj )�”}”(hŒ:c:type:`!anon_vma`”h]”hŒanon_vma”…”�”}”(hjTh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-type”eh"]”h$]”h&]”uh1j hj9ubhŒ and ”…”�”}”(hj9h²hh³Nh´Nubj )�”}”(hŒ:c:type:`!i_mmap`”h]”hŒi_mmap”…”�”}”(hjgh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-type”eh"]”h$]”h&]”uh1j hj9ubhŒJ trees at the same time, so all of these fields might be utilised at once.”…”�”}”(hj9h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mhj5ubah}”(h]”h ]”h"]”h$]”h&]”uh1jŒhjÀ h²hh³hÇh´Nubeh}”(h]”Œ vma-fields”ah ]”h"]”Œ vma fields”ah$]”h&]”uh1hÈhjõh²hh³hÇh´K�ubeh}”(h]”Œ lock-usage”ah ]”h"]”Œ lock usage”ah$]”h&]”uh1hÈhj¹h²hh³hÇh´KIubhÉ)�”}”(hhh]”(hÎ)�”}”(hŒ Page tables”h]”hŒ Page tables”…”�”}”(hj™h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj–h²hh³hÇh´Mubj)�”}”(hXæWe won't speak exhaustively on the subject but broadly speaking, page tables map virtual addresses to physical ones through a series of page tables, each of which contain entries with physical addresses for the next page table level (along with flags), and at the leaf level the physical addresses of the underlying physical data pages or a special entry such as a swap entry, migration entry or other special marker. Offsets into these pages are provided by the virtual address itself.”h]”hXèWe won’t speak exhaustively on the subject but broadly speaking, page tables map virtual addresses to physical ones through a series of page tables, each of which contain entries with physical addresses for the next page table level (along with flags), and at the leaf level the physical addresses of the underlying physical data pages or a special entry such as a swap entry, migration entry or other special marker. Offsets into these pages are provided by the virtual address itself.”…”�”}”(hj§h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mhj–h²hubj)�”}”(hŒÜIn Linux these are divided into five levels - PGD, P4D, PUD, PMD and PTE. Huge pages might eliminate one or two of these levels, but when this is the case we typically refer to the leaf level as the PTE level regardless.”h]”hŒÜIn Linux these are divided into five levels - PGD, P4D, PUD, PMD and PTE. Huge pages might eliminate one or two of these levels, but when this is the case we typically refer to the leaf level as the PTE level regardless.”…”�”}”(hjµh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M#hj–h²hubj�)�”}”(hXSIn instances where the architecture supports fewer page tables than five the kernel cleverly 'folds' page table levels, that is stubbing out functions related to the skipped levels. This allows us to conceptually act as if there were always five levels, even if the compiler might, in practice, eliminate any code relating to missing ones.”h]”j)�”}”(hXSIn instances where the architecture supports fewer page tables than five the kernel cleverly 'folds' page table levels, that is stubbing out functions related to the skipped levels. This allows us to conceptually act as if there were always five levels, even if the compiler might, in practice, eliminate any code relating to missing ones.”h]”hXWIn instances where the architecture supports fewer page tables than five the kernel cleverly ‘folds’ page table levels, that is stubbing out functions related to the skipped levels. This allows us to conceptually act as if there were always five levels, even if the compiler might, in practice, eliminate any code relating to missing ones.”…”�”}”(hjÇh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M'hjÃubah}”(h]”h ]”h"]”h$]”h&]”uh1jŒhj–h²hh³hÇh´Nubj)�”}”(hŒAThere are four key operations typically performed on page tables:”h]”hŒAThere are four key operations typically performed on page tables:”…”�”}”(hjÛh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M.hj–h²hubhŒenumerated_list”“”)�”}”(hhh]”(j)�”}”(hXŽ**Traversing** page tables - Simply reading page tables in order to traverse them. This only requires that the VMA is kept stable, so a lock which establishes this suffices for traversal (there are also lockless variants which eliminate even this requirement, such as :c:func:`!gup_fast`). There is also a special case of page table traversal for non-VMA regions which we consider separately below.”h]”j)�”}”(hXŽ**Traversing** page tables - Simply reading page tables in order to traverse them. This only requires that the VMA is kept stable, so a lock which establishes this suffices for traversal (there are also lockless variants which eliminate even this requirement, such as :c:func:`!gup_fast`). There is also a special case of page table traversal for non-VMA regions which we consider separately below.”h]”(jÓ)�”}”(hŒ**Traversing**”h]”hŒ Traversing”…”�”}”(hjöh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjòubhŒþ page tables - Simply reading page tables in order to traverse them. This only requires that the VMA is kept stable, so a lock which establishes this suffices for traversal (there are also lockless variants which eliminate even this requirement, such as ”…”�”}”(hjòh²hh³Nh´Nubj )�”}”(hŒ:c:func:`!gup_fast`”h]”hŒ gup_fast()”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjòubhŒo). There is also a special case of page table traversal for non-VMA regions which we consider separately below.”…”�”}”(hjòh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M0hjîubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjëh²hh³hÇh´Nubj)�”}”(hŒè**Installing** page table mappings - Whether creating a new mapping or modifying an existing one in such a way as to change its identity. This requires that the VMA is kept stable via an mmap or VMA lock (explicitly not rmap locks).”h]”j)�”}”(hŒè**Installing** page table mappings - Whether creating a new mapping or modifying an existing one in such a way as to change its identity. This requires that the VMA is kept stable via an mmap or VMA lock (explicitly not rmap locks).”h]”(jÓ)�”}”(hŒ**Installing**”h]”hŒ Installing”…”�”}”(hj/h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhj+ubhŒÚ page table mappings - Whether creating a new mapping or modifying an existing one in such a way as to change its identity. This requires that the VMA is kept stable via an mmap or VMA lock (explicitly not rmap locks).”…”�”}”(hj+h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M6hj'ubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjëh²hh³hÇh´Nubj)�”}”(hXë**Zapping/unmapping** page table entries - This is what the kernel calls clearing page table mappings at the leaf level only, whilst leaving all page tables in place. This is a very common operation in the kernel performed on file truncation, the :c:macro:`!MADV_DONTNEED` operation via :c:func:`!madvise`, and others. This is performed by a number of functions including :c:func:`!unmap_mapping_range` and :c:func:`!unmap_mapping_pages`. The VMA need only be kept stable for this operation.”h]”j)�”}”(hXë**Zapping/unmapping** page table entries - This is what the kernel calls clearing page table mappings at the leaf level only, whilst leaving all page tables in place. This is a very common operation in the kernel performed on file truncation, the :c:macro:`!MADV_DONTNEED` operation via :c:func:`!madvise`, and others. This is performed by a number of functions including :c:func:`!unmap_mapping_range` and :c:func:`!unmap_mapping_pages`. The VMA need only be kept stable for this operation.”h]”(jÓ)�”}”(hŒ**Zapping/unmapping**”h]”hŒZapping/unmapping”…”�”}”(hjUh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjQubhŒâ page table entries - This is what the kernel calls clearing page table mappings at the leaf level only, whilst leaving all page tables in place. This is a very common operation in the kernel performed on file truncation, the ”…”�”}”(hjQh²hh³Nh´Nubj )�”}”(hŒ:c:macro:`!MADV_DONTNEED`”h]”hŒ MADV_DONTNEED”…”�”}”(hjgh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-macro”eh"]”h$]”h&]”uh1j hjQubhŒ operation via ”…”�”}”(hjQh²hh³Nh´Nubj )�”}”(hŒ:c:func:`!madvise`”h]”hŒ madvise()”…”�”}”(hjzh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjQubhŒC, and others. This is performed by a number of functions including ”…”�”}”(hjQh²hh³Nh´Nubj )�”}”(hŒ:c:func:`!unmap_mapping_range`”h]”hŒunmap_mapping_range()”…”�”}”(hj�h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjQubhŒ and ”…”�”}”(hjQh²hh³Nh´Nubj )�”}”(hŒ:c:func:`!unmap_mapping_pages`”h]”hŒunmap_mapping_pages()”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjQubhŒ6. The VMA need only be kept stable for this operation.”…”�”}”(hjQh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M:hjMubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjëh²hh³hÇh´Nubj)�”}”(hX“**Freeing** page tables - When finally the kernel removes page tables from a userland process (typically via :c:func:`!free_pgtables`) extreme care must be taken to ensure this is done safely, as this logic finally frees all page tables in the specified range, ignoring existing leaf entries (it assumes the caller has both zapped the range and prevented any further faults or modifications within it). ”h]”j)�”}”(hX’**Freeing** page tables - When finally the kernel removes page tables from a userland process (typically via :c:func:`!free_pgtables`) extreme care must be taken to ensure this is done safely, as this logic finally frees all page tables in the specified range, ignoring existing leaf entries (it assumes the caller has both zapped the range and prevented any further faults or modifications within it).”h]”(jÓ)�”}”(hŒ **Freeing**”h]”hŒFreeing”…”�”}”(hjÇh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjÃubhŒb page tables - When finally the kernel removes page tables from a userland process (typically via ”…”�”}”(hjÃh²hh³Nh´Nubj )�”}”(hŒ:c:func:`!free_pgtables`”h]”hŒfree_pgtables()”…”�”}”(hjÙh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjÃubhX ) extreme care must be taken to ensure this is done safely, as this logic finally frees all page tables in the specified range, ignoring existing leaf entries (it assumes the caller has both zapped the range and prevented any further faults or modifications within it).”…”�”}”(hjÃh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MAhj¿ubah}”(h]”h ]”h"]”h$]”h&]”uh1jhjëh²hh³hÇh´Nubeh}”(h]”h ]”h"]”h$]”h&]”Œenumtype”Œarabic”Œprefix”hŒsuffix”Œ.”uh1jéhj–h²hh³hÇh´M0ubj�)�”}”(hŒ¡Modifying mappings for reclaim or migration is performed under rmap lock as it, like zapping, does not fundamentally modify the identity of what is being mapped.”h]”j)�”}”(hŒ¡Modifying mappings for reclaim or migration is performed under rmap lock as it, like zapping, does not fundamentally modify the identity of what is being mapped.”h]”hŒ¡Modifying mappings for reclaim or migration is performed under rmap lock as it, like zapping, does not fundamentally modify the identity of what is being mapped.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MHhjubah}”(h]”h ]”h"]”h$]”h&]”uh1jŒhj–h²hh³hÇh´Nubj)�”}”(hŒÌ**Traversing** and **zapping** ranges can be performed holding any one of the locks described in the terminology section above - that is the mmap lock, the VMA lock or either of the reverse mapping locks.”h]”(jÓ)�”}”(hŒ**Traversing**”h]”hŒ Traversing”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjubhŒ and ”…”�”}”(hjh²hh³Nh´NubjÓ)�”}”(hŒ **zapping**”h]”hŒzapping”…”�”}”(hj1h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjubhŒ® ranges can be performed holding any one of the locks described in the terminology section above - that is the mmap lock, the VMA lock or either of the reverse mapping locks.”…”�”}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MLhj–h²hubj)�”}”(hX4That is - as long as you keep the relevant VMA **stable** - you are good to go ahead and perform these operations on page tables (though internally, kernel operations that perform writes also acquire internal page table locks to serialise - see the page table implementation detail section for more details).”h]”(hŒ/That is - as long as you keep the relevant VMA ”…”�”}”(hjIh²hh³Nh´NubjÓ)�”}”(hŒ **stable**”h]”hŒstable”…”�”}”(hjQh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjIubhŒû - you are good to go ahead and perform these operations on page tables (though internally, kernel operations that perform writes also acquire internal page table locks to serialise - see the page table implementation detail section for more details).”…”�”}”(hjIh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MPhj–h²hubj�)�”}”(hŒ�We free empty PTE tables on zap under the RCU lock - this does not change the aforementioned locking requirements around zapping.”h]”j)�”}”(hŒ�We free empty PTE tables on zap under the RCU lock - this does not change the aforementioned locking requirements around zapping.”h]”hŒ�We free empty PTE tables on zap under the RCU lock - this does not change the aforementioned locking requirements around zapping.”…”�”}”(hjmh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MUhjiubah}”(h]”h ]”h"]”h$]”h&]”uh1jŒhj–h²hh³hÇh´Nubj)�”}”(hŒ©When **installing** page table entries, the mmap or VMA lock must be held to keep the VMA stable. We explore why this is in the page table locking details section below.”h]”(hŒWhen ”…”�”}”(hj�h²hh³Nh´NubjÓ)�”}”(hŒ**installing**”h]”hŒ installing”…”�”}”(hj‰h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhj�ubhŒ– page table entries, the mmap or VMA lock must be held to keep the VMA stable. We explore why this is in the page table locking details section below.”…”�”}”(hj�h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MXhj–h²hubj)�”}”(hŒŸ**Freeing** page tables is an entirely internal memory management operation and has special requirements (see the page freeing section below for more details).”h]”(jÓ)�”}”(hŒ **Freeing**”h]”hŒFreeing”…”�”}”(hj¥h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhj¡ubhŒ” page tables is an entirely internal memory management operation and has special requirements (see the page freeing section below for more details).”…”�”}”(hj¡h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M\hj–h²hubjs )�”}”(hXBWhen **freeing** page tables, it must not be possible for VMAs containing the ranges those page tables map to be accessible via the reverse mapping. The :c:func:`!free_pgtables` function removes the relevant VMAs from the reverse mappings, but no other VMAs can be permitted to be accessible and span the specified range.”h]”(j)�”}”(hŒ”When **freeing** page tables, it must not be possible for VMAs containing the ranges those page tables map to be accessible via the reverse mapping.”h]”(hŒWhen ”…”�”}”(hjÁh²hh³Nh´NubjÓ)�”}”(hŒ **freeing**”h]”hŒfreeing”…”�”}”(hjÉh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjÁubhŒ„ page tables, it must not be possible for VMAs containing the ranges those page tables map to be accessible via the reverse mapping.”…”�”}”(hjÁh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M_hj½ubj)�”}”(hŒ¬The :c:func:`!free_pgtables` function removes the relevant VMAs from the reverse mappings, but no other VMAs can be permitted to be accessible and span the specified range.”h]”(hŒThe ”…”�”}”(hjáh²hh³Nh´Nubj )�”}”(hŒ:c:func:`!free_pgtables`”h]”hŒfree_pgtables()”…”�”}”(hjéh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjáubhŒ� function removes the relevant VMAs from the reverse mappings, but no other VMAs can be permitted to be accessible and span the specified range.”…”�”}”(hjáh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mchj½ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jr hj–h²hh³hÇh´Nubeh}”(h]”Œ page-tables”ah ]”h"]”Œ page tables”ah$]”h&]”uh1hÈhj¹h²hh³hÇh´MubhÉ)�”}”(hhh]”(hÎ)�”}”(hŒTraversing non-VMA page tables”h]”hŒTraversing non-VMA page tables”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjh²hh³hÇh´Mhubj)�”}”(hŒ‘We've focused above on traversal of page tables belonging to VMAs. It is also possible to traverse page tables which are not represented by VMAs.”h]”hŒ“We’ve focused above on traversal of page tables belonging to VMAs. It is also possible to traverse page tables which are not represented by VMAs.”…”�”}”(hj!h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mjhjh²hubj)�”}”(hXKernel page table mappings themselves are generally managed but whatever part of the kernel established them and the aforementioned locking rules do not apply - for instance vmalloc has its own set of locks which are utilised for establishing and tearing down page its page tables.”h]”hXKernel page table mappings themselves are generally managed but whatever part of the kernel established them and the aforementioned locking rules do not apply - for instance vmalloc has its own set of locks which are utilised for establishing and tearing down page its page tables.”…”�”}”(hj/h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mmhjh²hubj)�”}”(hŒæHowever, for convenience we provide the :c:func:`!walk_kernel_page_table_range` function which is synchronised via the mmap lock on the :c:macro:`!init_mm` kernel instantiation of the :c:struct:`!struct mm_struct` metadata object.”h]”(hŒ(However, for convenience we provide the ”…”�”}”(hj=h²hh³Nh´Nubj )�”}”(hŒ':c:func:`!walk_kernel_page_table_range`”h]”hŒwalk_kernel_page_table_range()”…”�”}”(hjEh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj=ubhŒ9 function which is synchronised via the mmap lock on the ”…”�”}”(hj=h²hh³Nh´Nubj )�”}”(hŒ:c:macro:`!init_mm`”h]”hŒinit_mm”…”�”}”(hjXh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-macro”eh"]”h$]”h&]”uh1j hj=ubhŒ kernel instantiation of the ”…”�”}”(hj=h²hh³Nh´Nubj )�”}”(hŒ:c:struct:`!struct mm_struct`”h]”hŒstruct mm_struct”…”�”}”(hjkh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-struct”eh"]”h$]”h&]”uh1j hj=ubhŒ metadata object.”…”�”}”(hj=h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mrhjh²hubj)�”}”(hŒŸIf an operation requires exclusive access, a write lock is used, but if not, a read lock suffices - we assert only that at least a read lock has been acquired.”h]”hŒŸIf an operation requires exclusive access, a write lock is used, but if not, a read lock suffices - we assert only that at least a read lock has been acquired.”…”�”}”(hj„h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mvhjh²hubj)�”}”(hŒîSince, aside from vmalloc and memory hot plug, kernel page tables are not torn down all that often - this usually suffices, however any caller of this functionality must ensure that any additionally required locks are acquired in advance.”h]”hŒîSince, aside from vmalloc and memory hot plug, kernel page tables are not torn down all that often - this usually suffices, however any caller of this functionality must ensure that any additionally required locks are acquired in advance.”…”�”}”(hj’h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Myhjh²hubj)�”}”(hŒ“We also permit a truly unusual case is the traversal of non-VMA ranges in **userland** ranges, as provided for by :c:func:`!walk_page_range_debug`.”h]”(hŒJWe also permit a truly unusual case is the traversal of non-VMA ranges in ”…”�”}”(hj h²hh³Nh´NubjÓ)�”}”(hŒ **userland**”h]”hŒuserland”…”�”}”(hj¨h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhj ubhŒ ranges, as provided for by ”…”�”}”(hj h²hh³Nh´Nubj )�”}”(hŒ :c:func:`!walk_page_range_debug`”h]”hŒwalk_page_range_debug()”…”�”}”(hjºh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj ubhŒ.”…”�”}”(hj h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M~hjh²hubj)�”}”(hŒüThis has only one user - the general page table dumping logic (implemented in :c:macro:`!mm/ptdump.c`) - which seeks to expose all mappings for debug purposes even if they are highly unusual (possibly architecture-specific) and are not backed by a VMA.”h]”(hŒNThis has only one user - the general page table dumping logic (implemented in ”…”�”}”(hjÓh²hh³Nh´Nubj )�”}”(hŒ:c:macro:`!mm/ptdump.c`”h]”hŒ mm/ptdump.c”…”�”}”(hjÛh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-macro”eh"]”h$]”h&]”uh1j hjÓubhŒ—) - which seeks to expose all mappings for debug purposes even if they are highly unusual (possibly architecture-specific) and are not backed by a VMA.”…”�”}”(hjÓh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M�hjh²hubj)�”}”(hŒ·We must take great care in this case, as the :c:func:`!munmap` implementation detaches VMAs under an mmap write lock before tearing down page tables under a downgraded mmap read lock.”h]”(hŒ-We must take great care in this case, as the ”…”�”}”(hjôh²hh³Nh´Nubj )�”}”(hŒ:c:func:`!munmap`”h]”hŒmunmap()”…”�”}”(hjüh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjôubhŒy implementation detaches VMAs under an mmap write lock before tearing down page tables under a downgraded mmap read lock.”…”�”}”(hjôh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M†hjh²hubj)�”}”(hŒ_This means such an operation could race with this, and thus an mmap **write** lock is required.”h]”(hŒDThis means such an operation could race with this, and thus an mmap ”…”�”}”(hjh²hh³Nh´NubjÓ)�”}”(hŒ **write**”h]”hŒwrite”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjubhŒ lock is required.”…”�”}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MŠhjh²hubeh}”(h]”Œtraversing-non-vma-page-tables”ah ]”h"]”Œtraversing non-vma page tables”ah$]”h&]”uh1hÈhj¹h²hh³hÇh´MhubhÉ)�”}”(hhh]”(hÎ)�”}”(hŒ Lock ordering”h]”hŒ Lock ordering”…”�”}”(hj@h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj=h²hh³hÇh´MŽubj)�”}”(hŒðAs we have multiple locks across the kernel which may or may not be taken at the same time as explicit mm or VMA locks, we have to be wary of lock inversion, and the **order** in which locks are acquired and released becomes very important.”h]”(hŒ¦As we have multiple locks across the kernel which may or may not be taken at the same time as explicit mm or VMA locks, we have to be wary of lock inversion, and the ”…”�”}”(hjNh²hh³Nh´NubjÓ)�”}”(hŒ **order**”h]”hŒorder”…”�”}”(hjVh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjNubhŒA in which locks are acquired and released becomes very important.”…”�”}”(hjNh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M�hj=h²hubj�)�”}”(hXÔLock inversion occurs when two threads need to acquire multiple locks, but in doing so inadvertently cause a mutual deadlock. For example, consider thread 1 which holds lock A and tries to acquire lock B, while thread 2 holds lock B and tries to acquire lock A. Both threads are now deadlocked on each other. However, had they attempted to acquire locks in the same order, one would have waited for the other to complete its work and no deadlock would have occurred.”h]”(j)�”}”(hŒ}Lock inversion occurs when two threads need to acquire multiple locks, but in doing so inadvertently cause a mutual deadlock.”h]”hŒ}Lock inversion occurs when two threads need to acquire multiple locks, but in doing so inadvertently cause a mutual deadlock.”…”�”}”(hjrh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M”hjnubj)�”}”(hŒ‡For example, consider thread 1 which holds lock A and tries to acquire lock B, while thread 2 holds lock B and tries to acquire lock A.”h]”hŒ‡For example, consider thread 1 which holds lock A and tries to acquire lock B, while thread 2 holds lock B and tries to acquire lock A.”…”�”}”(hj€h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M—hjnubj)�”}”(hŒÌBoth threads are now deadlocked on each other. However, had they attempted to acquire locks in the same order, one would have waited for the other to complete its work and no deadlock would have occurred.”h]”hŒÌBoth threads are now deadlocked on each other. However, had they attempted to acquire locks in the same order, one would have waited for the other to complete its work and no deadlock would have occurred.”…”�”}”(hjŽh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mšhjnubeh}”(h]”h ]”h"]”h$]”h&]”uh1jŒhj=h²hh³hÇh´Nubj)�”}”(hŒ~The opening comment in :c:macro:`!mm/rmap.c` describes in detail the required ordering of locks within memory management code:”h]”(hŒThe opening comment in ”…”�”}”(hj¢h²hh³Nh´Nubj )�”}”(hŒ:c:macro:`!mm/rmap.c`”h]”hŒ mm/rmap.c”…”�”}”(hjªh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-macro”eh"]”h$]”h&]”uh1j hj¢ubhŒR describes in detail the required ordering of locks within memory management code:”…”�”}”(hj¢h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mžhj=h²hubhŒ literal_block”“”)�”}”(hXpinode->i_rwsem (while writing or truncating, not reading or faulting) mm->mmap_lock mapping->invalidate_lock (in filemap_fault) folio_lock hugetlbfs_i_mmap_rwsem_key (in huge_pmd_share, see hugetlbfs below) vma_start_write mapping->i_mmap_rwsem anon_vma->rwsem mm->page_table_lock or pte_lock swap_lock (in swap_duplicate, swap_info_get) mmlist_lock (in mmput, drain_mmlist and others) mapping->private_lock (in block_dirty_folio) i_pages lock (widely used) lruvec->lru_lock (in folio_lruvec_lock_irq) inode->i_lock (in set_page_dirty's __mark_inode_dirty) bdi.wb->list_lock (in set_page_dirty's __mark_inode_dirty) sb_lock (within inode_lock in fs/fs-writeback.c) i_pages lock (widely used, in set_page_dirty, in arch-dependent flush_dcache_mmap_lock, within bdi.wb->list_lock in __sync_single_inode)”h]”hXpinode->i_rwsem (while writing or truncating, not reading or faulting) mm->mmap_lock mapping->invalidate_lock (in filemap_fault) folio_lock hugetlbfs_i_mmap_rwsem_key (in huge_pmd_share, see hugetlbfs below) vma_start_write mapping->i_mmap_rwsem anon_vma->rwsem mm->page_table_lock or pte_lock swap_lock (in swap_duplicate, swap_info_get) mmlist_lock (in mmput, drain_mmlist and others) mapping->private_lock (in block_dirty_folio) i_pages lock (widely used) lruvec->lru_lock (in folio_lruvec_lock_irq) inode->i_lock (in set_page_dirty's __mark_inode_dirty) bdi.wb->list_lock (in set_page_dirty's __mark_inode_dirty) sb_lock (within inode_lock in fs/fs-writeback.c) i_pages lock (widely used, in set_page_dirty, in arch-dependent flush_dcache_mmap_lock, within bdi.wb->list_lock in __sync_single_inode)”…”�”}”hjÅsbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆŒforce”‰Œlanguage”Œnone”Œhighlight_args”}”uh1jÃh³hÇh´M¡hj=h²hubj)�”}”(hŒjThere is also a file-system specific lock ordering comment located at the top of :c:macro:`!mm/filemap.c`:”h]”(hŒQThere is also a file-system specific lock ordering comment located at the top of ”…”�”}”(hjØh²hh³Nh´Nubj )�”}”(hŒ:c:macro:`!mm/filemap.c`”h]”hŒ mm/filemap.c”…”�”}”(hjàh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-macro”eh"]”h$]”h&]”uh1j hjØubhŒ:”…”�”}”(hjØh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M¸hj=h²hubjÄ)�”}”(hXÆ->i_mmap_rwsem (truncate_pagecache) ->private_lock (__free_pte->block_dirty_folio) ->swap_lock (exclusive_swap_page, others) ->i_pages lock ->i_rwsem ->invalidate_lock (acquired by fs in truncate path) ->i_mmap_rwsem (truncate->unmap_mapping_range) ->mmap_lock ->i_mmap_rwsem ->page_table_lock or pte_lock (various, mainly in memory.c) ->i_pages lock (arch-dependent flush_dcache_mmap_lock) ->mmap_lock ->invalidate_lock (filemap_fault) ->lock_page (filemap_fault, access_process_vm) ->i_rwsem (generic_perform_write) ->mmap_lock (fault_in_readable->do_page_fault) bdi->wb.list_lock sb_lock (fs/fs-writeback.c) ->i_pages lock (__sync_single_inode) ->i_mmap_rwsem ->anon_vma.lock (vma_merge) ->anon_vma.lock ->page_table_lock or pte_lock (anon_vma_prepare and various) ->page_table_lock or pte_lock ->swap_lock (try_to_unmap_one) ->private_lock (try_to_unmap_one) ->i_pages lock (try_to_unmap_one) ->lruvec->lru_lock (follow_page_mask->mark_page_accessed) ->lruvec->lru_lock (check_pte_range->folio_isolate_lru) ->private_lock (folio_remove_rmap_pte->set_page_dirty) ->i_pages lock (folio_remove_rmap_pte->set_page_dirty) bdi.wb->list_lock (folio_remove_rmap_pte->set_page_dirty) ->inode->i_lock (folio_remove_rmap_pte->set_page_dirty) bdi.wb->list_lock (zap_pte_range->set_page_dirty) ->inode->i_lock (zap_pte_range->set_page_dirty) ->private_lock (zap_pte_range->block_dirty_folio)”h]”hXÆ->i_mmap_rwsem (truncate_pagecache) ->private_lock (__free_pte->block_dirty_folio) ->swap_lock (exclusive_swap_page, others) ->i_pages lock ->i_rwsem ->invalidate_lock (acquired by fs in truncate path) ->i_mmap_rwsem (truncate->unmap_mapping_range) ->mmap_lock ->i_mmap_rwsem ->page_table_lock or pte_lock (various, mainly in memory.c) ->i_pages lock (arch-dependent flush_dcache_mmap_lock) ->mmap_lock ->invalidate_lock (filemap_fault) ->lock_page (filemap_fault, access_process_vm) ->i_rwsem (generic_perform_write) ->mmap_lock (fault_in_readable->do_page_fault) bdi->wb.list_lock sb_lock (fs/fs-writeback.c) ->i_pages lock (__sync_single_inode) ->i_mmap_rwsem ->anon_vma.lock (vma_merge) ->anon_vma.lock ->page_table_lock or pte_lock (anon_vma_prepare and various) ->page_table_lock or pte_lock ->swap_lock (try_to_unmap_one) ->private_lock (try_to_unmap_one) ->i_pages lock (try_to_unmap_one) ->lruvec->lru_lock (follow_page_mask->mark_page_accessed) ->lruvec->lru_lock (check_pte_range->folio_isolate_lru) ->private_lock (folio_remove_rmap_pte->set_page_dirty) ->i_pages lock (folio_remove_rmap_pte->set_page_dirty) bdi.wb->list_lock (folio_remove_rmap_pte->set_page_dirty) ->inode->i_lock (folio_remove_rmap_pte->set_page_dirty) bdi.wb->list_lock (zap_pte_range->set_page_dirty) ->inode->i_lock (zap_pte_range->set_page_dirty) ->private_lock (zap_pte_range->block_dirty_folio)”…”�”}”hjùsbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆjÓ‰jÔjÕjÖ}”uh1jÃh³hÇh´M»hj=h²hubj)�”}”(hŒsPlease check the current state of these comments which may have changed since the time of writing of this document.”h]”hŒsPlease check the current state of these comments which may have changed since the time of writing of this document.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mêhj=h²hubeh}”(h]”Œ lock-ordering”ah ]”h"]”Œ lock ordering”ah$]”h&]”uh1hÈhj¹h²hh³hÇh´MŽubeh}”(h]”Œlocking”ah ]”h"]”Œlocking”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´K!ubhÉ)�”}”(hhh]”(hÎ)�”}”(hŒLocking Implementation Details”h]”hŒLocking Implementation Details”…”�”}”(hj)h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj&h²hh³hÇh´Mïubjs )�”}”(hŒnLocking rules for PTE-level page tables are very different from locking rules for page tables at other levels.”h]”j)�”}”(hŒnLocking rules for PTE-level page tables are very different from locking rules for page tables at other levels.”h]”hŒnLocking rules for PTE-level page tables are very different from locking rules for page tables at other levels.”…”�”}”(hj;h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mñhj7ubah}”(h]”h ]”h"]”h$]”h&]”uh1jr hj&h²hh³hÇh´NubhÉ)�”}”(hhh]”(hÎ)�”}”(hŒPage table locking details”h]”hŒPage table locking details”…”�”}”(hjRh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjOh²hh³hÇh´Mõubj�)�”}”(hŒ¹This section explores page table locking requirements for page tables encompassed by a VMA. See the above section on non-VMA page table traversal for details on how we handle that case.”h]”j)�”}”(hŒ¹This section explores page table locking requirements for page tables encompassed by a VMA. See the above section on non-VMA page table traversal for details on how we handle that case.”h]”hŒ¹This section explores page table locking requirements for page tables encompassed by a VMA. See the above section on non-VMA page table traversal for details on how we handle that case.”…”�”}”(hjdh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M÷hj`ubah}”(h]”h ]”h"]”h$]”h&]”uh1jŒhjOh²hh³hÇh´Nubj)�”}”(hŒwIn addition to the locks described in the terminology section above, we have additional locks dedicated to page tables:”h]”hŒwIn addition to the locks described in the terminology section above, we have additional locks dedicated to page tables:”…”�”}”(hjxh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MûhjOh²hubj)�”}”(hhh]”(j)�”}”(hŒÃ**Higher level page table locks** - Higher level page tables, that is PGD, P4D and PUD each make use of the process address space granularity :c:member:`!mm->page_table_lock` lock when modified. ”h]”j)�”}”(hŒÂ**Higher level page table locks** - Higher level page tables, that is PGD, P4D and PUD each make use of the process address space granularity :c:member:`!mm->page_table_lock` lock when modified.”h]”(jÓ)�”}”(hŒ!**Higher level page table locks**”h]”hŒHigher level page table locks”…”�”}”(hj‘h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhj�ubhŒm - Higher level page tables, that is PGD, P4D and PUD each make use of the process address space granularity ”…”�”}”(hj�h²hh³Nh´Nubj )�”}”(hŒ :c:member:`!mm->page_table_lock`”h]”hŒmm->page_table_lock”…”�”}”(hj£h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hj�ubhŒ lock when modified.”…”�”}”(hj�h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mþhj‰ubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj†h²hh³hÇh´Nubj)�”}”(hX—**Fine-grained page table locks** - PMDs and PTEs each have fine-grained locks either kept within the folios describing the page tables or allocated separated and pointed at by the folios if :c:macro:`!ALLOC_SPLIT_PTLOCKS` is set. The PMD spin lock is obtained via :c:func:`!pmd_lock`, however PTEs are mapped into higher memory (if a 32-bit system) and carefully locked via :c:func:`!pte_offset_map_lock`. ”h]”j)�”}”(hX–**Fine-grained page table locks** - PMDs and PTEs each have fine-grained locks either kept within the folios describing the page tables or allocated separated and pointed at by the folios if :c:macro:`!ALLOC_SPLIT_PTLOCKS` is set. The PMD spin lock is obtained via :c:func:`!pmd_lock`, however PTEs are mapped into higher memory (if a 32-bit system) and carefully locked via :c:func:`!pte_offset_map_lock`.”h]”(jÓ)�”}”(hŒ!**Fine-grained page table locks**”h]”hŒFine-grained page table locks”…”�”}”(hjÊh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjÆubhŒž - PMDs and PTEs each have fine-grained locks either kept within the folios describing the page tables or allocated separated and pointed at by the folios if ”…”�”}”(hjÆh²hh³Nh´Nubj )�”}”(hŒ:c:macro:`!ALLOC_SPLIT_PTLOCKS`”h]”hŒALLOC_SPLIT_PTLOCKS”…”�”}”(hjÜh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-macro”eh"]”h$]”h&]”uh1j hjÆubhŒ+ is set. The PMD spin lock is obtained via ”…”�”}”(hjÆh²hh³Nh´Nubj )�”}”(hŒ:c:func:`!pmd_lock`”h]”hŒ pmd_lock()”…”�”}”(hjïh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjÆubhŒ[, however PTEs are mapped into higher memory (if a 32-bit system) and carefully locked via ”…”�”}”(hjÆh²hh³Nh´Nubj )�”}”(hŒ:c:func:`!pte_offset_map_lock`”h]”hŒpte_offset_map_lock()”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjÆubhŒ.”…”�”}”(hjÆh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MhjÂubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj†h²hh³hÇh´Nubeh}”(h]”h ]”h"]”h$]”h&]”j�jžuh1jh³hÇh´MþhjOh²hubj)�”}”(hŒvThese locks represent the minimum required to interact with each page table level, but there are further requirements.”h]”hŒvThese locks represent the minimum required to interact with each page table level, but there are further requirements.”…”�”}”(hj'h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M hjOh²hubj)�”}”(hŒüImportantly, note that on a **traversal** of page tables, sometimes no such locks are taken. However, at the PTE level, at least concurrent page table deletion must be prevented (using RCU) and the page table must be mapped into high memory, see below.”h]”(hŒImportantly, note that on a ”…”�”}”(hj5h²hh³Nh´NubjÓ)�”}”(hŒ **traversal**”h]”hŒ traversal”…”�”}”(hj=h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhj5ubhŒÓ of page tables, sometimes no such locks are taken. However, at the PTE level, at least concurrent page table deletion must be prevented (using RCU) and the page table must be mapped into high memory, see below.”…”�”}”(hj5h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M hjOh²hubj)�”}”(hŒxWhether care is taken on reading the page table entries depends on the architecture, see the section on atomicity below.”h]”hŒxWhether care is taken on reading the page table entries depends on the architecture, see the section on atomicity below.”…”�”}”(hjUh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MhjOh²hubhÉ)�”}”(hhh]”(hÎ)�”}”(hŒ Locking rules”h]”hŒ Locking rules”…”�”}”(hjfh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjch²hh³hÇh´Mubj)�”}”(hŒCWe establish basic locking rules when interacting with page tables:”h]”hŒCWe establish basic locking rules when interacting with page tables:”…”�”}”(hjth²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mhjch²hubj)�”}”(hhh]”(j)�”}”(hŒÞWhen changing a page table entry the page table lock for that page table **must** be held, except if you can safely assume nobody can access the page tables concurrently (such as on invocation of :c:func:`!free_pgtables`).”h]”j)�”}”(hŒÞWhen changing a page table entry the page table lock for that page table **must** be held, except if you can safely assume nobody can access the page tables concurrently (such as on invocation of :c:func:`!free_pgtables`).”h]”(hŒIWhen changing a page table entry the page table lock for that page table ”…”�”}”(hj‰h²hh³Nh´NubjÓ)�”}”(hŒ**must**”h]”hŒmust”…”�”}”(hj‘h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhj‰ubhŒs be held, except if you can safely assume nobody can access the page tables concurrently (such as on invocation of ”…”�”}”(hj‰h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!free_pgtables`”h]”hŒfree_pgtables()”…”�”}”(hj£h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj‰ubhŒ).”…”�”}”(hj‰h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mhj…ubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj‚h²hh³hÇh´Nubj)�”}”(hŒ{Reads from and writes to page table entries must be *appropriately* atomic. See the section on atomicity below for details.”h]”j)�”}”(hŒ{Reads from and writes to page table entries must be *appropriately* atomic. See the section on atomicity below for details.”h]”(hŒ4Reads from and writes to page table entries must be ”…”�”}”(hjÆh²hh³Nh´Nubj\)�”}”(hŒ*appropriately*”h]”hŒ appropriately”…”�”}”(hjÎh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j[hjÆubhŒ8 atomic. See the section on atomicity below for details.”…”�”}”(hjÆh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MhjÂubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj‚h²hh³hÇh´Nubj)�”}”(hŒ«Populating previously empty entries requires that the mmap or VMA locks are held (read or write), doing so with only rmap locks would be dangerous (see the warning below).”h]”j)�”}”(hŒ«Populating previously empty entries requires that the mmap or VMA locks are held (read or write), doing so with only rmap locks would be dangerous (see the warning below).”h]”hŒ«Populating previously empty entries requires that the mmap or VMA locks are held (read or write), doing so with only rmap locks would be dangerous (see the warning below).”…”�”}”(hjðh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mhjìubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj‚h²hh³hÇh´Nubj)�”}”(hŒ�As mentioned previously, zapping can be performed while simply keeping the VMA stable, that is holding any one of the mmap, VMA or rmap locks. ”h]”j)�”}”(hŒŽAs mentioned previously, zapping can be performed while simply keeping the VMA stable, that is holding any one of the mmap, VMA or rmap locks.”h]”hŒŽAs mentioned previously, zapping can be performed while simply keeping the VMA stable, that is holding any one of the mmap, VMA or rmap locks.”…”�”}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M!hjubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj‚h²hh³hÇh´Nubeh}”(h]”h ]”h"]”h$]”h&]”j�jžuh1jh³hÇh´Mhjch²hubjs )�”}”(hXPopulating previously empty entries is dangerous as, when unmapping VMAs, :c:func:`!vms_clear_ptes` has a window of time between zapping (via :c:func:`!unmap_vmas`) and freeing page tables (via :c:func:`!free_pgtables`), where the VMA is still visible in the rmap tree. :c:func:`!free_pgtables` assumes that the zap has already been performed and removes PTEs unconditionally (along with all other page tables in the freed range), so installing new PTE entries could leak memory and also cause other unexpected and dangerous behaviour.”h]”j)�”}”(hXPopulating previously empty entries is dangerous as, when unmapping VMAs, :c:func:`!vms_clear_ptes` has a window of time between zapping (via :c:func:`!unmap_vmas`) and freeing page tables (via :c:func:`!free_pgtables`), where the VMA is still visible in the rmap tree. :c:func:`!free_pgtables` assumes that the zap has already been performed and removes PTEs unconditionally (along with all other page tables in the freed range), so installing new PTE entries could leak memory and also cause other unexpected and dangerous behaviour.”h]”(hŒJPopulating previously empty entries is dangerous as, when unmapping VMAs, ”…”�”}”(hj&h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!vms_clear_ptes`”h]”hŒvms_clear_ptes()”…”�”}”(hj.h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj&ubhŒ+ has a window of time between zapping (via ”…”�”}”(hj&h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!unmap_vmas`”h]”hŒ unmap_vmas()”…”�”}”(hjAh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj&ubhŒ) and freeing page tables (via ”…”�”}”(hj&h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!free_pgtables`”h]”hŒfree_pgtables()”…”�”}”(hjTh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj&ubhŒ4), where the VMA is still visible in the rmap tree. ”…”�”}”(hj&h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!free_pgtables`”h]”hŒfree_pgtables()”…”�”}”(hjgh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj&ubhŒñ assumes that the zap has already been performed and removes PTEs unconditionally (along with all other page tables in the freed range), so installing new PTE entries could leak memory and also cause other unexpected and dangerous behaviour.”…”�”}”(hj&h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M$hj"ubah}”(h]”h ]”h"]”h$]”h&]”uh1jr hjch²hh³hÇh´Nubj)�”}”(hŒsThere are additional rules applicable when moving page tables, which we discuss in the section on this topic below.”h]”hŒsThere are additional rules applicable when moving page tables, which we discuss in the section on this topic below.”…”�”}”(hj†h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M.hjch²hubj)�”}”(hŒzPTE-level page tables are different from page tables at other levels, and there are extra requirements for accessing them:”h]”hŒzPTE-level page tables are different from page tables at other levels, and there are extra requirements for accessing them:”…”�”}”(hj”h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M1hjch²hubj)�”}”(hhh]”(j)�”}”(hŒyOn 32-bit architectures, they may be in high memory (meaning they need to be mapped into kernel memory to be accessible).”h]”j)�”}”(hŒyOn 32-bit architectures, they may be in high memory (meaning they need to be mapped into kernel memory to be accessible).”h]”hŒyOn 32-bit architectures, they may be in high memory (meaning they need to be mapped into kernel memory to be accessible).”…”�”}”(hj©h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M4hj¥ubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj¢h²hh³hÇh´Nubj)�”}”(hXWhen empty, they can be unlinked and RCU-freed while holding an mmap lock or rmap lock for reading in combination with the PTE and PMD page table locks. In particular, this happens in :c:func:`!retract_page_tables` when handling :c:macro:`!MADV_COLLAPSE`. So accessing PTE-level page tables requires at least holding an RCU read lock; but that only suffices for readers that can tolerate racing with concurrent page table updates such that an empty PTE is observed (in a page table that has actually already been detached and marked for RCU freeing) while another new page table has been installed in the same location and filled with entries. Writers normally need to take the PTE lock and revalidate that the PMD entry still refers to the same PTE-level page table. If the writer does not care whether it is the same PTE-level page table, it can take the PMD lock and revalidate that the contents of pmd entry still meet the requirements. In particular, this also happens in :c:func:`!retract_page_tables` when handling :c:macro:`!MADV_COLLAPSE`. ”h]”j)�”}”(hXWhen empty, they can be unlinked and RCU-freed while holding an mmap lock or rmap lock for reading in combination with the PTE and PMD page table locks. In particular, this happens in :c:func:`!retract_page_tables` when handling :c:macro:`!MADV_COLLAPSE`. So accessing PTE-level page tables requires at least holding an RCU read lock; but that only suffices for readers that can tolerate racing with concurrent page table updates such that an empty PTE is observed (in a page table that has actually already been detached and marked for RCU freeing) while another new page table has been installed in the same location and filled with entries. Writers normally need to take the PTE lock and revalidate that the PMD entry still refers to the same PTE-level page table. If the writer does not care whether it is the same PTE-level page table, it can take the PMD lock and revalidate that the contents of pmd entry still meet the requirements. In particular, this also happens in :c:func:`!retract_page_tables` when handling :c:macro:`!MADV_COLLAPSE`.”h]”(hŒ¸When empty, they can be unlinked and RCU-freed while holding an mmap lock or rmap lock for reading in combination with the PTE and PMD page table locks. In particular, this happens in ”…”�”}”(hjÁh²hh³Nh´Nubj )�”}”(hŒ:c:func:`!retract_page_tables`”h]”hŒretract_page_tables()”…”�”}”(hjÉh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjÁubhŒ when handling ”…”�”}”(hjÁh²hh³Nh´Nubj )�”}”(hŒ:c:macro:`!MADV_COLLAPSE`”h]”hŒ MADV_COLLAPSE”…”�”}”(hjÜh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-macro”eh"]”h$]”h&]”uh1j hjÁubhXÓ. So accessing PTE-level page tables requires at least holding an RCU read lock; but that only suffices for readers that can tolerate racing with concurrent page table updates such that an empty PTE is observed (in a page table that has actually already been detached and marked for RCU freeing) while another new page table has been installed in the same location and filled with entries. Writers normally need to take the PTE lock and revalidate that the PMD entry still refers to the same PTE-level page table. If the writer does not care whether it is the same PTE-level page table, it can take the PMD lock and revalidate that the contents of pmd entry still meet the requirements. In particular, this also happens in ”…”�”}”(hjÁh²hh³Nh´Nubj )�”}”(hŒ:c:func:`!retract_page_tables`”h]”hŒretract_page_tables()”…”�”}”(hjïh²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjÁubhŒ when handling ”…”�”}”(hjÁh²hh³Nh´Nubj )�”}”(hŒ:c:macro:`!MADV_COLLAPSE`”h]”hŒ MADV_COLLAPSE”…”�”}”(hj h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-macro”eh"]”h$]”h&]”uh1j hjÁubhŒ.”…”�”}”(hjÁh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M6hj½ubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj¢h²hh³hÇh´Nubeh}”(h]”h ]”h"]”h$]”h&]”j�jžuh1jh³hÇh´M4hjch²hubj)�”}”(hX^To access PTE-level page tables, a helper like :c:func:`!pte_offset_map_lock` or :c:func:`!pte_offset_map` can be used depending on stability requirements. These map the page table into kernel memory if required, take the RCU lock, and depending on variant, may also look up or acquire the PTE lock. See the comment on :c:func:`!pte_offset_map_lock`.”h]”(hŒ/To access PTE-level page tables, a helper like ”…”�”}”(hj' h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!pte_offset_map_lock`”h]”hŒpte_offset_map_lock()”…”�”}”(hj/ h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj' ubhŒ or ”…”�”}”(hj' h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!pte_offset_map`”h]”hŒpte_offset_map()”…”�”}”(hjB h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj' ubhŒÕ can be used depending on stability requirements. These map the page table into kernel memory if required, take the RCU lock, and depending on variant, may also look up or acquire the PTE lock. See the comment on ”…”�”}”(hj' h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!pte_offset_map_lock`”h]”hŒpte_offset_map_lock()”…”�”}”(hjU h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj' ubhŒ.”…”�”}”(hj' h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MFhjch²hubeh}”(h]”Œ locking-rules”ah ]”h"]”Œ locking rules”ah$]”h&]”uh1hÈhjOh²hh³hÇh´MubhÉ)�”}”(hhh]”(hÎ)�”}”(hŒ Atomicity”h]”hŒ Atomicity”…”�”}”(hjy h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjv h²hh³hÇh´MMubj)�”}”(hX`Regardless of page table locks, the MMU hardware concurrently updates accessed and dirty bits (perhaps more, depending on architecture). Additionally, page table traversal operations in parallel (though holding the VMA stable) and functionality like GUP-fast locklessly traverses (that is reads) page tables, without even keeping the VMA stable at all.”h]”hX`Regardless of page table locks, the MMU hardware concurrently updates accessed and dirty bits (perhaps more, depending on architecture). Additionally, page table traversal operations in parallel (though holding the VMA stable) and functionality like GUP-fast locklessly traverses (that is reads) page tables, without even keeping the VMA stable at all.”…”�”}”(hj‡ h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MOhjv h²hubj)�”}”(hŒÙWhen performing a page table traversal and keeping the VMA stable, whether a read must be performed once and only once or not depends on the architecture (for instance x86-64 does not require any special precautions).”h]”hŒÙWhen performing a page table traversal and keeping the VMA stable, whether a read must be performed once and only once or not depends on the architecture (for instance x86-64 does not require any special precautions).”…”�”}”(hj• h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MUhjv h²hubj)�”}”(hXaIf a write is being performed, or if a read informs whether a write takes place (on an installation of a page table entry say, for instance in :c:func:`!__pud_install`), special care must always be taken. In these cases we can never assume that page table locks give us entirely exclusive access, and must retrieve page table entries once and only once.”h]”(hŒ�If a write is being performed, or if a read informs whether a write takes place (on an installation of a page table entry say, for instance in ”…”�”}”(hj£ h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!__pud_install`”h]”hŒ__pud_install()”…”�”}”(hj« h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj£ ubhŒº), special care must always be taken. In these cases we can never assume that page table locks give us entirely exclusive access, and must retrieve page table entries once and only once.”…”�”}”(hj£ h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MYhjv h²hubj)�”}”(hXIf we are reading page table entries, then we need only ensure that the compiler does not rearrange our loads. This is achieved via :c:func:`!pXXp_get` functions - :c:func:`!pgdp_get`, :c:func:`!p4dp_get`, :c:func:`!pudp_get`, :c:func:`!pmdp_get`, and :c:func:`!ptep_get`.”h]”(hŒ„If we are reading page table entries, then we need only ensure that the compiler does not rearrange our loads. This is achieved via ”…”�”}”(hjÄ h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!pXXp_get`”h]”hŒ pXXp_get()”…”�”}”(hjÌ h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjÄ ubhŒ functions - ”…”�”}”(hjÄ h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!pgdp_get`”h]”hŒ pgdp_get()”…”�”}”(hjß h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjÄ ubhŒ, ”…”�”}”(hjÄ h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!p4dp_get`”h]”hŒ p4dp_get()”…”�”}”(hjò h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjÄ ubhŒ, ”…”�”}”hjÄ sbj )�”}”(hŒ:c:func:`!pudp_get`”h]”hŒ pudp_get()”…”�”}”(hj!h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjÄ ubhŒ, ”…”�”}”(hjÄ h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!pmdp_get`”h]”hŒ pmdp_get()”…”�”}”(hj!h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjÄ ubhŒ, and ”…”�”}”(hjÄ h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!ptep_get`”h]”hŒ ptep_get()”…”�”}”(hj+!h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjÄ ubhŒ.”…”�”}”(hjÄ h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M_hjv h²hubj)�”}”(hŒlEach of these uses :c:func:`!READ_ONCE` to guarantee that the compiler reads the page table entry only once.”h]”(hŒEach of these uses ”…”�”}”(hjD!h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!READ_ONCE`”h]”hŒ READ_ONCE()”…”�”}”(hjL!h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjD!ubhŒE to guarantee that the compiler reads the page table entry only once.”…”�”}”(hjD!h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mdhjv h²hubj)�”}”(hŒÔHowever, if we wish to manipulate an existing page table entry and care about the previously stored data, we must go further and use an hardware atomic operation as, for example, in :c:func:`!ptep_get_and_clear`.”h]”(hŒ¶However, if we wish to manipulate an existing page table entry and care about the previously stored data, we must go further and use an hardware atomic operation as, for example, in ”…”�”}”(hje!h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!ptep_get_and_clear`”h]”hŒptep_get_and_clear()”…”�”}”(hjm!h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hje!ubhŒ.”…”�”}”(hje!h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mghjv h²hubj)�”}”(hXYEqually, operations that do not rely on the VMA being held stable, such as GUP-fast (see :c:func:`!gup_fast` and its various page table level handlers like :c:func:`!gup_fast_pte_range`), must very carefully interact with page table entries, using functions such as :c:func:`!ptep_get_lockless` and equivalent for higher level page table levels.”h]”(hŒYEqually, operations that do not rely on the VMA being held stable, such as GUP-fast (see ”…”�”}”(hj†!h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!gup_fast`”h]”hŒ gup_fast()”…”�”}”(hjŽ!h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj†!ubhŒ0 and its various page table level handlers like ”…”�”}”(hj†!h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!gup_fast_pte_range`”h]”hŒgup_fast_pte_range()”…”�”}”(hj¡!h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj†!ubhŒQ), must very carefully interact with page table entries, using functions such as ”…”�”}”(hj†!h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!ptep_get_lockless`”h]”hŒptep_get_lockless()”…”�”}”(hj´!h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj†!ubhŒ3 and equivalent for higher level page table levels.”…”�”}”(hj†!h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mkhjv h²hubj)�”}”(hŒØWrites to page table entries must also be appropriately atomic, as established by :c:func:`!set_pXX` functions - :c:func:`!set_pgd`, :c:func:`!set_p4d`, :c:func:`!set_pud`, :c:func:`!set_pmd`, and :c:func:`!set_pte`.”•h]”(hŒRWrites to page table entries must also be appropriately atomic, as established by ”…”�”}”(hjÍ!h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!set_pXX`”h]”hŒ set_pXX()”…”�”}”(hjÕ!h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjÍ!ubhŒ functions - ”…”�”}”(hjÍ!h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!set_pgd`”h]”hŒ set_pgd()”…”�”}”(hjè!h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjÍ!ubhŒ, ”…”�”}”(hjÍ!h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!set_p4d`”h]”hŒ set_p4d()”…”�”}”(hjû!h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjÍ!ubhŒ, ”…”�”}”(hjÍ!h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!set_pud`”h]”hŒ set_pud()”…”�”}”(hj"h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjÍ!ubhŒ, ”…”�”}”hjÍ!sbj )�”}”(hŒ:c:func:`!set_pmd`”h]”hŒ set_pmd()”…”�”}”(hj!"h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjÍ!ubhŒ, and ”…”�”}”(hjÍ!h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!set_pte`”h]”hŒ set_pte()”…”�”}”(hj4"h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjÍ!ubhŒ.”…”�”}”(hjÍ!h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mqhjv h²hubj)�”}”(hŒçEqually functions which clear page table entries must be appropriately atomic, as in :c:func:`!pXX_clear` functions - :c:func:`!pgd_clear`, :c:func:`!p4d_clear`, :c:func:`!pud_clear`, :c:func:`!pmd_clear`, and :c:func:`!pte_clear`.”h]”(hŒUEqually functions which clear page table entries must be appropriately atomic, as in ”…”�”}”(hjM"h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!pXX_clear`”h]”hŒ pXX_clear()”…”�”}”(hjU"h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjM"ubhŒ functions - ”…”�”}”(hjM"h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!pgd_clear`”h]”hŒ pgd_clear()”…”�”}”(hjh"h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjM"ubhŒ, ”…”�”}”(hjM"h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!p4d_clear`”h]”hŒ p4d_clear()”…”�”}”(hj{"h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjM"ubhŒ, ”…”�”}”(hjM"h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!pud_clear`”h]”hŒ pud_clear()”…”�”}”(hjŽ"h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjM"ubhŒ, ”…”�”}”hjM"sbj )�”}”(hŒ:c:func:`!pmd_clear`”h]”hŒ pmd_clear()”…”�”}”(hj¡"h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjM"ubhŒ, and ”…”�”}”(hjM"h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!pte_clear`”h]”hŒ pte_clear()”…”�”}”(hj´"h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjM"ubhŒ.”…”�”}”(hjM"h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Muhjv h²hubeh}”(h]”Œ atomicity”ah ]”h"]”Œ atomicity”ah$]”h&]”uh1hÈhjOh²hh³hÇh´MMubhÉ)�”}”(hhh]”(hÎ)�”}”(hŒPage table installation”h]”hŒPage table installation”…”�”}”(hjØ"h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjÕ"h²hh³hÇh´M{ubj)�”}”(hŒ»Page table installation is performed with the VMA held stable explicitly by an mmap or VMA lock in read or write mode (see the warning in the locking rules section for details as to why).”h]”hŒ»Page table installation is performed with the VMA held stable explicitly by an mmap or VMA lock in read or write mode (see the warning in the locking rules section for details as to why).”…”�”}”(hjæ"h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M}hjÕ"h²hubj)�”}”(hŒýWhen allocating a P4D, PUD or PMD and setting the relevant entry in the above PGD, P4D or PUD, the :c:member:`!mm->page_table_lock` must be held. This is acquired in :c:func:`!__p4d_alloc`, :c:func:`!__pud_alloc` and :c:func:`!__pmd_alloc` respectively.”h]”(hŒcWhen allocating a P4D, PUD or PMD and setting the relevant entry in the above PGD, P4D or PUD, the ”…”�”}”(hjô"h²hh³Nh´Nubj )�”}”(hŒ :c:member:`!mm->page_table_lock`”h]”hŒmm->page_table_lock”…”�”}”(hjü"h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hjô"ubhŒ# must be held. This is acquired in ”…”�”}”(hjô"h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!__p4d_alloc`”h]”hŒ __p4d_alloc()”…”�”}”(hj#h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjô"ubhŒ, ”…”�”}”(hjô"h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!__pud_alloc`”h]”hŒ __pud_alloc()”…”�”}”(hj"#h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjô"ubhŒ and ”…”�”}”(hjô"h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!__pmd_alloc`”h]”hŒ __pmd_alloc()”…”�”}”(hj5#h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjô"ubhŒ respectively.”…”�”}”(hjô"h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M�hjÕ"h²hubj�)�”}”(hŒ½:c:func:`!__pmd_alloc` actually invokes :c:func:`!pud_lock` and :c:func:`!pud_lockptr` in turn, however at the time of writing it ultimately references the :c:member:`!mm->page_table_lock`.”h]”j)�”}”(hŒ½:c:func:`!__pmd_alloc` actually invokes :c:func:`!pud_lock` and :c:func:`!pud_lockptr` in turn, however at the time of writing it ultimately references the :c:member:`!mm->page_table_lock`.”h]”(j )�”}”(hŒ:c:func:`!__pmd_alloc`”h]”hŒ __pmd_alloc()”…”�”}”(hjV#h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjR#ubhŒ actually invokes ”…”�”}”(hjR#h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!pud_lock`”h]”hŒ pud_lock()”…”�”}”(hji#h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjR#ubhŒ and ”…”�”}”(hjR#h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!pud_lockptr`”h]”hŒ pud_lockptr()”…”�”}”(hj|#h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjR#ubhŒF in turn, however at the time of writing it ultimately references the ”…”�”}”(hjR#h²hh³Nh´Nubj )�”}”(hŒ :c:member:`!mm->page_table_lock`”h]”hŒmm->page_table_lock”…”�”}”(hj�#h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hjR#ubhŒ.”…”�”}”(hjR#h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M†hjN#ubah}”(h]”h ]”h"]”h$]”h&]”uh1jŒhjÕ"h²hh³hÇh´Nubj)�”}”(hXBAllocating a PTE will either use the :c:member:`!mm->page_table_lock` or, if :c:macro:`!USE_SPLIT_PMD_PTLOCKS` is defined, a lock embedded in the PMD physical page metadata in the form of a :c:struct:`!struct ptdesc`, acquired by :c:func:`!pmd_ptdesc` called from :c:func:`!pmd_lock` and ultimately :c:func:`!__pte_alloc`.”h]”(hŒ%Allocating a PTE will either use the ”…”�”}”(hj®#h²hh³Nh´Nubj )�”}”(hŒ :c:member:`!mm->page_table_lock`”h]”hŒmm->page_table_lock”…”�”}”(hj¶#h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hj®#ubhŒ or, if ”…”�”}”(hj®#h²hh³Nh´Nubj )�”}”(hŒ!:c:macro:`!USE_SPLIT_PMD_PTLOCKS`”h]”hŒUSE_SPLIT_PMD_PTLOCKS”…”�”}”(hjÉ#h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-macro”eh"]”h$]”h&]”uh1j hj®#ubhŒP is defined, a lock embedded in the PMD physical page metadata in the form of a ”…”�”}”(hj®#h²hh³Nh´Nubj )�”}”(hŒ:c:struct:`!struct ptdesc`”h]”hŒ struct ptdesc”…”�”}”(hjÜ#h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-struct”eh"]”h$]”h&]”uh1j hj®#ubhŒ, acquired by ”…”�”}”(hj®#h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!pmd_ptdesc`”h]”hŒ pmd_ptdesc()”…”�”}”(hjï#h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj®#ubhŒ called from ”…”�”}”(hj®#h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!pmd_lock`”h]”hŒ pmd_lock()”…”�”}”(hj$h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj®#ubhŒ and ultimately ”…”�”}”(hj®#h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!__pte_alloc`”h]”hŒ __pte_alloc()”…”�”}”(hj$h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj®#ubhŒ.”…”�”}”(hj®#h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MŠhjÕ"h²hubj)�”}”(hŒêFinally, modifying the contents of the PTE requires special treatment, as the PTE page table lock must be acquired whenever we want stable and exclusive access to entries contained within a PTE, especially when we wish to modify them.”h]”hŒêFinally, modifying the contents of the PTE requires special treatment, as the PTE page table lock must be acquired whenever we want stable and exclusive access to entries contained within a PTE, especially when we wish to modify them.”…”�”}”(hj.$h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M�hjÕ"h²hubj)�”}”(hXfThis is performed via :c:func:`!pte_offset_map_lock` which carefully checks to ensure that the PTE hasn't changed from under us, ultimately invoking :c:func:`!pte_lockptr` to obtain a spin lock at PTE granularity contained within the :c:struct:`!struct ptdesc` associated with the physical PTE page. The lock must be released via :c:func:`!pte_unmap_unlock`.”h]”(hŒThis is performed via ”…”�”}”(hj<$h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!pte_offset_map_lock`”h]”hŒpte_offset_map_lock()”…”�”}”(hjD$h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj<$ubhŒc which carefully checks to ensure that the PTE hasn’t changed from under us, ultimately invoking ”…”�”}”(hj<$h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!pte_lockptr`”h]”hŒ pte_lockptr()”…”�”}”(hjW$h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj<$ubhŒ? to obtain a spin lock at PTE granularity contained within the ”…”�”}”(hj<$h²hh³Nh´Nubj )�”}”(hŒ:c:struct:`!struct ptdesc`”h]”hŒ struct ptdesc”…”�”}”(hjj$h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-struct”eh"]”h$]”h&]”uh1j hj<$ubhŒF associated with the physical PTE page. The lock must be released via ”…”�”}”(hj<$h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!pte_unmap_unlock`”h]”hŒpte_unmap_unlock()”…”�”}”(hj}$h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj<$ubhŒ.”…”�”}”(hj<$h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M•hjÕ"h²hubj�)�”}”(hŒÞThere are some variants on this, such as :c:func:`!pte_offset_map_rw_nolock` when we know we hold the PTE stable but for brevity we do not explore this. See the comment for :c:func:`!pte_offset_map_lock` for more details.”h]”j)�”}”(hŒÞThere are some variants on this, such as :c:func:`!pte_offset_map_rw_nolock` when we know we hold the PTE stable but for brevity we do not explore this. See the comment for :c:func:`!pte_offset_map_lock` for more details.”h]”(hŒ)There are some variants on this, such as ”…”�”}”(hjš$h²hh³Nh´Nubj )�”}”(hŒ#:c:func:`!pte_offset_map_rw_nolock`”h]”hŒpte_offset_map_rw_nolock()”…”�”}”(hj¢$h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjš$ubhŒb when we know we hold the PTE stable but for brevity we do not explore this. See the comment for ”…”�”}”(hjš$h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!pte_offset_map_lock`”h]”hŒpte_offset_map_lock()”…”�”}”(hjµ$h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjš$ubhŒ for more details.”…”�”}”(hjš$h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M›hj–$ubah}”(h]”h ]”h"]”h$]”h&]”uh1jŒhjÕ"h²hh³hÇh´Nubj)�”}”(hŒùWhen modifying data in ranges we typically only wish to allocate higher page tables as necessary, using these locks to avoid races or overwriting anything, and set/clear data at the PTE level as required (for instance when page faulting or zapping).”h]”hŒùWhen modifying data in ranges we typically only wish to allocate higher page tables as necessary, using these locks to avoid races or overwriting anything, and set/clear data at the PTE level as required (for instance when page faulting or zapping).”…”�”}”(hjÔ$h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M hjÕ"h²hubj)�”}”(hXA typical pattern taken when traversing page table entries to install a new mapping is to optimistically determine whether the page table entry in the table above is empty, if so, only then acquiring the page table lock and checking again to see if it was allocated underneath us.”h]”hXA typical pattern taken when traversing page table entries to install a new mapping is to optimistically determine whether the page table entry in the table above is empty, if so, only then acquiring the page table lock and checking again to see if it was allocated underneath us.”…”�”}”(hjâ$h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M¥hjÕ"h²hubj)�”}”(hŒThis allows for a traversal with page table locks only being taken when required. An example of this is :c:func:`!__pud_alloc`.”h]”(hŒhThis allows for a traversal with page table locks only being taken when required. An example of this is ”…”�”}”(hjð$h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!__pud_alloc`”h]”hŒ __pud_alloc()”…”�”}”(hjø$h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjð$ubhŒ.”…”�”}”(hjð$h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MªhjÕ"h²hubj)�”}”(hŒÛAt the leaf page table, that is the PTE, we can't entirely rely on this pattern as we have separate PMD and PTE locks and a THP collapse for instance might have eliminated the PMD entry as well as the PTE from under us.”h]”hŒÝAt the leaf page table, that is the PTE, we can’t entirely rely on this pattern as we have separate PMD and PTE locks and a THP collapse for instance might have eliminated the PMD entry as well as the PTE from under us.”…”�”}”(hj%h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M­hjÕ"h²hubj)�”}”(hŒåThis is why :c:func:`!pte_offset_map_lock` locklessly retrieves the PMD entry for the PTE, carefully checking it is as expected, before acquiring the PTE-specific lock, and then *again* checking that the PMD entry is as expected.”h]”(hŒ This is why ”…”�”}”(hj%h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!pte_offset_map_lock`”h]”hŒpte_offset_map_lock()”…”�”}”(hj'%h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj%ubhŒˆ locklessly retrieves the PMD entry for the PTE, carefully checking it is as expected, before acquiring the PTE-specific lock, and then ”…”�”}”(hj%h²hh³Nh´Nubj\)�”}”(hŒ*again*”h]”hŒagain”…”�”}”(hj:%h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j[hj%ubhŒ, checking that the PMD entry is as expected.”…”�”}”(hj%h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M±hjÕ"h²hubj)�”}”(hŒšIf a THP collapse (or similar) were to occur then the lock on both pages would be acquired, so we can ensure this is prevented while the PTE lock is held.”h]”hŒšIf a THP collapse (or similar) were to occur then the lock on both pages would be acquired, so we can ensure this is prevented while the PTE lock is held.”…”�”}”(hjR%h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MµhjÕ"h²hubj)�”}”(hŒ>Installing entries this way ensures mutual exclusion on write.”h]”hŒ>Installing entries this way ensures mutual exclusion on write.”…”�”}”(hj`%h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M¸hjÕ"h²hubeh}”(h]”Œpage-table-installation”ah ]”h"]”Œpage table installation”ah$]”h&]”uh1hÈhjOh²hh³hÇh´M{ubhÉ)�”}”(hhh]”(hÎ)�”}”(hŒPage table freeing”h]”hŒPage table freeing”…”�”}”(hjy%h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjv%h²hh³hÇh´M»ubj)�”}”(hŒÁTearing down page tables themselves is something that requires significant care. There must be no way that page tables designated for removal can be traversed or referenced by concurrent tasks.”h]”hŒÁTearing down page tables themselves is something that requires significant care. There must be no way that page tables designated for removal can be traversed or referenced by concurrent tasks.”…”�”}”(hj‡%h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M½hjv%h²hubj)�”}”(hŒåIt is insufficient to simply hold an mmap write lock and VMA lock (which will prevent racing faults, and rmap operations), as a file-backed mapping can be truncated under the :c:struct:`!struct address_space->i_mmap_rwsem` alone.”h]”(hŒ¯It is insufficient to simply hold an mmap write lock and VMA lock (which will prevent racing faults, and rmap operations), as a file-backed mapping can be truncated under the ”…”�”}”(hj•%h²hh³Nh´Nubj )�”}”(hŒ/:c:struct:`!struct address_space->i_mmap_rwsem`”h]”hŒ"struct address_space->i_mmap_rwsem”…”�”}”(hj�%h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-struct”eh"]”h$]”h&]”uh1j hj•%ubhŒ alone.”…”�”}”(hj•%h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MÁhjv%h²hubj)�”}”(hŒàAs a result, no VMA which can be accessed via the reverse mapping (either through the :c:struct:`!struct anon_vma->rb_root` or the :c:member:`!struct address_space->i_mmap` interval trees) can have its page tables torn down.”h]”(hŒVAs a result, no VMA which can be accessed via the reverse mapping (either through the ”…”�”}”(hj¶%h²hh³Nh´Nubj )�”}”(hŒ%:c:struct:`!struct anon_vma->rb_root`”h]”hŒstruct anon_vma->rb_root”…”�”}”(hj¾%h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-struct”eh"]”h$]”h&]”uh1j hj¶%ubhŒ or the ”…”�”}”(hj¶%h²hh³Nh´Nubj )�”}”(hŒ):c:member:`!struct address_space->i_mmap`”h]”hŒstruct address_space->i_mmap”…”�”}”(hjÑ%h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hj¶%ubhŒ4 interval trees) can have its page tables torn down.”…”�”}”(hj¶%h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MÅhjv%h²hubj)�”}”(hŒÝThe operation is typically performed via :c:func:`!free_pgtables`, which assumes either the mmap write lock has been taken (as specified by its :c:member:`!mm_wr_locked` parameter), or that the VMA is already unreachable.”h]”(hŒ)The operation is typically performed via ”…”�”}”(hjê%h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!free_pgtables`”h]”hŒfree_pgtables()”…”�”}”(hjò%h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjê%ubhŒO, which assumes either the mmap write lock has been taken (as specified by its ”…”�”}”(hjê%h²hh³Nh´Nubj )�”}”(hŒ:c:member:`!mm_wr_locked`”h]”hŒ mm_wr_locked”…”�”}”(hj&h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hjê%ubhŒ4 parameter), or that the VMA is already unreachable.”…”�”}”(hjê%h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MÉhjv%h²hubj)�”}”(hŒ×It carefully removes the VMA from all reverse mappings, however it's important that no new ones overlap these or any route remain to permit access to addresses within the range whose page tables are being torn down.”h]”hŒÙIt carefully removes the VMA from all reverse mappings, however it’s important that no new ones overlap these or any route remain to permit access to addresses within the range whose page tables are being torn down.”…”�”}”(hj&h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MÍhjv%h²hubj)�”}”(hŒÖAdditionally, it assumes that a zap has already been performed and steps have been taken to ensure that no further page table entries can be installed between the zap and the invocation of :c:func:`!free_pgtables`.”h]”(hŒ½Additionally, it assumes that a zap has already been performed and steps have been taken to ensure that no further page table entries can be installed between the zap and the invocation of ”…”�”}”(hj,&h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!free_pgtables`”h]”hŒfree_pgtables()”…”�”}”(hj4&h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj,&ubhŒ.”…”�”}”(hj,&h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MÑhjv%h²hubj)�”}”(hŒßSince it is assumed that all such steps have been taken, page table entries are cleared without page table locks (in the :c:func:`!pgd_clear`, :c:func:`!p4d_clear`, :c:func:`!pud_clear`, and :c:func:`!pmd_clear` functions).”h]”(hŒySince it is assumed that all such steps have been taken, page table entries are cleared without page table locks (in the ”…”�”}”(hjM&h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!pgd_clear`”h]”hŒ pgd_clear()”…”�”}”(hjU&h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjM&ubhŒ, ”…”�”}”(hjM&h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!p4d_clear`”h]”hŒ p4d_clear()”…”�”}”(hjh&h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjM&ubhŒ, ”…”�”}”(hjM&h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!pud_clear`”h]”hŒ pud_clear()”…”�”}”(hj{&h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjM&ubhŒ, and ”…”�”}”(hjM&h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!pmd_clear`”h]”hŒ pmd_clear()”…”�”}”(hjŽ&h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjM&ubhŒ functions).”…”�”}”(hjM&h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MÕhjv%h²hubj�)�”}”(hŒóIt is possible for leaf page tables to be torn down independent of the page tables above it as is done by :c:func:`!retract_page_tables`, which is performed under the i_mmap read lock, PMD, and PTE page table locks, without this level of care.”h]”j)�”}”(hŒóIt is possible for leaf page tables to be torn down independent of the page tables above it as is done by :c:func:`!retract_page_tables`, which is performed under the i_mmap read lock, PMD, and PTE page table locks, without this level of care.”h]”(hŒjIt is possible for leaf page tables to be torn down independent of the page tables above it as is done by ”…”�”}”(hj«&h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!retract_page_tables`”h]”hŒretract_page_tables()”…”�”}”(hj³&h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj«&ubhŒk, which is performed under the i_mmap read lock, PMD, and PTE page table locks, without this level of care.”…”�”}”(hj«&h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MÙhj§&ubah}”(h]”h ]”h"]”h$]”h&]”uh1jŒhjv%h²hh³hÇh´Nubeh}”(h]”Œpage-table-freeing”ah ]”h"]”Œpage table freeing”ah$]”h&]”uh1hÈhjOh²hh³hÇh´M»ubhÉ)�”}”(hhh]”(hÎ)�”}”(hŒPage table moving”h]”hŒPage table moving”…”�”}”(hjÝ&h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjÚ&h²hh³hÇh´Mßubj)�”}”(hŒ¾Some functions manipulate page table levels above PMD (that is PUD, P4D and PGD page tables). Most notable of these is :c:func:`!mremap`, which is capable of moving higher level page tables.”h]”(hŒwSome functions manipulate page table levels above PMD (that is PUD, P4D and PGD page tables). Most notable of these is ”…”�”}”(hjë&h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!mremap`”h]”hŒmremap()”…”�”}”(hjó&h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjë&ubhŒ6, which is capable of moving higher level page tables.”…”�”}”(hjë&h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MáhjÚ&h²hubj)�”}”(hŒ�In these instances, it is required that **all** locks are taken, that is the mmap lock, the VMA lock and the relevant rmap locks.”h]”(hŒ(In these instances, it is required that ”…”�”}”(hj 'h²hh³Nh´NubjÓ)�”}”(hŒ**all**”h]”hŒall”…”�”}”(hj'h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhj 'ubhŒR locks are taken, that is the mmap lock, the VMA lock and the relevant rmap locks.”…”�”}”(hj 'h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MåhjÚ&h²hubj)�”}”(hŒëYou can observe this in the :c:func:`!mremap` implementation in the functions :c:func:`!take_rmap_locks` and :c:func:`!drop_rmap_locks` which perform the rmap side of lock acquisition, invoked ultimately by :c:func:`!move_page_tables`.”h]”(hŒYou can observe this in the ”…”�”}”(hj,'h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!mremap`”h]”hŒmremap()”…”�”}”(hj4'h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj,'ubhŒ! implementation in the functions ”…”�”}”(hj,'h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!take_rmap_locks`”h]”hŒtake_rmap_locks()”…”�”}”(hjG'h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj,'ubhŒ and ”…”�”}”(hj,'h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!drop_rmap_locks`”h]”hŒdrop_rmap_locks()”…”�”}”(hjZ'h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj,'ubhŒH which perform the rmap side of lock acquisition, invoked ultimately by ”…”�”}”(hj,'h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!move_page_tables`”h]”hŒmove_page_tables()”…”�”}”(hjm'h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj,'ubhŒ.”…”�”}”(hj,'h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MèhjÚ&h²hubeh}”(h]”Œpage-table-moving”ah ]”h"]”Œpage table moving”ah$]”h&]”uh1hÈhjOh²hh³hÇh´Mßubeh}”(h]”Œpage-table-locking-details”ah ]”h"]”Œpage table locking details”ah$]”h&]”uh1hÈhj&h²hh³hÇh´MõubhÉ)�”}”(hhh]”(hÎ)�”}”(hŒVMA lock internals”h]”hŒVMA lock internals”…”�”}”(hj™'h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj–'h²hh³hÇh´MíubhÉ)�”}”(hhh]”(hÎ)�”}”(hŒOverview”h]”hŒOverview”…”�”}”(hjª'h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj§'h²hh³hÇh´Mðubj)�”}”(hŒ‡VMA read locking is entirely optimistic - if the lock is contended or a competing write has started, then we do not obtain a read lock.”h]”hŒ‡VMA read locking is entirely optimistic - if the lock is contended or a competing write has started, then we do not obtain a read lock.”…”�”}”(hj¸'h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mòhj§'h²hubj)�”}”(hX&A VMA **read** lock is obtained by :c:func:`!lock_vma_under_rcu`, which first calls :c:func:`!rcu_read_lock` to ensure that the VMA is looked up in an RCU critical section, then attempts to VMA lock it via :c:func:`!vma_start_read`, before releasing the RCU lock via :c:func:`!rcu_read_unlock`.”h]”(hŒA VMA ”…”�”}”(hjÆ'h²hh³Nh´NubjÓ)�”}”(hŒ**read**”h]”hŒread”…”�”}”(hjÎ'h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjÆ'ubhŒ lock is obtained by ”…”�”}”(hjÆ'h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!lock_vma_under_rcu`”h]”hŒlock_vma_under_rcu()”…”�”}”(hjà'h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjÆ'ubhŒ, which first calls ”…”�”}”(hjÆ'h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!rcu_read_lock`”h]”hŒrcu_read_lock()”…”�”}”(hjó'h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjÆ'ubhŒb to ensure that the VMA is looked up in an RCU critical section, then attempts to VMA lock it via ”…”�”}”(hjÆ'h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!vma_start_read`”h]”hŒvma_start_read()”…”�”}”(hj(h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjÆ'ubhŒ$, before releasing the RCU lock via ”…”�”}”(hjÆ'h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!rcu_read_unlock`”h]”hŒrcu_read_unlock()”…”�”}”(hj(h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjÆ'ubhŒ.”…”�”}”(hjÆ'h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mõhj§'h²hubj)�”}”(hXIn cases when the user already holds mmap read lock, :c:func:`!vma_start_read_locked` and :c:func:`!vma_start_read_locked_nested` can be used. These functions do not fail due to lock contention but the caller should still check their return values in case they fail for other reasons.”h]”(hŒ5In cases when the user already holds mmap read lock, ”…”�”}”(hj2(h²hh³Nh´Nubj )�”}”(hŒ :c:func:`!vma_start_read_locked`”h]”hŒvma_start_read_locked()”…”�”}”(hj:(h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj2(ubhŒ and ”…”�”}”(hj2(h²hh³Nh´Nubj )�”}”(hŒ':c:func:`!vma_start_read_locked_nested`”h]”hŒvma_start_read_locked_nested()”…”�”}”(hjM(h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj2(ubhŒ› can be used. These functions do not fail due to lock contention but the caller should still check their return values in case they fail for other reasons.”…”�”}”(hj2(h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Múhj§'h²hubj)�”}”(hŒ²VMA read locks increment :c:member:`!vma.vm_refcnt` reference counter for their duration and the caller of :c:func:`!lock_vma_under_rcu` must drop it via :c:func:`!vma_end_read`.”h]”(hŒVMA read locks increment ”…”�”}”(hjf(h²hh³Nh´Nubj )�”}”(hŒ:c:member:`!vma.vm_refcnt`”h]”hŒ vma.vm_refcnt”…”�”}”(hjn(h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hjf(ubhŒ8 reference counter for their duration and the caller of ”…”�”}”(hjf(h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!lock_vma_under_rcu`”h]”hŒlock_vma_under_rcu()”…”�”}”(hj�(h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjf(ubhŒ must drop it via ”…”�”}”(hjf(h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!vma_end_read`”h]”hŒvma_end_read()”…”�”}”(hj”(h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjf(ubhŒ.”…”�”}”(hjf(h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mÿhj§'h²hubj)�”}”(hX{VMA **write** locks are acquired via :c:func:`!vma_start_write` in instances where a VMA is about to be modified, unlike :c:func:`!vma_start_read` the lock is always acquired. An mmap write lock **must** be held for the duration of the VMA write lock, releasing or downgrading the mmap write lock also releases the VMA write lock so there is no :c:func:`!vma_end_write` function.”h]”(hŒVMA ”…”�”}”(hj­(h²hh³Nh´NubjÓ)�”}”(hŒ **write**”h]”hŒwrite”…”�”}”(hjµ(h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhj­(ubhŒ locks are acquired via ”…”�”}”(hj­(h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!vma_start_write`”h]”hŒvma_start_write()”…”�”}”(hjÇ(h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj­(ubhŒ: in instances where a VMA is about to be modified, unlike ”…”�”}”(hj­(h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!vma_start_read`”h]”hŒvma_start_read()”…”�”}”(hjÚ(h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj­(ubhŒ1 the lock is always acquired. An mmap write lock ”…”�”}”(hj­(h²hh³Nh´NubjÓ)�”}”(hŒ**must**”h]”hŒmust”…”�”}”(hjí(h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhj­(ubhŒŽ be held for the duration of the VMA write lock, releasing or downgrading the mmap write lock also releases the VMA write lock so there is no ”…”�”}”(hj­(h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!vma_end_write`”h]”hŒvma_end_write()”…”�”}”(hjÿ(h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj­(ubhŒ function.”…”�”}”(hj­(h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mhj§'h²hubj)�”}”(hŒöNote that when write-locking a VMA lock, the :c:member:`!vma.vm_refcnt` is temporarily modified so that readers can detect the presence of a writer. The reference counter is restored once the vma sequence number used for serialisation is updated.”h]”(hŒ-Note that when write-locking a VMA lock, the ”…”�”}”(hj)h²hh³Nh´Nubj )�”}”(hŒ:c:member:`!vma.vm_refcnt`”h]”hŒ vma.vm_refcnt”…”�”}”(hj )h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hj)ubhŒ¯ is temporarily modified so that readers can detect the presence of a writer. The reference counter is restored once the vma sequence number used for serialisation is updated.”…”�”}”(hj)h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M hj§'h²hubj)�”}”(hŒbThis ensures the semantics we require - VMA write locks provide exclusive write access to the VMA.”h]”hŒbThis ensures the semantics we require - VMA write locks provide exclusive write access to the VMA.”…”�”}”(hj9)h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M hj§'h²hubeh}”(h]”Œoverview”ah ]”h"]”Œoverview”ah$]”h&]”uh1hÈhj–'h²hh³hÇh´MðubhÉ)�”}”(hhh]”(hÎ)�”}”(hŒImplementation details”h]”hŒImplementation details”…”�”}”(hjR)h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjO)h²hh³hÇh´Mubj)�”}”(hX The VMA lock mechanism is designed to be a lightweight means of avoiding the use of the heavily contended mmap lock. It is implemented using a combination of a reference counter and sequence numbers belonging to the containing :c:struct:`!struct mm_struct` and the VMA.”h]”(hŒãThe VMA lock mechanism is designed to be a lightweight means of avoiding the use of the heavily contended mmap lock. It is implemented using a combination of a reference counter and sequence numbers belonging to the containing ”…”�”}”(hj`)h²hh³Nh´Nubj )�”}”(hŒ:c:struct:`!struct mm_struct`”h]”hŒstruct mm_struct”…”�”}”(hjh)h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-struct”eh"]”h$]”h&]”uh1j hj`)ubhŒ and the VMA.”…”�”}”(hj`)h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MhjO)h²hubj)�”}”(hX Read locks are acquired via :c:func:`!vma_start_read`, which is an optimistic operation, i.e. it tries to acquire a read lock but returns false if it is unable to do so. At the end of the read operation, :c:func:`!vma_end_read` is called to release the VMA read lock.”h]”(hŒRead locks are acquired via ”…”�”}”(hj�)h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!vma_start_read`”h]”hŒvma_start_read()”…”�”}”(hj‰)h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj�)ubhŒ—, which is an optimistic operation, i.e. it tries to acquire a read lock but returns false if it is unable to do so. At the end of the read operation, ”…”�”}”(hj�)h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!vma_end_read`”h]”hŒvma_end_read()”…”�”}”(hjœ)h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj�)ubhŒ( is called to release the VMA read lock.”…”�”}”(hj�)h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MhjO)h²hubj)�”}”(hXaInvoking :c:func:`!vma_start_read` requires that :c:func:`!rcu_read_lock` has been called first, establishing that we are in an RCU critical section upon VMA read lock acquisition. Once acquired, the RCU lock can be released as it is only required for lookup. This is abstracted by :c:func:`!lock_vma_under_rcu` which is the interface a user should use.”h]”(hŒ Invoking ”…”�”}”(hjµ)h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!vma_start_read`”h]”hŒvma_start_read()”…”�”}”(hj½)h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjµ)ubhŒ requires that ”…”�”}”(hjµ)h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!rcu_read_lock`”h]”hŒrcu_read_lock()”…”�”}”(hjÐ)h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjµ)ubhŒÑ has been called first, establishing that we are in an RCU critical section upon VMA read lock acquisition. Once acquired, the RCU lock can be released as it is only required for lookup. This is abstracted by ”…”�”}”(hjµ)h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!lock_vma_under_rcu`”h]”hŒlock_vma_under_rcu()”…”�”}”(hjã)h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjµ)ubhŒ* which is the interface a user should use.”…”�”}”(hjµ)h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MhjO)h²hubj)�”}”(hŒòWriting requires the mmap to be write-locked and the VMA lock to be acquired via :c:func:`!vma_start_write`, however the write lock is released by the termination or downgrade of the mmap write lock so no :c:func:`!vma_end_write` is required.”h]”(hŒQWriting requires the mmap to be write-locked and the VMA lock to be acquired via ”…”�”}”(hjü)h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!vma_start_write`”h]”hŒvma_start_write()”…”�”}”(hj*h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjü)ubhŒb, however the write lock is released by the termination or downgrade of the mmap write lock so no ”…”�”}”(hjü)h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!vma_end_write`”h]”hŒvma_end_write()”…”�”}”(hj*h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjü)ubhŒ is required.”…”�”}”(hjü)h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M#hjO)h²hubj)�”}”(hŒ¶All this is achieved by the use of per-mm and per-VMA sequence counts, which are used in order to reduce complexity, especially for operations which write-lock multiple VMAs at once.”h]”hŒ¶All this is achieved by the use of per-mm and per-VMA sequence counts, which are used in order to reduce complexity, especially for operations which write-lock multiple VMAs at once.”…”�”}”(hj0*h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M'hjO)h²hubj)�”}”(hŒµIf the mm sequence count, :c:member:`!mm->mm_lock_seq` is equal to the VMA sequence count :c:member:`!vma->vm_lock_seq` then the VMA is write-locked. If they differ, then it is not.”h]”(hŒIf the mm sequence count, ”…”�”}”(hj>*h²hh³Nh´Nubj )�”}”(hŒ:c:member:`!mm->mm_lock_seq`”h]”hŒmm->mm_lock_seq”…”�”}”(hjF*h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hj>*ubhŒ$ is equal to the VMA sequence count ”…”�”}”(hj>*h²hh³Nh´Nubj )�”}”(hŒ:c:member:`!vma->vm_lock_seq`”h]”hŒvma->vm_lock_seq”…”�”}”(hjY*h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hj>*ubhŒ> then the VMA is write-locked. If they differ, then it is not.”…”�”}”(hj>*h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M+hjO)h²hubj)�”}”(hŒíEach time the mmap write lock is released in :c:func:`!mmap_write_unlock` or :c:func:`!mmap_write_downgrade`, :c:func:`!vma_end_write_all` is invoked which also increments :c:member:`!mm->mm_lock_seq` via :c:func:`!mm_lock_seqcount_end`.”h]”(hŒ-Each time the mmap write lock is released in ”…”�”}”(hjr*h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!mmap_write_unlock`”h]”hŒmmap_write_unlock()”…”�”}”(hjz*h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjr*ubhŒ or ”…”�”}”(hjr*h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!mmap_write_downgrade`”h]”hŒmmap_write_downgrade()”…”�”}”(hj�*h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjr*ubhŒ, ”…”�”}”(hjr*h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!vma_end_write_all`”h]”hŒvma_end_write_all()”…”�”}”(hj *h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjr*ubhŒ" is invoked which also increments ”…”�”}”(hjr*h²hh³Nh´Nubj )�”}”(hŒ:c:member:`!mm->mm_lock_seq`”h]”hŒmm->mm_lock_seq”…”�”}”(hj³*h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hjr*ubhŒ via ”…”�”}”(hjr*h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!mm_lock_seqcount_end`”h]”hŒmm_lock_seqcount_end()”…”�”}”(hjÆ*h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjr*ubhŒ.”…”�”}”(hjr*h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M/hjO)h²hubj)�”}”(hŒõThis way, we ensure that, regardless of the VMA's sequence number, a write lock is never incorrectly indicated and that when we release an mmap write lock we efficiently release **all** VMA write locks contained within the mmap at the same time.”h]”(hŒ´This way, we ensure that, regardless of the VMA’s sequence number, a write lock is never incorrectly indicated and that when we release an mmap write lock we efficiently release ”…”�”}”(hjß*h²hh³Nh´NubjÓ)�”}”(hŒ**all**”h]”hŒall”…”�”}”(hjç*h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjß*ubhŒ< VMA write locks contained within the mmap at the same time.”…”�”}”(hjß*h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M4hjO)h²hubj)�”}”(hXSince the mmap write lock is exclusive against others who hold it, the automatic release of any VMA locks on its release makes sense, as you would never want to keep VMAs locked across entirely separate write operations. It also maintains correct lock ordering.”h]”hXSince the mmap write lock is exclusive against others who hold it, the automatic release of any VMA locks on its release makes sense, as you would never want to keep VMAs locked across entirely separate write operations. It also maintains correct lock ordering.”…”�”}”(hjÿ*h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M9hjO)h²hubj)�”}”(hŒ¬Each time a VMA read lock is acquired, we increment :c:member:`!vma.vm_refcnt` reference counter and check that the sequence count of the VMA does not match that of the mm.”h]”(hŒ4Each time a VMA read lock is acquired, we increment ”…”�”}”(hj +h²hh³Nh´Nubj )�”}”(hŒ:c:member:`!vma.vm_refcnt`”h]”hŒ vma.vm_refcnt”…”�”}”(hj+h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hj +ubhŒ^ reference counter and check that the sequence count of the VMA does not match that of the mm.”…”�”}”(hj +h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M>hjO)h²hubj)�”}”(hŒÚIf it does, the read lock fails and :c:member:`!vma.vm_refcnt` is dropped. If it does not, we keep the reference counter raised, excluding writers, but permitting other readers, who can also obtain this lock under RCU.”h]”(hŒ$If it does, the read lock fails and ”…”�”}”(hj.+h²hh³Nh´Nubj )�”}”(hŒ:c:member:`!vma.vm_refcnt`”h]”hŒ vma.vm_refcnt”…”�”}”(hj6+h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hj.+ubhŒœ is dropped. If it does not, we keep the reference counter raised, excluding writers, but permitting other readers, who can also obtain this lock under RCU.”…”�”}”(hj.+h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MBhjO)h²hubj)�”}”(hŒ¦Importantly, maple tree operations performed in :c:func:`!lock_vma_under_rcu` are also RCU safe, so the whole read lock operation is guaranteed to function correctly.”h]”(hŒ0Importantly, maple tree operations performed in ”…”�”}”(hjO+h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!lock_vma_under_rcu`”h]”hŒlock_vma_under_rcu()”…”�”}”(hjW+h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hjO+ubhŒY are also RCU safe, so the whole read lock operation is guaranteed to function correctly.”…”�”}”(hjO+h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MFhjO)h²hubj)�”}”(hX#On the write side, we set a bit in :c:member:`!vma.vm_refcnt` which can't be modified by readers and wait for all readers to drop their reference count. Once there are no readers, the VMA's sequence number is set to match that of the mm. During this entire operation mmap write lock is held.”h]”(hŒ#On the write side, we set a bit in ”…”�”}”(hjp+h²hh³Nh´Nubj )�”}”(hŒ:c:member:`!vma.vm_refcnt`”h]”hŒ vma.vm_refcnt”…”�”}”(hjx+h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hjp+ubhŒê which can’t be modified by readers and wait for all readers to drop their reference count. Once there are no readers, the VMA’s sequence number is set to match that of the mm. During this entire operation mmap write lock is held.”…”�”}”(hjp+h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MJhjO)h²hubj)�”}”(hŒ‹This way, if any read locks are in effect, :c:func:`!vma_start_write` will sleep until these are finished and mutual exclusion is achieved.”h]”(hŒ+This way, if any read locks are in effect, ”…”�”}”(hj‘+h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!vma_start_write`”h]”hŒvma_start_write()”…”�”}”(hj™+h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj‘+ubhŒF will sleep until these are finished and mutual exclusion is achieved.”…”�”}”(hj‘+h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MOhjO)h²hubj)�”}”(hŒïAfter setting the VMA's sequence number, the bit in :c:member:`!vma.vm_refcnt` indicating a writer is cleared. From this point on, VMA's sequence number will indicate VMA's write-locked state until mmap write lock is dropped or downgraded.”h]”(hŒ6After setting the VMA’s sequence number, the bit in ”…”�”}”(hj²+h²hh³Nh´Nubj )�”}”(hŒ:c:member:`!vma.vm_refcnt`”h]”hŒ vma.vm_refcnt”…”�”}”(hjº+h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-member”eh"]”h$]”h&]”uh1j hj²+ubhŒ¥ indicating a writer is cleared. From this point on, VMA’s sequence number will indicate VMA’s write-locked state until mmap write lock is dropped or downgraded.”…”�”}”(hj²+h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MRhjO)h²hubj)�”}”(hŒØThis clever combination of a reference counter and sequence count allows for fast RCU-based per-VMA lock acquisition (especially on page fault, though utilised elsewhere) with minimal complexity around lock ordering.”h]”hŒØThis clever combination of a reference counter and sequence count allows for fast RCU-based per-VMA lock acquisition (especially on page fault, though utilised elsewhere) with minimal complexity around lock ordering.”…”�”}”(hjÓ+h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MVhjO)h²hubeh}”(h]”Œimplementation-details”ah ]”h"]”Œimplementation details”ah$]”h&]”uh1hÈhj–'h²hh³hÇh´Mubeh}”(h]”Œvma-lock-internals”ah ]”h"]”Œvma lock internals”ah$]”h&]”uh1hÈhj&h²hh³hÇh´MíubhÉ)�”}”(hhh]”(hÎ)�”}”(hŒmmap write lock downgrading”h]”hŒmmap write lock downgrading”…”�”}”(hjô+h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjñ+h²hh³hÇh´M[ubj)�”}”(hŒÀWhen an mmap write lock is held one has exclusive access to resources within the mmap (with the usual caveats about requiring VMA write locks to avoid races with tasks holding VMA read locks).”h]”hŒÀWhen an mmap write lock is held one has exclusive access to resources within the mmap (with the usual caveats about requiring VMA write locks to avoid races with tasks holding VMA read locks).”…”�”}”(hj,h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M]hjñ+h²hubj)�”}”(hXeIt is then possible to **downgrade** from a write lock to a read lock via :c:func:`!mmap_write_downgrade` which, similar to :c:func:`!mmap_write_unlock`, implicitly terminates all VMA write locks via :c:func:`!vma_end_write_all`, but importantly does not relinquish the mmap lock while downgrading, therefore keeping the locked virtual address space stable.”h]”(hŒIt is then possible to ”…”�”}”(hj,h²hh³Nh´NubjÓ)�”}”(hŒ **downgrade**”h]”hŒ downgrade”…”�”}”(hj,h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhj,ubhŒ& from a write lock to a read lock via ”…”�”}”(hj,h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!mmap_write_downgrade`”h]”hŒmmap_write_downgrade()”…”�”}”(hj*,h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj,ubhŒ which, similar to ”…”�”}”(hj,h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!mmap_write_unlock`”h]”hŒmmap_write_unlock()”…”�”}”(hj=,h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj,ubhŒ0, implicitly terminates all VMA write locks via ”…”�”}”(hj,h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!vma_end_write_all`”h]”hŒvma_end_write_all()”…”�”}”(hjP,h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj,ubhŒ�, but importantly does not relinquish the mmap lock while downgrading, therefore keeping the locked virtual address space stable.”…”�”}”(hj,h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mahjñ+h²hubj)�”}”(hX8An interesting consequence of this is that downgraded locks are exclusive against any other task possessing a downgraded lock (since a racing task would have to acquire a write lock first to downgrade it, and the downgraded lock prevents a new write lock from being obtained until the original lock is released).”h]”hX8An interesting consequence of this is that downgraded locks are exclusive against any other task possessing a downgraded lock (since a racing task would have to acquire a write lock first to downgrade it, and the downgraded lock prevents a new write lock from being obtained until the original lock is released).”…”�”}”(hji,h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mghjñ+h²hubj)�”}”(hŒ}For clarity, we map read (R)/downgraded write (D)/write (W) locks against one another showing which locks exclude the others:”h]”hŒ}For clarity, we map read (R)/downgraded write (D)/write (W) locks against one another showing which locks exclude the others:”…”�”}”(hjw,h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mmhjñ+h²hubjn)�”}”(hhh]”(hÎ)�”}”(hŒLock exclusivity”h]”hŒLock exclusivity”…”�”}”(hjˆ,h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍh³hÇh´Mphj…,ubjs)�”}”(hhh]”(jx)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œcolwidth”KŒstub”Kuh1jwhj–,ubjx)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”j¢,Kuh1jwhj–,ubjx)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”j¢,Kuh1jwhj–,ubjx)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”j¢,Kuh1jwhj–,ubjÀ)�”}”(hhh]”jÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjÂ,ubjÊ)�”}”(hhh]”j)�”}”(hjCh]”hŒR”…”�”}”(hjÑ,h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MvhjÎ,ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjÂ,ubjÊ)�”}”(hhh]”j)�”}”(hŒD”h]”hŒD”…”�”}”(hjç,h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mwhjä,ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjÂ,ubjÊ)�”}”(hhh]”j)�”}”(hj h]”hŒW”…”�”}”(hjþ,h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mxhjû,ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjÂ,ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhj¿,ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¿hj–,ubjy)�”}”(hhh]”(jÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hjCh]”hŒR”…”�”}”(hj&-h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Myhj#-ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj -ubjÊ)�”}”(hhh]”j)�”}”(hjÊh]”hŒN”…”�”}”(hj<-h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mzhj9-ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj -ubjÊ)�”}”(hhh]”j)�”}”(hjÊh]”hŒN”…”�”}”(hjR-h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M{hjO-ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj -ubjÊ)�”}”(hhh]”j)�”}”(hjqh]”hŒY”…”�”}”(hjh-h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M|hje-ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj -ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhj-ubjÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hjé,h]”hŒD”…”�”}”(hj‡-h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M}hj„-ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj�-ubjÊ)�”}”(hhh]”j)�”}”(hjÊh]”hŒN”…”�”}”(hj�-h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M~hjš-ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj�-ubjÊ)�”}”(hhh]”j)�”}”(hjqh]”hŒY”…”�”}”(hj³-h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mhj°-ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj�-ubjÊ)�”}”(hhh]”j)�”}”(hjqh]”hŒY”…”�”}”(hjÉ-h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M€hjÆ-ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhj�-ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhj-ubjÅ)�”}”(hhh]”(jÊ)�”}”(hhh]”j)�”}”(hj h]”hŒW”…”�”}”(hjè-h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M�hjå-ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjâ-ubjÊ)�”}”(hhh]”j)�”}”(hjqh]”hŒY”…”�”}”(hjþ-h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M‚hjû-ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjâ-ubjÊ)�”}”(hhh]”j)�”}”(hjqh]”hŒY”…”�”}”(hj.h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´Mƒhj.ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjâ-ubjÊ)�”}”(hhh]”j)�”}”(hjqh]”hŒY”…”�”}”(hj*.h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M„hj'.ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÉhjâ-ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jÄhj-ubeh}”(h]”h ]”h"]”h$]”h&]”uh1jxhj–,ubeh}”(h]”h ]”h"]”h$]”h&]”Œcols”Kuh1jrhj…,ubeh}”(h]”Œid5”ah ]”Œcolwidths-given”ah"]”h$]”h&]”uh1jmhjñ+h²hh³Nh´Nubj)�”}”(hŒrHere a Y indicates the locks in the matching row/column are mutually exclusive, and N indicates that they are not.”h]”hŒrHere a Y indicates the locks in the matching row/column are mutually exclusive, and N indicates that they are not.”…”�”}”(hjX.h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´M†hjñ+h²hubeh}”(h]”Œmmap-write-lock-downgrading”ah ]”h"]”Œmmap write lock downgrading”ah$]”h&]”uh1hÈhj&h²hh³hÇh´M[ubhÉ)�”}”(hhh]”(hÎ)�”}”(hŒStack expansion”h]”hŒStack expansion”…”�”}”(hjq.h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjn.h²hh³hÇh´MŠubj)�”}”(hŒèStack expansion throws up additional complexities in that we cannot permit there to be racing page faults, as a result we invoke :c:func:`!vma_start_write` to prevent this in :c:func:`!expand_downwards` or :c:func:`!expand_upwards`.”h]”(hŒ�Stack expansion throws up additional complexities in that we cannot permit there to be racing page faults, as a result we invoke ”…”�”}”(hj.h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!vma_start_write`”h]”hŒvma_start_write()”…”�”}”(hj‡.h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj.ubhŒ to prevent this in ”…”�”}”(hj.h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!expand_downwards`”h]”hŒexpand_downwards()”…”�”}”(hjš.h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj.ubhŒ or ”…”�”}”(hj.h²hh³Nh´Nubj )�”}”(hŒ:c:func:`!expand_upwards`”h]”hŒexpand_upwards()”…”�”}”(hj­.h²hh³Nh´Nubah}”(h]”h ]”(jjŒc-func”eh"]”h$]”h&]”uh1j hj.ubhŒ.”…”�”}”(hj.h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³hÇh´MŒhjn.h²hubeh}”(h]”Œstack-expansion”ah ]”h"]”Œstack expansion”ah$]”h&]”uh1hÈhj&h²hh³hÇh´MŠubeh}”(h]”Œlocking-implementation-details”ah ]”h"]”Œlocking implementation details”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´MïubhÉ)�”}”(hhh]”(hÎ)�”}”(hŒFunctions and structures”h]”hŒFunctions and structures”…”�”}”(hjÙ.h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjÖ.h²hh³hÇh´M’ubhŒindex”“”)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œentries”]”(Œsingle”Œvma_refcount_put (C function)”Œc.vma_refcount_put”hNt”auh1jç.hjÖ.h²hh³Nh´NubhŒdesc”“”)�”}”(hhh]”(hŒdesc_signature”“”)�”}”(hŒ2void vma_refcount_put (struct vm_area_struct *vma)”h]”hŒdesc_signature_line”“”)�”}”(hŒ1void vma_refcount_put(struct vm_area_struct *vma)”h]”(hŒdesc_sig_keyword_type”“”)�”}”(hŒvoid”h]”hŒvoid”…”�”}”(hj /h²hh³Nh´Nubah}”(h]”h ]”Œkt”ah"]”h$]”h&]”uh1j /hj/h²hh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´KËubhŒdesc_sig_space”“”)�”}”(hŒ ”h]”hŒ ”…”�”}”(hj/h²hh³Nh´Nubah}”(h]”h ]”Œw”ah"]”h$]”h&]”uh1j/hj/h²hh³j/h´KËubhŒ desc_name”“”)�”}”(hŒvma_refcount_put”h]”hŒ desc_sig_name”“”)�”}”(hŒvma_refcount_put”h]”hŒvma_refcount_put”…”�”}”(hj4/h²hh³Nh´Nubah}”(h]”h ]”Œn”ah"]”h$]”h&]”uh1j2/hj./ubah}”(h]”h ]”(Œsig-name”Œdescname”eh"]”h$]”h&]”hÅhÆuh1j,/hj/h²hh³j/h´KËubhŒdesc_parameterlist”“”)�”}”(hŒ(struct vm_area_struct *vma)”h]”hŒdesc_parameter”“”)�”}”(hŒstruct vm_area_struct *vma”h]”(hŒdesc_sig_keyword”“”)�”}”(hŒstruct”h]”hŒstruct”…”�”}”(hjY/h²hh³Nh´Nubah}”(h]”h ]”Œk”ah"]”h$]”h&]”uh1jW/hjS/ubj/)�”}”(hŒ ”h]”hŒ ”…”�”}”(hjh/h²hh³Nh´Nubah}”(h]”h ]”j(/ah"]”h$]”h&]”uh1j/hjS/ubh)�”}”(hhh]”j3/)�”}”(hŒvm_area_struct”h]”hŒvm_area_struct”…”�”}”(hjy/h²hh³Nh´Nubah}”(h]”h ]”j?/ah"]”h$]”h&]”uh1j2/hjv/ubah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”jŒreftype”Œ identifier”Œ reftarget”j{/Œmodname”NŒ classname”NŒ c:parent_key”Œsphinx.domains.c”Œ LookupKey”“”)�”}”Œdata”]”j”/Œ ASTIdentifier”“”)�”}”j�/j6/sbŒc.vma_refcount_put”†”asbuh1hhjS/ubj/)�”}”(hŒ ”h]”hŒ ”…”�”}”(hj¡/h²hh³Nh´Nubah}”(h]”h ]”j(/ah"]”h$]”h&]”uh1j/hjS/ubhŒdesc_sig_punctuation”“”)�”}”(hjžh]”hŒ*”…”�”}”(hj±/h²hh³Nh´Nubah}”(h]”h ]”Œp”ah"]”h$]”h&]”uh1j¯/hjS/ubj3/)�”}”(hŒvma”h]”hŒvma”…”�”}”(hj¿/h²hh³Nh´Nubah}”(h]”h ]”j?/ah"]”h$]”h&]”uh1j2/hjS/ubeh}”(h]”h ]”h"]”h$]”h&]”Œnoemph”ˆhÅhÆuh1jQ/hjM/ubah}”(h]”h ]”h"]”h$]”h&]”hÅhÆuh1jK/hj/h²hh³j/h´KËubeh}”(h]”h ]”h"]”h$]”h&]”hÅhÆŒ add_permalink”ˆuh1j/Œsphinx_line_type”Œ declarator”hjÿ.h²hh³j/h´KËubah}”(h]”jö.ah ]”(Œsig”Œ sig-object”eh"]”h$]”h&]”Œ is_multiline”ˆŒ _toc_parts”)Œ _toc_name”huh1jý.h³j/h´KËhjú.h²hubhŒ desc_content”“”)�”}”(hhh]”j)�”}”(hŒMDrop reference count in VMA vm_refcnt field due to a read-lock being dropped.”h]”hŒMDrop reference count in VMA vm_refcnt field due to a read-lock being dropped.”…”�”}”(hjó/h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´KËhjð/h²hubah}”(h]”h ]”h"]”h$]”h&]”uh1jî/hjú.h²hh³j/h´KËubeh}”(h]”h ]”(jŒfunction”eh"]”h$]”h&]”Œdomain”jŒobjtype”j 0Œdesctype”j 0Œnoindex”‰Œ noindexentry”‰Œnocontentsentry”‰uh1jø.h²hhjÖ.h³Nh´NubhŒ container”“”)�”}”(hŒÇ**Parameters** ``struct vm_area_struct *vma`` The VMA whose reference count we wish to decrement. **Description** If we were the last reader, wake up threads waiting to obtain an exclusive lock.”h]”(j)�”}”(hŒ**Parameters**”h]”jÓ)�”}”(hj0h]”hŒ Parameters”…”�”}”(hj0h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhj0ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´KÏhj0ubhŒdefinition_list”“”)�”}”(hhh]”hŒdefinition_list_item”“”)�”}”(hŒS``struct vm_area_struct *vma`` The VMA whose reference count we wish to decrement. ”h]”(hŒterm”“”)�”}”(hŒ``struct vm_area_struct *vma``”h]”j )�”}”(hjB0h]”hŒstruct vm_area_struct *vma”…”�”}”(hjD0h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j hj@0ubah}”(h]”h ]”h"]”h$]”h&]”uh1j>0h³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´KÍhj:0ubhŒ definition”“”)�”}”(hhh]”j)�”}”(hŒ3The VMA whose reference count we wish to decrement.”h]”hŒ3The VMA whose reference count we wish to decrement.”…”�”}”(hj]0h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³jW0h´KÍhjZ0ubah}”(h]”h ]”h"]”h$]”h&]”uh1jX0hj:0ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j80h³jW0h´KÍhj50ubah}”(h]”h ]”h"]”h$]”h&]”uh1j30hj0ubj)�”}”(hŒ**Description**”h]”jÓ)�”}”(hj0h]”hŒ Description”…”�”}”(hj�0h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhj}0ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´KÏhj0ubj)�”}”(hŒPIf we were the last reader, wake up threads waiting to obtain an exclusive lock.”h]”hŒPIf we were the last reader, wake up threads waiting to obtain an exclusive lock.”…”�”}”(hj•0h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´KÎhj0ubeh}”(h]”h ]”Œ kernelindent”ah"]”h$]”h&]”uh1j0hjÖ.h²hh³Nh´Nubjè.)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œentries”]”(jô.Œ%vma_start_write_killable (C function)”Œc.vma_start_write_killable”hNt”auh1jç.hjÖ.h²hh³Nh´Nubjù.)�”}”(hhh]”(jþ.)�”}”(hŒ9int vma_start_write_killable (struct vm_area_struct *vma)”h]”j/)�”}”(hŒ8int vma_start_write_killable(struct vm_area_struct *vma)”h]”(j /)�”}”(hŒint”h]”hŒint”…”�”}”(hjÄ0h²hh³Nh´Nubah}”(h]”h ]”j/ah"]”h$]”h&]”uh1j /hjÀ0h²hh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´M3ubj/)�”}”(hŒ ”h]”hŒ ”…”�”}”(hjÓ0h²hh³Nh´Nubah}”(h]”h ]”j(/ah"]”h$]”h&]”uh1j/hjÀ0h²hh³jÒ0h´M3ubj-/)�”}”(hŒvma_start_write_killable”h]”j3/)�”}”(hŒvma_start_write_killable”h]”hŒvma_start_write_killable”…”�”}”(hjå0h²hh³Nh´Nubah}”(h]”h ]”j?/ah"]”h$]”h&]”uh1j2/hjá0ubah}”(h]”h ]”(jF/jG/eh"]”h$]”h&]”hÅhÆuh1j,/hjÀ0h²hh³jÒ0h´M3ubjL/)�”}”(hŒ(struct vm_area_struct *vma)”h]”jR/)�”}”(hŒstruct vm_area_struct *vma”h]”(jX/)�”}”(hj[/h]”hŒstruct”…”�”}”(hj1h²hh³Nh´Nubah}”(h]”h ]”jd/ah"]”h$]”h&]”uh1jW/hjý0ubj/)�”}”(hŒ ”h]”hŒ ”…”�”}”(hj1h²hh³Nh´Nubah}”(h]”h ]”j(/ah"]”h$]”h&]”uh1j/hjý0ubh)�”}”(hhh]”j3/)�”}”(hŒvm_area_struct”h]”hŒvm_area_struct”…”�”}”(hj1h²hh³Nh´Nubah}”(h]”h ]”j?/ah"]”h$]”h&]”uh1j2/hj1ubah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”jŒreftype”j�/Œ reftarget”j!1Œmodname”NŒ classname”Nj“/j–/)�”}”j™/]”jœ/)�”}”j�/jç0sbŒc.vma_start_write_killable”†”asbuh1hhjý0ubj/)�”}”(hŒ ”h]”hŒ ”…”�”}”(hj?1h²hh³Nh´Nubah}”(h]”h ]”j(/ah"]”h$]”h&]”uh1j/hjý0ubj°/)�”}”(hjžh]”hŒ*”…”�”}”(hjM1h²hh³Nh´Nubah}”(h]”h ]”j»/ah"]”h$]”h&]”uh1j¯/hjý0ubj3/)�”}”(hŒvma”h]”hŒvma”…”�”}”(hjZ1h²hh³Nh´Nubah}”(h]”h ]”j?/ah"]”h$]”h&]”uh1j2/hjý0ubeh}”(h]”h ]”h"]”h$]”h&]”Œnoemph”ˆhÅhÆuh1jQ/hjù0ubah}”(h]”h ]”h"]”h$]”h&]”hÅhÆuh1jK/hjÀ0h²hh³jÒ0h´M3ubeh}”(h]”h ]”h"]”h$]”h&]”hÅhÆjà/ˆuh1j/já/jâ/hj¼0h²hh³jÒ0h´M3ubah}”(h]”j·0ah ]”(jæ/jç/eh"]”h$]”h&]”jë/ˆjì/)jí/huh1jý.h³jÒ0h´M3hj¹0h²hubjï/)�”}”(hhh]”j)�”}”(hŒBegin writing to a VMA.”h]”hŒBegin writing to a VMA.”…”�”}”(hj„1h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´M3hj�1h²hubah}”(h]”h ]”h"]”h$]”h&]”uh1jî/hj¹0h²hh³jÒ0h´M3ubeh}”(h]”h ]”(jŒfunction”eh"]”h$]”h&]”j0jj0jœ1j0jœ1j0‰j0‰j0‰uh1jø.h²hhjÖ.h³Nh´Nubj0)�”}”(hX­**Parameters** ``struct vm_area_struct *vma`` The VMA we are going to modify. **Description** Exclude concurrent readers under the per-VMA lock until the currently write-locked mmap_lock is dropped or downgraded. **Context** May sleep while waiting for readers to drop the vma read lock. Caller must already hold the mmap_lock for write. **Return** 0 for a successful acquisition. -EINTR if a fatal signal was received.”h]”(j)�”}”(hŒ**Parameters**”h]”jÓ)�”}”(hj¦1h]”hŒ Parameters”…”�”}”(hj¨1h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhj¤1ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´M7hj 1ubj40)�”}”(hhh]”j90)�”}”(hŒ?``struct vm_area_struct *vma`` The VMA we are going to modify. ”h]”(j?0)�”}”(hŒ``struct vm_area_struct *vma``”h]”j )�”}”(hjÅ1h]”hŒstruct vm_area_struct *vma”…”�”}”(hjÇ1h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j hjÃ1ubah}”(h]”h ]”h"]”h$]”h&]”uh1j>0h³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´M4hj¿1ubjY0)�”}”(hhh]”j)�”}”(hŒThe VMA we are going to modify.”h]”hŒThe VMA we are going to modify.”…”�”}”(hjÞ1h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³jÚ1h´M4hjÛ1ubah}”(h]”h ]”h"]”h$]”h&]”uh1jX0hj¿1ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j80h³jÚ1h´M4hj¼1ubah}”(h]”h ]”h"]”h$]”h&]”uh1j30hj 1ubj)�”}”(hŒ**Description**”h]”jÓ)�”}”(hj2h]”hŒ Description”…”�”}”(hj2h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjþ1ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´M6hj 1ubj)�”}”(hŒvExclude concurrent readers under the per-VMA lock until the currently write-locked mmap_lock is dropped or downgraded.”h]”hŒvExclude concurrent readers under the per-VMA lock until the currently write-locked mmap_lock is dropped or downgraded.”…”�”}”(hj2h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´M5hj 1ubj)�”}”(hŒ **Context**”h]”jÓ)�”}”(hj'2h]”hŒContext”…”�”}”(hj)2h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhj%2ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´M8hj 1ubj)�”}”(hŒpMay sleep while waiting for readers to drop the vma read lock. Caller must already hold the mmap_lock for write.”h]”hŒpMay sleep while waiting for readers to drop the vma read lock. Caller must already hold the mmap_lock for write.”…”�”}”(hj=2h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´M9hj 1ubj)�”}”(hŒ **Return**”h]”jÓ)�”}”(hjN2h]”hŒReturn”…”�”}”(hjP2h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjL2ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´M<hj 1ubj)�”}”(hŒG0 for a successful acquisition. -EINTR if a fatal signal was received.”h]”hŒG0 for a successful acquisition. -EINTR if a fatal signal was received.”…”�”}”(hjd2h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´M<hj 1ubeh}”(h]”h ]”Œ kernelindent”ah"]”h$]”h&]”uh1j0hjÖ.h²hh³Nh´Nubjè.)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œentries”]”(jô.Œ$vma_assert_write_locked (C function)”Œc.vma_assert_write_locked”hNt”auh1jç.hjÖ.h²hh³Nh´Nubjù.)�”}”(hhh]”(jþ.)�”}”(hŒ9void vma_assert_write_locked (struct vm_area_struct *vma)”h]”j/)�”}”(hŒ8void vma_assert_write_locked(struct vm_area_struct *vma)”h]”(j /)�”}”(hŒvoid”h]”hŒvoid”…”�”}”(hj“2h²hh³Nh´Nubah}”(h]”h ]”j/ah"]”h$]”h&]”uh1j /hj�2h²hh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´MIubj/)�”}”(hŒ ”h]”hŒ ”…”�”}”(hj¢2h²hh³Nh´Nubah}”(h]”h ]”j(/ah"]”h$]”h&]”uh1j/hj�2h²hh³j¡2h´MIubj-/)�”}”(hŒvma_assert_write_locked”h]”j3/)�”}”(hŒvma_assert_write_locked”h]”hŒvma_assert_write_locked”…”�”}”(hj´2h²hh³Nh´Nubah}”(h]”h ]”j?/ah"]”h$]”h&]”uh1j2/hj°2ubah}”(h]”h ]”(jF/jG/eh"]”h$]”h&]”hÅhÆuh1j,/hj�2h²hh³j¡2h´MIubjL/)�”}”(hŒ(struct vm_area_struct *vma)”h]”jR/)�”}”(hŒstruct vm_area_struct *vma”h]”(jX/•«;)�”}”(hj[/h]”hŒstruct”…”�”}”(hjÐ2h²hh³Nh´Nubah}”(h]”h ]”jd/ah"]”h$]”h&]”uh1jW/hjÌ2ubj/)�”}”(hŒ ”h]”hŒ ”…”�”}”(hjÝ2h²hh³Nh´Nubah}”(h]”h ]”j(/ah"]”h$]”h&]”uh1j/hjÌ2ubh)�”}”(hhh]”j3/)�”}”(hŒvm_area_struct”h]”hŒvm_area_struct”…”�”}”(hjî2h²hh³Nh´Nubah}”(h]”h ]”j?/ah"]”h$]”h&]”uh1j2/hjë2ubah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”jŒreftype”j�/Œ reftarget”jð2Œmodname”NŒ classname”Nj“/j–/)�”}”j™/]”jœ/)�”}”j�/j¶2sbŒc.vma_assert_write_locked”†”asbuh1hhjÌ2ubj/)�”}”(hŒ ”h]”hŒ ”…”�”}”(hj3h²hh³Nh´Nubah}”(h]”h ]”j(/ah"]”h$]”h&]”uh1j/hjÌ2ubj°/)�”}”(hjžh]”hŒ*”…”�”}”(hj3h²hh³Nh´Nubah}”(h]”h ]”j»/ah"]”h$]”h&]”uh1j¯/hjÌ2ubj3/)�”}”(hŒvma”h]”hŒvma”…”�”}”(hj)3h²hh³Nh´Nubah}”(h]”h ]”j?/ah"]”h$]”h&]”uh1j2/hjÌ2ubeh}”(h]”h ]”h"]”h$]”h&]”Œnoemph”ˆhÅhÆuh1jQ/hjÈ2ubah}”(h]”h ]”h"]”h$]”h&]”hÅhÆuh1jK/hj�2h²hh³j¡2h´MIubeh}”(h]”h ]”h"]”h$]”h&]”hÅhÆjà/ˆuh1j/já/jâ/hj‹2h²hh³j¡2h´MIubah}”(h]”j†2ah ]”(jæ/jç/eh"]”h$]”h&]”jë/ˆjì/)jí/huh1jý.h³j¡2h´MIhjˆ2h²hubjï/)�”}”(hhh]”j)�”}”(hŒ+assert that **vma** holds a VMA write lock.”h]”(hŒ assert that ”…”�”}”(hjS3h²hh³Nh´NubjÓ)�”}”(hŒ**vma**”h]”hŒvma”…”�”}”(hj[3h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjS3ubhŒ holds a VMA write lock.”…”�”}”(hjS3h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´MIhjP3h²hubah}”(h]”h ]”h"]”h$]”h&]”uh1jî/hjˆ2h²hh³j¡2h´MIubeh}”(h]”h ]”(jŒfunction”eh"]”h$]”h&]”j0jj0j}3j0j}3j0‰j0‰j0‰uh1jø.h²hhjÖ.h³Nh´Nubj0)�”}”(hŒC**Parameters** ``struct vm_area_struct *vma`` The VMA to assert.”h]”(j)�”}”(hŒ**Parameters**”h]”jÓ)�”}”(hj‡3h]”hŒ Parameters”…”�”}”(hj‰3h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhj…3ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´MMhj�3ubj40)�”}”(hhh]”j90)�”}”(hŒ1``struct vm_area_struct *vma`` The VMA to assert.”h]”(j?0)�”}”(hŒ``struct vm_area_struct *vma``”h]”j )�”}”(hj¦3h]”hŒstruct vm_area_struct *vma”…”�”}”(hj¨3h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j hj¤3ubah}”(h]”h ]”h"]”h$]”h&]”uh1j>0h³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´MOhj 3ubjY0)�”}”(hhh]”j)�”}”(hŒThe VMA to assert.”h]”hŒThe VMA to assert.”…”�”}”(hj¿3h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´MJhj¼3ubah}”(h]”h ]”h"]”h$]”h&]”uh1jX0hj 3ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j80h³j»3h´MOhj�3ubah}”(h]”h ]”h"]”h$]”h&]”uh1j30hj�3ubeh}”(h]”h ]”Œ kernelindent”ah"]”h$]”h&]”uh1j0hjÖ.h²hh³Nh´Nubjè.)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œentries”]”(jô.Œvma_assert_locked (C function)”Œc.vma_assert_locked”hNt”auh1jç.hjÖ.h²hh³Nh´Nubjù.)�”}”(hhh]”(jþ.)�”}”(hŒ3void vma_assert_locked (struct vm_area_struct *vma)”h]”j/)�”}”(hŒ2void vma_assert_locked(struct vm_area_struct *vma)”h]”(j /)�”}”(hŒvoid”h]”hŒvoid”…”�”}”(hj4h²hh³Nh´Nubah}”(h]”h ]”j/ah"]”h$]”h&]”uh1j /hjü3h²hh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´MRubj/)�”}”(hŒ ”h]”hŒ ”…”�”}”(hj4h²hh³Nh´Nubah}”(h]”h ]”j(/ah"]”h$]”h&]”uh1j/hjü3h²hh³j4h´MRubj-/)�”}”(hŒvma_assert_locked”h]”j3/)�”}”(hŒvma_assert_locked”h]”hŒvma_assert_locked”…”�”}”(hj!4h²hh³Nh´Nubah}”(h]”h ]”j?/ah"]”h$]”h&]”uh1j2/hj4ubah}”(h]”h ]”(jF/jG/eh"]”h$]”h&]”hÅhÆuh1j,/hjü3h²hh³j4h´MRubjL/)�”}”(hŒ(struct vm_area_struct *vma)”h]”jR/)�”}”(hŒstruct vm_area_struct *vma”h]”(jX/)�”}”(hj[/h]”hŒstruct”…”�”}”(hj=4h²hh³Nh´Nubah}”(h]”h ]”jd/ah"]”h$]”h&]”uh1jW/hj94ubj/)�”}”(hŒ ”h]”hŒ ”…”�”}”(hjJ4h²hh³Nh´Nubah}”(h]”h ]”j(/ah"]”h$]”h&]”uh1j/hj94ubh)�”}”(hhh]”j3/)�”}”(hŒvm_area_struct”h]”hŒvm_area_struct”…”�”}”(hj[4h²hh³Nh´Nubah}”(h]”h ]”j?/ah"]”h$]”h&]”uh1j2/hjX4ubah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”jŒreftype”j�/Œ reftarget”j]4Œmodname”NŒ classname”Nj“/j–/)�”}”j™/]”jœ/)�”}”j�/j#4sbŒc.vma_assert_locked”†”asbuh1hhj94ubj/)�”}”(hŒ ”h]”hŒ ”…”�”}”(hj{4h²hh³Nh´Nubah}”(h]”h ]”j(/ah"]”h$]”h&]”uh1j/hj94ubj°/)�”}”(hjžh]”hŒ*”…”�”}”(hj‰4h²hh³Nh´Nubah}”(h]”h ]”j»/ah"]”h$]”h&]”uh1j¯/hj94ubj3/)�”}”(hŒvma”h]”hŒvma”…”�”}”(hj–4h²hh³Nh´Nubah}”(h]”h ]”j?/ah"]”h$]”h&]”uh1j2/hj94ubeh}”(h]”h ]”h"]”h$]”h&]”Œnoemph”ˆhÅhÆuh1jQ/hj54ubah}”(h]”h ]”h"]”h$]”h&]”hÅhÆuh1jK/hjü3h²hh³j4h´MRubeh}”(h]”h ]”h"]”h$]”h&]”hÅhÆjà/ˆuh1j/já/jâ/hjø3h²hh³j4h´MRubah}”(h]”jó3ah ]”(jæ/jç/eh"]”h$]”h&]”jë/ˆjì/)jí/huh1jý.h³j4h´MRhjõ3h²hubjï/)�”}”(hhh]”j)�”}”(hŒTassert that **vma** holds either a VMA read or a VMA write lock and is not detached.”h]”(hŒ assert that ”…”�”}”(hjÀ4h²hh³Nh´NubjÓ)�”}”(hŒ**vma**”h]”hŒvma”…”�”}”(hjÈ4h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjÀ4ubhŒA holds either a VMA read or a VMA write lock and is not detached.”…”�”}”(hjÀ4h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´MRhj½4h²hubah}”(h]”h ]”h"]”h$]”h&]”uh1jî/hjõ3h²hh³j4h´MRubeh}”(h]”h ]”(jŒfunction”eh"]”h$]”h&]”j0jj0jê4j0jê4j0‰j0‰j0‰uh1jø.h²hhjÖ.h³Nh´Nubj0)�”}”(hŒC**Parameters** ``struct vm_area_struct *vma`` The VMA to assert.”h]”(j)�”}”(hŒ**Parameters**”h]”jÓ)�”}”(hjô4h]”hŒ Parameters”…”�”}”(hjö4h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjò4ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´MVhjî4ubj40)�”}”(hhh]”j90)�”}”(hŒ1``struct vm_area_struct *vma`` The VMA to assert.”h]”(j?0)�”}”(hŒ``struct vm_area_struct *vma``”h]”j )�”}”(hj5h]”hŒstruct vm_area_struct *vma”…”�”}”(hj5h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j hj5ubah}”(h]”h ]”h"]”h$]”h&]”uh1j>0h³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´MXhj 5ubjY0)�”}”(hhh]”j)�”}”(hŒThe VMA to assert.”h]”hŒThe VMA to assert.”…”�”}”(hj,5h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´MThj)5ubah}”(h]”h ]”h"]”h$]”h&]”uh1jX0hj 5ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j80h³j(5h´MXhj 5ubah}”(h]”h ]”h"]”h$]”h&]”uh1j30hjî4ubeh}”(h]”h ]”Œ kernelindent”ah"]”h$]”h&]”uh1j0hjÖ.h²hh³Nh´Nubjè.)�”}”(hhh]”h}”(h]”h ]”h"]”h$]”h&]”Œentries”]”(jô.Œ"vma_assert_stabilised (C function)”Œc.vma_assert_stabilised”hNt”auh1jç.hjÖ.h²hh³Nh´Nubjù.)�”}”(hhh]”(jþ.)�”}”(hŒ7void vma_assert_stabilised (struct vm_area_struct *vma)”h]”j/)�”}”(hŒ6void vma_assert_stabilised(struct vm_area_struct *vma)”h]”(j /)�”}”(hŒvoid”h]”hŒvoid”…”�”}”(hjm5h²hh³Nh´Nubah}”(h]”h ]”j/ah"]”h$]”h&]”uh1j /hji5h²hh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´Mzubj/)�”}”(hŒ ”h]”hŒ ”…”�”}”(hj|5h²hh³Nh´Nubah}”(h]”h ]”j(/ah"]”h$]”h&]”uh1j/hji5h²hh³j{5h´Mzubj-/)�”}”(hŒvma_assert_stabilised”h]”j3/)�”}”(hŒvma_assert_stabilised”h]”hŒvma_assert_stabilised”…”�”}”(hjŽ5h²hh³Nh´Nubah}”(h]”h ]”j?/ah"]”h$]”h&]”uh1j2/hjŠ5ubah}”(h]”h ]”(jF/jG/eh"]”h$]”h&]”hÅhÆuh1j,/hji5h²hh³j{5h´MzubjL/)�”}”(hŒ(struct vm_area_struct *vma)”h]”jR/)�”}”(hŒstruct vm_area_struct *vma”h]”(jX/)�”}”(hj[/h]”hŒstruct”…”�”}”(hjª5h²hh³Nh´Nubah}”(h]”h ]”jd/ah"]”h$]”h&]”uh1jW/hj¦5ubj/)�”}”(hŒ ”h]”hŒ ”…”�”}”(hj·5h²hh³Nh´Nubah}”(h]”h ]”j(/ah"]”h$]”h&]”uh1j/hj¦5ubh)�”}”(hhh]”j3/)�”}”(hŒvm_area_struct”h]”hŒvm_area_struct”…”�”}”(hjÈ5h²hh³Nh´Nubah}”(h]”h ]”j?/ah"]”h$]”h&]”uh1j2/hjÅ5ubah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”jŒreftype”j�/Œ reftarget”jÊ5Œmodname”NŒ classname”Nj“/j–/)�”}”j™/]”jœ/)�”}”j�/j�5sbŒc.vma_assert_stabilised”†”asbuh1hhj¦5ubj/)�”}”(hŒ ”h]”hŒ ”…”�”}”(hjè5h²hh³Nh´Nubah}”(h]”h ]”j(/ah"]”h$]”h&]”uh1j/hj¦5ubj°/)�”}”(hjžh]”hŒ*”…”�”}”(hjö5h²hh³Nh´Nubah}”(h]”h ]”j»/ah"]”h$]”h&]”uh1j¯/hj¦5ubj3/)�”}”(hŒvma”h]”hŒvma”…”�”}”(hj6h²hh³Nh´Nubah}”(h]”h ]”j?/ah"]”h$]”h&]”uh1j2/hj¦5ubeh}”(h]”h ]”h"]”h$]”h&]”Œnoemph”ˆhÅhÆuh1jQ/hj¢5ubah}”(h]”h ]”h"]”h$]”h&]”hÅhÆuh1jK/hji5h²hh³j{5h´Mzubeh}”(h]”h ]”h"]”h$]”h&]”hÅhÆjà/ˆuh1j/já/jâ/hje5h²hh³j{5h´Mzubah}”(h]”j`5ah ]”(jæ/jç/eh"]”h$]”h&]”jë/ˆjì/)jí/huh1jý.h³j{5h´Mzhjb5h²hubjï/)�”}”(hhh]”j)�”}”(hŒcassert that this VMA cannot be changed from underneath us either by having a VMA or mmap lock held.”h]”hŒcassert that this VMA cannot be changed from underneath us either by having a VMA or mmap lock held.”…”�”}”(hj-6h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´Mzhj*6h²hubah}”(h]”h ]”h"]”h$]”h&]”uh1jî/hjb5h²hh³j{5h´Mzubeh}”(h]”h ]”(jŒfunction”eh"]”h$]”h&]”j0jj0jE6j0jE6j0‰j0‰j0‰uh1jø.h²hhjÖ.h³Nh´Nubj0)�”}”(hXc**Parameters** ``struct vm_area_struct *vma`` The VMA whose stability we wish to assess. **Description** If lockdep is enabled we can precisely ensure stability via either an mmap lock owned by us or a specific VMA lock. With lockdep disabled we may sometimes race with other threads acquiring the mmap read lock simultaneous with our VMA read lock.”h]”(j)�”}”(hŒ**Parameters**”h]”jÓ)�”}”(hjO6h]”hŒ Parameters”…”�”}”(hjQ6h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhjM6ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´M~hjI6ubj40)�”}”(hhh]”j90)�”}”(hŒJ``struct vm_area_struct *vma`` The VMA whose stability we wish to assess. ”h]”(j?0)�”}”(hŒ``struct vm_area_struct *vma``”h]”j )�”}”(hjn6h]”hŒstruct vm_area_struct *vma”…”�”}”(hjp6h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j hjl6ubah}”(h]”h ]”h"]”h$]”h&]”uh1j>0h³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´M|hjh6ubjY0)�”}”(hhh]”j)�”}”(hŒ*The VMA whose stability we wish to assess.”h]”hŒ*The VMA whose stability we wish to assess.”…”�”}”(hj‡6h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³jƒ6h´M|hj„6ubah}”(h]”h ]”h"]”h$]”h&]”uh1jX0hjh6ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j80h³jƒ6h´M|hje6ubah}”(h]”h ]”h"]”h$]”h&]”uh1j30hjI6ubj)�”}”(hŒ**Description**”h]”jÓ)�”}”(hj©6h]”hŒ Description”…”�”}”(hj«6h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jÒhj§6ubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´M~hjI6ubj)�”}”(hŒsIf lockdep is enabled we can precisely ensure stability via either an mmap lock owned by us or a specific VMA lock.”h]”hŒsIf lockdep is enabled we can precisely ensure stability via either an mmap lock owned by us or a specific VMA lock.”…”�”}”(hj¿6h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´M}hjI6ubj)�”}”(hŒ€With lockdep disabled we may sometimes race with other threads acquiring the mmap read lock simultaneous with our VMA read lock.”h]”hŒ€With lockdep disabled we may sometimes race with other threads acquiring the mmap read lock simultaneous with our VMA read lock.”…”�”}”(hjÎ6h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1jh³Œ[/var/lib/git/docbuild/linux/Documentation/mm/process_addrs:916: ./include/linux/mmap_lock.h”h´M€hjI6ubeh}”(h]”h ]”Œ kernelindent”ah"]”h$]”h&]”uh1j0hjÖ.h²hh³Nh´Nubeh}”(h]”Œfunctions-and-structures”ah ]”h"]”Œfunctions and structures”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´M’ubeh}”(h]”Œprocess-addresses”ah ]”h"]”Œprocess addresses”ah$]”h&]”uh1hÈhhh²hh³hÇh´Kubeh}”(h]”h ]”h"]”h$]”h&]”Œsource”hÇuh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)�”}”(hÍNŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”jÉŒfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”j7Œerror_encoding”Œutf-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”hÇŒ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”Œsubstitution_names”}”Œrefnames”}”Œrefids”}”Œnameids”}”(jñ6jî6j#j jòjïj“j�j‹jˆj j j:j7jjjÓ.jÐ.j“'j�'js jp jÒ"jÏ"js%jp%j×&jÔ&j‹'jˆ'jî+jë+jL)jI)jæ+jã+jk.jh.jË.jÈ.jé6jæ6uŒ nametypes”}”(jñ6‰j#‰jò‰j“‰j‹‰j ‰j:‰j‰jÓ.‰j“'‰js ‰jÒ"‰js%‰j×&‰j‹'‰jî+‰jL)‰jæ+‰jk.‰jË.‰jé6‰uh}”(jî6hÊj j¹jïjj�jõjˆjÀ j j–j7jjj=jÐ.j&j�'jOjp jcjÏ"jv jp%jÕ"jÔ&jv%jˆ'jÚ&jë+j–'jI)j§'jã+jO)jh.jñ+jÈ.jn.jæ6jÖ.jö.jÿ.j·0j¼0j†2j‹2jó3jø3j`5je5jÓ j j[jæ jÒjnjüjåjR.j…,uŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”j$7Ks…”R”Œparse_messages”]”Œtransform_messages”]”Œ transformer”NŒ include_log”]”Œ decoration”Nh²hub.