diff options
author | Trond Myklebust <trondmy@gmail.com> | 2020-03-02 00:21:43 +0100 |
---|---|---|
committer | Chuck Lever <chuck.lever@oracle.com> | 2020-03-16 17:04:34 +0100 |
commit | 277f27e2f27752cd1a7901443d72e908ddea8a2e (patch) | |
tree | 470b71a2c1a36a0d0e04f000c483a901f3c914db /net/sunrpc/cache.c | |
parent | nfsd: export upcalls must not return ESTALE when mountd is down (diff) | |
download | linux-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.c | 36 |
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); |