diff options
Diffstat (limited to 'net/sunrpc/cache.c')
-rw-r--r-- | net/sunrpc/cache.c | 66 |
1 files changed, 41 insertions, 25 deletions
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 45cdaff9b361..ade8a7e99cd3 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
@@ -103,7 +103,7 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, | |||
103 | EXPORT_SYMBOL_GPL(sunrpc_cache_lookup); | 103 | EXPORT_SYMBOL_GPL(sunrpc_cache_lookup); |
104 | 104 | ||
105 | 105 | ||
106 | static void queue_loose(struct cache_detail *detail, struct cache_head *ch); | 106 | static void cache_dequeue(struct cache_detail *detail, struct cache_head *ch); |
107 | 107 | ||
108 | static int cache_fresh_locked(struct cache_head *head, time_t expiry) | 108 | static int cache_fresh_locked(struct cache_head *head, time_t expiry) |
109 | { | 109 | { |
@@ -119,7 +119,7 @@ static void cache_fresh_unlocked(struct cache_head *head, | |||
119 | cache_revisit_request(head); | 119 | cache_revisit_request(head); |
120 | if (test_and_clear_bit(CACHE_PENDING, &head->flags)) { | 120 | if (test_and_clear_bit(CACHE_PENDING, &head->flags)) { |
121 | cache_revisit_request(head); | 121 | cache_revisit_request(head); |
122 | queue_loose(detail, head); | 122 | cache_dequeue(detail, head); |
123 | } | 123 | } |
124 | } | 124 | } |
125 | 125 | ||
@@ -184,6 +184,22 @@ static int cache_make_upcall(struct cache_detail *cd, struct cache_head *h) | |||
184 | return cd->cache_upcall(cd, h); | 184 | return cd->cache_upcall(cd, h); |
185 | } | 185 | } |
186 | 186 | ||
187 | static inline int cache_is_valid(struct cache_detail *detail, struct cache_head *h) | ||
188 | { | ||
189 | if (!test_bit(CACHE_VALID, &h->flags) || | ||
190 | h->expiry_time < get_seconds()) | ||
191 | return -EAGAIN; | ||
192 | else if (detail->flush_time > h->last_refresh) | ||
193 | return -EAGAIN; | ||
194 | else { | ||
195 | /* entry is valid */ | ||
196 | if (test_bit(CACHE_NEGATIVE, &h->flags)) | ||
197 | return -ENOENT; | ||
198 | else | ||
199 | return 0; | ||
200 | } | ||
201 | } | ||
202 | |||
187 | /* | 203 | /* |
188 | * This is the generic cache management routine for all | 204 | * This is the generic cache management routine for all |
189 | * the authentication caches. | 205 | * the authentication caches. |
@@ -192,8 +208,10 @@ static int cache_make_upcall(struct cache_detail *cd, struct cache_head *h) | |||
192 | * | 208 | * |
193 | * | 209 | * |
194 | * Returns 0 if the cache_head can be used, or cache_puts it and returns | 210 | * Returns 0 if the cache_head can be used, or cache_puts it and returns |
195 | * -EAGAIN if upcall is pending, | 211 | * -EAGAIN if upcall is pending and request has been queued |
196 | * -ETIMEDOUT if upcall failed and should be retried, | 212 | * -ETIMEDOUT if upcall failed or request could not be queue or |
213 | * upcall completed but item is still invalid (implying that | ||
214 | * the cache item has been replaced with a newer one). | ||
197 | * -ENOENT if cache entry was negative | 215 | * -ENOENT if cache entry was negative |
198 | */ | 216 | */ |
199 | int cache_check(struct cache_detail *detail, | 217 | int cache_check(struct cache_detail *detail, |
@@ -203,17 +221,7 @@ int cache_check(struct cache_detail *detail, | |||
203 | long refresh_age, age; | 221 | long refresh_age, age; |
204 | 222 | ||
205 | /* First decide return status as best we can */ | 223 | /* First decide return status as best we can */ |
206 | if (!test_bit(CACHE_VALID, &h->flags) || | 224 | rv = cache_is_valid(detail, h); |
207 | h->expiry_time < get_seconds()) | ||
208 | rv = -EAGAIN; | ||
209 | else if (detail->flush_time > h->last_refresh) | ||
210 | rv = -EAGAIN; | ||
211 | else { | ||
212 | /* entry is valid */ | ||
213 | if (test_bit(CACHE_NEGATIVE, &h->flags)) | ||
214 | rv = -ENOENT; | ||
215 | else rv = 0; | ||
216 | } | ||
217 | 225 | ||
218 | /* now see if we want to start an upcall */ | 226 | /* now see if we want to start an upcall */ |
219 | refresh_age = (h->expiry_time - h->last_refresh); | 227 | refresh_age = (h->expiry_time - h->last_refresh); |
@@ -229,6 +237,7 @@ int cache_check(struct cache_detail *detail, | |||
229 | switch (cache_make_upcall(detail, h)) { | 237 | switch (cache_make_upcall(detail, h)) { |
230 | case -EINVAL: | 238 | case -EINVAL: |
231 | clear_bit(CACHE_PENDING, &h->flags); | 239 | clear_bit(CACHE_PENDING, &h->flags); |
240 | cache_revisit_request(h); | ||
232 | if (rv == -EAGAIN) { | 241 | if (rv == -EAGAIN) { |
233 | set_bit(CACHE_NEGATIVE, &h->flags); | 242 | set_bit(CACHE_NEGATIVE, &h->flags); |
234 | cache_fresh_unlocked(h, detail, | 243 | cache_fresh_unlocked(h, detail, |
@@ -245,10 +254,14 @@ int cache_check(struct cache_detail *detail, | |||
245 | } | 254 | } |
246 | } | 255 | } |
247 | 256 | ||
248 | if (rv == -EAGAIN) | 257 | if (rv == -EAGAIN) { |
249 | if (cache_defer_req(rqstp, h) != 0) | 258 | if (cache_defer_req(rqstp, h) == 0) { |
250 | rv = -ETIMEDOUT; | 259 | /* Request is not deferred */ |
251 | 260 | rv = cache_is_valid(detail, h); | |
261 | if (rv == -EAGAIN) | ||
262 | rv = -ETIMEDOUT; | ||
263 | } | ||
264 | } | ||
252 | if (rv) | 265 | if (rv) |
253 | cache_put(h, detail); | 266 | cache_put(h, detail); |
254 | return rv; | 267 | return rv; |
@@ -396,7 +409,7 @@ static int cache_clean(void) | |||
396 | ) | 409 | ) |
397 | continue; | 410 | continue; |
398 | if (test_and_clear_bit(CACHE_PENDING, &ch->flags)) | 411 | if (test_and_clear_bit(CACHE_PENDING, &ch->flags)) |
399 | queue_loose(current_detail, ch); | 412 | cache_dequeue(current_detail, ch); |
400 | 413 | ||
401 | if (atomic_read(&ch->ref.refcount) == 1) | 414 | if (atomic_read(&ch->ref.refcount) == 1) |
402 | break; | 415 | break; |
@@ -412,8 +425,10 @@ static int cache_clean(void) | |||
412 | if (!ch) | 425 | if (!ch) |
413 | current_index ++; | 426 | current_index ++; |
414 | spin_unlock(&cache_list_lock); | 427 | spin_unlock(&cache_list_lock); |
415 | if (ch) | 428 | if (ch) { |
429 | cache_revisit_request(ch); | ||
416 | cache_put(ch, d); | 430 | cache_put(ch, d); |
431 | } | ||
417 | } else | 432 | } else |
418 | spin_unlock(&cache_list_lock); | 433 | spin_unlock(&cache_list_lock); |
419 | 434 | ||
@@ -496,11 +511,11 @@ static int cache_defer_req(struct cache_req *req, struct cache_head *item) | |||
496 | * or continue and drop the oldest below | 511 | * or continue and drop the oldest below |
497 | */ | 512 | */ |
498 | if (net_random()&1) | 513 | if (net_random()&1) |
499 | return -ETIMEDOUT; | 514 | return 0; |
500 | } | 515 | } |
501 | dreq = req->defer(req); | 516 | dreq = req->defer(req); |
502 | if (dreq == NULL) | 517 | if (dreq == NULL) |
503 | return -ETIMEDOUT; | 518 | return 0; |
504 | 519 | ||
505 | dreq->item = item; | 520 | dreq->item = item; |
506 | 521 | ||
@@ -530,8 +545,9 @@ static int cache_defer_req(struct cache_req *req, struct cache_head *item) | |||
530 | if (!test_bit(CACHE_PENDING, &item->flags)) { | 545 | if (!test_bit(CACHE_PENDING, &item->flags)) { |
531 | /* must have just been validated... */ | 546 | /* must have just been validated... */ |
532 | cache_revisit_request(item); | 547 | cache_revisit_request(item); |
548 | return 0; | ||
533 | } | 549 | } |
534 | return 0; | 550 | return 1; |
535 | } | 551 | } |
536 | 552 | ||
537 | static void cache_revisit_request(struct cache_head *item) | 553 | static void cache_revisit_request(struct cache_head *item) |
@@ -887,7 +903,7 @@ static int cache_release(struct inode *inode, struct file *filp, | |||
887 | 903 | ||
888 | 904 | ||
889 | 905 | ||
890 | static void queue_loose(struct cache_detail *detail, struct cache_head *ch) | 906 | static void cache_dequeue(struct cache_detail *detail, struct cache_head *ch) |
891 | { | 907 | { |
892 | struct cache_queue *cq; | 908 | struct cache_queue *cq; |
893 | spin_lock(&queue_lock); | 909 | spin_lock(&queue_lock); |