Skip to content

Commit 94db151

Browse files
committed
vfio: disable filesystem-dax page pinning
Filesystem-DAX is incompatible with 'longterm' page pinning. Without page cache indirection a DAX mapping maps filesystem blocks directly. This means that the filesystem must not modify a file's block map while any page in a mapping is pinned. In order to prevent the situation of userspace holding of filesystem operations indefinitely, disallow 'longterm' Filesystem-DAX mappings. RDMA has the same conflict and the plan there is to add a 'with lease' mechanism to allow the kernel to notify userspace that the mapping is being torn down for block-map maintenance. Perhaps something similar can be put in place for vfio. Note that xfs and ext4 still report: "DAX enabled. Warning: EXPERIMENTAL, use at your own risk" ...at mount time, and resolving the dax-dma-vs-truncate problem is one of the last hurdles to remove that designation. Acked-by: Alex Williamson <[email protected]> Cc: Michal Hocko <[email protected]> Cc: [email protected] Cc: <[email protected]> Reported-by: Haozhong Zhang <[email protected]> Tested-by: Haozhong Zhang <[email protected]> Fixes: d475c63 ("dax,ext2: replace XIP read and write with DAX I/O") Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Dan Williams <[email protected]>
1 parent 230f5a8 commit 94db151

File tree

1 file changed

+15
-3
lines changed

1 file changed

+15
-3
lines changed

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

0 commit comments

Comments
 (0)