mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-06 00:39:48 +00:00
virtiofs: add DAX mmap support
Add DAX mmap() support. Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
parent
c2d0ad00d9
commit
2a9a609a0c
2 changed files with 64 additions and 0 deletions
|
@ -575,6 +575,65 @@ ssize_t fuse_dax_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static vm_fault_t __fuse_dax_fault(struct vm_fault *vmf,
|
||||||
|
enum page_entry_size pe_size, bool write)
|
||||||
|
{
|
||||||
|
vm_fault_t ret;
|
||||||
|
struct inode *inode = file_inode(vmf->vma->vm_file);
|
||||||
|
struct super_block *sb = inode->i_sb;
|
||||||
|
pfn_t pfn;
|
||||||
|
|
||||||
|
if (write)
|
||||||
|
sb_start_pagefault(sb);
|
||||||
|
|
||||||
|
ret = dax_iomap_fault(vmf, pe_size, &pfn, NULL, &fuse_iomap_ops);
|
||||||
|
|
||||||
|
if (ret & VM_FAULT_NEEDDSYNC)
|
||||||
|
ret = dax_finish_sync_fault(vmf, pe_size, pfn);
|
||||||
|
|
||||||
|
if (write)
|
||||||
|
sb_end_pagefault(sb);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static vm_fault_t fuse_dax_fault(struct vm_fault *vmf)
|
||||||
|
{
|
||||||
|
return __fuse_dax_fault(vmf, PE_SIZE_PTE,
|
||||||
|
vmf->flags & FAULT_FLAG_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static vm_fault_t fuse_dax_huge_fault(struct vm_fault *vmf,
|
||||||
|
enum page_entry_size pe_size)
|
||||||
|
{
|
||||||
|
return __fuse_dax_fault(vmf, pe_size, vmf->flags & FAULT_FLAG_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static vm_fault_t fuse_dax_page_mkwrite(struct vm_fault *vmf)
|
||||||
|
{
|
||||||
|
return __fuse_dax_fault(vmf, PE_SIZE_PTE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static vm_fault_t fuse_dax_pfn_mkwrite(struct vm_fault *vmf)
|
||||||
|
{
|
||||||
|
return __fuse_dax_fault(vmf, PE_SIZE_PTE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct vm_operations_struct fuse_dax_vm_ops = {
|
||||||
|
.fault = fuse_dax_fault,
|
||||||
|
.huge_fault = fuse_dax_huge_fault,
|
||||||
|
.page_mkwrite = fuse_dax_page_mkwrite,
|
||||||
|
.pfn_mkwrite = fuse_dax_pfn_mkwrite,
|
||||||
|
};
|
||||||
|
|
||||||
|
int fuse_dax_mmap(struct file *file, struct vm_area_struct *vma)
|
||||||
|
{
|
||||||
|
file_accessed(file);
|
||||||
|
vma->vm_ops = &fuse_dax_vm_ops;
|
||||||
|
vma->vm_flags |= VM_MIXEDMAP | VM_HUGEPAGE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void fuse_free_dax_mem_ranges(struct list_head *mem_list)
|
static void fuse_free_dax_mem_ranges(struct list_head *mem_list)
|
||||||
{
|
{
|
||||||
struct fuse_dax_mapping *range, *temp;
|
struct fuse_dax_mapping *range, *temp;
|
||||||
|
|
|
@ -2325,6 +2325,10 @@ static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
|
||||||
{
|
{
|
||||||
struct fuse_file *ff = file->private_data;
|
struct fuse_file *ff = file->private_data;
|
||||||
|
|
||||||
|
/* DAX mmap is superior to direct_io mmap */
|
||||||
|
if (FUSE_IS_DAX(file_inode(file)))
|
||||||
|
return fuse_dax_mmap(file, vma);
|
||||||
|
|
||||||
if (ff->open_flags & FOPEN_DIRECT_IO) {
|
if (ff->open_flags & FOPEN_DIRECT_IO) {
|
||||||
/* Can't provide the coherency needed for MAP_SHARED */
|
/* Can't provide the coherency needed for MAP_SHARED */
|
||||||
if (vma->vm_flags & VM_MAYSHARE)
|
if (vma->vm_flags & VM_MAYSHARE)
|
||||||
|
@ -3413,6 +3417,7 @@ static const struct file_operations fuse_file_operations = {
|
||||||
.release = fuse_release,
|
.release = fuse_release,
|
||||||
.fsync = fuse_fsync,
|
.fsync = fuse_fsync,
|
||||||
.lock = fuse_file_lock,
|
.lock = fuse_file_lock,
|
||||||
|
.get_unmapped_area = thp_get_unmapped_area,
|
||||||
.flock = fuse_file_flock,
|
.flock = fuse_file_flock,
|
||||||
.splice_read = generic_file_splice_read,
|
.splice_read = generic_file_splice_read,
|
||||||
.splice_write = iter_file_splice_write,
|
.splice_write = iter_file_splice_write,
|
||||||
|
|
Loading…
Reference in a new issue