diff options
| -rw-r--r-- | drivers/dax/super.c | 6 | ||||
| -rw-r--r-- | drivers/nvdimm/pmem.c | 3 | ||||
| -rw-r--r-- | drivers/vfio/vfio_iommu_type1.c | 18 | ||||
| -rw-r--r-- | include/linux/fs.h | 2 | ||||
| -rw-r--r-- | kernel/memremap.c | 15 |
5 files changed, 27 insertions, 17 deletions
diff --git a/drivers/dax/super.c b/drivers/dax/super.c index 473af694ad1c..ecdc292aa4e4 100644 --- a/drivers/dax/super.c +++ b/drivers/dax/super.c | |||
| @@ -246,12 +246,6 @@ long dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages, | |||
| 246 | { | 246 | { |
| 247 | long avail; | 247 | long avail; |
| 248 | 248 | ||
| 249 | /* | ||
| 250 | * The device driver is allowed to sleep, in order to make the | ||
| 251 | * memory directly accessible. | ||
| 252 | */ | ||
| 253 | might_sleep(); | ||
| 254 | |||
| 255 | if (!dax_dev) | 249 | if (!dax_dev) |
| 256 | return -EOPNOTSUPP; | 250 | return -EOPNOTSUPP; |
| 257 | 251 | ||
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 10041ac4032c..06f8dcc52ca6 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c | |||
| @@ -335,8 +335,7 @@ static int pmem_attach_disk(struct device *dev, | |||
| 335 | dev_warn(dev, "unable to guarantee persistence of writes\n"); | 335 | dev_warn(dev, "unable to guarantee persistence of writes\n"); |
| 336 | fua = 0; | 336 | fua = 0; |
| 337 | } | 337 | } |
| 338 | wbc = nvdimm_has_cache(nd_region) && | 338 | wbc = nvdimm_has_cache(nd_region); |
| 339 | !test_bit(ND_REGION_PERSIST_CACHE, &nd_region->flags); | ||
| 340 | 339 | ||
| 341 | if (!devm_request_mem_region(dev, res->start, resource_size(res), | 340 | if (!devm_request_mem_region(dev, res->start, resource_size(res), |
| 342 | dev_name(&ndns->dev))) { | 341 | dev_name(&ndns->dev))) { |
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index e30e29ae4819..45657e2b1ff7 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c | |||
| @@ -338,11 +338,12 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr, | |||
| 338 | { | 338 | { |
| 339 | struct page *page[1]; | 339 | struct page *page[1]; |
| 340 | struct vm_area_struct *vma; | 340 | struct vm_area_struct *vma; |
| 341 | struct vm_area_struct *vmas[1]; | ||
| 341 | int ret; | 342 | int ret; |
| 342 | 343 | ||
| 343 | if (mm == current->mm) { | 344 | if (mm == current->mm) { |
| 344 | ret = get_user_pages_fast(vaddr, 1, !!(prot & IOMMU_WRITE), | 345 | ret = get_user_pages_longterm(vaddr, 1, !!(prot & IOMMU_WRITE), |
| 345 | page); | 346 | page, vmas); |
| 346 | } else { | 347 | } else { |
| 347 | unsigned int flags = 0; | 348 | unsigned int flags = 0; |
| 348 | 349 | ||
| @@ -351,7 +352,18 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr, | |||
| 351 | 352 | ||
| 352 | down_read(&mm->mmap_sem); | 353 | down_read(&mm->mmap_sem); |
| 353 | ret = get_user_pages_remote(NULL, mm, vaddr, 1, flags, page, | 354 | 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 | } | ||
| 355 | up_read(&mm->mmap_sem); | 367 | up_read(&mm->mmap_sem); |
| 356 | } | 368 | } |
| 357 | 369 | ||
diff --git a/include/linux/fs.h b/include/linux/fs.h index 2a815560fda0..79c413985305 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -3198,7 +3198,7 @@ static inline bool vma_is_fsdax(struct vm_area_struct *vma) | |||
| 3198 | if (!vma_is_dax(vma)) | 3198 | if (!vma_is_dax(vma)) |
| 3199 | return false; | 3199 | return false; |
| 3200 | inode = file_inode(vma->vm_file); | 3200 | inode = file_inode(vma->vm_file); |
| 3201 | if (inode->i_mode == S_IFCHR) | 3201 | if (S_ISCHR(inode->i_mode)) |
| 3202 | return false; /* device-dax */ | 3202 | return false; /* device-dax */ |
| 3203 | return true; | 3203 | return true; |
| 3204 | } | 3204 | } |
diff --git a/kernel/memremap.c b/kernel/memremap.c index 4849be5f9b3c..4dd4274cabe2 100644 --- a/kernel/memremap.c +++ b/kernel/memremap.c | |||
| @@ -275,8 +275,15 @@ static unsigned long pfn_end(struct dev_pagemap *pgmap) | |||
| 275 | return (res->start + resource_size(res)) >> PAGE_SHIFT; | 275 | return (res->start + resource_size(res)) >> PAGE_SHIFT; |
| 276 | } | 276 | } |
| 277 | 277 | ||
| 278 | static unsigned long pfn_next(unsigned long pfn) | ||
| 279 | { | ||
| 280 | if (pfn % 1024 == 0) | ||
| 281 | cond_resched(); | ||
| 282 | return pfn + 1; | ||
| 283 | } | ||
| 284 | |||
| 278 | #define for_each_device_pfn(pfn, map) \ | 285 | #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)) |
| 280 | 287 | ||
| 281 | static void devm_memremap_pages_release(void *data) | 288 | static void devm_memremap_pages_release(void *data) |
| 282 | { | 289 | { |
| @@ -337,10 +344,10 @@ void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap) | |||
| 337 | resource_size_t align_start, align_size, align_end; | 344 | resource_size_t align_start, align_size, align_end; |
| 338 | struct vmem_altmap *altmap = pgmap->altmap_valid ? | 345 | struct vmem_altmap *altmap = pgmap->altmap_valid ? |
| 339 | &pgmap->altmap : NULL; | 346 | &pgmap->altmap : NULL; |
| 347 | struct resource *res = &pgmap->res; | ||
| 340 | unsigned long pfn, pgoff, order; | 348 | unsigned long pfn, pgoff, order; |
| 341 | pgprot_t pgprot = PAGE_KERNEL; | 349 | pgprot_t pgprot = PAGE_KERNEL; |
| 342 | int error, nid, is_ram, i = 0; | 350 | int error, nid, is_ram; |
| 343 | struct resource *res = &pgmap->res; | ||
| 344 | 351 | ||
| 345 | align_start = res->start & ~(SECTION_SIZE - 1); | 352 | align_start = res->start & ~(SECTION_SIZE - 1); |
| 346 | align_size = ALIGN(res->start + resource_size(res), SECTION_SIZE) | 353 | 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) | |||
| 409 | list_del(&page->lru); | 416 | list_del(&page->lru); |
| 410 | page->pgmap = pgmap; | 417 | page->pgmap = pgmap; |
| 411 | percpu_ref_get(pgmap->ref); | 418 | percpu_ref_get(pgmap->ref); |
| 412 | if (!(++i % 1024)) | ||
| 413 | cond_resched(); | ||
| 414 | } | 419 | } |
| 415 | 420 | ||
| 416 | devm_add_action(dev, devm_memremap_pages_release, pgmap); | 421 | devm_add_action(dev, devm_memremap_pages_release, pgmap); |
