aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2009-08-04 01:22:38 -0400
committerJ. Bruce Fields <bfields@citi.umich.edu>2009-08-04 16:21:44 -0400
commit989a19b9b10635eeb91c08cefe6cf82986bd4ee2 (patch)
treedc18e7d07558c7a217daed108ec9d62ec9be4836 /net
parent5c4d26390341732a8d614141a4cf4663610a1698 (diff)
sunrpc/cache: recheck cache validity after cache_defer_req
If cache_defer_req did not leave the request on a queue, then it could possibly have waited long enough that the cache became valid. So check the status after the call. Signed-off-by: NeilBrown <neilb@suse.de> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/cache.c53
1 files changed, 33 insertions, 20 deletions
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 44f45166378a..bbd31f1215e7 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -176,6 +176,22 @@ struct cache_head *sunrpc_cache_update(struct cache_detail *detail,
176EXPORT_SYMBOL_GPL(sunrpc_cache_update); 176EXPORT_SYMBOL_GPL(sunrpc_cache_update);
177 177
178static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h); 178static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h);
179
180static inline int cache_is_valid(struct cache_detail *detail, struct cache_head *h)
181{
182 if (!test_bit(CACHE_VALID, &h->flags) ||
183 h->expiry_time < get_seconds())
184 return -EAGAIN;
185 else if (detail->flush_time > h->last_refresh)
186 return -EAGAIN;
187 else {
188 /* entry is valid */
189 if (test_bit(CACHE_NEGATIVE, &h->flags))
190 return -ENOENT;
191 else
192 return 0;
193 }
194}
179/* 195/*
180 * This is the generic cache management routine for all 196 * This is the generic cache management routine for all
181 * the authentication caches. 197 * the authentication caches.
@@ -184,8 +200,10 @@ static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h);
184 * 200 *
185 * 201 *
186 * Returns 0 if the cache_head can be used, or cache_puts it and returns 202 * Returns 0 if the cache_head can be used, or cache_puts it and returns
187 * -EAGAIN if upcall is pending, 203 * -EAGAIN if upcall is pending and request has been queued
188 * -ETIMEDOUT if upcall failed and should be retried, 204 * -ETIMEDOUT if upcall failed or request could not be queue or
205 * upcall completed but item is still invalid (implying that
206 * the cache item has been replaced with a newer one).
189 * -ENOENT if cache entry was negative 207 * -ENOENT if cache entry was negative
190 */ 208 */
191int cache_check(struct cache_detail *detail, 209int cache_check(struct cache_detail *detail,
@@ -195,17 +213,7 @@ int cache_check(struct cache_detail *detail,
195 long refresh_age, age; 213 long refresh_age, age;
196 214
197 /* First decide return status as best we can */ 215 /* First decide return status as best we can */
198 if (!test_bit(CACHE_VALID, &h->flags) || 216 rv = cache_is_valid(detail, h);
199 h->expiry_time < get_seconds())
200 rv = -EAGAIN;
201 else if (detail->flush_time > h->last_refresh)
202 rv = -EAGAIN;
203 else {
204 /* entry is valid */
205 if (test_bit(CACHE_NEGATIVE, &h->flags))
206 rv = -ENOENT;
207 else rv = 0;
208 }
209 217
210 /* now see if we want to start an upcall */ 218 /* now see if we want to start an upcall */
211 refresh_age = (h->expiry_time - h->last_refresh); 219 refresh_age = (h->expiry_time - h->last_refresh);
@@ -238,10 +246,14 @@ int cache_check(struct cache_detail *detail,
238 } 246 }
239 } 247 }
240 248
241 if (rv == -EAGAIN) 249 if (rv == -EAGAIN) {
242 if (cache_defer_req(rqstp, h) != 0) 250 if (cache_defer_req(rqstp, h) == 0) {
243 rv = -ETIMEDOUT; 251 /* Request is not deferred */
244 252 rv = cache_is_valid(detail, h);
253 if (rv == -EAGAIN)
254 rv = -ETIMEDOUT;
255 }
256 }
245 if (rv) 257 if (rv)
246 cache_put(h, detail); 258 cache_put(h, detail);
247 return rv; 259 return rv;
@@ -560,11 +572,11 @@ static int cache_defer_req(struct cache_req *req, struct cache_head *item)
560 * or continue and drop the oldest below 572 * or continue and drop the oldest below
561 */ 573 */
562 if (net_random()&1) 574 if (net_random()&1)
563 return -ETIMEDOUT; 575 return 0;
564 } 576 }
565 dreq = req->defer(req); 577 dreq = req->defer(req);
566 if (dreq == NULL) 578 if (dreq == NULL)
567 return -ETIMEDOUT; 579 return 0;
568 580
569 dreq->item = item; 581 dreq->item = item;
570 582
@@ -594,8 +606,9 @@ static int cache_defer_req(struct cache_req *req, struct cache_head *item)
594 if (!test_bit(CACHE_PENDING, &item->flags)) { 606 if (!test_bit(CACHE_PENDING, &item->flags)) {
595 /* must have just been validated... */ 607 /* must have just been validated... */
596 cache_revisit_request(item); 608 cache_revisit_request(item);
609 return 0;
597 } 610 }
598 return 0; 611 return 1;
599} 612}
600 613
601static void cache_revisit_request(struct cache_head *item) 614static void cache_revisit_request(struct cache_head *item)