Commit d202cce8 authored by NeilBrown's avatar NeilBrown Committed by J. Bruce Fields

sunrpc: never return expired entries in sunrpc_cache_lookup

If sunrpc_cache_lookup finds an expired entry, remove it from
the cache and return a freshly created non-VALID entry instead.
This ensures that we only ever get a usable entry, or an
entry that will become usable once an update arrives.
i.e. we will never need to repeat the lookup.

This allows us to remove the 'is_expired' test from cache_check
(i.e. from cache_is_valid).  cache_check should never get an expired
entry as 'lookup' will never return one.  If it does happen - due to
inconvenient timing - then just accept it as still valid, it won't be
very much past it's use-by date.
Signed-off-by: default avatarNeilBrown <neilb@suse.de>
Signed-off-by: default avatarJ. Bruce Fields <bfields@citi.umich.edu>
parent 2f50d8b6
...@@ -59,7 +59,7 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, ...@@ -59,7 +59,7 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,
struct cache_head *key, int hash) struct cache_head *key, int hash)
{ {
struct cache_head **head, **hp; struct cache_head **head, **hp;
struct cache_head *new = NULL; struct cache_head *new = NULL, *freeme = NULL;
head = &detail->hash_table[hash]; head = &detail->hash_table[hash];
...@@ -68,6 +68,9 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, ...@@ -68,6 +68,9 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,
for (hp=head; *hp != NULL ; hp = &(*hp)->next) { for (hp=head; *hp != NULL ; hp = &(*hp)->next) {
struct cache_head *tmp = *hp; struct cache_head *tmp = *hp;
if (detail->match(tmp, key)) { if (detail->match(tmp, key)) {
if (cache_is_expired(detail, tmp))
/* This entry is expired, we will discard it. */
break;
cache_get(tmp); cache_get(tmp);
read_unlock(&detail->hash_lock); read_unlock(&detail->hash_lock);
return tmp; return tmp;
...@@ -92,6 +95,13 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, ...@@ -92,6 +95,13 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,
for (hp=head; *hp != NULL ; hp = &(*hp)->next) { for (hp=head; *hp != NULL ; hp = &(*hp)->next) {
struct cache_head *tmp = *hp; struct cache_head *tmp = *hp;
if (detail->match(tmp, key)) { if (detail->match(tmp, key)) {
if (cache_is_expired(detail, tmp)) {
*hp = tmp->next;
tmp->next = NULL;
detail->entries --;
freeme = tmp;
break;
}
cache_get(tmp); cache_get(tmp);
write_unlock(&detail->hash_lock); write_unlock(&detail->hash_lock);
cache_put(new, detail); cache_put(new, detail);
...@@ -104,6 +114,8 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, ...@@ -104,6 +114,8 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,
cache_get(new); cache_get(new);
write_unlock(&detail->hash_lock); write_unlock(&detail->hash_lock);
if (freeme)
cache_put(freeme, detail);
return new; return new;
} }
EXPORT_SYMBOL_GPL(sunrpc_cache_lookup); EXPORT_SYMBOL_GPL(sunrpc_cache_lookup);
...@@ -189,8 +201,7 @@ static int cache_make_upcall(struct cache_detail *cd, struct cache_head *h) ...@@ -189,8 +201,7 @@ static int cache_make_upcall(struct cache_detail *cd, struct cache_head *h)
static inline int cache_is_valid(struct cache_detail *detail, struct cache_head *h) static inline int cache_is_valid(struct cache_detail *detail, struct cache_head *h)
{ {
if (!test_bit(CACHE_VALID, &h->flags) || if (!test_bit(CACHE_VALID, &h->flags))
cache_is_expired(detail, h))
return -EAGAIN; return -EAGAIN;
else { else {
/* entry is valid */ /* entry is valid */
......
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