diff options
Diffstat (limited to 'net/sunrpc/cache.c')
-rw-r--r-- | net/sunrpc/cache.c | 83 |
1 files changed, 47 insertions, 36 deletions
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 80fe5c86efd1..49eb37010aa3 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
@@ -50,12 +50,6 @@ static void cache_init(struct cache_head *h) | |||
50 | h->last_refresh = now; | 50 | h->last_refresh = now; |
51 | } | 51 | } |
52 | 52 | ||
53 | static inline int cache_is_expired(struct cache_detail *detail, struct cache_head *h) | ||
54 | { | ||
55 | return (h->expiry_time < seconds_since_boot()) || | ||
56 | (detail->flush_time > h->last_refresh); | ||
57 | } | ||
58 | |||
59 | struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, | 53 | struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, |
60 | struct cache_head *key, int hash) | 54 | struct cache_head *key, int hash) |
61 | { | 55 | { |
@@ -201,7 +195,7 @@ static int cache_make_upcall(struct cache_detail *cd, struct cache_head *h) | |||
201 | return sunrpc_cache_pipe_upcall(cd, h); | 195 | return sunrpc_cache_pipe_upcall(cd, h); |
202 | } | 196 | } |
203 | 197 | ||
204 | static inline int cache_is_valid(struct cache_detail *detail, struct cache_head *h) | 198 | static inline int cache_is_valid(struct cache_head *h) |
205 | { | 199 | { |
206 | if (!test_bit(CACHE_VALID, &h->flags)) | 200 | if (!test_bit(CACHE_VALID, &h->flags)) |
207 | return -EAGAIN; | 201 | return -EAGAIN; |
@@ -227,16 +221,15 @@ static int try_to_negate_entry(struct cache_detail *detail, struct cache_head *h | |||
227 | int rv; | 221 | int rv; |
228 | 222 | ||
229 | write_lock(&detail->hash_lock); | 223 | write_lock(&detail->hash_lock); |
230 | rv = cache_is_valid(detail, h); | 224 | rv = cache_is_valid(h); |
231 | if (rv != -EAGAIN) { | 225 | if (rv == -EAGAIN) { |
232 | write_unlock(&detail->hash_lock); | 226 | set_bit(CACHE_NEGATIVE, &h->flags); |
233 | return rv; | 227 | cache_fresh_locked(h, seconds_since_boot()+CACHE_NEW_EXPIRY); |
228 | rv = -ENOENT; | ||
234 | } | 229 | } |
235 | set_bit(CACHE_NEGATIVE, &h->flags); | ||
236 | cache_fresh_locked(h, seconds_since_boot()+CACHE_NEW_EXPIRY); | ||
237 | write_unlock(&detail->hash_lock); | 230 | write_unlock(&detail->hash_lock); |
238 | cache_fresh_unlocked(h, detail); | 231 | cache_fresh_unlocked(h, detail); |
239 | return -ENOENT; | 232 | return rv; |
240 | } | 233 | } |
241 | 234 | ||
242 | /* | 235 | /* |
@@ -260,7 +253,7 @@ int cache_check(struct cache_detail *detail, | |||
260 | long refresh_age, age; | 253 | long refresh_age, age; |
261 | 254 | ||
262 | /* First decide return status as best we can */ | 255 | /* First decide return status as best we can */ |
263 | rv = cache_is_valid(detail, h); | 256 | rv = cache_is_valid(h); |
264 | 257 | ||
265 | /* now see if we want to start an upcall */ | 258 | /* now see if we want to start an upcall */ |
266 | refresh_age = (h->expiry_time - h->last_refresh); | 259 | refresh_age = (h->expiry_time - h->last_refresh); |
@@ -269,19 +262,17 @@ int cache_check(struct cache_detail *detail, | |||
269 | if (rqstp == NULL) { | 262 | if (rqstp == NULL) { |
270 | if (rv == -EAGAIN) | 263 | if (rv == -EAGAIN) |
271 | rv = -ENOENT; | 264 | rv = -ENOENT; |
272 | } else if (rv == -EAGAIN || age > refresh_age/2) { | 265 | } else if (rv == -EAGAIN || |
266 | (h->expiry_time != 0 && age > refresh_age/2)) { | ||
273 | dprintk("RPC: Want update, refage=%ld, age=%ld\n", | 267 | dprintk("RPC: Want update, refage=%ld, age=%ld\n", |
274 | refresh_age, age); | 268 | refresh_age, age); |
275 | if (!test_and_set_bit(CACHE_PENDING, &h->flags)) { | 269 | if (!test_and_set_bit(CACHE_PENDING, &h->flags)) { |
276 | switch (cache_make_upcall(detail, h)) { | 270 | switch (cache_make_upcall(detail, h)) { |
277 | case -EINVAL: | 271 | case -EINVAL: |
278 | clear_bit(CACHE_PENDING, &h->flags); | ||
279 | cache_revisit_request(h); | ||
280 | rv = try_to_negate_entry(detail, h); | 272 | rv = try_to_negate_entry(detail, h); |
281 | break; | 273 | break; |
282 | case -EAGAIN: | 274 | case -EAGAIN: |
283 | clear_bit(CACHE_PENDING, &h->flags); | 275 | cache_fresh_unlocked(h, detail); |
284 | cache_revisit_request(h); | ||
285 | break; | 276 | break; |
286 | } | 277 | } |
287 | } | 278 | } |
@@ -293,7 +284,7 @@ int cache_check(struct cache_detail *detail, | |||
293 | * Request was not deferred; handle it as best | 284 | * Request was not deferred; handle it as best |
294 | * we can ourselves: | 285 | * we can ourselves: |
295 | */ | 286 | */ |
296 | rv = cache_is_valid(detail, h); | 287 | rv = cache_is_valid(h); |
297 | if (rv == -EAGAIN) | 288 | if (rv == -EAGAIN) |
298 | rv = -ETIMEDOUT; | 289 | rv = -ETIMEDOUT; |
299 | } | 290 | } |
@@ -310,7 +301,7 @@ EXPORT_SYMBOL_GPL(cache_check); | |||
310 | * a current pointer into that list and into the table | 301 | * a current pointer into that list and into the table |
311 | * for that entry. | 302 | * for that entry. |
312 | * | 303 | * |
313 | * Each time clean_cache is called it finds the next non-empty entry | 304 | * Each time cache_clean is called it finds the next non-empty entry |
314 | * in the current table and walks the list in that entry | 305 | * in the current table and walks the list in that entry |
315 | * looking for entries that can be removed. | 306 | * looking for entries that can be removed. |
316 | * | 307 | * |
@@ -457,9 +448,8 @@ static int cache_clean(void) | |||
457 | current_index ++; | 448 | current_index ++; |
458 | spin_unlock(&cache_list_lock); | 449 | spin_unlock(&cache_list_lock); |
459 | if (ch) { | 450 | if (ch) { |
460 | if (test_and_clear_bit(CACHE_PENDING, &ch->flags)) | 451 | set_bit(CACHE_CLEANED, &ch->flags); |
461 | cache_dequeue(current_detail, ch); | 452 | cache_fresh_unlocked(ch, d); |
462 | cache_revisit_request(ch); | ||
463 | cache_put(ch, d); | 453 | cache_put(ch, d); |
464 | } | 454 | } |
465 | } else | 455 | } else |
@@ -1036,23 +1026,32 @@ static int cache_release(struct inode *inode, struct file *filp, | |||
1036 | 1026 | ||
1037 | static void cache_dequeue(struct cache_detail *detail, struct cache_head *ch) | 1027 | static void cache_dequeue(struct cache_detail *detail, struct cache_head *ch) |
1038 | { | 1028 | { |
1039 | struct cache_queue *cq; | 1029 | struct cache_queue *cq, *tmp; |
1030 | struct cache_request *cr; | ||
1031 | struct list_head dequeued; | ||
1032 | |||
1033 | INIT_LIST_HEAD(&dequeued); | ||
1040 | spin_lock(&queue_lock); | 1034 | spin_lock(&queue_lock); |
1041 | list_for_each_entry(cq, &detail->queue, list) | 1035 | list_for_each_entry_safe(cq, tmp, &detail->queue, list) |
1042 | if (!cq->reader) { | 1036 | if (!cq->reader) { |
1043 | struct cache_request *cr = container_of(cq, struct cache_request, q); | 1037 | cr = container_of(cq, struct cache_request, q); |
1044 | if (cr->item != ch) | 1038 | if (cr->item != ch) |
1045 | continue; | 1039 | continue; |
1040 | if (test_bit(CACHE_PENDING, &ch->flags)) | ||
1041 | /* Lost a race and it is pending again */ | ||
1042 | break; | ||
1046 | if (cr->readers != 0) | 1043 | if (cr->readers != 0) |
1047 | continue; | 1044 | continue; |
1048 | list_del(&cr->q.list); | 1045 | list_move(&cr->q.list, &dequeued); |
1049 | spin_unlock(&queue_lock); | ||
1050 | cache_put(cr->item, detail); | ||
1051 | kfree(cr->buf); | ||
1052 | kfree(cr); | ||
1053 | return; | ||
1054 | } | 1046 | } |
1055 | spin_unlock(&queue_lock); | 1047 | spin_unlock(&queue_lock); |
1048 | while (!list_empty(&dequeued)) { | ||
1049 | cr = list_entry(dequeued.next, struct cache_request, q.list); | ||
1050 | list_del(&cr->q.list); | ||
1051 | cache_put(cr->item, detail); | ||
1052 | kfree(cr->buf); | ||
1053 | kfree(cr); | ||
1054 | } | ||
1056 | } | 1055 | } |
1057 | 1056 | ||
1058 | /* | 1057 | /* |
@@ -1166,6 +1165,7 @@ int sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h) | |||
1166 | 1165 | ||
1167 | char *buf; | 1166 | char *buf; |
1168 | struct cache_request *crq; | 1167 | struct cache_request *crq; |
1168 | int ret = 0; | ||
1169 | 1169 | ||
1170 | if (!detail->cache_request) | 1170 | if (!detail->cache_request) |
1171 | return -EINVAL; | 1171 | return -EINVAL; |
@@ -1174,6 +1174,9 @@ int sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h) | |||
1174 | warn_no_listener(detail); | 1174 | warn_no_listener(detail); |
1175 | return -EINVAL; | 1175 | return -EINVAL; |
1176 | } | 1176 | } |
1177 | if (test_bit(CACHE_CLEANED, &h->flags)) | ||
1178 | /* Too late to make an upcall */ | ||
1179 | return -EAGAIN; | ||
1177 | 1180 | ||
1178 | buf = kmalloc(PAGE_SIZE, GFP_KERNEL); | 1181 | buf = kmalloc(PAGE_SIZE, GFP_KERNEL); |
1179 | if (!buf) | 1182 | if (!buf) |
@@ -1191,10 +1194,18 @@ int sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h) | |||
1191 | crq->len = 0; | 1194 | crq->len = 0; |
1192 | crq->readers = 0; | 1195 | crq->readers = 0; |
1193 | spin_lock(&queue_lock); | 1196 | spin_lock(&queue_lock); |
1194 | list_add_tail(&crq->q.list, &detail->queue); | 1197 | if (test_bit(CACHE_PENDING, &h->flags)) |
1198 | list_add_tail(&crq->q.list, &detail->queue); | ||
1199 | else | ||
1200 | /* Lost a race, no longer PENDING, so don't enqueue */ | ||
1201 | ret = -EAGAIN; | ||
1195 | spin_unlock(&queue_lock); | 1202 | spin_unlock(&queue_lock); |
1196 | wake_up(&queue_wait); | 1203 | wake_up(&queue_wait); |
1197 | return 0; | 1204 | if (ret == -EAGAIN) { |
1205 | kfree(buf); | ||
1206 | kfree(crq); | ||
1207 | } | ||
1208 | return ret; | ||
1198 | } | 1209 | } |
1199 | EXPORT_SYMBOL_GPL(sunrpc_cache_pipe_upcall); | 1210 | EXPORT_SYMBOL_GPL(sunrpc_cache_pipe_upcall); |
1200 | 1211 | ||