@@ -2294,9 +2294,29 @@ static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, st
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(struct inode *inode, struct rpc_cred *cred, struct nfs_access_entry *res, bool may_block)
{
struct nfs_inode *nfsi = NFS_I(inode);
+ const struct cred *cur_cred = current_cred();
+ u64 login_time = nfs_access_login_time(current, cur_cred);
struct nfs_access_entry *cache;
bool retry = true;
int err;
@@ -2324,6 +2344,9 @@ static int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, str
spin_lock(&inode->i_lock);
retry = false;
}
+ err = -ENOENT;
+ if ((s64)(login_time - cache->timestamp) > 0)
+ goto out;
res->cred = cache->cred;
res->mask = cache->mask;
list_move_tail(&cache->lru, &nfsi->access_cache_entry_lru);
@@ -2387,6 +2410,7 @@ static void nfs_access_add_rbtree(struct inode *inode, struct nfs_access_entry *
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);
@@ -52,6 +52,7 @@ struct nfs_access_entry {
struct rb_node rb_node;
struct list_head lru;
struct rpc_cred * cred;
+ u64 timestamp;
__u32 mask;
struct rcu_head rcu_head;
};