Commit 57b69181 authored by Trond Myklebust's avatar Trond Myklebust

NFS: Cache access checks more aggressively

If an attribute revalidation fails, then we already know that we'll
zap the access cache. If, OTOH, the inode isn't changing, there should
be no need to eject access calls just because they are old.
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
parent 38512aa9
...@@ -2228,21 +2228,37 @@ static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, st ...@@ -2228,21 +2228,37 @@ static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, st
return NULL; return NULL;
} }
static int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs_access_entry *res) 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); struct nfs_inode *nfsi = NFS_I(inode);
struct nfs_access_entry *cache; struct nfs_access_entry *cache;
int err = -ENOENT; bool retry = true;
int err;
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
if (nfsi->cache_validity & NFS_INO_INVALID_ACCESS) for(;;) {
goto out_zap; if (nfsi->cache_validity & NFS_INO_INVALID_ACCESS)
cache = nfs_access_search_rbtree(inode, cred); goto out_zap;
if (cache == NULL) cache = nfs_access_search_rbtree(inode, cred);
goto out; err = -ENOENT;
if (!nfs_have_delegated_attributes(inode) && if (cache == NULL)
!time_in_range_open(jiffies, cache->jiffies, cache->jiffies + nfsi->attrtimeo)) goto out;
goto out_stale; /* Found an entry, is our attribute cache valid? */
if (!nfs_attribute_cache_expired(inode) &&
!(nfsi->cache_validity & NFS_INO_INVALID_ATTR))
break;
err = -ECHILD;
if (!may_block)
goto out;
if (!retry)
goto out_zap;
spin_unlock(&inode->i_lock);
err = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
if (err)
return err;
spin_lock(&inode->i_lock);
retry = false;
}
res->jiffies = cache->jiffies; res->jiffies = cache->jiffies;
res->cred = cache->cred; res->cred = cache->cred;
res->mask = cache->mask; res->mask = cache->mask;
...@@ -2251,12 +2267,6 @@ static int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, str ...@@ -2251,12 +2267,6 @@ static int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, str
out: out:
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
return err; return err;
out_stale:
rb_erase(&cache->rb_node, &nfsi->access_cache);
list_del(&cache->lru);
spin_unlock(&inode->i_lock);
nfs_access_free_entry(cache);
return -ENOENT;
out_zap: out_zap:
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
nfs_access_zap_cache(inode); nfs_access_zap_cache(inode);
...@@ -2283,13 +2293,12 @@ static int nfs_access_get_cached_rcu(struct inode *inode, struct rpc_cred *cred, ...@@ -2283,13 +2293,12 @@ static int nfs_access_get_cached_rcu(struct inode *inode, struct rpc_cred *cred,
cache = NULL; cache = NULL;
if (cache == NULL) if (cache == NULL)
goto out; goto out;
if (!nfs_have_delegated_attributes(inode) && err = nfs_revalidate_inode_rcu(NFS_SERVER(inode), inode);
!time_in_range_open(jiffies, cache->jiffies, cache->jiffies + nfsi->attrtimeo)) if (err)
goto out; goto out;
res->jiffies = cache->jiffies; res->jiffies = cache->jiffies;
res->cred = cache->cred; res->cred = cache->cred;
res->mask = cache->mask; res->mask = cache->mask;
err = 0;
out: out:
rcu_read_unlock(); rcu_read_unlock();
return err; return err;
...@@ -2378,18 +2387,19 @@ EXPORT_SYMBOL_GPL(nfs_access_set_mask); ...@@ -2378,18 +2387,19 @@ EXPORT_SYMBOL_GPL(nfs_access_set_mask);
static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask) static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
{ {
struct nfs_access_entry cache; struct nfs_access_entry cache;
bool may_block = (mask & MAY_NOT_BLOCK) == 0;
int status; int status;
trace_nfs_access_enter(inode); trace_nfs_access_enter(inode);
status = nfs_access_get_cached_rcu(inode, cred, &cache); status = nfs_access_get_cached_rcu(inode, cred, &cache);
if (status != 0) if (status != 0)
status = nfs_access_get_cached(inode, cred, &cache); status = nfs_access_get_cached(inode, cred, &cache, may_block);
if (status == 0) if (status == 0)
goto out_cached; goto out_cached;
status = -ECHILD; status = -ECHILD;
if (mask & MAY_NOT_BLOCK) if (!may_block)
goto out; goto out;
/* Be clever: ask server to check for all possible rights */ /* Be clever: ask server to check for all possible rights */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment