€•:gŒ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/filesystems/mmap_prepare”Œ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/filesystems/mmap_prepare”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ,/translations/it_IT/filesystems/mmap_prepare”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ,/translations/ja_JP/filesystems/mmap_prepare”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ,/translations/ko_KR/filesystems/mmap_prepare”Œ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/filesystems/mmap_prepare”Œ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/filesystems/mmap_prepare”Œ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³ŒF/var/lib/git/docbuild/linux/Documentation/filesystems/mmap_prepare.rst”h´KubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒmmap_prepare callback HOWTO”h]”hŒmmap_prepare callback HOWTO”…””}”(hhÏh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhhÊh²hh³hÇh´KubhÉ)”}”(hhh]”(hÎ)”}”(hŒ Introduction”h]”hŒ Introduction”…””}”(hhàh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhhÝh²hh³hÇh´KubhŒ paragraph”“”)”}”(hŒÕThe ``struct file->f_op->mmap()`` callback has been deprecated as it is both a stability and security risk, and doesn't always permit the merging of adjacent mappings resulting in unnecessary memory fragmentation.”h]”(hŒThe ”…””}”(hhðh²hh³Nh´NubhŒliteral”“”)”}”(hŒ``struct file->f_op->mmap()``”h]”hŒstruct file->f_op->mmap()”…””}”(hhúh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1høhhðubhŒ¶ callback has been deprecated as it is both a stability and security risk, and doesn’t always permit the merging of adjacent mappings resulting in unnecessary memory fragmentation.”…””}”(hhðh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´K hhÝh²hubhï)”}”(hŒbIt has been replaced with the ``file->f_op->mmap_prepare()`` callback which solves these problems.”h]”(hŒIt has been replaced with the ”…””}”(hjh²hh³Nh´Nubhù)”}”(hŒ``file->f_op->mmap_prepare()``”h]”hŒfile->f_op->mmap_prepare()”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1høhjubhŒ& callback which solves these problems.”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´KhhÝh²hubhï)”}”(hŒžThis hook is called right at the beginning of setting up the mapping, and importantly it is invoked *before* any merging of adjacent mappings has taken place.”h]”(hŒdThis hook is called right at the beginning of setting up the mapping, and importantly it is invoked ”…””}”(hj2h²hh³Nh´NubhŒemphasis”“”)”}”(hŒ*before*”h]”hŒbefore”…””}”(hj<h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j:hj2ubhŒ2 any merging of adjacent mappings has taken place.”…””}”(hj2h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´KhhÝh²hubhï)”}”(hŒŽIf an error arises upon mapping, it might arise after this callback has been invoked, therefore it should be treated as effectively stateless.”h]”hŒŽIf an error arises upon mapping, it might arise after this callback has been invoked, therefore it should be treated as effectively stateless.”…””}”(hjTh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´KhhÝh²hubhï)”}”(hŒÆThat is - no resources should be allocated nor state updated to reflect that a mapping has been established, as the mapping may either be merged, or fail to be mapped after the callback is complete.”h]”hŒÆThat is - no resources should be allocated nor state updated to reflect that a mapping has been established, as the mapping may either be merged, or fail to be mapped after the callback is complete.”…””}”(hjbh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´KhhÝh²hubhÉ)”}”(hhh]”(hÎ)”}”(hŒMapped callback”h]”hŒMapped callback”…””}”(hjsh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjph²hh³hÇh´Kubhï)”}”(hŒ×If resources need to be allocated per-mapping, or state such as a reference count needs to be manipulated, this should be done using the ``vm_ops->mapped`` hook, which itself should be set by the >mmap_prepare hook.”h]”(hŒ‰If resources need to be allocated per-mapping, or state such as a reference count needs to be manipulated, this should be done using the ”…””}”(hjh²hh³Nh´Nubhù)”}”(hŒ``vm_ops->mapped``”h]”hŒvm_ops->mapped”…””}”(hj‰h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1høhjubhŒ< hook, which itself should be set by the >mmap_prepare hook.”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´Khjph²hubhï)”}”(hŒ¼This callback is only invoked if a new mapping has been established and was not merged with any other, and is invoked at a point where no error may occur before the mapping is established.”h]”hŒ¼This callback is only invoked if a new mapping has been established and was not merged with any other, and is invoked at a point where no error may occur before the mapping is established.”…””}”(hj¡h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´K#hjph²hubhï)”}”(hŒÝYou may return an error to the callback itself, which will cause the mapping to become unmapped and an error returned to the mmap() caller. This is useful if resources need to be allocated, and that allocation might fail.”h]”hŒÝYou may return an error to the callback itself, which will cause the mapping to become unmapped and an error returned to the mmap() caller. This is useful if resources need to be allocated, and that allocation might fail.”…””}”(hj¯h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´K'hjph²hubeh}”(h]”Œmapped-callback”ah ]”h"]”Œmapped callback”ah$]”h&]”uh1hÈhhÝh²hh³hÇh´Kubeh}”(h]”Œ introduction”ah ]”h"]”Œ introduction”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´KubhÉ)”}”(hhh]”(hÎ)”}”(hŒ How To Use”h]”hŒ How To Use”…””}”(hjÐh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjÍh²hh³hÇh´K,ubhï)”}”(hŒ€In your driver's struct file_operations struct, specify an ``mmap_prepare`` callback rather than an ``mmap`` one, e.g. for ext4:”h]”(hŒ=In your driver’s struct file_operations struct, specify an ”…””}”(hjÞh²hh³Nh´Nubhù)”}”(hŒ``mmap_prepare``”h]”hŒ mmap_prepare”…””}”(hjæh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1høhjÞubhŒ callback rather than an ”…””}”(hjÞh²hh³Nh´Nubhù)”}”(hŒ``mmap``”h]”hŒmmap”…””}”(hjøh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1høhjÞubhŒ one, e.g. for ext4:”…””}”(hjÞh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´K.hjÍh²hubhŒ literal_block”“”)”}”(hŒoconst struct file_operations ext4_file_operations = { ... .mmap_prepare = ext4_file_mmap_prepare, };”h]”hŒoconst struct file_operations ext4_file_operations = { ... .mmap_prepare = ext4_file_mmap_prepare, };”…””}”hjsbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆŒforce”‰Œlanguage”ŒC”Œhighlight_args”}”uh1jh³hÇh´K1hjÍh²hubhï)”}”(hŒGThis has a signature of ``int (*mmap_prepare)(struct vm_area_desc *)``.”h]”(hŒThis has a signature of ”…””}”(hj%h²hh³Nh´Nubhù)”}”(hŒ.``int (*mmap_prepare)(struct vm_area_desc *)``”h]”hŒ*int (*mmap_prepare)(struct vm_area_desc *)”…””}”(hj-h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1høhj%ubhŒ.”…””}”(hj%h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´K8hjÍh²hubhï)”}”(hŒ'Examining the struct vm_area_desc type:”h]”hŒ'Examining the struct vm_area_desc type:”…””}”(hjEh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´K:hjÍh²hubj)”}”(hXstruct vm_area_desc { /* Immutable state. */ const struct mm_struct *const mm; struct file *const file; /* May vary from vm_file in stacked callers. */ unsigned long start; unsigned long end; /* Mutable fields. Populated with initial state. */ pgoff_t pgoff; struct file *vm_file; vma_flags_t vma_flags; pgprot_t page_prot; /* Write-only fields. */ const struct vm_operations_struct *vm_ops; void *private_data; /* Take further action? */ struct mmap_action action; };”h]”hXstruct vm_area_desc { /* Immutable state. */ const struct mm_struct *const mm; struct file *const file; /* May vary from vm_file in stacked callers. */ unsigned long start; unsigned long end; /* Mutable fields. Populated with initial state. */ pgoff_t pgoff; struct file *vm_file; vma_flags_t vma_flags; pgprot_t page_prot; /* Write-only fields. */ const struct vm_operations_struct *vm_ops; void *private_data; /* Take further action? */ struct mmap_action action; };”…””}”hjSsbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆj ‰j!j"j#}”uh1jh³hÇh´Kfile; struct inode *inode = file->f_mapping->host; ... file_accessed(file); if (IS_DAX(file_inode(file))) { desc->vm_ops = &ext4_dax_vm_ops; vma_desc_set_flags(desc, VMA_HUGEPAGE_BIT); } else { desc->vm_ops = &ext4_file_vm_ops; } return 0; }”h]”hX‘static int ext4_file_mmap_prepare(struct vm_area_desc *desc) { int ret; struct file *file = desc->file; struct inode *inode = file->f_mapping->host; ... file_accessed(file); if (IS_DAX(file_inode(file))) { desc->vm_ops = &ext4_dax_vm_ops; vma_desc_set_flags(desc, VMA_HUGEPAGE_BIT); } else { desc->vm_ops = &ext4_file_vm_ops; } return 0; }”…””}”hjpsbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆj ‰j!j"j#}”uh1jh³hÇh´KVhjÍh²hubhï)”}”(hŒ˜Importantly, you no longer have to dance around with reference counts or locks when updating these fields - **you can simply go ahead and change them**.”h]”(hŒlImportantly, you no longer have to dance around with reference counts or locks when updating these fields - ”…””}”(hjh²hh³Nh´NubhŒstrong”“”)”}”(hŒ+**you can simply go ahead and change them**”h]”hŒ'you can simply go ahead and change them”…””}”(hj‰h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j‡hjubhŒ.”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´KjhjÍh²hubhï)”}”(hŒ0Everything is taken care of by the mapping code.”h]”hŒ0Everything is taken care of by the mapping code.”…””}”(hj¡h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´KmhjÍh²hubhÉ)”}”(hhh]”(hÎ)”}”(hŒ VMA Flags”h]”hŒ VMA Flags”…””}”(hj²h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj¯h²hh³hÇh´Kpubhï)”}”(hXAlong with ``mmap_prepare``, VMA flags have undergone an overhaul. Where before you would invoke one of vm_flags_init(), vm_flags_reset(), vm_flags_set(), vm_flags_clear(), and vm_flags_mod() to modify flags (and to have the locking done correctly for you, this is no longer necessary.”h]”(hŒ Along with ”…””}”(hjÀh²hh³Nh´Nubhù)”}”(hŒ``mmap_prepare``”h]”hŒ mmap_prepare”…””}”(hjÈh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1høhjÀubhX, VMA flags have undergone an overhaul. Where before you would invoke one of vm_flags_init(), vm_flags_reset(), vm_flags_set(), vm_flags_clear(), and vm_flags_mod() to modify flags (and to have the locking done correctly for you, this is no longer necessary.”…””}”(hjÀh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´Krhj¯h²hubhï)”}”(hŒˆAlso, the legacy approach of specifying VMA flags via ``VM_READ``, ``VM_WRITE``, etc. - i.e. using a ``-VM_xxx``- macro has changed too.”h]”(hŒ6Also, the legacy approach of specifying VMA flags via ”…””}”(hjàh²hh³Nh´Nubhù)”}”(hŒ ``VM_READ``”h]”hŒVM_READ”…””}”(hjèh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1høhjàubhŒ, ”…””}”(hjàh²hh³Nh´Nubhù)”}”(hŒ ``VM_WRITE``”h]”hŒVM_WRITE”…””}”(hjúh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1høhjàubhŒ, etc. - i.e. using a ”…””}”(hjàh²hh³Nh´Nubhù)”}”(hŒ ``-VM_xxx``”h]”hŒ-VM_xxx”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1høhjàubhŒ- macro has changed too.”…””}”(hjàh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´Kwhj¯h²hubhï)”}”(hŒÞWhen implementing mmap_prepare(), reference flags by their bit number, defined as a ``VMA_xxx_BIT`` macro, e.g. ``VMA_READ_BIT``, ``VMA_WRITE_BIT`` etc., and use one of (where ``desc`` is a pointer to struct vm_area_desc):”h]”(hŒTWhen implementing mmap_prepare(), reference flags by their bit number, defined as a ”…””}”(hj$h²hh³Nh´Nubhù)”}”(hŒ``VMA_xxx_BIT``”h]”hŒ VMA_xxx_BIT”…””}”(hj,h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1høhj$ubhŒ macro, e.g. ”…””}”(hj$h²hh³Nh´Nubhù)”}”(hŒ``VMA_READ_BIT``”h]”hŒ VMA_READ_BIT”…””}”(hj>h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1høhj$ubhŒ, ”…””}”(hj$h²hh³Nh´Nubhù)”}”(hŒ``VMA_WRITE_BIT``”h]”hŒ VMA_WRITE_BIT”…””}”(hjPh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1høhj$ubhŒ etc., and use one of (where ”…””}”(hj$h²hh³Nh´Nubhù)”}”(hŒ``desc``”h]”hŒdesc”…””}”(hjbh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1høhj$ubhŒ& is a pointer to struct vm_area_desc):”…””}”(hj$h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´Kzhj¯h²hubhŒ bullet_list”“”)”}”(hhh]”(hŒ list_item”“”)”}”(hŒø``vma_desc_test_any(desc, ...)`` - Specify a comma-separated list of flags you wish to test for (whether _any_ are set), e.g. - ``vma_desc_test_any( desc, VMA_WRITE_BIT, VMA_MAYWRITE_BIT)`` - returns ``true`` if either are set, otherwise ``false``.”h]”hï)”}”(hŒø``vma_desc_test_any(desc, ...)`` - Specify a comma-separated list of flags you wish to test for (whether _any_ are set), e.g. - ``vma_desc_test_any( desc, VMA_WRITE_BIT, VMA_MAYWRITE_BIT)`` - returns ``true`` if either are set, otherwise ``false``.”h]”(hù)”}”(hŒ ``vma_desc_test_any(desc, ...)``”h]”hŒvma_desc_test_any(desc, ...)”…””}”(hj‰h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1høhj…ubhŒ` - Specify a comma-separated list of flags you wish to test for (whether _any_ are set), e.g. - ”…””}”(hj…h²hh³Nh´Nubhù)”}”(hŒ=``vma_desc_test_any( desc, VMA_WRITE_BIT, VMA_MAYWRITE_BIT)``”h]”hŒ9vma_desc_test_any( desc, VMA_WRITE_BIT, VMA_MAYWRITE_BIT)”…””}”(hj›h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1høhj…ubhŒ - returns ”…””}”(hj…h²hh³Nh´Nubhù)”}”(hŒ``true``”h]”hŒtrue”…””}”(hj­h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1høhj…ubhŒ if either are set, otherwise ”…””}”(hj…h²hh³Nh´Nubhù)”}”(hŒ ``false``”h]”hŒfalse”…””}”(hj¿h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1høhj…ubhŒ.”…””}”(hj…h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´K~hjubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj|h²hh³hÇh´Nubj€)”}”(hŒÁ``vma_desc_set_flags(desc, ...)`` - Update the VMA descriptor flags to set additional flags specified by a comma-separated list, e.g. - ``vma_desc_set_flags(desc, VMA_PFNMAP_BIT, VMA_IO_BIT)``.”h]”hï)”}”(hŒÁ``vma_desc_set_flags(desc, ...)`` - Update the VMA descriptor flags to set additional flags specified by a comma-separated list, e.g. - ``vma_desc_set_flags(desc, VMA_PFNMAP_BIT, VMA_IO_BIT)``.”h]”(hù)”}”(hŒ!``vma_desc_set_flags(desc, ...)``”h]”hŒvma_desc_set_flags(desc, ...)”…””}”(hjåh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1høhjáubhŒg - Update the VMA descriptor flags to set additional flags specified by a comma-separated list, e.g. - ”…””}”(hjáh²hh³Nh´Nubhù)”}”(hŒ8``vma_desc_set_flags(desc, VMA_PFNMAP_BIT, VMA_IO_BIT)``”h]”hŒ4vma_desc_set_flags(desc, VMA_PFNMAP_BIT, VMA_IO_BIT)”…””}”(hj÷h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1høhjáubhŒ.”…””}”(hjáh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´K‚hjÝubah}”(h]”h ]”h"]”h$]”h&]”uh1jhj|h²hh³hÇh´Nubj€)”}”(hŒÃ``vma_desc_clear_flags(desc, ...)`` - Update the VMA descriptor flags to clear flags specified by a comma-separated list, e.g. - ``vma_desc_clear_flags( desc, VMA_WRITE_BIT, VMA_MAYWRITE_BIT)``. ”h]”hï)”}”(hŒÂ``vma_desc_clear_flags(desc, ...)`` - Update the VMA descriptor flags to clear flags specified by a comma-separated list, e.g. - ``vma_desc_clear_flags( desc, VMA_WRITE_BIT, VMA_MAYWRITE_BIT)``.”h]”(hù)”}”(hŒ#``vma_desc_clear_flags(desc, ...)``”h]”hŒvma_desc_clear_flags(desc, ...)”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1høhjubhŒ^ - Update the VMA descriptor flags to clear flags specified by a comma-separated list, e.g. - ”…””}”(hjh²hh³Nh´Nubhù)”}”(hŒ@``vma_desc_clear_flags( desc, VMA_WRITE_BIT, VMA_MAYWRITE_BIT)``”h]”hŒ