Skip to content

Commit 0eb4381

Browse files
author
Trond Myklebust
committed
NFS: Clear the file access cache upon login
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]>
1 parent b7b275e commit 0eb4381

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
@@ -2948,9 +2948,28 @@ static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, co
29482948
return NULL;
29492949
}
29502950

2951+
static u64 nfs_access_login_time(const struct task_struct *task,
2952+
const struct cred *cred)
2953+
{
2954+
const struct task_struct *parent;
2955+
u64 ret;
2956+
2957+
rcu_read_lock();
2958+
for (;;) {
2959+
parent = rcu_dereference(task->real_parent);
2960+
if (parent == task || cred_fscmp(parent->cred, cred) != 0)
2961+
break;
2962+
task = parent;
2963+
}
2964+
ret = task->start_time;
2965+
rcu_read_unlock();
2966+
return ret;
2967+
}
2968+
29512969
static int nfs_access_get_cached_locked(struct inode *inode, const struct cred *cred, u32 *mask, bool may_block)
29522970
{
29532971
struct nfs_inode *nfsi = NFS_I(inode);
2972+
u64 login_time = nfs_access_login_time(current, cred);
29542973
struct nfs_access_entry *cache;
29552974
bool retry = true;
29562975
int err;
@@ -2978,6 +2997,9 @@ static int nfs_access_get_cached_locked(struct inode *inode, const struct cred *
29782997
spin_lock(&inode->i_lock);
29792998
retry = false;
29802999
}
3000+
err = -ENOENT;
3001+
if ((s64)(login_time - cache->timestamp) > 0)
3002+
goto out;
29813003
*mask = cache->mask;
29823004
list_move_tail(&cache->lru, &nfsi->access_cache_entry_lru);
29833005
err = 0;
@@ -3057,6 +3079,7 @@ static void nfs_access_add_rbtree(struct inode *inode,
30573079
else
30583080
goto found;
30593081
}
3082+
set->timestamp = ktime_get_ns();
30603083
rb_link_node(&set->rb_node, parent, p);
30613084
rb_insert_color(&set->rb_node, root_node);
30623085
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)