Re: [PATCH 3/9] sunrpc: never return expired entries in sunrpc_cache_lookup

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Feb 03, 2010 at 05:31:31PM +1100, NeilBrown wrote:
> 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.

Looks right to me.  Thanks, applied.

By the way, if we get sunrpc_cache_update(old, new1) and
sunrpc_cache_update(old, new2) simultaneously, what happens?

More generally: should we try to ensure that a cache never contains two
entries which match the same key?

--b.

> 
> Signed-off-by: NeilBrown <neilb@xxxxxxx>
> ---
>  net/sunrpc/cache.c |   17 ++++++++++++++---
>  1 files changed, 14 insertions(+), 3 deletions(-)
> 
> diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
> index 9826c5c..3e1ef8b 100644
> --- a/net/sunrpc/cache.c
> +++ b/net/sunrpc/cache.c
> @@ -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 */
> 
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux