From: Horst Birthelmer Date: Fri, 27 Mar 2026 17:28:54 +0000 (+0100) Subject: fuse: fix inode initialization race X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=aff12041b4b2f4f2c164a0cf1b9688408515d036;p=thirdparty%2Fkernel%2Flinux.git fuse: fix inode initialization race Fix a race between fuse_iget() and fuse_reverse_inval_inode() where invalidation can arrive while an inode is being initialized, causing the invalidation to be lost. By keeping the inode state I_NEW as long as the attributes are not valid the invalidation can wait until the inode is fully initialized. Suggested-by: Joanne Koong Signed-off-by: Horst Birthelmer Signed-off-by: Miklos Szeredi --- diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 84f78fb89d353..8b64034ab0bbd 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -470,6 +470,7 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid, struct inode *inode; struct fuse_inode *fi; struct fuse_conn *fc = get_fuse_conn_super(sb); + bool is_new_inode = false; /* * Auto mount points get their node id from the submount root, which is @@ -505,13 +506,13 @@ retry: if (!inode) return NULL; - if ((inode_state_read_once(inode) & I_NEW)) { + is_new_inode = inode_state_read_once(inode) & I_NEW; + if (is_new_inode) { inode->i_flags |= S_NOATIME; if (!fc->writeback_cache || !S_ISREG(attr->mode)) inode->i_flags |= S_NOCMTIME; inode->i_generation = generation; fuse_init_inode(inode, attr, fc); - unlock_new_inode(inode); } else if (fuse_stale_inode(inode, generation, attr)) { /* nodeid was reused, any I/O on the old inode should fail */ fuse_make_bad(inode); @@ -528,6 +529,8 @@ retry: done: fuse_change_attributes_i(inode, attr, NULL, attr_valid, attr_version, evict_ctr); + if (is_new_inode) + unlock_new_inode(inode); return inode; }