aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/cache.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2006-03-27 04:15:08 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-27 11:44:43 -0500
commitebd0cb1af3be2729cc1f574681dfba01fcf458d9 (patch)
treeed97a94406ed973573576fca585e1c87c15a4d05 /net/sunrpc/cache.c
parent4d90452cb23b08a9a9dd001010f0ee6b1ee83a45 (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.c51
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}
97EXPORT_SYMBOL(sunrpc_cache_lookup); 97EXPORT_SYMBOL(sunrpc_cache_lookup);
98 98
99
100static void queue_loose(struct cache_detail *detail, struct cache_head *ch);
101
102static 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
109static 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
99struct cache_head *sunrpc_cache_update(struct cache_detail *detail, 120struct 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
216static void queue_loose(struct cache_detail *detail, struct cache_head *ch);
217
218void 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