diff options
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 |