diff options
Diffstat (limited to 'net/sunrpc/auth.c')
-rw-r--r-- | net/sunrpc/auth.c | 46 |
1 files changed, 32 insertions, 14 deletions
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index ad7bde2c437..cf1198d10ee 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
@@ -120,6 +120,18 @@ rpcauth_unhash_cred_locked(struct rpc_cred *cred) | |||
120 | clear_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags); | 120 | clear_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags); |
121 | } | 121 | } |
122 | 122 | ||
123 | static void | ||
124 | rpcauth_unhash_cred(struct rpc_cred *cred) | ||
125 | { | ||
126 | spinlock_t *cache_lock; | ||
127 | |||
128 | cache_lock = &cred->cr_auth->au_credcache->lock; | ||
129 | spin_lock(cache_lock); | ||
130 | if (atomic_read(&cred->cr_count) == 0) | ||
131 | rpcauth_unhash_cred_locked(cred); | ||
132 | spin_unlock(cache_lock); | ||
133 | } | ||
134 | |||
123 | /* | 135 | /* |
124 | * Initialize RPC credential cache | 136 | * Initialize RPC credential cache |
125 | */ | 137 | */ |
@@ -134,6 +146,7 @@ rpcauth_init_credcache(struct rpc_auth *auth, unsigned long expire) | |||
134 | return -ENOMEM; | 146 | return -ENOMEM; |
135 | for (i = 0; i < RPC_CREDCACHE_NR; i++) | 147 | for (i = 0; i < RPC_CREDCACHE_NR; i++) |
136 | INIT_HLIST_HEAD(&new->hashtable[i]); | 148 | INIT_HLIST_HEAD(&new->hashtable[i]); |
149 | spin_lock_init(&new->lock); | ||
137 | new->expire = expire; | 150 | new->expire = expire; |
138 | new->nextgc = jiffies + (expire >> 1); | 151 | new->nextgc = jiffies + (expire >> 1); |
139 | auth->au_credcache = new; | 152 | auth->au_credcache = new; |
@@ -168,6 +181,7 @@ rpcauth_clear_credcache(struct rpc_cred_cache *cache) | |||
168 | int i; | 181 | int i; |
169 | 182 | ||
170 | spin_lock(&rpc_credcache_lock); | 183 | spin_lock(&rpc_credcache_lock); |
184 | spin_lock(&cache->lock); | ||
171 | for (i = 0; i < RPC_CREDCACHE_NR; i++) { | 185 | for (i = 0; i < RPC_CREDCACHE_NR; i++) { |
172 | head = &cache->hashtable[i]; | 186 | head = &cache->hashtable[i]; |
173 | while (!hlist_empty(head)) { | 187 | while (!hlist_empty(head)) { |
@@ -177,6 +191,7 @@ rpcauth_clear_credcache(struct rpc_cred_cache *cache) | |||
177 | rpcauth_unhash_cred_locked(cred); | 191 | rpcauth_unhash_cred_locked(cred); |
178 | } | 192 | } |
179 | } | 193 | } |
194 | spin_unlock(&cache->lock); | ||
180 | spin_unlock(&rpc_credcache_lock); | 195 | spin_unlock(&rpc_credcache_lock); |
181 | rpcauth_destroy_credlist(&free); | 196 | rpcauth_destroy_credlist(&free); |
182 | } | 197 | } |
@@ -202,6 +217,7 @@ rpcauth_destroy_credcache(struct rpc_auth *auth) | |||
202 | static void | 217 | static void |
203 | rpcauth_prune_expired(struct list_head *free) | 218 | rpcauth_prune_expired(struct list_head *free) |
204 | { | 219 | { |
220 | spinlock_t *cache_lock; | ||
205 | struct rpc_cred *cred; | 221 | struct rpc_cred *cred; |
206 | 222 | ||
207 | while (!list_empty(&cred_unused)) { | 223 | while (!list_empty(&cred_unused)) { |
@@ -212,9 +228,14 @@ rpcauth_prune_expired(struct list_head *free) | |||
212 | list_del_init(&cred->cr_lru); | 228 | list_del_init(&cred->cr_lru); |
213 | if (atomic_read(&cred->cr_count) != 0) | 229 | if (atomic_read(&cred->cr_count) != 0) |
214 | continue; | 230 | continue; |
215 | get_rpccred(cred); | 231 | cache_lock = &cred->cr_auth->au_credcache->lock; |
216 | list_add_tail(&cred->cr_lru, free); | 232 | spin_lock(cache_lock); |
217 | rpcauth_unhash_cred_locked(cred); | 233 | if (atomic_read(&cred->cr_count) == 0) { |
234 | get_rpccred(cred); | ||
235 | list_add_tail(&cred->cr_lru, free); | ||
236 | rpcauth_unhash_cred_locked(cred); | ||
237 | } | ||
238 | spin_unlock(cache_lock); | ||
218 | } | 239 | } |
219 | } | 240 | } |
220 | 241 | ||
@@ -253,21 +274,19 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, | |||
253 | hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) { | 274 | hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) { |
254 | if (!entry->cr_ops->crmatch(acred, entry, flags)) | 275 | if (!entry->cr_ops->crmatch(acred, entry, flags)) |
255 | continue; | 276 | continue; |
256 | spin_lock(&rpc_credcache_lock); | 277 | spin_lock(&cache->lock); |
257 | if (test_bit(RPCAUTH_CRED_HASHED, &entry->cr_flags) == 0) { | 278 | if (test_bit(RPCAUTH_CRED_HASHED, &entry->cr_flags) == 0) { |
258 | spin_unlock(&rpc_credcache_lock); | 279 | spin_unlock(&cache->lock); |
259 | continue; | 280 | continue; |
260 | } | 281 | } |
261 | cred = get_rpccred(entry); | 282 | cred = get_rpccred(entry); |
262 | spin_unlock(&rpc_credcache_lock); | 283 | spin_unlock(&cache->lock); |
263 | break; | 284 | break; |
264 | } | 285 | } |
265 | rcu_read_unlock(); | 286 | rcu_read_unlock(); |
266 | 287 | ||
267 | if (cred != NULL) { | 288 | if (cred != NULL) |
268 | rpcauth_gc_credcache(cache, &free); | ||
269 | goto found; | 289 | goto found; |
270 | } | ||
271 | 290 | ||
272 | new = auth->au_ops->crcreate(auth, acred, flags); | 291 | new = auth->au_ops->crcreate(auth, acred, flags); |
273 | if (IS_ERR(new)) { | 292 | if (IS_ERR(new)) { |
@@ -275,7 +294,7 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, | |||
275 | goto out; | 294 | goto out; |
276 | } | 295 | } |
277 | 296 | ||
278 | spin_lock(&rpc_credcache_lock); | 297 | spin_lock(&cache->lock); |
279 | hlist_for_each_entry(entry, pos, &cache->hashtable[nr], cr_hash) { | 298 | hlist_for_each_entry(entry, pos, &cache->hashtable[nr], cr_hash) { |
280 | if (!entry->cr_ops->crmatch(acred, entry, flags)) | 299 | if (!entry->cr_ops->crmatch(acred, entry, flags)) |
281 | continue; | 300 | continue; |
@@ -288,9 +307,7 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, | |||
288 | hlist_add_head_rcu(&cred->cr_hash, &cache->hashtable[nr]); | 307 | hlist_add_head_rcu(&cred->cr_hash, &cache->hashtable[nr]); |
289 | } else | 308 | } else |
290 | list_add_tail(&new->cr_lru, &free); | 309 | list_add_tail(&new->cr_lru, &free); |
291 | rpcauth_prune_expired(&free); | 310 | spin_unlock(&cache->lock); |
292 | cache->nextgc = jiffies + cache->expire; | ||
293 | spin_unlock(&rpc_credcache_lock); | ||
294 | found: | 311 | found: |
295 | if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags) | 312 | if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags) |
296 | && cred->cr_ops->cr_init != NULL | 313 | && cred->cr_ops->cr_init != NULL |
@@ -301,6 +318,7 @@ found: | |||
301 | cred = ERR_PTR(res); | 318 | cred = ERR_PTR(res); |
302 | } | 319 | } |
303 | } | 320 | } |
321 | rpcauth_gc_credcache(cache, &free); | ||
304 | rpcauth_destroy_credlist(&free); | 322 | rpcauth_destroy_credlist(&free); |
305 | out: | 323 | out: |
306 | return cred; | 324 | return cred; |
@@ -393,7 +411,7 @@ need_lock: | |||
393 | if (!list_empty(&cred->cr_lru)) | 411 | if (!list_empty(&cred->cr_lru)) |
394 | list_del_init(&cred->cr_lru); | 412 | list_del_init(&cred->cr_lru); |
395 | if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0) | 413 | if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0) |
396 | rpcauth_unhash_cred_locked(cred); | 414 | rpcauth_unhash_cred(cred); |
397 | else if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) { | 415 | else if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) { |
398 | cred->cr_expire = jiffies; | 416 | cred->cr_expire = jiffies; |
399 | list_add_tail(&cred->cr_lru, &cred_unused); | 417 | list_add_tail(&cred->cr_lru, &cred_unused); |