diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 4f0474e2e31def..4a52a3bc443ca7 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -896,6 +896,9 @@ struct fuse_conn { /** Version counter for attribute changes */ atomic64_t attr_version; + /** Waitqueue for attr_version initialization */ + wait_queue_head_t attr_version_waitq; + /** Version counter for evict inode */ atomic64_t evict_ctr; diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 61962fd615857a..67612fde6ad84e 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -238,6 +238,7 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, set_mask_bits(&fi->inval_mask, STATX_BASIC_STATS, 0); fi->attr_version = atomic64_inc_return(&fc->attr_version); + wake_up_all(&fc->attr_version_waitq); fi->i_time = attr_valid; inode->i_ino = fuse_squash_ino(attr->ino); @@ -597,10 +598,17 @@ int fuse_reverse_inval_inode(struct fuse_conn *fc, u64 nodeid, return -ENOENT; fi = get_fuse_inode(inode); + spin_lock(&fi->lock); + while (fi->attr_version == 0) { + spin_unlock(&fi->lock); + wait_event(fc->attr_version_waitq, READ_ONCE(fi->attr_version) != 0); + spin_lock(&fi->lock); + } + fi->attr_version = atomic64_inc_return(&fc->attr_version); spin_unlock(&fi->lock); - + if (fc->inval_inode_entries) fuse_invalidate_inode_entry(inode); else if (fc->expire_inode_entries) @@ -1017,6 +1025,7 @@ void fuse_conn_init(struct fuse_conn *fc, struct fuse_mount *fm, refcount_set(&fc->count, 1); atomic_set(&fc->dev_count, 1); init_waitqueue_head(&fc->blocked_waitq); + init_waitqueue_head(&fc->attr_version_waitq); fuse_iqueue_init(&fc->iq, fiq_ops, fiq_priv); INIT_LIST_HEAD(&fc->bg_queue); INIT_LIST_HEAD(&fc->entry);