|
@@ -3466,8 +3466,8 @@ static int create_huge_pmd(struct vm_fault *vmf)
|
|
|
{
|
|
|
if (vma_is_anonymous(vmf->vma))
|
|
|
return do_huge_pmd_anonymous_page(vmf);
|
|
|
- if (vmf->vma->vm_ops->pmd_fault)
|
|
|
- return vmf->vma->vm_ops->pmd_fault(vmf);
|
|
|
+ if (vmf->vma->vm_ops->huge_fault)
|
|
|
+ return vmf->vma->vm_ops->huge_fault(vmf);
|
|
|
return VM_FAULT_FALLBACK;
|
|
|
}
|
|
|
|
|
@@ -3475,8 +3475,8 @@ static int wp_huge_pmd(struct vm_fault *vmf, pmd_t orig_pmd)
|
|
|
{
|
|
|
if (vma_is_anonymous(vmf->vma))
|
|
|
return do_huge_pmd_wp_page(vmf, orig_pmd);
|
|
|
- if (vmf->vma->vm_ops->pmd_fault)
|
|
|
- return vmf->vma->vm_ops->pmd_fault(vmf);
|
|
|
+ if (vmf->vma->vm_ops->huge_fault)
|
|
|
+ return vmf->vma->vm_ops->huge_fault(vmf);
|
|
|
|
|
|
/* COW handled on pte level: split pmd */
|
|
|
VM_BUG_ON_VMA(vmf->vma->vm_flags & VM_SHARED, vmf->vma);
|
|
@@ -3606,6 +3606,7 @@ static int __handle_mm_fault(struct vm_area_struct *vma, unsigned long address,
|
|
|
struct mm_struct *mm = vma->vm_mm;
|
|
|
pgd_t *pgd;
|
|
|
pud_t *pud;
|
|
|
+ int ret;
|
|
|
|
|
|
pgd = pgd_offset(mm, address);
|
|
|
pud = pud_alloc(mm, pgd, address);
|
|
@@ -3615,15 +3616,18 @@ static int __handle_mm_fault(struct vm_area_struct *vma, unsigned long address,
|
|
|
if (!vmf.pmd)
|
|
|
return VM_FAULT_OOM;
|
|
|
if (pmd_none(*vmf.pmd) && transparent_hugepage_enabled(vma)) {
|
|
|
- int ret = create_huge_pmd(&vmf);
|
|
|
+ vmf.flags |= FAULT_FLAG_SIZE_PMD;
|
|
|
+ ret = create_huge_pmd(&vmf);
|
|
|
if (!(ret & VM_FAULT_FALLBACK))
|
|
|
return ret;
|
|
|
+ /* fall through path, remove PMD flag */
|
|
|
+ vmf.flags &= ~FAULT_FLAG_SIZE_PMD;
|
|
|
} else {
|
|
|
pmd_t orig_pmd = *vmf.pmd;
|
|
|
- int ret;
|
|
|
|
|
|
barrier();
|
|
|
if (pmd_trans_huge(orig_pmd) || pmd_devmap(orig_pmd)) {
|
|
|
+ vmf.flags |= FAULT_FLAG_SIZE_PMD;
|
|
|
if (pmd_protnone(orig_pmd) && vma_is_accessible(vma))
|
|
|
return do_huge_pmd_numa_page(&vmf, orig_pmd);
|
|
|
|
|
@@ -3632,6 +3636,8 @@ static int __handle_mm_fault(struct vm_area_struct *vma, unsigned long address,
|
|
|
ret = wp_huge_pmd(&vmf, orig_pmd);
|
|
|
if (!(ret & VM_FAULT_FALLBACK))
|
|
|
return ret;
|
|
|
+ /* fall through path, remove PUD flag */
|
|
|
+ vmf.flags &= ~FAULT_FLAG_SIZE_PUD;
|
|
|
} else {
|
|
|
huge_pmd_set_accessed(&vmf, orig_pmd);
|
|
|
return 0;
|