summaryrefslogtreecommitdiffstats
path: root/fs/9p/vfs_inode.c
diff options
context:
space:
mode:
authorEric Van Hensbergen <ericvh@kernel.org>2023-03-27 02:06:37 +0000
committerEric Van Hensbergen <ericvh@kernel.org>2023-03-27 02:33:48 +0000
commit1543b4c5071c54d76aad7a7a26a6e43082269b0c (patch)
tree2cfdbff4d66d6e793a3d64bb6da9260a73e92773 /fs/9p/vfs_inode.c
parent6deffc8924b59df173da5fc7a9c96d3717cd9e96 (diff)
downloadlinux-1543b4c5071c54d76aad7a7a26a6e43082269b0c.tar.gz
linux-1543b4c5071c54d76aad7a7a26a6e43082269b0c.tar.bz2
linux-1543b4c5071c54d76aad7a7a26a6e43082269b0c.zip
fs/9p: remove writeback fid and fix per-file modes
This patch removes the creating of an additional writeback_fid for opened files. The patch addresses problems when files were opened write-only or getattr on files with dirty caches. This patch also incorporates information about cache behavior in the fid for every file. This allows us to reflect cache behavior from mount flags, open mode, and information from the server to inform readahead and writeback behavior. This includes adding support for a 9p semantic that qid.version==0 is used to mark a file as non-cachable which is important for synthetic files. This may have a side-effect of not supporting caching on certain legacy file servers that do not properly set qid.version. There is also now a mount flag which can disable the qid.version behavior. Signed-off-by: Eric Van Hensbergen <ericvh@kernel.org>
Diffstat (limited to 'fs/9p/vfs_inode.c')
-rw-r--r--fs/9p/vfs_inode.c45
1 files changed, 15 insertions, 30 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 63590f55363b..fb5e5c0e41e4 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -230,7 +230,6 @@ struct inode *v9fs_alloc_inode(struct super_block *sb)
v9inode = alloc_inode_sb(sb, v9fs_inode_cache, GFP_KERNEL);
if (!v9inode)
return NULL;
- v9inode->writeback_fid = NULL;
v9inode->cache_validity = 0;
mutex_init(&v9inode->v_mutex);
return &v9inode->netfs.inode;
@@ -383,9 +382,6 @@ void v9fs_evict_inode(struct inode *inode)
filemap_fdatawrite(&inode->i_data);
fscache_relinquish_cookie(v9fs_inode_cookie(v9inode), false);
- /* clunk the fid stashed in writeback_fid */
- p9_fid_put(v9inode->writeback_fid);
- v9inode->writeback_fid = NULL;
}
static int v9fs_test_inode(struct inode *inode, void *data)
@@ -796,9 +792,10 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
u32 perm;
struct v9fs_inode *v9inode;
struct v9fs_session_info *v9ses;
- struct p9_fid *fid, *inode_fid;
+ struct p9_fid *fid;
struct dentry *res = NULL;
struct inode *inode;
+ int p9_omode;
if (d_in_lookup(dentry)) {
res = v9fs_vfs_lookup(dir, dentry, 0);
@@ -817,9 +814,14 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
v9ses = v9fs_inode2v9ses(dir);
perm = unixmode2p9mode(v9ses, mode);
- fid = v9fs_create(v9ses, dir, dentry, NULL, perm,
- v9fs_uflags2omode(flags,
- v9fs_proto_dotu(v9ses)));
+ p9_omode = v9fs_uflags2omode(flags, v9fs_proto_dotu(v9ses));
+
+ if ((v9ses->cache >= CACHE_WRITEBACK) && (p9_omode & P9_OWRITE)) {
+ p9_omode = (p9_omode & !P9_OWRITE) | P9_ORDWR;
+ p9_debug(P9_DEBUG_CACHE,
+ "write-only file with writeback enabled, creating w/ O_RDWR\n");
+ }
+ fid = v9fs_create(v9ses, dir, dentry, NULL, perm, p9_omode);
if (IS_ERR(fid)) {
err = PTR_ERR(fid);
goto error;
@@ -828,25 +830,6 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
v9fs_invalidate_inode_attr(dir);
inode = d_inode(dentry);
v9inode = V9FS_I(inode);
- mutex_lock(&v9inode->v_mutex);
- if ((v9ses->cache >= CACHE_WRITEBACK) && !v9inode->writeback_fid &&
- ((flags & O_ACCMODE) != O_RDONLY)) {
- /*
- * clone a fid and add it to writeback_fid
- * we do it during open time instead of
- * page dirty time via write_begin/page_mkwrite
- * because we want write after unlink usecase
- * to work.
- */
- inode_fid = v9fs_writeback_fid(dentry);
- if (IS_ERR(inode_fid)) {
- err = PTR_ERR(inode_fid);
- mutex_unlock(&v9inode->v_mutex);
- goto error;
- }
- v9inode->writeback_fid = (void *) inode_fid;
- }
- mutex_unlock(&v9inode->v_mutex);
err = finish_open(file, dentry, generic_file_open);
if (err)
goto error;
@@ -855,6 +838,8 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
fscache_use_cookie(v9fs_inode_cookie(v9inode),
file->f_mode & FMODE_WRITE);
+
+ v9fs_fid_add_modes(fid, v9ses->flags, v9ses->cache, file->f_flags);
v9fs_open_fid_add(inode, &fid);
file->f_mode |= FMODE_CREATED;
@@ -1024,7 +1009,7 @@ v9fs_vfs_getattr(struct mnt_idmap *idmap, const struct path *path,
p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry);
v9ses = v9fs_dentry2v9ses(dentry);
if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
- generic_fillattr(&nop_mnt_idmap, d_inode(dentry), stat);
+ generic_fillattr(&nop_mnt_idmap, inode, stat);
return 0;
} else if (v9ses->cache >= CACHE_WRITEBACK) {
if (S_ISREG(inode->i_mode)) {
@@ -1128,10 +1113,10 @@ static int v9fs_vfs_setattr(struct mnt_idmap *idmap,
if ((iattr->ia_valid & ATTR_SIZE) &&
iattr->ia_size != i_size_read(inode)) {
truncate_setsize(inode, iattr->ia_size);
+ truncate_pagecache(inode, 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);