Skip to content

Commit 20f1417

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: "A 4.16 regression fix, three fixes for -stable, and a cleanup fix: - During the merge window support for the new ACPI NVDIMM Platform Capabilities structure disabled support for "deep flush", a force-unit- access like mechanism for persistent memory. Restore that mechanism. - VFIO like RDMA is yet one more memory registration / pinning interface that is incompatible with Filesystem-DAX. Disable long term pins of Filesystem-DAX mappings via VFIO. - The Filesystem-DAX detection to prevent long terms pins mistakenly also disabled Device-DAX pins which are not subject to the same block- map collision concerns. - Similar to the setup path, softlockup warnings can trigger in the shutdown path for large persistent memory namespaces. Teach for_each_device_pfn() to perform cond_resched() in all cases. - Boaz noticed that the might_sleep() in dax_direct_access() is stale as of the v4.15 kernel. These have received a build success notification from the 0day robot, and the longterm pin fixes have appeared in -next. However, I recently rebased the tree to remove some other fixes that need to be reworked after review feedback. * 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm: memremap: fix softlockup reports at teardown libnvdimm: re-enable deep flush for pmem devices via fsync() vfio: disable filesystem-dax page pinning dax: fix vma_is_fsdax() helper dax: ->direct_access does not sleep anymore
2 parents 0eb3412 + 949b932 commit 20f1417

File tree

5 files changed

+27
-17
lines changed

5 files changed

+27
-17
lines changed

drivers/dax/super.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -246,12 +246,6 @@ long dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages,
246246
{
247247
long avail;
248248

249-
/*
250-
* The device driver is allowed to sleep, in order to make the
251-
* memory directly accessible.
252-
*/
253-
might_sleep();
254-
255249
if (!dax_dev)
256250
return -EOPNOTSUPP;
257251

drivers/nvdimm/pmem.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,8 +335,7 @@ static int pmem_attach_disk(struct device *dev,
335335
dev_warn(dev, "unable to guarantee persistence of writes\n");
336336
fua = 0;
337337
}
338-
wbc = nvdimm_has_cache(nd_region) &&
339-
!test_bit(ND_REGION_PERSIST_CACHE, &nd_region->flags);
338+
wbc = nvdimm_has_cache(nd_region);
340339

341340
if (!devm_request_mem_region(dev, res->start, resource_size(res),
342341
dev_name(&ndns->dev))) {

drivers/vfio/vfio_iommu_type1.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -338,11 +338,12 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr,
338338
{
339339
struct page *page[1];
340340
struct vm_area_struct *vma;
341+
struct vm_area_struct *vmas[1];
341342
int ret;
342343

343344
if (mm == current->mm) {
344-
ret = get_user_pages_fast(vaddr, 1, !!(prot & IOMMU_WRITE),
345-
page);
345+
ret = get_user_pages_longterm(vaddr, 1, !!(prot & IOMMU_WRITE),
346+
page, vmas);
346347
} else {
347348
unsigned int flags = 0;
348349

@@ -351,7 +352,18 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr,
351352

352353
down_read(&mm->mmap_sem);
353354
ret = get_user_pages_remote(NULL, mm, vaddr, 1, flags, page,
354-
NULL, NULL);
355+
vmas, NULL);
356+
/*
357+
* The lifetime of a vaddr_get_pfn() page pin is
358+
* userspace-controlled. In the fs-dax case this could
359+
* lead to indefinite stalls in filesystem operations.
360+
* Disallow attempts to pin fs-dax pages via this
361+
* interface.
362+
*/
363+
if (ret > 0 && vma_is_fsdax(vmas[0])) {
364+
ret = -EOPNOTSUPP;
365+
put_page(page[0]);
366+
}
355367
up_read(&mm->mmap_sem);
356368
}
357369

include/linux/fs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3198,7 +3198,7 @@ static inline bool vma_is_fsdax(struct vm_area_struct *vma)
31983198
if (!vma_is_dax(vma))
31993199
return false;
32003200
inode = file_inode(vma->vm_file);
3201-
if (inode->i_mode == S_IFCHR)
3201+
if (S_ISCHR(inode->i_mode))
32023202
return false; /* device-dax */
32033203
return true;
32043204
}

kernel/memremap.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,15 @@ static unsigned long pfn_end(struct dev_pagemap *pgmap)
275275
return (res->start + resource_size(res)) >> PAGE_SHIFT;
276276
}
277277

278+
static unsigned long pfn_next(unsigned long pfn)
279+
{
280+
if (pfn % 1024 == 0)
281+
cond_resched();
282+
return pfn + 1;
283+
}
284+
278285
#define for_each_device_pfn(pfn, map) \
279-
for (pfn = pfn_first(map); pfn < pfn_end(map); pfn++)
286+
for (pfn = pfn_first(map); pfn < pfn_end(map); pfn = pfn_next(pfn))
280287

281288
static void devm_memremap_pages_release(void *data)
282289
{
@@ -337,10 +344,10 @@ void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap)
337344
resource_size_t align_start, align_size, align_end;
338345
struct vmem_altmap *altmap = pgmap->altmap_valid ?
339346
&pgmap->altmap : NULL;
347+
struct resource *res = &pgmap->res;
340348
unsigned long pfn, pgoff, order;
341349
pgprot_t pgprot = PAGE_KERNEL;
342-
int error, nid, is_ram, i = 0;
343-
struct resource *res = &pgmap->res;
350+
int error, nid, is_ram;
344351

345352
align_start = res->start & ~(SECTION_SIZE - 1);
346353
align_size = ALIGN(res->start + resource_size(res), SECTION_SIZE)
@@ -409,8 +416,6 @@ void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap)
409416
list_del(&page->lru);
410417
page->pgmap = pgmap;
411418
percpu_ref_get(pgmap->ref);
412-
if (!(++i % 1024))
413-
cond_resched();
414419
}
415420

416421
devm_add_action(dev, devm_memremap_pages_release, pgmap);

0 commit comments

Comments
 (0)