Commit 1b8df619 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm

Pull device-dax fixes from Dan Williams:
 "The device-dax driver was not being careful to handle falling back to
  smaller fault-granularity sizes.

  The driver already fails fault attempts that are smaller than the
  device's alignment, but it also needs to handle the cases where a
  larger page mapping could be established. For simplicity of the
  immediate fix the implementation just signals VM_FAULT_FALLBACK until
  fault-size == device-alignment.

  One fix is for -stable to address pmd-to-pte fallback from the
  original implementation, another fix is for the new (introduced in
  4.11-rc1) pud-to-pmd regression, and a typo fix comes along for the
  ride.

  These have received a build success notification from the kbuild
  robot"

* 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm:
  device-dax: fix debug output typo
  device-dax: fix pud fault fallback handling
  device-dax: fix pmd/pte fault fallback handling
parents 93afaa45 52084f89
...@@ -427,6 +427,7 @@ static int __dax_dev_pte_fault(struct dax_dev *dax_dev, struct vm_fault *vmf) ...@@ -427,6 +427,7 @@ static int __dax_dev_pte_fault(struct dax_dev *dax_dev, struct vm_fault *vmf)
int rc = VM_FAULT_SIGBUS; int rc = VM_FAULT_SIGBUS;
phys_addr_t phys; phys_addr_t phys;
pfn_t pfn; pfn_t pfn;
unsigned int fault_size = PAGE_SIZE;
if (check_vma(dax_dev, vmf->vma, __func__)) if (check_vma(dax_dev, vmf->vma, __func__))
return VM_FAULT_SIGBUS; return VM_FAULT_SIGBUS;
...@@ -437,9 +438,12 @@ static int __dax_dev_pte_fault(struct dax_dev *dax_dev, struct vm_fault *vmf) ...@@ -437,9 +438,12 @@ static int __dax_dev_pte_fault(struct dax_dev *dax_dev, struct vm_fault *vmf)
return VM_FAULT_SIGBUS; return VM_FAULT_SIGBUS;
} }
if (fault_size != dax_region->align)
return VM_FAULT_SIGBUS;
phys = pgoff_to_phys(dax_dev, vmf->pgoff, PAGE_SIZE); phys = pgoff_to_phys(dax_dev, vmf->pgoff, PAGE_SIZE);
if (phys == -1) { if (phys == -1) {
dev_dbg(dev, "%s: phys_to_pgoff(%#lx) failed\n", __func__, dev_dbg(dev, "%s: pgoff_to_phys(%#lx) failed\n", __func__,
vmf->pgoff); vmf->pgoff);
return VM_FAULT_SIGBUS; return VM_FAULT_SIGBUS;
} }
...@@ -464,6 +468,7 @@ static int __dax_dev_pmd_fault(struct dax_dev *dax_dev, struct vm_fault *vmf) ...@@ -464,6 +468,7 @@ static int __dax_dev_pmd_fault(struct dax_dev *dax_dev, struct vm_fault *vmf)
phys_addr_t phys; phys_addr_t phys;
pgoff_t pgoff; pgoff_t pgoff;
pfn_t pfn; pfn_t pfn;
unsigned int fault_size = PMD_SIZE;
if (check_vma(dax_dev, vmf->vma, __func__)) if (check_vma(dax_dev, vmf->vma, __func__))
return VM_FAULT_SIGBUS; return VM_FAULT_SIGBUS;
...@@ -480,10 +485,20 @@ static int __dax_dev_pmd_fault(struct dax_dev *dax_dev, struct vm_fault *vmf) ...@@ -480,10 +485,20 @@ static int __dax_dev_pmd_fault(struct dax_dev *dax_dev, struct vm_fault *vmf)
return VM_FAULT_SIGBUS; 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); pgoff = linear_page_index(vmf->vma, pmd_addr);
phys = pgoff_to_phys(dax_dev, pgoff, PMD_SIZE); phys = pgoff_to_phys(dax_dev, pgoff, PMD_SIZE);
if (phys == -1) { if (phys == -1) {
dev_dbg(dev, "%s: phys_to_pgoff(%#lx) failed\n", __func__, dev_dbg(dev, "%s: pgoff_to_phys(%#lx) failed\n", __func__,
pgoff); pgoff);
return VM_FAULT_SIGBUS; return VM_FAULT_SIGBUS;
} }
...@@ -503,6 +518,8 @@ static int __dax_dev_pud_fault(struct dax_dev *dax_dev, struct vm_fault *vmf) ...@@ -503,6 +518,8 @@ static int __dax_dev_pud_fault(struct dax_dev *dax_dev, struct vm_fault *vmf)
phys_addr_t phys; phys_addr_t phys;
pgoff_t pgoff; pgoff_t pgoff;
pfn_t pfn; pfn_t pfn;
unsigned int fault_size = PUD_SIZE;
if (check_vma(dax_dev, vmf->vma, __func__)) if (check_vma(dax_dev, vmf->vma, __func__))
return VM_FAULT_SIGBUS; return VM_FAULT_SIGBUS;
...@@ -519,10 +536,20 @@ static int __dax_dev_pud_fault(struct dax_dev *dax_dev, struct vm_fault *vmf) ...@@ -519,10 +536,20 @@ static int __dax_dev_pud_fault(struct dax_dev *dax_dev, struct vm_fault *vmf)
return VM_FAULT_SIGBUS; 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 (pud_addr < vmf->vma->vm_start ||
(pud_addr + PUD_SIZE) > vmf->vma->vm_end)
return VM_FAULT_SIGBUS;
pgoff = linear_page_index(vmf->vma, pud_addr); pgoff = linear_page_index(vmf->vma, pud_addr);
phys = pgoff_to_phys(dax_dev, pgoff, PUD_SIZE); phys = pgoff_to_phys(dax_dev, pgoff, PUD_SIZE);
if (phys == -1) { if (phys == -1) {
dev_dbg(dev, "%s: phys_to_pgoff(%#lx) failed\n", __func__, dev_dbg(dev, "%s: pgoff_to_phys(%#lx) failed\n", __func__,
pgoff); pgoff);
return VM_FAULT_SIGBUS; return VM_FAULT_SIGBUS;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment