Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions fs/fuse/fuse_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
11 changes: 10 additions & 1 deletion fs/fuse/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down