diff options
author | NeilBrown <neilb@suse.de> | 2006-03-27 04:15:08 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-27 11:44:43 -0500 |
commit | ebd0cb1af3be2729cc1f574681dfba01fcf458d9 (patch) | |
tree | ed97a94406ed973573576fca585e1c87c15a4d05 /net/sunrpc/cache.c | |
parent | 4d90452cb23b08a9a9dd001010f0ee6b1ee83a45 (diff) |
[PATCH] knfsd: Unexport cache_fresh and fix a small race
Cache_fresh is now only used in cache.c, so unexport it.
Part of cache_fresh (setting CACHE_VALID) should really be done under the
lock, while part (calling cache_revisit_request etc) must be done outside the
lock. So we split it up appropriately.
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'net/sunrpc/cache.c')
-rw-r--r-- | net/sunrpc/cache.c | 51 |
1 files changed, 30 insertions, 21 deletions
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index b242f491cea9..edcda4fd88e8 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
@@ -96,6 +96,27 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, | |||
96 | } | 96 | } |
97 | EXPORT_SYMBOL(sunrpc_cache_lookup); | 97 | EXPORT_SYMBOL(sunrpc_cache_lookup); |
98 | 98 | ||
99 | |||
100 | static void queue_loose(struct cache_detail *detail, struct cache_head *ch); | ||
101 | |||
102 | static int cache_fresh_locked(struct cache_head *head, time_t expiry) | ||
103 | { | ||
104 | head->expiry_time = expiry; | ||
105 | head->last_refresh = get_seconds(); | ||
106 | return !test_and_set_bit(CACHE_VALID, &head->flags); | ||
107 | } | ||
108 | |||
109 | static void cache_fresh_unlocked(struct cache_head *head, | ||
110 | struct cache_detail *detail, int new) | ||
111 | { | ||
112 | if (new) | ||
113 | cache_revisit_request(head); | ||
114 | if (test_and_clear_bit(CACHE_PENDING, &head->flags)) { | ||
115 | cache_revisit_request(head); | ||
116 | queue_loose(detail, head); | ||
117 | } | ||
118 | } | ||
119 | |||
99 | struct cache_head *sunrpc_cache_update(struct cache_detail *detail, | 120 | struct cache_head *sunrpc_cache_update(struct cache_detail *detail, |
100 | struct cache_head *new, struct cache_head *old, int hash) | 121 | struct cache_head *new, struct cache_head *old, int hash) |
101 | { | 122 | { |
@@ -105,6 +126,7 @@ struct cache_head *sunrpc_cache_update(struct cache_detail *detail, | |||
105 | */ | 126 | */ |
106 | struct cache_head **head; | 127 | struct cache_head **head; |
107 | struct cache_head *tmp; | 128 | struct cache_head *tmp; |
129 | int is_new; | ||
108 | 130 | ||
109 | if (!test_bit(CACHE_VALID, &old->flags)) { | 131 | if (!test_bit(CACHE_VALID, &old->flags)) { |
110 | write_lock(&detail->hash_lock); | 132 | write_lock(&detail->hash_lock); |
@@ -113,9 +135,9 @@ struct cache_head *sunrpc_cache_update(struct cache_detail *detail, | |||
113 | set_bit(CACHE_NEGATIVE, &old->flags); | 135 | set_bit(CACHE_NEGATIVE, &old->flags); |
114 | else | 136 | else |
115 | detail->update(old, new); | 137 | detail->update(old, new); |
116 | /* FIXME cache_fresh should come first */ | 138 | is_new = cache_fresh_locked(old, new->expiry_time); |
117 | write_unlock(&detail->hash_lock); | 139 | write_unlock(&detail->hash_lock); |
118 | cache_fresh(detail, old, new->expiry_time); | 140 | cache_fresh_unlocked(old, detail, is_new); |
119 | return old; | 141 | return old; |
120 | } | 142 | } |
121 | write_unlock(&detail->hash_lock); | 143 | write_unlock(&detail->hash_lock); |
@@ -138,9 +160,11 @@ struct cache_head *sunrpc_cache_update(struct cache_detail *detail, | |||
138 | tmp->next = *head; | 160 | tmp->next = *head; |
139 | *head = tmp; | 161 | *head = tmp; |
140 | cache_get(tmp); | 162 | cache_get(tmp); |
163 | is_new = cache_fresh_locked(tmp, new->expiry_time); | ||
164 | cache_fresh_locked(old, 0); | ||
141 | write_unlock(&detail->hash_lock); | 165 | write_unlock(&detail->hash_lock); |
142 | cache_fresh(detail, tmp, new->expiry_time); | 166 | cache_fresh_unlocked(tmp, detail, is_new); |
143 | cache_fresh(detail, old, 0); | 167 | cache_fresh_unlocked(old, detail, 0); |
144 | detail->cache_put(old, detail); | 168 | detail->cache_put(old, detail); |
145 | return tmp; | 169 | return tmp; |
146 | } | 170 | } |
@@ -192,7 +216,8 @@ int cache_check(struct cache_detail *detail, | |||
192 | clear_bit(CACHE_PENDING, &h->flags); | 216 | clear_bit(CACHE_PENDING, &h->flags); |
193 | if (rv == -EAGAIN) { | 217 | if (rv == -EAGAIN) { |
194 | set_bit(CACHE_NEGATIVE, &h->flags); | 218 | set_bit(CACHE_NEGATIVE, &h->flags); |
195 | cache_fresh(detail, h, get_seconds()+CACHE_NEW_EXPIRY); | 219 | cache_fresh_unlocked(h, detail, |
220 | cache_fresh_locked(h, get_seconds()+CACHE_NEW_EXPIRY)); | ||
196 | rv = -ENOENT; | 221 | rv = -ENOENT; |
197 | } | 222 | } |
198 | break; | 223 | break; |
@@ -213,22 +238,6 @@ int cache_check(struct cache_detail *detail, | |||
213 | return rv; | 238 | return rv; |
214 | } | 239 | } |
215 | 240 | ||
216 | static void queue_loose(struct cache_detail *detail, struct cache_head *ch); | ||
217 | |||
218 | void cache_fresh(struct cache_detail *detail, | ||
219 | struct cache_head *head, time_t expiry) | ||
220 | { | ||
221 | |||
222 | head->expiry_time = expiry; | ||
223 | head->last_refresh = get_seconds(); | ||
224 | if (!test_and_set_bit(CACHE_VALID, &head->flags)) | ||
225 | cache_revisit_request(head); | ||
226 | if (test_and_clear_bit(CACHE_PENDING, &head->flags)) { | ||
227 | cache_revisit_request(head); | ||
228 | queue_loose(detail, head); | ||
229 | } | ||
230 | } | ||
231 | |||
232 | /* | 241 | /* |
233 | * caches need to be periodically cleaned. | 242 | * caches need to be periodically cleaned. |
234 | * For this we maintain a list of cache_detail and | 243 | * For this we maintain a list of cache_detail and |