Skip to content
Merged
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
5 changes: 2 additions & 3 deletions fs/fuse/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
fuse_change_attributes(inode, &ext_out.entry.attr, &sx,
ATTR_TIMEOUT(&ext_out.entry),
attr_version);
if ((ext_out.mask & STATX_BASIC_STATS) == STATX_BASIC_STATS)
fuse_change_entry_timeout(entry, &ext_out.entry);
fuse_change_entry_timeout(entry, &ext_out.entry);
} else if (inode) {
fi = get_fuse_inode(inode);
if (flags & LOOKUP_RCU) {
Expand Down Expand Up @@ -1640,7 +1639,7 @@ static int fuse_permission(struct mnt_idmap *idmap,
struct fuse_inode *fi = get_fuse_inode(inode);

if (perm_mask & READ_ONCE(fi->inval_mask) ||
time_before64(fi->i_time, get_jiffies_64())) {
time_before64(fi->i_perm_time, get_jiffies_64())) {
refreshed = true;

err = fuse_perm_getattr(inode, mask, perm_mask);
Expand Down
9 changes: 9 additions & 0 deletions fs/fuse/fuse_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ struct fuse_inode {
/** Time in jiffies until the file attributes are valid */
u64 i_time;

/*
* Time in jiffies until mode/uid/gid (the permission-check subset of
* STATX_BASIC_STATS) are valid. Tracked separately from i_time so that
* a partial statx refresh covering only the perm bits can extend the
* permission-check cache without falsely advancing i_time for the
* other (un-refreshed) attributes.
*/
u64 i_perm_time;

/* Which attributes are invalid */
u32 inval_mask;

Expand Down
12 changes: 12 additions & 0 deletions fs/fuse/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,17 @@ static void fuse_change_attributes_common_sx(struct inode *inode,
fi->i_time = attr_valid;
}

/*
* Permission-check cache: independent of i_time so that a partial
* refresh which covers only mode/uid/gid (e.g. fuse_perm_getattr())
* still extends the window during which fuse_permission() can hit
* the cache. Requires all three perm bits because generic_permission()
* needs the full triple.
*/
if ((returned_attrs & (STATX_MODE | STATX_UID | STATX_GID)) ==
(STATX_MODE | STATX_UID | STATX_GID))
fi->i_perm_time = attr_valid;

/*
* Only update inode fields for attributes that were actually returned.
* TYPE is part of i_mode but already set during inode creation.
Expand Down Expand Up @@ -379,6 +390,7 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
fi->attr_version = atomic64_inc_return(&fc->attr_version);
wake_up_all(&fc->attr_version_waitq);
fi->i_time = attr_valid;
fi->i_perm_time = attr_valid;

inode->i_ino = fuse_squash_ino(attr->ino);
inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
Expand Down
Loading