summaryrefslogtreecommitdiffstats
path: root/net/sunrpc/cache.c
diff options
context:
space:
mode:
authorTrond Myklebust <trondmy@gmail.com>2020-03-02 00:21:43 +0100
committerChuck Lever <chuck.lever@oracle.com>2020-03-16 17:04:34 +0100
commit277f27e2f27752cd1a7901443d72e908ddea8a2e (patch)
tree470b71a2c1a36a0d0e04f000c483a901f3c914db /net/sunrpc/cache.c
parentnfsd: export upcalls must not return ESTALE when mountd is down (diff)
downloadlinux-277f27e2f27752cd1a7901443d72e908ddea8a2e.tar.xz
linux-277f27e2f27752cd1a7901443d72e908ddea8a2e.zip
SUNRPC/cache: Allow garbage collection of invalid cache entries
If the cache entry never gets initialised, we want the garbage collector to be able to evict it. Otherwise if the upcall daemon fails to initialise the entry, we end up never expiring it. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> [ cel: resolved a merge conflict ] Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Diffstat (limited to 'net/sunrpc/cache.c')
-rw-r--r--net/sunrpc/cache.c36
1 files changed, 19 insertions, 17 deletions
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 7f2e5d818e05..cd76ef2d26b8 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -64,13 +64,14 @@ static struct cache_head *sunrpc_cache_find_rcu(struct cache_detail *detail,
rcu_read_lock();
hlist_for_each_entry_rcu(tmp, head, cache_list) {
- if (detail->match(tmp, key)) {
- if (cache_is_expired(detail, tmp))
- continue;
- tmp = cache_get_rcu(tmp);
- rcu_read_unlock();
- return tmp;
- }
+ if (!detail->match(tmp, key))
+ continue;
+ if (test_bit(CACHE_VALID, &tmp->flags) &&
+ cache_is_expired(detail, tmp))
+ continue;
+ tmp = cache_get_rcu(tmp);
+ rcu_read_unlock();
+ return tmp;
}
rcu_read_unlock();
return NULL;
@@ -114,17 +115,18 @@ static struct cache_head *sunrpc_cache_add_entry(struct cache_detail *detail,
/* check if entry appeared while we slept */
hlist_for_each_entry_rcu(tmp, head, cache_list,
lockdep_is_held(&detail->hash_lock)) {
- if (detail->match(tmp, key)) {
- if (cache_is_expired(detail, tmp)) {
- sunrpc_begin_cache_remove_entry(tmp, detail);
- freeme = tmp;
- break;
- }
- cache_get(tmp);
- spin_unlock(&detail->hash_lock);
- cache_put(new, detail);
- return tmp;
+ if (!detail->match(tmp, key))
+ continue;
+ if (test_bit(CACHE_VALID, &tmp->flags) &&
+ cache_is_expired(detail, tmp)) {
+ sunrpc_begin_cache_remove_entry(tmp, detail);
+ freeme = tmp;
+ break;
}
+ cache_get(tmp);
+ spin_unlock(&detail->hash_lock);
+ cache_put(new, detail);
+ return tmp;
}
hlist_add_head_rcu(&new->cache_list, head);