| /* |
| * Copyright (c) 1998-2014 Erez Zadok |
| * Copyright (c) 2009 Shrikar Archak |
| * Copyright (c) 2003-2014 Stony Brook University |
| * Copyright (c) 2003-2014 The Research Foundation of SUNY |
| * Copyright (C) 2013-2014, 2016 Motorola Mobility, LLC |
| * Copyright (C) 2017 Google, Inc. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License version 2 as |
| * published by the Free Software Foundation. |
| */ |
| |
| #include "esdfs.h" |
| |
| static vm_fault_t esdfs_fault(struct vm_fault *vmf) |
| { |
| vm_fault_t err; |
| struct file *file; |
| const struct vm_operations_struct *lower_vm_ops; |
| struct esdfs_sb_info *sbi; |
| const struct cred *creds; |
| const struct vm_area_struct *vma = vmf->vma; |
| |
| file = (struct file *)vma->vm_private_data; |
| sbi = ESDFS_SB(file->f_path.dentry->d_sb); |
| creds = esdfs_override_creds(sbi, ESDFS_I(file->f_inode), NULL); |
| if (!creds) |
| return VM_FAULT_OOM; |
| |
| lower_vm_ops = ESDFS_F(file)->lower_vm_ops; |
| BUG_ON(!lower_vm_ops); |
| err = lower_vm_ops->fault(vmf); |
| esdfs_revert_creds(creds, NULL); |
| return err; |
| } |
| |
| static void esdfs_vm_open(struct vm_area_struct *vma) |
| { |
| struct file *file = (struct file *)vma->vm_private_data; |
| |
| get_file(file); |
| } |
| |
| static void esdfs_vm_close(struct vm_area_struct *vma) |
| { |
| struct file *file = (struct file *)vma->vm_private_data; |
| |
| fput(file); |
| } |
| |
| static vm_fault_t esdfs_page_mkwrite(struct vm_fault *vmf) |
| { |
| vm_fault_t err = 0; |
| struct file *file; |
| const struct vm_operations_struct *lower_vm_ops; |
| struct esdfs_sb_info *sbi; |
| const struct cred *creds; |
| const struct vm_area_struct *vma = vmf->vma; |
| |
| file = (struct file *)vma->vm_private_data; |
| sbi = ESDFS_SB(file->f_path.dentry->d_sb); |
| creds = esdfs_override_creds(sbi, ESDFS_I(file->f_inode), NULL); |
| if (!creds) |
| return VM_FAULT_OOM; |
| |
| lower_vm_ops = ESDFS_F(file)->lower_vm_ops; |
| BUG_ON(!lower_vm_ops); |
| if (!lower_vm_ops->page_mkwrite) |
| goto out; |
| |
| err = lower_vm_ops->page_mkwrite(vmf); |
| out: |
| esdfs_revert_creds(creds, NULL); |
| return err; |
| } |
| |
| static ssize_t esdfs_direct_IO(struct kiocb *iocb, |
| struct iov_iter *iter) |
| { |
| /* |
| * This function should never be called directly. We need it |
| * to exist, to get past a check in open_check_o_direct(), |
| * which is called from do_last(). |
| */ |
| return -EINVAL; |
| } |
| |
| const struct address_space_operations esdfs_aops = { |
| .direct_IO = esdfs_direct_IO, |
| }; |
| |
| const struct vm_operations_struct esdfs_vm_ops = { |
| .fault = esdfs_fault, |
| .page_mkwrite = esdfs_page_mkwrite, |
| .open = esdfs_vm_open, |
| .close = esdfs_vm_close, |
| }; |