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: NeilBrown <neilb@suse.de> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
This commit is contained in:
parent
2f50d8b63d
commit
d202cce896
@ -59,7 +59,7 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,
|
||||
struct cache_head *key, int hash)
|
||||
{
|
||||
struct cache_head **head, **hp;
|
||||
struct cache_head *new = NULL;
|
||||
struct cache_head *new = NULL, *freeme = NULL;
|
||||
|
||||
head = &detail->hash_table[hash];
|
||||
|
||||
@ -68,6 +68,9 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,
|
||||
for (hp=head; *hp != NULL ; hp = &(*hp)->next) {
|
||||
struct cache_head *tmp = *hp;
|
||||
if (detail->match(tmp, key)) {
|
||||
if (cache_is_expired(detail, tmp))
|
||||
/* This entry is expired, we will discard it. */
|
||||
break;
|
||||
cache_get(tmp);
|
||||
read_unlock(&detail->hash_lock);
|
||||
return tmp;
|
||||
@ -92,6 +95,13 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,
|
||||
for (hp=head; *hp != NULL ; hp = &(*hp)->next) {
|
||||
struct cache_head *tmp = *hp;
|
||||
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);
|
||||
write_unlock(&detail->hash_lock);
|
||||
cache_put(new, detail);
|
||||
@ -104,6 +114,8 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,
|
||||
cache_get(new);
|
||||
write_unlock(&detail->hash_lock);
|
||||
|
||||
if (freeme)
|
||||
cache_put(freeme, detail);
|
||||
return new;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sunrpc_cache_lookup);
|
||||
@ -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)
|
||||
{
|
||||
if (!test_bit(CACHE_VALID, &h->flags) ||
|
||||
cache_is_expired(detail, h))
|
||||
if (!test_bit(CACHE_VALID, &h->flags))
|
||||
return -EAGAIN;
|
||||
else {
|
||||
/* entry is valid */
|
||||
|
Loading…
Reference in New Issue
Block a user