cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

file.c (5414B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 *  linux/fs/ext2/file.c
      4 *
      5 * Copyright (C) 1992, 1993, 1994, 1995
      6 * Remy Card (card@masi.ibp.fr)
      7 * Laboratoire MASI - Institut Blaise Pascal
      8 * Universite Pierre et Marie Curie (Paris VI)
      9 *
     10 *  from
     11 *
     12 *  linux/fs/minix/file.c
     13 *
     14 *  Copyright (C) 1991, 1992  Linus Torvalds
     15 *
     16 *  ext2 fs regular file handling primitives
     17 *
     18 *  64-bit file support on 64-bit platforms by Jakub Jelinek
     19 * 	(jj@sunsite.ms.mff.cuni.cz)
     20 */
     21
     22#include <linux/time.h>
     23#include <linux/pagemap.h>
     24#include <linux/dax.h>
     25#include <linux/quotaops.h>
     26#include <linux/iomap.h>
     27#include <linux/uio.h>
     28#include "ext2.h"
     29#include "xattr.h"
     30#include "acl.h"
     31
     32#ifdef CONFIG_FS_DAX
     33static ssize_t ext2_dax_read_iter(struct kiocb *iocb, struct iov_iter *to)
     34{
     35	struct inode *inode = iocb->ki_filp->f_mapping->host;
     36	ssize_t ret;
     37
     38	if (!iov_iter_count(to))
     39		return 0; /* skip atime */
     40
     41	inode_lock_shared(inode);
     42	ret = dax_iomap_rw(iocb, to, &ext2_iomap_ops);
     43	inode_unlock_shared(inode);
     44
     45	file_accessed(iocb->ki_filp);
     46	return ret;
     47}
     48
     49static ssize_t ext2_dax_write_iter(struct kiocb *iocb, struct iov_iter *from)
     50{
     51	struct file *file = iocb->ki_filp;
     52	struct inode *inode = file->f_mapping->host;
     53	ssize_t ret;
     54
     55	inode_lock(inode);
     56	ret = generic_write_checks(iocb, from);
     57	if (ret <= 0)
     58		goto out_unlock;
     59	ret = file_remove_privs(file);
     60	if (ret)
     61		goto out_unlock;
     62	ret = file_update_time(file);
     63	if (ret)
     64		goto out_unlock;
     65
     66	ret = dax_iomap_rw(iocb, from, &ext2_iomap_ops);
     67	if (ret > 0 && iocb->ki_pos > i_size_read(inode)) {
     68		i_size_write(inode, iocb->ki_pos);
     69		mark_inode_dirty(inode);
     70	}
     71
     72out_unlock:
     73	inode_unlock(inode);
     74	if (ret > 0)
     75		ret = generic_write_sync(iocb, ret);
     76	return ret;
     77}
     78
     79/*
     80 * The lock ordering for ext2 DAX fault paths is:
     81 *
     82 * mmap_lock (MM)
     83 *   sb_start_pagefault (vfs, freeze)
     84 *     address_space->invalidate_lock
     85 *       address_space->i_mmap_rwsem or page_lock (mutually exclusive in DAX)
     86 *         ext2_inode_info->truncate_mutex
     87 *
     88 * The default page_lock and i_size verification done by non-DAX fault paths
     89 * is sufficient because ext2 doesn't support hole punching.
     90 */
     91static vm_fault_t ext2_dax_fault(struct vm_fault *vmf)
     92{
     93	struct inode *inode = file_inode(vmf->vma->vm_file);
     94	vm_fault_t ret;
     95	bool write = (vmf->flags & FAULT_FLAG_WRITE) &&
     96		(vmf->vma->vm_flags & VM_SHARED);
     97
     98	if (write) {
     99		sb_start_pagefault(inode->i_sb);
    100		file_update_time(vmf->vma->vm_file);
    101	}
    102	filemap_invalidate_lock_shared(inode->i_mapping);
    103
    104	ret = dax_iomap_fault(vmf, PE_SIZE_PTE, NULL, NULL, &ext2_iomap_ops);
    105
    106	filemap_invalidate_unlock_shared(inode->i_mapping);
    107	if (write)
    108		sb_end_pagefault(inode->i_sb);
    109	return ret;
    110}
    111
    112static const struct vm_operations_struct ext2_dax_vm_ops = {
    113	.fault		= ext2_dax_fault,
    114	/*
    115	 * .huge_fault is not supported for DAX because allocation in ext2
    116	 * cannot be reliably aligned to huge page sizes and so pmd faults
    117	 * will always fail and fail back to regular faults.
    118	 */
    119	.page_mkwrite	= ext2_dax_fault,
    120	.pfn_mkwrite	= ext2_dax_fault,
    121};
    122
    123static int ext2_file_mmap(struct file *file, struct vm_area_struct *vma)
    124{
    125	if (!IS_DAX(file_inode(file)))
    126		return generic_file_mmap(file, vma);
    127
    128	file_accessed(file);
    129	vma->vm_ops = &ext2_dax_vm_ops;
    130	return 0;
    131}
    132#else
    133#define ext2_file_mmap	generic_file_mmap
    134#endif
    135
    136/*
    137 * Called when filp is released. This happens when all file descriptors
    138 * for a single struct file are closed. Note that different open() calls
    139 * for the same file yield different struct file structures.
    140 */
    141static int ext2_release_file (struct inode * inode, struct file * filp)
    142{
    143	if (filp->f_mode & FMODE_WRITE) {
    144		mutex_lock(&EXT2_I(inode)->truncate_mutex);
    145		ext2_discard_reservation(inode);
    146		mutex_unlock(&EXT2_I(inode)->truncate_mutex);
    147	}
    148	return 0;
    149}
    150
    151int ext2_fsync(struct file *file, loff_t start, loff_t end, int datasync)
    152{
    153	int ret;
    154	struct super_block *sb = file->f_mapping->host->i_sb;
    155
    156	ret = generic_file_fsync(file, start, end, datasync);
    157	if (ret == -EIO)
    158		/* We don't really know where the IO error happened... */
    159		ext2_error(sb, __func__,
    160			   "detected IO error when writing metadata buffers");
    161	return ret;
    162}
    163
    164static ssize_t ext2_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
    165{
    166#ifdef CONFIG_FS_DAX
    167	if (IS_DAX(iocb->ki_filp->f_mapping->host))
    168		return ext2_dax_read_iter(iocb, to);
    169#endif
    170	return generic_file_read_iter(iocb, to);
    171}
    172
    173static ssize_t ext2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
    174{
    175#ifdef CONFIG_FS_DAX
    176	if (IS_DAX(iocb->ki_filp->f_mapping->host))
    177		return ext2_dax_write_iter(iocb, from);
    178#endif
    179	return generic_file_write_iter(iocb, from);
    180}
    181
    182const struct file_operations ext2_file_operations = {
    183	.llseek		= generic_file_llseek,
    184	.read_iter	= ext2_file_read_iter,
    185	.write_iter	= ext2_file_write_iter,
    186	.unlocked_ioctl = ext2_ioctl,
    187#ifdef CONFIG_COMPAT
    188	.compat_ioctl	= ext2_compat_ioctl,
    189#endif
    190	.mmap		= ext2_file_mmap,
    191	.open		= dquot_file_open,
    192	.release	= ext2_release_file,
    193	.fsync		= ext2_fsync,
    194	.get_unmapped_area = thp_get_unmapped_area,
    195	.splice_read	= generic_file_splice_read,
    196	.splice_write	= iter_file_splice_write,
    197};
    198
    199const struct inode_operations ext2_file_inode_operations = {
    200	.listxattr	= ext2_listxattr,
    201	.getattr	= ext2_getattr,
    202	.setattr	= ext2_setattr,
    203	.get_acl	= ext2_get_acl,
    204	.set_acl	= ext2_set_acl,
    205	.fiemap		= ext2_fiemap,
    206	.fileattr_get	= ext2_fileattr_get,
    207	.fileattr_set	= ext2_fileattr_set,
    208};