diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-19 20:24:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-19 20:24:54 -0400 |
commit | f72caf7e496465182eeda842ac66a5e75404ddf1 (patch) | |
tree | 682e2e4b34d6240ea5dbc516d368dd14b21de182 /net/sunrpc/cache.c | |
parent | 6a6be470c3071559970c5659354484d4f664050e (diff) | |
parent | e4e83ea47babd9d4bf95a13aed87f8ef51e46472 (diff) |
Merge branch 'for-2.6.35' of git://linux-nfs.org/~bfields/linux
* 'for-2.6.35' of git://linux-nfs.org/~bfields/linux: (45 commits)
Revert "nfsd4: distinguish expired from stale stateids"
nfsd: safer initialization order in find_file()
nfs4: minor callback code simplification, comment
NFSD: don't report compiled-out versions as present
nfsd4: implement reclaim_complete
nfsd4: nfsd4_destroy_session must set callback client under the state lock
nfsd4: keep a reference count on client while in use
nfsd4: mark_client_expired
nfsd4: introduce nfs4_client.cl_refcount
nfsd4: refactor expire_client
nfsd4: extend the client_lock to cover cl_lru
nfsd4: use list_move in move_to_confirmed
nfsd4: fold release_session into expire_client
nfsd4: rename sessionid_lock to client_lock
nfsd4: fix bare destroy_session null dereference
nfsd4: use local variable in nfs4svc_encode_compoundres
nfsd: further comment typos
sunrpc: centralise most calls to svc_xprt_received
nfsd4: fix unlikely race in session replay case
nfsd4: fix filehandle comment
...
Diffstat (limited to 'net/sunrpc/cache.c')
-rw-r--r-- | net/sunrpc/cache.c | 45 |
1 files changed, 29 insertions, 16 deletions
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 77970fe8bff2..c2173ebdb33c 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
@@ -50,11 +50,17 @@ 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 < get_seconds()) || | ||
56 | (detail->flush_time > h->last_refresh); | ||
57 | } | ||
58 | |||
53 | struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, | 59 | struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, |
54 | struct cache_head *key, int hash) | 60 | struct cache_head *key, int hash) |
55 | { | 61 | { |
56 | struct cache_head **head, **hp; | 62 | struct cache_head **head, **hp; |
57 | struct cache_head *new = NULL; | 63 | struct cache_head *new = NULL, *freeme = NULL; |
58 | 64 | ||
59 | head = &detail->hash_table[hash]; | 65 | head = &detail->hash_table[hash]; |
60 | 66 | ||
@@ -63,6 +69,9 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, | |||
63 | for (hp=head; *hp != NULL ; hp = &(*hp)->next) { | 69 | for (hp=head; *hp != NULL ; hp = &(*hp)->next) { |
64 | struct cache_head *tmp = *hp; | 70 | struct cache_head *tmp = *hp; |
65 | if (detail->match(tmp, key)) { | 71 | if (detail->match(tmp, key)) { |
72 | if (cache_is_expired(detail, tmp)) | ||
73 | /* This entry is expired, we will discard it. */ | ||
74 | break; | ||
66 | cache_get(tmp); | 75 | cache_get(tmp); |
67 | read_unlock(&detail->hash_lock); | 76 | read_unlock(&detail->hash_lock); |
68 | return tmp; | 77 | return tmp; |
@@ -87,6 +96,13 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, | |||
87 | for (hp=head; *hp != NULL ; hp = &(*hp)->next) { | 96 | for (hp=head; *hp != NULL ; hp = &(*hp)->next) { |
88 | struct cache_head *tmp = *hp; | 97 | struct cache_head *tmp = *hp; |
89 | if (detail->match(tmp, key)) { | 98 | if (detail->match(tmp, key)) { |
99 | if (cache_is_expired(detail, tmp)) { | ||
100 | *hp = tmp->next; | ||
101 | tmp->next = NULL; | ||
102 | detail->entries --; | ||
103 | freeme = tmp; | ||
104 | break; | ||
105 | } | ||
90 | cache_get(tmp); | 106 | cache_get(tmp); |
91 | write_unlock(&detail->hash_lock); | 107 | write_unlock(&detail->hash_lock); |
92 | cache_put(new, detail); | 108 | cache_put(new, detail); |
@@ -99,6 +115,8 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, | |||
99 | cache_get(new); | 115 | cache_get(new); |
100 | write_unlock(&detail->hash_lock); | 116 | write_unlock(&detail->hash_lock); |
101 | 117 | ||
118 | if (freeme) | ||
119 | cache_put(freeme, detail); | ||
102 | return new; | 120 | return new; |
103 | } | 121 | } |
104 | EXPORT_SYMBOL_GPL(sunrpc_cache_lookup); | 122 | EXPORT_SYMBOL_GPL(sunrpc_cache_lookup); |
@@ -184,10 +202,7 @@ static int cache_make_upcall(struct cache_detail *cd, struct cache_head *h) | |||
184 | 202 | ||
185 | static inline int cache_is_valid(struct cache_detail *detail, struct cache_head *h) | 203 | static inline int cache_is_valid(struct cache_detail *detail, struct cache_head *h) |
186 | { | 204 | { |
187 | if (!test_bit(CACHE_VALID, &h->flags) || | 205 | if (!test_bit(CACHE_VALID, &h->flags)) |
188 | h->expiry_time < get_seconds()) | ||
189 | return -EAGAIN; | ||
190 | else if (detail->flush_time > h->last_refresh) | ||
191 | return -EAGAIN; | 206 | return -EAGAIN; |
192 | else { | 207 | else { |
193 | /* entry is valid */ | 208 | /* entry is valid */ |
@@ -398,31 +413,27 @@ static int cache_clean(void) | |||
398 | /* Ok, now to clean this strand */ | 413 | /* Ok, now to clean this strand */ |
399 | 414 | ||
400 | cp = & current_detail->hash_table[current_index]; | 415 | cp = & current_detail->hash_table[current_index]; |
401 | ch = *cp; | 416 | for (ch = *cp ; ch ; cp = & ch->next, ch = *cp) { |
402 | for (; ch; cp= & ch->next, ch= *cp) { | ||
403 | if (current_detail->nextcheck > ch->expiry_time) | 417 | if (current_detail->nextcheck > ch->expiry_time) |
404 | current_detail->nextcheck = ch->expiry_time+1; | 418 | current_detail->nextcheck = ch->expiry_time+1; |
405 | if (ch->expiry_time >= get_seconds() && | 419 | if (!cache_is_expired(current_detail, ch)) |
406 | ch->last_refresh >= current_detail->flush_time) | ||
407 | continue; | 420 | continue; |
408 | if (test_and_clear_bit(CACHE_PENDING, &ch->flags)) | ||
409 | cache_dequeue(current_detail, ch); | ||
410 | 421 | ||
411 | if (atomic_read(&ch->ref.refcount) == 1) | ||
412 | break; | ||
413 | } | ||
414 | if (ch) { | ||
415 | *cp = ch->next; | 422 | *cp = ch->next; |
416 | ch->next = NULL; | 423 | ch->next = NULL; |
417 | current_detail->entries--; | 424 | current_detail->entries--; |
418 | rv = 1; | 425 | rv = 1; |
426 | break; | ||
419 | } | 427 | } |
428 | |||
420 | write_unlock(¤t_detail->hash_lock); | 429 | write_unlock(¤t_detail->hash_lock); |
421 | d = current_detail; | 430 | d = current_detail; |
422 | if (!ch) | 431 | if (!ch) |
423 | current_index ++; | 432 | current_index ++; |
424 | spin_unlock(&cache_list_lock); | 433 | spin_unlock(&cache_list_lock); |
425 | if (ch) { | 434 | if (ch) { |
435 | if (test_and_clear_bit(CACHE_PENDING, &ch->flags)) | ||
436 | cache_dequeue(current_detail, ch); | ||
426 | cache_revisit_request(ch); | 437 | cache_revisit_request(ch); |
427 | cache_put(ch, d); | 438 | cache_put(ch, d); |
428 | } | 439 | } |
@@ -1234,8 +1245,10 @@ static int content_open(struct inode *inode, struct file *file, | |||
1234 | if (!cd || !try_module_get(cd->owner)) | 1245 | if (!cd || !try_module_get(cd->owner)) |
1235 | return -EACCES; | 1246 | return -EACCES; |
1236 | han = __seq_open_private(file, &cache_content_op, sizeof(*han)); | 1247 | han = __seq_open_private(file, &cache_content_op, sizeof(*han)); |
1237 | if (han == NULL) | 1248 | if (han == NULL) { |
1249 | module_put(cd->owner); | ||
1238 | return -ENOMEM; | 1250 | return -ENOMEM; |
1251 | } | ||
1239 | 1252 | ||
1240 | han->cd = cd; | 1253 | han->cd = cd; |
1241 | return 0; | 1254 | return 0; |