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 | |
| 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>
| -rw-r--r-- | include/linux/sunrpc/cache.h | 2 | ||||
| -rw-r--r-- | net/sunrpc/cache.c | 51 | ||||
| -rw-r--r-- | net/sunrpc/sunrpc_syms.c | 1 |
3 files changed, 30 insertions, 24 deletions
diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index afc481dd02dd..a37fead1873b 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h | |||
| @@ -165,8 +165,6 @@ static inline int cache_put(struct cache_head *h, struct cache_detail *cd) | |||
| 165 | } | 165 | } |
| 166 | 166 | ||
| 167 | extern void cache_init(struct cache_head *h); | 167 | extern void cache_init(struct cache_head *h); |
| 168 | extern void cache_fresh(struct cache_detail *detail, | ||
| 169 | struct cache_head *head, time_t expiry); | ||
| 170 | extern int cache_check(struct cache_detail *detail, | 168 | extern int cache_check(struct cache_detail *detail, |
| 171 | struct cache_head *h, struct cache_req *rqstp); | 169 | struct cache_head *h, struct cache_req *rqstp); |
| 172 | extern void cache_flush(void); | 170 | extern void cache_flush(void); |
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 |
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 40401196e7de..69b8238f3d10 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c | |||
| @@ -105,7 +105,6 @@ EXPORT_SYMBOL(auth_unix_lookup); | |||
| 105 | EXPORT_SYMBOL(cache_check); | 105 | EXPORT_SYMBOL(cache_check); |
| 106 | EXPORT_SYMBOL(cache_flush); | 106 | EXPORT_SYMBOL(cache_flush); |
| 107 | EXPORT_SYMBOL(cache_purge); | 107 | EXPORT_SYMBOL(cache_purge); |
| 108 | EXPORT_SYMBOL(cache_fresh); | ||
| 109 | EXPORT_SYMBOL(cache_init); | 108 | EXPORT_SYMBOL(cache_init); |
| 110 | EXPORT_SYMBOL(cache_register); | 109 | EXPORT_SYMBOL(cache_register); |
| 111 | EXPORT_SYMBOL(cache_unregister); | 110 | EXPORT_SYMBOL(cache_unregister); |
