linux/fs/nfs/file.c

// 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();