diff options
author | NeilBrown <neilb@suse.de> | 2010-02-03 01:31:31 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2010-03-14 21:48:52 -0400 |
commit | d202cce8963d9268ff355a386e20243e8332b308 (patch) | |
tree | df95cd2ee9b5fc9663b8fa97e81a4ff1387f2d6e /net/sunrpc | |
parent | 2f50d8b63dd6e5320a9d223298df19df3502da29 (diff) |
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>
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | 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 9826c5ceb995..3e1ef8bf4dc2 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, | |||
59 | struct cache_head *key, int hash) | 59 | struct cache_head *key, int hash) |
60 | { | 60 | { |
61 | struct cache_head **head, **hp; | 61 | struct cache_head **head, **hp; |
62 | struct cache_head *new = NULL; | 62 | struct cache_head *new = NULL, *freeme = NULL; |
63 | 63 | ||
64 | head = &detail->hash_table[hash]; | 64 | head = &detail->hash_table[hash]; |
65 | 65 | ||
@@ -68,6 +68,9 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, | |||
68 | for (hp=head; *hp != NULL ; hp = &(*hp)->next) { | 68 | for (hp=head; *hp != NULL ; hp = &(*hp)->next) { |
69 | struct cache_head *tmp = *hp; | 69 | struct cache_head *tmp = *hp; |
70 | if (detail->match(tmp, key)) { | 70 | if (detail->match(tmp, key)) { |
71 | if (cache_is_expired(detail, tmp)) | ||
72 | /* This entry is expired, we will discard it. */ | ||
73 | break; | ||
71 | cache_get(tmp); | 74 | cache_get(tmp); |
72 | read_unlock(&detail->hash_lock); | 75 | read_unlock(&detail->hash_lock); |
73 | return tmp; | 76 | return tmp; |
@@ -92,6 +95,13 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, | |||
92 | for (hp=head; *hp != NULL ; hp = &(*hp)->next) { | 95 | for (hp=head; *hp != NULL ; hp = &(*hp)->next) { |
93 | struct cache_head *tmp = *hp; | 96 | struct cache_head *tmp = *hp; |
94 | if (detail->match(tmp, key)) { | 97 | if (detail->match(tmp, key)) { |
98 | if (cache_is_expired(detail, tmp)) { | ||
99 | *hp = tmp->next; | ||
100 | tmp->next = NULL; | ||
101 | detail->entries --; | ||
102 | freeme = tmp; | ||
103 | break; | ||
104 | } | ||
95 | cache_get(tmp); | 105 | cache_get(tmp); |
96 | write_unlock(&detail->hash_lock); | 106 | write_unlock(&detail->hash_lock); |
97 | cache_put(new, detail); | 107 | cache_put(new, detail); |
@@ -104,6 +114,8 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, | |||
104 | cache_get(new); | 114 | cache_get(new); |
105 | write_unlock(&detail->hash_lock); | 115 | write_unlock(&detail->hash_lock); |
106 | 116 | ||
117 | if (freeme) | ||
118 | cache_put(freeme, detail); | ||
107 | return new; | 119 | return new; |
108 | } | 120 | } |
109 | EXPORT_SYMBOL_GPL(sunrpc_cache_lookup); | 121 | EXPORT_SYMBOL_GPL(sunrpc_cache_lookup); |
@@ -189,8 +201,7 @@ static int cache_make_upcall(struct cache_detail *cd, struct cache_head *h) | |||
189 | 201 | ||
190 | static inline int cache_is_valid(struct cache_detail *detail, struct cache_head *h) | 202 | static inline int cache_is_valid(struct cache_detail *detail, struct cache_head *h) |
191 | { | 203 | { |
192 | if (!test_bit(CACHE_VALID, &h->flags) || | 204 | if (!test_bit(CACHE_VALID, &h->flags)) |
193 | cache_is_expired(detail, h)) | ||
194 | return -EAGAIN; | 205 | return -EAGAIN; |
195 | else { | 206 | else { |
196 | /* entry is valid */ | 207 | /* entry is valid */ |