Skip to content
Draft
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
34 changes: 31 additions & 3 deletions fs/fuse/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,13 +231,14 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
* if the attr_version would've been preserved.
*
* !evict_ctr -> this is create
* fi->attr_version != 0 -> this is not a new inode
* fi->attr_version > 1 -> this is not a new inode
* evict_ctr == fuse_get_evict_ctr() -> no evicts while during request
*/
if (!evict_ctr || fi->attr_version || evict_ctr == fuse_get_evict_ctr(fc))
if (!evict_ctr || fi->attr_version > 1 || evict_ctr == fuse_get_evict_ctr(fc))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why these changes >1, same as >0?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah not >0

set_mask_bits(&fi->inval_mask, STATX_BASIC_STATS, 0);

fi->attr_version = atomic64_inc_return(&fc->attr_version);
if (fi->attr_version != 1) /* fuse_iget() handle if attr_version == 1 */
fi->attr_version = atomic64_inc_return(&fc->attr_version);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is if this is later on called?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's assume there is no invalidate, and just two times fuse_change_attributes_common() from two different calls.

fi->i_time = attr_valid;

inode->i_ino = fuse_squash_ino(attr->ino);
Expand Down Expand Up @@ -520,6 +521,18 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
done:
fuse_change_attributes_i(inode, attr, NULL, attr_valid, attr_version,
evict_ctr);

spin_lock(&fi->lock);
if (fi->attr_version == 1) /* delayed inode invalidation */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I must be missing something, somehow I think this is always true? fuse_change_attributes_common() increases to 1?

{
spin_unlock(&fi->lock);
down_read(&fc->killsb);
fuse_reverse_inval_inode(fc, nodeid, 0, 0);
up_read(&fc->killsb);
}
else
spin_unlock(&fi->lock);

return inode;
}

Expand Down Expand Up @@ -598,6 +611,21 @@ int fuse_reverse_inval_inode(struct fuse_conn *fc, u64 nodeid,

fi = get_fuse_inode(inode);
spin_lock(&fi->lock);

if (fi->attr_version == 0)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just return -EAGAIN and let userspace handle it?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The alternative would be too add a waitq

{
/* attr_version == 0 indicate fuse_iget() is not completed yet.
Skip the inode invalidation operation here, and delay it in the
function fuse_iget(), after call to fuse_change_attributes_i().
Initialized value of fc->attr_version is 1, so fi->attr_version
will be 0 or >= 2, we use value 1 to indicate the "delayed"
inode invalidation operation been recorded */
fi->attr_version = 1;
spin_unlock(&fi->lock);
iput(inode);
return 0;
}

fi->attr_version = atomic64_inc_return(&fc->attr_version);
spin_unlock(&fi->lock);

Expand Down