// SPDX-License-Identifier: GPL-2.0-only /* * linux/fs/nfs/file.c * * Copyright (C) 1992 Rick Sladkey * * Changes Copyright (C) 1994 by Florian La Roche * - Do not copy data too often around in the kernel. * - In nfs_file_read the return value of kmalloc wasn't checked. * - Put in a better version of read look-ahead buffering. Original idea * and implementation by Wai S Kok [email protected]. * * Expire cache on write to a file by Wai S Kok (Oct 1994). * * Total rewrite of read side for new NFS buffer cache.. Linus. * * nfs regular file handling functions */ #include <linux/module.h> #include <linux/time.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/fcntl.h> #include <linux/stat.h> #include <linux/nfs_fs.h> #include <linux/nfs_mount.h> #include <linux/mm.h> #include <linux/pagemap.h> #include <linux/gfp.h> #include <linux/swap.h> #include <linux/uaccess.h> #include <linux/filelock.h> #include "delegation.h" #include "internal.h" #include "iostat.h" #include "fscache.h" #include "pnfs.h" #include "nfstrace.h" #define NFSDBG_FACILITY … static const struct vm_operations_struct nfs_file_vm_ops; int nfs_check_flags(int flags) { … } EXPORT_SYMBOL_GPL(…); /* * Open file */ static int nfs_file_open(struct inode *inode, struct file *filp) { … } int nfs_file_release(struct inode *inode, struct file *filp) { … } EXPORT_SYMBOL_GPL(…); /** * nfs_revalidate_file_size - Revalidate the file size * @inode: pointer to inode struct * @filp: pointer to struct file * * Revalidates the file length. This is basically a wrapper around * nfs_revalidate_inode() that takes into account the fact that we may * have cached writes (in which case we don't care about the server's * idea of what the file length is), or O_DIRECT (in which case we * shouldn't trust the cache). */ static int nfs_revalidate_file_size(struct inode *inode, struct file *filp) { … } loff_t nfs_file_llseek(struct file *filp, loff_t offset, int whence) { … } EXPORT_SYMBOL_GPL(…); /* * Flush all dirty pages, and check for write errors. */ static int nfs_file_flush(struct file *file, fl_owner_t id) { … } ssize_t nfs_file_read(struct kiocb *iocb, struct iov_iter *to) { … } EXPORT_SYMBOL_GPL(…); ssize_t nfs_file_splice_read(struct file *in, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags) { … } EXPORT_SYMBOL_GPL(…); int nfs_file_mmap(struct file *file, struct vm_area_struct *vma) { … } EXPORT_SYMBOL_GPL(…); /* * Flush any dirty pages for this process, and check for write errors. * The return status from this call provides a reliable indication of * whether any write errors occurred for this process. */ static int nfs_file_fsync_commit(struct file *file, int datasync) { … } int nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) { … } EXPORT_SYMBOL_GPL(…); /* * Decide whether a read/modify/write cycle may be more efficient * then a modify/write/read cycle when writing to a page in the * page cache. * * Some pNFS layout drivers can only read/write at a certain block * granularity like all block devices and therefore we must perform * read/modify/write whenever a page hasn't read yet and the data * to be written there is not aligned to a block boundary and/or * smaller than the block size. * * The modify/write/read cycle may occur if a page is read before * being completely filled by the writer. In this situation, the * page must be completely written to stable storage on the server * before it can be refilled by reading in the page from the server. * This can lead to expensive, small, FILE_SYNC mode writes being * done. * * It may be more efficient to read the page first if the file is * open for reading in addition to writing, the page is not marked * as Uptodate, it is not dirty or waiting to be committed, * indicating that it was previously allocated and then modified, * that there were valid bytes of data in that range of the file, * and that the new data won't completely replace the old data in * that range of the file. */ static bool nfs_folio_is_full_write(struct folio *folio, loff_t pos, unsigned int len) { … } static bool nfs_want_read_modify_write(struct file *file, struct folio *folio, loff_t pos, unsigned int len) { … } /* * This does the "real" work of the write. We must allocate and lock the * page to be sent back to the generic routine, which then copies the * data from user space. * * If the writer ends up delaying the write, the writer needs to * increment the page use counts until he is done with the page. */ static int nfs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, struct page **pagep, void **fsdata) { … } static int nfs_write_end(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned copied, struct page *page, void *fsdata) { … } /* * Partially or wholly invalidate a page * - Release the private state associated with a page if undergoing complete * page invalidation * - Called if either PG_private or PG_fscache is set on the page * - Caller holds page lock */ static void nfs_invalidate_folio(struct folio *folio, size_t offset, size_t length) { … } /* * Attempt to release the private state associated with a folio * - Called if either private or fscache flags are set on the folio * - Caller holds folio lock * - Return true (may release folio) or false (may not) */ static bool nfs_release_folio(struct folio *folio, gfp_t gfp) { … } static void nfs_check_dirty_writeback(struct folio *folio, bool *dirty, bool *writeback) { … } /* * Attempt to clear the private state associated with a page when an error * occurs that requires the cached contents of an inode to be written back or * destroyed * - Called if either PG_private or fscache is set on the page * - Caller holds page lock * - Return 0 if successful, -error otherwise */ static int nfs_launder_folio(struct folio *folio) { … } static int nfs_swap_activate(struct swap_info_struct *sis, struct file *file, sector_t *span) { … } static void nfs_swap_deactivate(struct file *file) { … } const struct address_space_operations nfs_file_aops = …; /* * Notification that a PTE pointing to an NFS page is about to be made * writable, implying that someone is about to modify the page through a * shared-writable mapping */ static vm_fault_t nfs_vm_page_mkwrite(struct vm_fault *vmf) { … } static const struct vm_operations_struct nfs_file_vm_ops = …; ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from) { … } EXPORT_SYMBOL_GPL(…); static int do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) { … } static int do_unlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) { … } static int do_setlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) { … } /* * Lock a (portion of) a file */ int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) { … } EXPORT_SYMBOL_GPL(…); /* * Lock a (portion of) a file */ int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) { … } EXPORT_SYMBOL_GPL(…); const struct file_operations nfs_file_operations = …; EXPORT_SYMBOL_GPL(…);