const struct file_operations ext4_file_operations = {
     .llseek        = ext4_llseek,
     .read_iter    = ext4_file_read_iter,
     .write_iter    = ext4_file_write_iter,
     .unlocked_ioctl = ext4_ioctl,
 #ifdef CONFIG_COMPAT
     .compat_ioctl    = ext4_compat_ioctl,
 #endif
     .mmap        = ext4_file_mmap,
     .mmap_supported_flags = MAP_SYNC,
     .open        = ext4_file_open,
     .release    = ext4_release_file,
     .fsync        = ext4_sync_file,
     .get_unmapped_area = thp_get_unmapped_area,
     .splice_read    = generic_file_splice_read,
     .splice_write    = iter_file_splice_write,
     .fallocate    = ext4_fallocate,
 }; 
static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma)
 {
     struct inode *inode = file->f_mapping->host;    if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
         return -EIO;    /*
      * We don't support synchronous mappings for non-DAX files. At least
      * until someone comes with a sensible use case.
      */
     if (!IS_DAX(file_inode(file)) && (vma->vm_flags & VM_SYNC))
         return -EOPNOTSUPP;    file_accessed(file);
     dump_stack();
     if (IS_DAX(file_inode(file))) {
         vma->vm_ops = &ext4_dax_vm_ops;
         vma->vm_flags |= VM_HUGEPAGE;
     } else {
         vma->vm_ops = &ext4_file_vm_ops;
     }
     
     return 0;
 } 
 static const struct vm_operations_struct ext4_file_vm_ops = {
     .fault        = ext4_filemap_fault,
     .map_pages    = filemap_map_pages,
     .page_mkwrite   = ext4_page_mkwrite,
 }; 
文件映射的缺页处理