mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 21:51:40 +00:00
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 <bcodding@redhat.com> Tested-by: Benjamin Coddington <bcodding@redhat.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
This commit is contained in:
parent
b7b275e60b
commit
0eb43812c0
23
fs/nfs/dir.c
23
fs/nfs/dir.c
@ -2948,9 +2948,28 @@ static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, co
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static u64 nfs_access_login_time(const struct task_struct *task,
|
||||
const struct cred *cred)
|
||||
{
|
||||
const struct task_struct *parent;
|
||||
u64 ret;
|
||||
|
||||
rcu_read_lock();
|
||||
for (;;) {
|
||||
parent = rcu_dereference(task->real_parent);
|
||||
if (parent == task || cred_fscmp(parent->cred, cred) != 0)
|
||||
break;
|
||||
task = parent;
|
||||
}
|
||||
ret = task->start_time;
|
||||
rcu_read_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nfs_access_get_cached_locked(struct inode *inode, const struct cred *cred, u32 *mask, bool may_block)
|
||||
{
|
||||
struct nfs_inode *nfsi = NFS_I(inode);
|
||||
u64 login_time = nfs_access_login_time(current, cred);
|
||||
struct nfs_access_entry *cache;
|
||||
bool retry = true;
|
||||
int err;
|
||||
@ -2978,6 +2997,9 @@ static int nfs_access_get_cached_locked(struct inode *inode, const struct cred *
|
||||
spin_lock(&inode->i_lock);
|
||||
retry = false;
|
||||
}
|
||||
err = -ENOENT;
|
||||
if ((s64)(login_time - cache->timestamp) > 0)
|
||||
goto out;
|
||||
*mask = cache->mask;
|
||||
list_move_tail(&cache->lru, &nfsi->access_cache_entry_lru);
|
||||
err = 0;
|
||||
@ -3057,6 +3079,7 @@ static void nfs_access_add_rbtree(struct inode *inode,
|
||||
else
|
||||
goto found;
|
||||
}
|
||||
set->timestamp = ktime_get_ns();
|
||||
rb_link_node(&set->rb_node, parent, p);
|
||||
rb_insert_color(&set->rb_node, root_node);
|
||||
list_add_tail(&set->lru, &nfsi->access_cache_entry_lru);
|
||||
|
@ -59,6 +59,7 @@ struct nfs_access_entry {
|
||||
kuid_t fsuid;
|
||||
kgid_t fsgid;
|
||||
struct group_info *group_info;
|
||||
u64 timestamp;
|
||||
__u32 mask;
|
||||
struct rcu_head rcu_head;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user