Skip to content

Commit 2904344

Browse files
micromaomaomartinetd
authored andcommitted
fs/9p: Refresh metadata in d_revalidate for uncached mode too
Currently if another process keeps a file open, due to existing dentry in the dcache, other processes will not see updated metadata of that file if it is changed on the server, even in uncached mode. This can also manifest as -ENODATA when reading a file that has shrunk on the server (even if it's re-opened in another process), or -ENOTSUPP if the file has changed type (e.g. regular file to directory) on the server. We can end up in a situation where both `readdir` or `read` fails until the file is closed by all processes using it. This commit fixes that, and invalidates the dentry altogether if the inode type is changed (for uncached mode). Signed-off-by: Tingmao Wang <[email protected]> Message-ID: <bfac417f65cc1d6812be822f8913f0d4ba0c1052.1743956147.git.m@maowtm.org> Signed-off-by: Dominique Martinet <[email protected]>
1 parent 8f5ae30 commit 2904344

3 files changed

Lines changed: 24 additions & 3 deletions

File tree

fs/9p/vfs_dentry.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ static int __v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
6666
struct p9_fid *fid;
6767
struct inode *inode;
6868
struct v9fs_inode *v9inode;
69+
unsigned int cached;
6970

7071
if (flags & LOOKUP_RCU)
7172
return -ECHILD;
@@ -75,7 +76,11 @@ static int __v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
7576
goto out_valid;
7677

7778
v9inode = V9FS_I(inode);
78-
if (v9inode->cache_validity & V9FS_INO_INVALID_ATTR) {
79+
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
80+
81+
cached = v9ses->cache & (CACHE_META | CACHE_LOOSE);
82+
83+
if (!cached || v9inode->cache_validity & V9FS_INO_INVALID_ATTR) {
7984
int retval;
8085
struct v9fs_session_info *v9ses;
8186

@@ -92,6 +97,8 @@ static int __v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
9297

9398
if (retval == -ENOENT)
9499
return 0;
100+
if (!cached && v9inode->cache_validity & V9FS_INO_INVALID_ATTR)
101+
return 0;
95102
if (retval < 0)
96103
return retval;
97104
}
@@ -127,6 +134,8 @@ const struct dentry_operations v9fs_cached_dentry_operations = {
127134
};
128135

129136
const struct dentry_operations v9fs_dentry_operations = {
137+
.d_revalidate = v9fs_lookup_revalidate,
138+
.d_weak_revalidate = __v9fs_lookup_revalidate,
130139
.d_release = v9fs_dentry_release,
131140
.d_unalias_trylock = v9fs_dentry_unalias_trylock,
132141
.d_unalias_unlock = v9fs_dentry_unalias_unlock,

fs/9p/vfs_inode.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1349,8 +1349,14 @@ int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
13491349
* Don't update inode if the file type is different
13501350
*/
13511351
umode = p9mode2unixmode(v9ses, st, &rdev);
1352-
if (inode_wrong_type(inode, umode))
1352+
if (inode_wrong_type(inode, umode)) {
1353+
/*
1354+
* Do this as a way of letting the caller know the inode should not
1355+
* be reused
1356+
*/
1357+
v9fs_invalidate_inode_attr(inode);
13531358
goto out;
1359+
}
13541360

13551361
/*
13561362
* We don't want to refresh inode->i_size,

fs/9p/vfs_inode_dotl.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -902,8 +902,14 @@ int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode)
902902
/*
903903
* Don't update inode if the file type is different
904904
*/
905-
if (inode_wrong_type(inode, st->st_mode))
905+
if (inode_wrong_type(inode, st->st_mode)) {
906+
/*
907+
* Do this as a way of letting the caller know the inode should not
908+
* be reused
909+
*/
910+
v9fs_invalidate_inode_attr(inode);
906911
goto out;
912+
}
907913

908914
/*
909915
* We don't want to refresh inode->i_size,

0 commit comments

Comments
 (0)