Skip to content

Commit 4129cb6

Browse files
committed
NFS: Clear the file access cache upon login
jira LE-1907 Rebuild_History Non-Buildable kernel-rt-5.14.0-284.30.1.rt14.315.el9_2 commit-author Trond Myklebust <[email protected]> commit 0eb4381 POSIX typically only refreshes the user's supplementary group information upon login. Since NFS servers may often refresh their concept of the user supplementary group membership at their own cadence, it is possible for the NFS client's access cache to become stale due to the user's group membership changing on the server after the user has already logged in on the client. While it is reasonable to expect that such group membership changes are rare, and that we do not want to optimise the cache to accommodate them, it is also not unreasonable for the user to expect that if they log out and log back in again, that the staleness would clear up. Reviewed-by: Benjamin Coddington <[email protected]> Tested-by: Benjamin Coddington <[email protected]> Signed-off-by: Trond Myklebust <[email protected]> (cherry picked from commit 0eb4381) Signed-off-by: Jonathan Maple <[email protected]>
1 parent 3fe433a commit 4129cb6

File tree

2 files changed

+24
-0
lines changed

2 files changed

+24
-0
lines changed

fs/nfs/dir.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2901,9 +2901,28 @@ static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, co
29012901
return NULL;
29022902
}
29032903

2904+
static u64 nfs_access_login_time(const struct task_struct *task,
2905+
const struct cred *cred)
2906+
{
2907+
const struct task_struct *parent;
2908+
u64 ret;
2909+
2910+
rcu_read_lock();
2911+
for (;;) {
2912+
parent = rcu_dereference(task->real_parent);
2913+
if (parent == task || cred_fscmp(parent->cred, cred) != 0)
2914+
break;
2915+
task = parent;
2916+
}
2917+
ret = task->start_time;
2918+
rcu_read_unlock();
2919+
return ret;
2920+
}
2921+
29042922
static int nfs_access_get_cached_locked(struct inode *inode, const struct cred *cred, u32 *mask, bool may_block)
29052923
{
29062924
struct nfs_inode *nfsi = NFS_I(inode);
2925+
u64 login_time = nfs_access_login_time(current, cred);
29072926
struct nfs_access_entry *cache;
29082927
bool retry = true;
29092928
int err;
@@ -2931,6 +2950,9 @@ static int nfs_access_get_cached_locked(struct inode *inode, const struct cred *
29312950
spin_lock(&inode->i_lock);
29322951
retry = false;
29332952
}
2953+
err = -ENOENT;
2954+
if ((s64)(login_time - cache->timestamp) > 0)
2955+
goto out;
29342956
*mask = cache->mask;
29352957
list_move_tail(&cache->lru, &nfsi->access_cache_entry_lru);
29362958
err = 0;
@@ -3010,6 +3032,7 @@ static void nfs_access_add_rbtree(struct inode *inode,
30103032
else
30113033
goto found;
30123034
}
3035+
set->timestamp = ktime_get_ns();
30133036
rb_link_node(&set->rb_node, parent, p);
30143037
rb_insert_color(&set->rb_node, root_node);
30153038
list_add_tail(&set->lru, &nfsi->access_cache_entry_lru);

include/linux/nfs_fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ struct nfs_access_entry {
5959
kuid_t fsuid;
6060
kgid_t fsgid;
6161
struct group_info *group_info;
62+
u64 timestamp;
6263
__u32 mask;
6364
struct rcu_head rcu_head;
6465
};

0 commit comments

Comments
 (0)