@@ -16,6 +16,88 @@
#include "famfs_internal.h"
+/*********************************************************************
+ * vm_operations
+ */
+static vm_fault_t
+__famfs_filemap_fault(struct vm_fault *vmf, unsigned int pe_size,
+ bool write_fault)
+{
+ struct inode *inode = file_inode(vmf->vma->vm_file);
+ struct super_block *sb = inode->i_sb;
+ struct famfs_fs_info *fsi = sb->s_fs_info;
+ vm_fault_t ret;
+ pfn_t pfn;
+
+ if (fsi->deverror)
+ return VM_FAULT_SIGBUS;
+
+ if (!IS_DAX(file_inode(vmf->vma->vm_file))) {
+ pr_err("%s: file not marked IS_DAX!!\n", __func__);
+ return VM_FAULT_SIGBUS;
+ }
+
+ if (write_fault) {
+ sb_start_pagefault(inode->i_sb);
+ file_update_time(vmf->vma->vm_file);
+ }
+
+ ret = dax_iomap_fault(vmf, pe_size, &pfn, NULL, NULL /*&famfs_iomap_ops */);
+ if (ret & VM_FAULT_NEEDDSYNC)
+ ret = dax_finish_sync_fault(vmf, pe_size, pfn);
+
+ if (write_fault)
+ sb_end_pagefault(inode->i_sb);
+
+ return ret;
+}
+
+static inline bool
+famfs_is_write_fault(struct vm_fault *vmf)
+{
+ return (vmf->flags & FAULT_FLAG_WRITE) &&
+ (vmf->vma->vm_flags & VM_SHARED);
+}
+
+static vm_fault_t
+famfs_filemap_fault(struct vm_fault *vmf)
+{
+ return __famfs_filemap_fault(vmf, 0, famfs_is_write_fault(vmf));
+}
+
+static vm_fault_t
+famfs_filemap_huge_fault(struct vm_fault *vmf, unsigned int pe_size)
+{
+ return __famfs_filemap_fault(vmf, pe_size, famfs_is_write_fault(vmf));
+}
+
+static vm_fault_t
+famfs_filemap_page_mkwrite(struct vm_fault *vmf)
+{
+ return __famfs_filemap_fault(vmf, 0, true);
+}
+
+static vm_fault_t
+famfs_filemap_pfn_mkwrite(struct vm_fault *vmf)
+{
+ return __famfs_filemap_fault(vmf, 0, true);
+}
+
+static vm_fault_t
+famfs_filemap_map_pages(struct vm_fault *vmf, pgoff_t start_pgoff,
+ pgoff_t end_pgoff)
+{
+ return filemap_map_pages(vmf, start_pgoff, end_pgoff);
+}
+
+const struct vm_operations_struct famfs_file_vm_ops = {
+ .fault = famfs_filemap_fault,
+ .huge_fault = famfs_filemap_huge_fault,
+ .map_pages = famfs_filemap_map_pages,
+ .page_mkwrite = famfs_filemap_page_mkwrite,
+ .pfn_mkwrite = famfs_filemap_pfn_mkwrite,
+};
+
/*********************************************************************
* file_operations
*/
@@ -25,7 +107,8 @@ static ssize_t
famfs_file_invalid(struct inode *inode)
{
if (!IS_DAX(inode)) {
- pr_debug("%s: inode %llx IS_DAX is false\n", __func__, (u64)inode);
+ pr_debug("%s: inode %llx IS_DAX is false\n",
+ __func__, (u64)inode);
return -ENXIO;
}
return 0;
@@ -101,6 +184,27 @@ famfs_dax_write_iter(struct kiocb *iocb, struct iov_iter *from)
return dax_iomap_rw(iocb, from, NULL /*&famfs_iomap_ops*/);
}
+static int
+famfs_file_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct inode *inode = file_inode(file);
+ struct super_block *sb = inode->i_sb;
+ struct famfs_fs_info *fsi = sb->s_fs_info;
+ ssize_t rc;
+
+ if (fsi->deverror)
+ return -ENODEV;
+
+ rc = famfs_file_invalid(inode);
+ if (rc)
+ return (int)rc;
+
+ file_accessed(file);
+ vma->vm_ops = &famfs_file_vm_ops;
+ vm_flags_set(vma, VM_HUGEPAGE);
+ return 0;
+}
+
const struct file_operations famfs_file_operations = {
.owner = THIS_MODULE,
@@ -108,7 +212,7 @@ const struct file_operations famfs_file_operations = {
.write_iter = famfs_dax_write_iter,
.read_iter = famfs_dax_read_iter,
.unlocked_ioctl = NULL /*famfs_file_ioctl*/,
- .mmap = NULL /* famfs_file_mmap */,
+ .mmap = famfs_file_mmap,
/* Force PMD alignment for mmap */
.get_unmapped_area = thp_get_unmapped_area,
This commit adds vm_operations, plus famfs_mmap() and fault handlers. It is still missing iomap_ops, iomap mapping resolution, and famfs_ioctl() for setting up file-to-memory mappings. Signed-off-by: John Groves <john@groves.net> --- fs/famfs/famfs_file.c | 108 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 106 insertions(+), 2 deletions(-)