mirror of
https://github.com/torvalds/linux.git
synced 2025-12-01 07:26:02 +07:00
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 <m@maowtm.org> Message-ID: <bfac417f65cc1d6812be822f8913f0d4ba0c1052.1743956147.git.m@maowtm.org> Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
This commit is contained in:
committed by
Dominique Martinet
parent
8f5ae30d69
commit
290434474c
@@ -66,6 +66,7 @@ static int __v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
|
||||
struct p9_fid *fid;
|
||||
struct inode *inode;
|
||||
struct v9fs_inode *v9inode;
|
||||
unsigned int cached;
|
||||
|
||||
if (flags & LOOKUP_RCU)
|
||||
return -ECHILD;
|
||||
@@ -75,7 +76,11 @@ static int __v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
|
||||
goto out_valid;
|
||||
|
||||
v9inode = V9FS_I(inode);
|
||||
if (v9inode->cache_validity & V9FS_INO_INVALID_ATTR) {
|
||||
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
|
||||
|
||||
cached = v9ses->cache & (CACHE_META | CACHE_LOOSE);
|
||||
|
||||
if (!cached || v9inode->cache_validity & V9FS_INO_INVALID_ATTR) {
|
||||
int retval;
|
||||
struct v9fs_session_info *v9ses;
|
||||
|
||||
@@ -92,6 +97,8 @@ static int __v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
|
||||
|
||||
if (retval == -ENOENT)
|
||||
return 0;
|
||||
if (!cached && v9inode->cache_validity & V9FS_INO_INVALID_ATTR)
|
||||
return 0;
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
}
|
||||
@@ -127,6 +134,8 @@ const struct dentry_operations v9fs_cached_dentry_operations = {
|
||||
};
|
||||
|
||||
const struct dentry_operations v9fs_dentry_operations = {
|
||||
.d_revalidate = v9fs_lookup_revalidate,
|
||||
.d_weak_revalidate = __v9fs_lookup_revalidate,
|
||||
.d_release = v9fs_dentry_release,
|
||||
.d_unalias_trylock = v9fs_dentry_unalias_trylock,
|
||||
.d_unalias_unlock = v9fs_dentry_unalias_unlock,
|
||||
|
||||
@@ -1349,8 +1349,14 @@ int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
|
||||
* Don't update inode if the file type is different
|
||||
*/
|
||||
umode = p9mode2unixmode(v9ses, st, &rdev);
|
||||
if (inode_wrong_type(inode, umode))
|
||||
if (inode_wrong_type(inode, umode)) {
|
||||
/*
|
||||
* Do this as a way of letting the caller know the inode should not
|
||||
* be reused
|
||||
*/
|
||||
v9fs_invalidate_inode_attr(inode);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't want to refresh inode->i_size,
|
||||
|
||||
@@ -902,8 +902,14 @@ int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode)
|
||||
/*
|
||||
* Don't update inode if the file type is different
|
||||
*/
|
||||
if (inode_wrong_type(inode, st->st_mode))
|
||||
if (inode_wrong_type(inode, st->st_mode)) {
|
||||
/*
|
||||
* Do this as a way of letting the caller know the inode should not
|
||||
* be reused
|
||||
*/
|
||||
v9fs_invalidate_inode_attr(inode);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't want to refresh inode->i_size,
|
||||
|
||||
Reference in New Issue
Block a user