diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h index 7f221e8a87cc..0fa409e827bb 100644 --- a/include/linux/vm_event_item.h +++ b/include/linux/vm_event_item.h @@ -115,8 +115,7 @@ enum vm_event_item { PGPGIN, PGPGOUT, SWAP_RA_HIT, #endif #ifdef CONFIG_SPECULATIVE_PAGE_FAULT - SPECULATIVE_PGFAULT_ANON, - SPECULATIVE_PGFAULT_FILE, + SPECULATIVE_PGFAULT, #endif NR_VM_EVENT_ITEMS }; diff --git a/mm/filemap.c b/mm/filemap.c index c8b28c6538a2..3eff4f1388b2 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2562,12 +2562,12 @@ static struct file *do_sync_mmap_readahead(struct vm_fault *vmf) pgoff_t offset = vmf->pgoff; /* If we don't want any read-ahead, don't bother */ - if (vmf->vma_flags & VM_RAND_READ) + if (vmf->vma->vm_flags & VM_RAND_READ) return fpin; if (!ra->ra_pages) return fpin; - if (vmf->vma_flags & VM_SEQ_READ) { + if (vmf->vma->vm_flags & VM_SEQ_READ) { fpin = maybe_unlock_mmap_for_io(vmf, fpin); page_cache_sync_readahead(mapping, ra, file, offset, ra->ra_pages); @@ -2611,7 +2611,7 @@ static struct file *do_async_mmap_readahead(struct vm_fault *vmf, pgoff_t offset = vmf->pgoff; /* If we don't want any read-ahead, don't bother */ - if (vmf->vma_flags & VM_RAND_READ || !ra->ra_pages) + if (vmf->vma->vm_flags & VM_RAND_READ || !ra->ra_pages) return fpin; if (ra->mmap_miss > 0) ra->mmap_miss--; @@ -2634,7 +2634,7 @@ static struct file *do_async_mmap_readahead(struct vm_fault *vmf, * it in the page cache, and handles the special cases reasonably without * having a lot of duplicated code. * - * vma->vm_mm->mmap_sem must be held on entry (except FAULT_FLAG_SPECULATIVE). + * vma->vm_mm->mmap_sem must be held on entry. * * If our return value has VM_FAULT_RETRY set, it's because the mmap_sem * may be dropped before doing I/O or by lock_page_maybe_drop_mmap(). diff --git a/mm/memory.c b/mm/memory.c index bbd1616db8c9..faffb6adb66f 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -4235,7 +4235,6 @@ static vm_fault_t wp_huge_pud(struct vm_fault *vmf, pud_t orig_pud) static vm_fault_t handle_pte_fault(struct vm_fault *vmf) { pte_t entry; - vm_fault_t ret = 0; if (unlikely(pmd_none(*vmf->pmd))) { /* @@ -4288,6 +4287,8 @@ static vm_fault_t handle_pte_fault(struct vm_fault *vmf) if (!vmf->pte) { if (vma_is_anonymous(vmf->vma)) return do_anonymous_page(vmf); + else if (vmf->flags & FAULT_FLAG_SPECULATIVE) + return VM_FAULT_RETRY; else return do_fault(vmf); } @@ -4321,12 +4322,10 @@ static vm_fault_t handle_pte_fault(struct vm_fault *vmf) */ if (vmf->flags & FAULT_FLAG_WRITE) flush_tlb_fix_spurious_fault(vmf->vma, vmf->address); - if (vmf->flags & FAULT_FLAG_SPECULATIVE) - ret = VM_FAULT_RETRY; } unlock: pte_unmap_unlock(vmf->pte, vmf->ptl); - return ret; + return 0; } /* @@ -4471,12 +4470,22 @@ int __handle_speculative_fault(struct mm_struct *mm, unsigned long address, return VM_FAULT_RETRY; } + /* + * Can't call vm_ops service has we don't know what they would do + * with the VMA. + * This include huge page from hugetlbfs. + */ + if (vmf.vma->vm_ops) { + trace_spf_vma_notsup(_RET_IP_, vmf.vma, address); + return VM_FAULT_RETRY; + } + /* * __anon_vma_prepare() requires the mmap_sem to be held * because vm_next and vm_prev must be safe. This can't be guaranteed * in the speculative path. */ - if (unlikely(vma_is_anonymous(vmf.vma) && !vmf.vma->anon_vma)) { + if (unlikely(!vmf.vma->anon_vma)) { trace_spf_vma_notsup(_RET_IP_, vmf.vma, address); return VM_FAULT_RETRY; } @@ -4618,10 +4627,7 @@ int __handle_speculative_fault(struct mm_struct *mm, unsigned long address, * If there is no need to retry, don't return the vma to the caller. */ if (ret != VM_FAULT_RETRY) { - if (vma_is_anonymous(vmf.vma)) - count_vm_event(SPECULATIVE_PGFAULT_ANON); - else - count_vm_event(SPECULATIVE_PGFAULT_FILE); + count_vm_event(SPECULATIVE_PGFAULT); put_vma(vmf.vma); *vma = NULL; } diff --git a/mm/shmem.c b/mm/shmem.c index 9ae6831e7b07..e2f72b220988 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2072,10 +2072,10 @@ static vm_fault_t shmem_fault(struct vm_fault *vmf) sgp = SGP_CACHE; - if ((vmf->vma_flags & VM_NOHUGEPAGE) || + if ((vma->vm_flags & VM_NOHUGEPAGE) || test_bit(MMF_DISABLE_THP, &vma->vm_mm->flags)) sgp = SGP_NOHUGE; - else if (vmf->vma_flags & VM_HUGEPAGE) + else if (vma->vm_flags & VM_HUGEPAGE) sgp = SGP_HUGE; err = shmem_getpage_gfp(inode, vmf->pgoff, &vmf->page, sgp, diff --git a/mm/vmstat.c b/mm/vmstat.c index af290e42d497..8c7e6e718a5f 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -1301,8 +1301,7 @@ const char * const vmstat_text[] = { "swap_ra_hit", #endif #ifdef CONFIG_SPECULATIVE_PAGE_FAULT - "speculative_pgfault_anon", - "speculative_pgfault_file", + "speculative_pgfault" #endif #endif /* CONFIG_VM_EVENT_COUNTERS */ };