summaryrefslogtreecommitdiffstats
path: root/fs/fuse
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@redhat.com>2020-05-19 14:50:38 +0200
committerMiklos Szeredi <mszeredi@redhat.com>2020-05-19 14:50:38 +0200
commit5ddd9ced9aef6cfa76af27d384c17c9e2d610ce8 (patch)
tree827d10adb9e7f066d37fd33438496da8aa08441d /fs/fuse
parent32f98877c57bee6bc27f443a96f49678a2cd6a50 (diff)
downloadlinux-stable-5ddd9ced9aef6cfa76af27d384c17c9e2d610ce8.tar.gz
linux-stable-5ddd9ced9aef6cfa76af27d384c17c9e2d610ce8.tar.bz2
linux-stable-5ddd9ced9aef6cfa76af27d384c17c9e2d610ce8.zip
fuse: update attr_version counter on fuse_notify_inval_inode()
A GETATTR request can race with FUSE_NOTIFY_INVAL_INODE, resulting in the attribute cache being updated with stale information after the invalidation. Fix this by bumping the attribute version in fuse_reverse_inval_inode(). Reported-by: Krzysztof Rusek <rusek@9livesdata.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/fuse')
-rw-r--r--fs/fuse/inode.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 6fae66cc096a..5b4aebf5821f 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -321,6 +321,8 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
int fuse_reverse_inval_inode(struct super_block *sb, u64 nodeid,
loff_t offset, loff_t len)
{
+ struct fuse_conn *fc = get_fuse_conn_super(sb);
+ struct fuse_inode *fi;
struct inode *inode;
pgoff_t pg_start;
pgoff_t pg_end;
@@ -329,6 +331,11 @@ int fuse_reverse_inval_inode(struct super_block *sb, u64 nodeid,
if (!inode)
return -ENOENT;
+ fi = get_fuse_inode(inode);
+ spin_lock(&fi->lock);
+ fi->attr_version = atomic64_inc_return(&fc->attr_version);
+ spin_unlock(&fi->lock);
+
fuse_invalidate_attr(inode);
forget_all_cached_acls(inode);
if (offset >= 0) {