]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
fuse: update attr_version counter on fuse_notify_inval_inode()
authorMiklos Szeredi <mszeredi@redhat.com>
Tue, 19 May 2020 12:50:38 +0000 (14:50 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 1 Oct 2020 11:18:02 +0000 (13:18 +0200)
[ Upstream commit 5ddd9ced9aef6cfa76af27d384c17c9e2d610ce8 ]

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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/fuse/inode.c

index 5dca643a257c9b7c02f5cc9cfede6c1e74a5e8c1..f58ab84b09fb3326407e692d474de989a489f854 100644 (file)
@@ -323,6 +323,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;
@@ -331,6 +333,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) {