ANDROID: mm: allow vmas with vm_ops to be speculatively handled
Right now only anonymous page faults are speculatively handled, thus leaving out a large percentage of faults still requiring to take mmap_sem. These were left out since there can be fault handlers mainly in the fs layer which may use vma in unknown ways. This patch enables speculative fault for ext4, f2fs and shmem. The feature is disabled by default and enabled via allow_file_spec_access kernel param. Bug: 171954515 Change-Id: I0d23ebf299000e4ac5e2c71bc0b7fc9006e98da9 Signed-off-by: Vinayak Menon <vinmenon@codeaurora.org>
This commit is contained in:
28
mm/filemap.c
28
mm/filemap.c
@@ -2864,6 +2864,11 @@ static bool filemap_map_pmd(struct vm_fault *vmf, struct page *page)
|
||||
}
|
||||
|
||||
if (pmd_none(*vmf->pmd)) {
|
||||
if (vmf->flags & FAULT_FLAG_SPECULATIVE) {
|
||||
unlock_page(page);
|
||||
put_page(page);
|
||||
return true;
|
||||
}
|
||||
vmf->ptl = pmd_lock(mm, vmf->pmd);
|
||||
if (likely(pmd_none(*vmf->pmd))) {
|
||||
mm_inc_nr_ptes(mm);
|
||||
@@ -2942,6 +2947,14 @@ static inline struct page *next_map_page(struct address_space *mapping,
|
||||
mapping, xas, end_pgoff);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
|
||||
bool filemap_allow_speculation(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(filemap_allow_speculation);
|
||||
#endif
|
||||
|
||||
vm_fault_t filemap_map_pages(struct vm_fault *vmf,
|
||||
pgoff_t start_pgoff, pgoff_t end_pgoff)
|
||||
{
|
||||
@@ -2961,12 +2974,22 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf,
|
||||
goto out;
|
||||
|
||||
if (filemap_map_pmd(vmf, head)) {
|
||||
if (pmd_none(*vmf->pmd) &&
|
||||
vmf->flags & FAULT_FLAG_SPECULATIVE) {
|
||||
ret = VM_FAULT_RETRY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = VM_FAULT_NOPAGE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
addr = vma->vm_start + ((start_pgoff - vma->vm_pgoff) << PAGE_SHIFT);
|
||||
vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd, addr, &vmf->ptl);
|
||||
if (!pte_map_lock_addr(vmf, addr)) {
|
||||
ret = VM_FAULT_RETRY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
do {
|
||||
page = find_subpage(head, xas.xa_index);
|
||||
if (PageHWPoison(page))
|
||||
@@ -3033,6 +3056,9 @@ const struct vm_operations_struct generic_file_vm_ops = {
|
||||
.fault = filemap_fault,
|
||||
.map_pages = filemap_map_pages,
|
||||
.page_mkwrite = filemap_page_mkwrite,
|
||||
#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
|
||||
.allow_speculation = filemap_allow_speculation,
|
||||
#endif
|
||||
};
|
||||
|
||||
/* This is used for a general mmap of a disk file */
|
||||
|
Reference in New Issue
Block a user