FAILED: patch "[PATCH] device-dax: fix pmd/pte fault fallback handling" failed to apply to 4.9-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 4.9-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
Quoted 1 line
From
0134ed4fb9e78672ee9f7b18007114404c81e63fMon Sep 17 00:00:00 2001
From: Dave Jiang <[email protected]>
Date: Fri, 10 Mar 2017 13:24:22 -0700
Subject: [PATCH] device-dax: fix pmd/pte fault fallback handling
Jeff Moyer reports:
With a device dax alignment of 4KB or 2MB, I get sigbus when running the attached fio job file for the current kernel (4.11.0-rc1+). If I specify an alignment of 1GB, it works.
I turned on debug output, and saw that it was failing in the huge fault code.
dax dax1.0: dax_open
dax dax1.0: dax_mmap
dax dax1.0: dax_dev_huge_fault: fio: write (0x7f08f0a00000 - dax dax1.0: __dax_dev_pud_fault: phys_to_pgoff(0xffffffffcf60 dax dax1.0: dax_release
fio config for reproduce:
[global]
ioengine=dev-dax
direct=0
filename=/dev/dax0.0
bs=2m
[write]
rw=write
[read]
stonewall
rw=read
The driver fails to fallback when taking a fault that is larger than the device alignment, or handling a larger fault when a smaller mapping is already established. While we could support larger mappings for a device with a smaller alignment, that change is too large for the immediate fix. The simplest change is to force fallback until the fault size matches the alignment.
drivers/dax/dax.c +15 -0
@@ -427,6 +427,7 @@ static int __dax_dev_pte_fault(struct dax_dev *dax_dev, struct vm_fault *vmf)int rc =VM_FAULT_SIGBUS ;phys_addr_t phys;pfn_t pfn; +unsigned int fault_size =PAGE_SIZE ;if (check_vma (dax_dev, vmf->vma, __func__))return VM_FAULT_SIGBUS ;
@@ -437,6 +438,9 @@ static int __dax_dev_pte_fault(struct dax_dev *dax_dev, struct vm_fault *vmf)return VM_FAULT_SIGBUS ; } +if (fault_size != dax_region->align) +return VM_FAULT_SIGBUS ; + phys =pgoff_to_phys (dax_dev, vmf->pgoff,PAGE_SIZE );if (phys ==-1 ) { dev_dbg(dev, "%s: phys_to_pgoff(%#lx) failed\n", __func__,
@@ -464,6 +468,7 @@ static int __dax_dev_pmd_fault(struct dax_dev *dax_dev, struct vm_fault *vmf)phys_addr_t phys;pgoff_t pgoff;pfn_t pfn; +unsigned int fault_size =PMD_SIZE ;if (check_vma (dax_dev, vmf->vma, __func__))return VM_FAULT_SIGBUS ;
@@ -480,6 +485,16 @@ static int __dax_dev_pmd_fault(struct dax_dev *dax_dev, struct vm_fault *vmf)return VM_FAULT_SIGBUS ; } +if (fault_size < dax_region->align) +return VM_FAULT_SIGBUS ; +else if (fault_size > dax_region->align) +return VM_FAULT_FALLBACK ; + +/* if we are outside of the VMA */ +if (pmd_addr < vmf->vma->vm_start || + (pmd_addr +PMD_SIZE ) > vmf->vma->vm_end) +return VM_FAULT_SIGBUS ; + pgoff =linear_page_index (vmf->vma, pmd_addr); phys =pgoff_to_phys (dax_dev, pgoff,PMD_SIZE );if (phys ==-1 ) {