Skip to content

Commit

Permalink
fs/9p: Consolidate file operations and add readahead and writeback
Browse files Browse the repository at this point in the history
We had 3 different sets of file operations across 2 different protocol
variants differentiated by cache which really only changed 3
functions.  But the real problem is that certain file modes, mount
options, and other factors weren't being considered when we
decided whether or not to use caches.

This consolidates all the operations and switches
to conditionals within a common set to decide whether or not
to do different aspects of caching.

Signed-off-by: Eric Van Hensbergen <ericvh@kernel.org>
Reviewed-by: Dominique Martinet <asmadeus@codewreck.org>
  • Loading branch information
ericvh committed Mar 27, 2023
1 parent fe15c26 commit d9bc0d1
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 162 deletions.
30 changes: 12 additions & 18 deletions fs/9p/v9fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ enum {
Opt_uname, Opt_remotename, Opt_cache, Opt_cachetag,
/* Options that take no arguments */
Opt_nodevmap,
/* Cache options */
Opt_cache_loose, Opt_fscache, Opt_mmap,
/* Access options */
Opt_access, Opt_posixacl,
/* Lock timeout option */
Expand All @@ -58,9 +56,6 @@ static const match_table_t tokens = {
{Opt_remotename, "aname=%s"},
{Opt_nodevmap, "nodevmap"},
{Opt_cache, "cache=%s"},
{Opt_cache_loose, "loose"},
{Opt_fscache, "fscache"},
{Opt_mmap, "mmap"},
{Opt_cachetag, "cachetag=%s"},
{Opt_access, "access=%s"},
{Opt_posixacl, "posixacl"},
Expand All @@ -69,10 +64,12 @@ static const match_table_t tokens = {
};

static const char *const v9fs_cache_modes[nr__p9_cache_modes] = {
[CACHE_NONE] = "none",
[CACHE_MMAP] = "mmap",
[CACHE_LOOSE] = "loose",
[CACHE_FSCACHE] = "fscache",
[CACHE_NONE] = "none",
[CACHE_READAHEAD] = "readahead",
[CACHE_WRITEBACK] = "writeback",
[CACHE_MMAP] = "mmap",
[CACHE_LOOSE] = "loose",
[CACHE_FSCACHE] = "fscache",
};

/* Interpret mount options for cache mode */
Expand All @@ -89,6 +86,12 @@ static int get_cache_mode(char *s)
} else if (!strcmp(s, "mmap")) {
version = CACHE_MMAP;
p9_debug(P9_DEBUG_9P, "Cache mode: mmap\n");
} else if (!strcmp(s, "writeback")) {
version = CACHE_WRITEBACK;
p9_debug(P9_DEBUG_9P, "Cache mode: writeback\n");
} else if (!strcmp(s, "readahead")) {
version = CACHE_READAHEAD;
p9_debug(P9_DEBUG_9P, "Cache mode: readahead\n");
} else if (!strcmp(s, "none")) {
version = CACHE_NONE;
p9_debug(P9_DEBUG_9P, "Cache mode: none\n");
Expand Down Expand Up @@ -266,15 +269,6 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
case Opt_nodevmap:
v9ses->nodev = 1;
break;
case Opt_cache_loose:
v9ses->cache = CACHE_LOOSE;
break;
case Opt_fscache:
v9ses->cache = CACHE_FSCACHE;
break;
case Opt_mmap:
v9ses->cache = CACHE_MMAP;
break;
case Opt_cachetag:
#ifdef CONFIG_9P_FSCACHE
kfree(v9ses->cachetag);
Expand Down
2 changes: 2 additions & 0 deletions fs/9p/v9fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ enum p9_session_flags {

enum p9_cache_modes {
CACHE_NONE,
CACHE_READAHEAD,
CACHE_WRITEBACK,
CACHE_MMAP,
CACHE_LOOSE,
CACHE_FSCACHE,
Expand Down
4 changes: 0 additions & 4 deletions fs/9p/v9fs_vfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,6 @@ extern const struct file_operations v9fs_dir_operations;
extern const struct file_operations v9fs_dir_operations_dotl;
extern const struct dentry_operations v9fs_dentry_operations;
extern const struct dentry_operations v9fs_cached_dentry_operations;
extern const struct file_operations v9fs_cached_file_operations;
extern const struct file_operations v9fs_cached_file_operations_dotl;
extern const struct file_operations v9fs_mmap_file_operations;
extern const struct file_operations v9fs_mmap_file_operations_dotl;
extern struct kmem_cache *v9fs_inode_cache;

struct inode *v9fs_alloc_inode(struct super_block *sb);
Expand Down
10 changes: 7 additions & 3 deletions fs/9p/vfs_dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,9 @@ static int v9fs_dir_readdir_dotl(struct file *file, struct dir_context *ctx)


/**
* v9fs_dir_release - called on a close of a file or directory
* @inode: inode of the directory
* @filp: file pointer to a directory
* v9fs_dir_release - close a directory or a file
* @inode: inode of the directory or file
* @filp: file pointer to a directory or file
*
*/

Expand All @@ -214,7 +214,11 @@ int v9fs_dir_release(struct inode *inode, struct file *filp)
fid = filp->private_data;
p9_debug(P9_DEBUG_VFS, "inode: %p filp: %p fid: %d\n",
inode, filp, fid ? fid->fid : -1);

if (fid) {
if ((S_ISREG(inode->i_mode)) && (filp->f_mode & FMODE_WRITE))
retval = filemap_fdatawrite(inode->i_mapping);

spin_lock(&inode->i_lock);
hlist_del(&fid->ilist);
spin_unlock(&inode->i_lock);
Expand Down
131 changes: 20 additions & 111 deletions fs/9p/vfs_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
#include "fid.h"
#include "cache.h"

static const struct vm_operations_struct v9fs_file_vm_ops;
static const struct vm_operations_struct v9fs_mmap_file_vm_ops;

/**
Expand Down Expand Up @@ -74,7 +73,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
}

mutex_lock(&v9inode->v_mutex);
if ((v9ses->cache) && !v9inode->writeback_fid &&
if ((v9ses->cache >= CACHE_WRITEBACK) && !v9inode->writeback_fid &&
((file->f_flags & O_ACCMODE) != O_RDONLY)) {
/*
* clone a fid and add it to writeback_fid
Expand Down Expand Up @@ -368,10 +367,15 @@ v9fs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
{
struct p9_fid *fid = iocb->ki_filp->private_data;
int ret, err = 0;
struct inode *inode = file_inode(iocb->ki_filp);
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);

p9_debug(P9_DEBUG_VFS, "count %zu offset %lld\n",
iov_iter_count(to), iocb->ki_pos);

if (v9ses->cache > CACHE_MMAP)
return generic_file_read_iter(iocb, to);

if (iocb->ki_filp->f_flags & O_NONBLOCK)
ret = p9_client_read_once(fid, iocb->ki_pos, to, &err);
else
Expand All @@ -396,6 +400,11 @@ v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
ssize_t retval;
loff_t origin;
int err = 0;
struct inode *inode = file_inode(iocb->ki_filp);
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);

if (v9ses->cache >= CACHE_WRITEBACK)
return generic_file_write_iter(iocb, from);

retval = generic_write_checks(iocb, from);
if (retval <= 0)
Expand Down Expand Up @@ -478,25 +487,16 @@ static int
v9fs_file_mmap(struct file *filp, struct vm_area_struct *vma)
{
int retval;


retval = generic_file_mmap(filp, vma);
if (!retval)
vma->vm_ops = &v9fs_file_vm_ops;

return retval;
}

static int
v9fs_mmap_file_mmap(struct file *filp, struct vm_area_struct *vma)
{
int retval;
struct inode *inode;
struct v9fs_inode *v9inode;
struct inode *inode = file_inode(filp);
struct v9fs_inode *v9inode = V9FS_I(inode);
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
struct p9_fid *fid;

inode = file_inode(filp);
v9inode = V9FS_I(inode);
if (v9ses->cache < CACHE_MMAP) {
invalidate_inode_pages2(filp->f_mapping);
return generic_file_readonly_mmap(filp, vma);
}

mutex_lock(&v9inode->v_mutex);
if (!v9inode->writeback_fid &&
(vma->vm_flags & VM_SHARED) &&
Expand Down Expand Up @@ -564,35 +564,6 @@ v9fs_vm_page_mkwrite(struct vm_fault *vmf)
return VM_FAULT_NOPAGE;
}

/**
* v9fs_mmap_file_read_iter - read from a file
* @iocb: The operation parameters
* @to: The buffer to read into
*
*/
static ssize_t
v9fs_mmap_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
{
/* TODO: Check if there are dirty pages */
return v9fs_file_read_iter(iocb, to);
}

/**
* v9fs_mmap_file_write_iter - write to a file
* @iocb: The operation parameters
* @from: The data to write
*
*/
static ssize_t
v9fs_mmap_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
{
/*
* TODO: invalidate mmaps on filp's inode between
* offset and offset+count
*/
return v9fs_file_write_iter(iocb, from);
}

static void v9fs_mmap_vm_close(struct vm_area_struct *vma)
{
struct inode *inode;
Expand All @@ -615,48 +586,13 @@ static void v9fs_mmap_vm_close(struct vm_area_struct *vma)
filemap_fdatawrite_wbc(inode->i_mapping, &wbc);
}


static const struct vm_operations_struct v9fs_file_vm_ops = {
.fault = filemap_fault,
.map_pages = filemap_map_pages,
.page_mkwrite = v9fs_vm_page_mkwrite,
};

static const struct vm_operations_struct v9fs_mmap_file_vm_ops = {
.close = v9fs_mmap_vm_close,
.fault = filemap_fault,
.map_pages = filemap_map_pages,
.page_mkwrite = v9fs_vm_page_mkwrite,
};


const struct file_operations v9fs_cached_file_operations = {
.llseek = generic_file_llseek,
.read_iter = generic_file_read_iter,
.write_iter = generic_file_write_iter,
.open = v9fs_file_open,
.release = v9fs_dir_release,
.lock = v9fs_file_lock,
.mmap = v9fs_file_mmap,
.splice_read = generic_file_splice_read,
.splice_write = iter_file_splice_write,
.fsync = v9fs_file_fsync,
};

const struct file_operations v9fs_cached_file_operations_dotl = {
.llseek = generic_file_llseek,
.read_iter = generic_file_read_iter,
.write_iter = generic_file_write_iter,
.open = v9fs_file_open,
.release = v9fs_dir_release,
.lock = v9fs_file_lock_dotl,
.flock = v9fs_file_flock_dotl,
.mmap = v9fs_file_mmap,
.splice_read = generic_file_splice_read,
.splice_write = iter_file_splice_write,
.fsync = v9fs_file_fsync_dotl,
};

const struct file_operations v9fs_file_operations = {
.llseek = generic_file_llseek,
.read_iter = v9fs_file_read_iter,
Expand All @@ -678,34 +614,7 @@ const struct file_operations v9fs_file_operations_dotl = {
.release = v9fs_dir_release,
.lock = v9fs_file_lock_dotl,
.flock = v9fs_file_flock_dotl,
.mmap = generic_file_readonly_mmap,
.splice_read = generic_file_splice_read,
.splice_write = iter_file_splice_write,
.fsync = v9fs_file_fsync_dotl,
};

const struct file_operations v9fs_mmap_file_operations = {
.llseek = generic_file_llseek,
.read_iter = v9fs_mmap_file_read_iter,
.write_iter = v9fs_mmap_file_write_iter,
.open = v9fs_file_open,
.release = v9fs_dir_release,
.lock = v9fs_file_lock,
.mmap = v9fs_mmap_file_mmap,
.splice_read = generic_file_splice_read,
.splice_write = iter_file_splice_write,
.fsync = v9fs_file_fsync,
};

const struct file_operations v9fs_mmap_file_operations_dotl = {
.llseek = generic_file_llseek,
.read_iter = v9fs_mmap_file_read_iter,
.write_iter = v9fs_mmap_file_write_iter,
.open = v9fs_file_open,
.release = v9fs_dir_release,
.lock = v9fs_file_lock_dotl,
.flock = v9fs_file_flock_dotl,
.mmap = v9fs_mmap_file_mmap,
.mmap = v9fs_file_mmap,
.splice_read = generic_file_splice_read,
.splice_write = iter_file_splice_write,
.fsync = v9fs_file_fsync_dotl,
Expand Down
44 changes: 23 additions & 21 deletions fs/9p/vfs_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,24 +287,10 @@ int v9fs_init_inode(struct v9fs_session_info *v9ses,
case S_IFREG:
if (v9fs_proto_dotl(v9ses)) {
inode->i_op = &v9fs_file_inode_operations_dotl;
if (v9ses->cache == CACHE_LOOSE ||
v9ses->cache == CACHE_FSCACHE)
inode->i_fop =
&v9fs_cached_file_operations_dotl;
else if (v9ses->cache == CACHE_MMAP)
inode->i_fop = &v9fs_mmap_file_operations_dotl;
else
inode->i_fop = &v9fs_file_operations_dotl;
inode->i_fop = &v9fs_file_operations_dotl;
} else {
inode->i_op = &v9fs_file_inode_operations;
if (v9ses->cache == CACHE_LOOSE ||
v9ses->cache == CACHE_FSCACHE)
inode->i_fop =
&v9fs_cached_file_operations;
else if (v9ses->cache == CACHE_MMAP)
inode->i_fop = &v9fs_mmap_file_operations;
else
inode->i_fop = &v9fs_file_operations;
inode->i_fop = &v9fs_file_operations;
}

break;
Expand Down Expand Up @@ -843,7 +829,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
inode = d_inode(dentry);
v9inode = V9FS_I(inode);
mutex_lock(&v9inode->v_mutex);
if ((v9ses->cache) && !v9inode->writeback_fid &&
if ((v9ses->cache >= CACHE_WRITEBACK) && !v9inode->writeback_fid &&
((flags & O_ACCMODE) != O_RDONLY)) {
/*
* clone a fid and add it to writeback_fid
Expand Down Expand Up @@ -1030,6 +1016,7 @@ v9fs_vfs_getattr(struct mnt_idmap *idmap, const struct path *path,
struct kstat *stat, u32 request_mask, unsigned int flags)
{
struct dentry *dentry = path->dentry;
struct inode *inode = d_inode(dentry);
struct v9fs_session_info *v9ses;
struct p9_fid *fid;
struct p9_wstat *st;
Expand All @@ -1039,6 +1026,14 @@ v9fs_vfs_getattr(struct mnt_idmap *idmap, const struct path *path,
if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
generic_fillattr(&nop_mnt_idmap, d_inode(dentry), stat);
return 0;
} else if (v9ses->cache >= CACHE_WRITEBACK) {
if (S_ISREG(inode->i_mode)) {
int retval = filemap_fdatawrite(inode->i_mapping);

if (retval)
p9_debug(P9_DEBUG_ERROR,
"flushing writeback during getattr returned %d\n", retval);
}
}
fid = v9fs_fid_lookup(dentry);
if (IS_ERR(fid))
Expand Down Expand Up @@ -1115,8 +1110,12 @@ static int v9fs_vfs_setattr(struct mnt_idmap *idmap,
}

/* Write all dirty data */
if (d_is_reg(dentry))
filemap_write_and_wait(inode->i_mapping);
if (d_is_reg(dentry)) {
retval = filemap_fdatawrite(inode->i_mapping);
if (retval)
p9_debug(P9_DEBUG_ERROR,
"flushing writeback during setattr returned %d\n", retval);
}

retval = p9_client_wstat(fid, &wstat);

Expand All @@ -1127,9 +1126,12 @@ static int v9fs_vfs_setattr(struct mnt_idmap *idmap,
return retval;

if ((iattr->ia_valid & ATTR_SIZE) &&
iattr->ia_size != i_size_read(inode)) {
iattr->ia_size != i_size_read(inode)) {
truncate_setsize(inode, iattr->ia_size);
fscache_resize_cookie(v9fs_inode_cookie(v9inode), iattr->ia_size);
if (v9ses->cache == CACHE_FSCACHE)
fscache_resize_cookie(v9fs_inode_cookie(v9inode), iattr->ia_size);
else
invalidate_mapping_pages(&inode->i_data, 0, -1);
}

v9fs_invalidate_inode_attr(inode);
Expand Down
Loading

0 comments on commit d9bc0d1

Please sign in to comment.