Skip to content

Commit 98ac9a6

Browse files
committed
Merge branch 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm
Pull libnvdimm fixes from Dan Williams: "nvdimm fixes for v4.8, two of them are tagged for -stable: - Fix devm_memremap_pages() to use track_pfn_insert(). Otherwise, DAX pmd mappings end up with an uncached pgprot, and unusable performance for the device-dax interface. The device-dax interface appeared in 4.7 so this is tagged for -stable. - Fix a couple VM_BUG_ON() checks in the show_smaps() path to understand DAX pmd entries. This fix is tagged for -stable. - Fix a mis-merge of the nfit machine-check handler to flip the polarity of an if() to match the final version of the patch that Vishal sent for 4.8-rc1. Without this the nfit machine check handler never detects / inserts new 'badblocks' entries which applications use to identify lost portions of files. - For test purposes, fix the nvdimm_clear_poison() path to operate on legacy / simulated nvdimm memory ranges. Without this fix a test can set badblocks, but never clear them on these ranges. - Fix the range checking done by dax_dev_pmd_fault(). This is not tagged for -stable since this problem is mitigated by specifying aligned resources at device-dax setup time. These patches have appeared in a next release over the past week. The recent rebase you can see in the timestamps was to drop an invalid fix as identified by the updated device-dax unit tests [1]. The -mm touches have an ack from Andrew" [1]: "[ndctl PATCH 0/3] device-dax test for recent kernel bugs" https://lists.01.org/pipermail/linux-nvdimm/2016-September/006855.html * 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm: libnvdimm: allow legacy (e820) pmem region to clear bad blocks nfit, mce: Fix SPA matching logic in MCE handler mm: fix cache mode of dax pmd mappings mm: fix show_smap() for zone_device-pmd ranges dax: fix mapping size check
2 parents b8db371 + 1e8b8d9 commit 98ac9a6

File tree

7 files changed

+30
-12
lines changed

7 files changed

+30
-12
lines changed

arch/x86/mm/pat.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -927,9 +927,10 @@ int track_pfn_copy(struct vm_area_struct *vma)
927927
}
928928

929929
/*
930-
* prot is passed in as a parameter for the new mapping. If the vma has a
931-
* linear pfn mapping for the entire range reserve the entire vma range with
932-
* single reserve_pfn_range call.
930+
* prot is passed in as a parameter for the new mapping. If the vma has
931+
* a linear pfn mapping for the entire range, or no vma is provided,
932+
* reserve the entire pfn + size range with single reserve_pfn_range
933+
* call.
933934
*/
934935
int track_pfn_remap(struct vm_area_struct *vma, pgprot_t *prot,
935936
unsigned long pfn, unsigned long addr, unsigned long size)
@@ -938,11 +939,12 @@ int track_pfn_remap(struct vm_area_struct *vma, pgprot_t *prot,
938939
enum page_cache_mode pcm;
939940

940941
/* reserve the whole chunk starting from paddr */
941-
if (addr == vma->vm_start && size == (vma->vm_end - vma->vm_start)) {
942+
if (!vma || (addr == vma->vm_start
943+
&& size == (vma->vm_end - vma->vm_start))) {
942944
int ret;
943945

944946
ret = reserve_pfn_range(paddr, size, prot, 0);
945-
if (!ret)
947+
if (ret == 0 && vma)
946948
vma->vm_flags |= VM_PAT;
947949
return ret;
948950
}
@@ -997,7 +999,7 @@ void untrack_pfn(struct vm_area_struct *vma, unsigned long pfn,
997999
resource_size_t paddr;
9981000
unsigned long prot;
9991001

1000-
if (!(vma->vm_flags & VM_PAT))
1002+
if (vma && !(vma->vm_flags & VM_PAT))
10011003
return;
10021004

10031005
/* free the chunk starting from pfn or the whole chunk */
@@ -1011,7 +1013,8 @@ void untrack_pfn(struct vm_area_struct *vma, unsigned long pfn,
10111013
size = vma->vm_end - vma->vm_start;
10121014
}
10131015
free_pfn_range(paddr, size);
1014-
vma->vm_flags &= ~VM_PAT;
1016+
if (vma)
1017+
vma->vm_flags &= ~VM_PAT;
10151018
}
10161019

10171020
/*

drivers/acpi/nfit/mce.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ static int nfit_handle_mce(struct notifier_block *nb, unsigned long val,
4242
list_for_each_entry(nfit_spa, &acpi_desc->spas, list) {
4343
struct acpi_nfit_system_address *spa = nfit_spa->spa;
4444

45-
if (nfit_spa_type(spa) == NFIT_SPA_PM)
45+
if (nfit_spa_type(spa) != NFIT_SPA_PM)
4646
continue;
4747
/* find the spa that covers the mce addr */
4848
if (spa->address > mce->addr)

drivers/dax/dax.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ static int __dax_dev_pmd_fault(struct dax_dev *dax_dev,
459459
}
460460

461461
pgoff = linear_page_index(vma, pmd_addr);
462-
phys = pgoff_to_phys(dax_dev, pgoff, PAGE_SIZE);
462+
phys = pgoff_to_phys(dax_dev, pgoff, PMD_SIZE);
463463
if (phys == -1) {
464464
dev_dbg(dev, "%s: phys_to_pgoff(%#lx) failed\n", __func__,
465465
pgoff);

drivers/nvdimm/bus.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,12 @@ long nvdimm_clear_poison(struct device *dev, phys_addr_t phys,
185185
return -ENXIO;
186186

187187
nd_desc = nvdimm_bus->nd_desc;
188+
/*
189+
* if ndctl does not exist, it's PMEM_LEGACY and
190+
* we want to just pretend everything is handled.
191+
*/
188192
if (!nd_desc->ndctl)
189-
return -ENXIO;
193+
return len;
190194

191195
memset(&ars_cap, 0, sizeof(ars_cap));
192196
ars_cap.address = phys;

fs/proc/task_mmu.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,8 @@ static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr,
581581
mss->anonymous_thp += HPAGE_PMD_SIZE;
582582
else if (PageSwapBacked(page))
583583
mss->shmem_thp += HPAGE_PMD_SIZE;
584+
else if (is_zone_device_page(page))
585+
/* pass */;
584586
else
585587
VM_BUG_ON_PAGE(1, page);
586588
smaps_account(mss, page, true, pmd_young(*pmd), pmd_dirty(*pmd));

kernel/memremap.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ static void devm_memremap_pages_release(struct device *dev, void *data)
247247
align_start = res->start & ~(SECTION_SIZE - 1);
248248
align_size = ALIGN(resource_size(res), SECTION_SIZE);
249249
arch_remove_memory(align_start, align_size);
250+
untrack_pfn(NULL, PHYS_PFN(align_start), align_size);
250251
pgmap_radix_release(res);
251252
dev_WARN_ONCE(dev, pgmap->altmap && pgmap->altmap->alloc,
252253
"%s: failed to free all reserved pages\n", __func__);
@@ -282,6 +283,7 @@ void *devm_memremap_pages(struct device *dev, struct resource *res,
282283
struct percpu_ref *ref, struct vmem_altmap *altmap)
283284
{
284285
resource_size_t key, align_start, align_size, align_end;
286+
pgprot_t pgprot = PAGE_KERNEL;
285287
struct dev_pagemap *pgmap;
286288
struct page_map *page_map;
287289
int error, nid, is_ram;
@@ -351,6 +353,11 @@ void *devm_memremap_pages(struct device *dev, struct resource *res,
351353
if (nid < 0)
352354
nid = numa_mem_id();
353355

356+
error = track_pfn_remap(NULL, &pgprot, PHYS_PFN(align_start), 0,
357+
align_size);
358+
if (error)
359+
goto err_pfn_remap;
360+
354361
error = arch_add_memory(nid, align_start, align_size, true);
355362
if (error)
356363
goto err_add_memory;
@@ -371,6 +378,8 @@ void *devm_memremap_pages(struct device *dev, struct resource *res,
371378
return __va(res->start);
372379

373380
err_add_memory:
381+
untrack_pfn(NULL, PHYS_PFN(align_start), align_size);
382+
err_pfn_remap:
374383
err_radix:
375384
pgmap_radix_release(res);
376385
devres_free(page_map);

mm/huge_memory.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,7 +1078,7 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
10781078
goto out;
10791079

10801080
page = pmd_page(*pmd);
1081-
VM_BUG_ON_PAGE(!PageHead(page), page);
1081+
VM_BUG_ON_PAGE(!PageHead(page) && !is_zone_device_page(page), page);
10821082
if (flags & FOLL_TOUCH)
10831083
touch_pmd(vma, addr, pmd);
10841084
if ((flags & FOLL_MLOCK) && (vma->vm_flags & VM_LOCKED)) {
@@ -1116,7 +1116,7 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
11161116
}
11171117
skip_mlock:
11181118
page += (addr & ~HPAGE_PMD_MASK) >> PAGE_SHIFT;
1119-
VM_BUG_ON_PAGE(!PageCompound(page), page);
1119+
VM_BUG_ON_PAGE(!PageCompound(page) && !is_zone_device_page(page), page);
11201120
if (flags & FOLL_GET)
11211121
get_page(page);
11221122

0 commit comments

Comments
 (0)