diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-06-24 15:57:57 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-07-10 23:40:36 -0400 |
commit | 9499b4341b56935f61af9e7e354e7d11e70f5258 (patch) | |
tree | d6ef7a4608e405aef3d270a641fa1f2cbaed6c7d | |
parent | 31be5bf15f3dafffce110eb1afadccbf2e3067b4 (diff) |
SUNRPC: Give credential cache a local spinlock
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r-- | include/linux/sunrpc/auth.h | 3 | ||||
-rw-r--r-- | net/sunrpc/auth.c | 46 | ||||
-rw-r--r-- | net/sunrpc/auth_unix.c | 5 | ||||
-rw-r--r-- | net/sunrpc/sunrpc_syms.c | 1 |
4 files changed, 41 insertions, 14 deletions
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h index 5974e8a493c4..e5a3b5141ed2 100644 --- a/include/linux/sunrpc/auth.h +++ b/include/linux/sunrpc/auth.h | |||
@@ -63,6 +63,7 @@ struct rpc_cred { | |||
63 | #define RPC_CREDCACHE_MASK (RPC_CREDCACHE_NR - 1) | 63 | #define RPC_CREDCACHE_MASK (RPC_CREDCACHE_NR - 1) |
64 | struct rpc_cred_cache { | 64 | struct rpc_cred_cache { |
65 | struct hlist_head hashtable[RPC_CREDCACHE_NR]; | 65 | struct hlist_head hashtable[RPC_CREDCACHE_NR]; |
66 | spinlock_t lock; | ||
66 | unsigned long nextgc; /* next garbage collection */ | 67 | unsigned long nextgc; /* next garbage collection */ |
67 | unsigned long expire; /* cache expiry interval */ | 68 | unsigned long expire; /* cache expiry interval */ |
68 | }; | 69 | }; |
@@ -126,6 +127,8 @@ struct rpc_credops { | |||
126 | extern const struct rpc_authops authunix_ops; | 127 | extern const struct rpc_authops authunix_ops; |
127 | extern const struct rpc_authops authnull_ops; | 128 | extern const struct rpc_authops authnull_ops; |
128 | 129 | ||
130 | void __init rpc_init_authunix(void); | ||
131 | |||
129 | int rpcauth_register(const struct rpc_authops *); | 132 | int rpcauth_register(const struct rpc_authops *); |
130 | int rpcauth_unregister(const struct rpc_authops *); | 133 | int rpcauth_unregister(const struct rpc_authops *); |
131 | struct rpc_auth * rpcauth_create(rpc_authflavor_t, struct rpc_clnt *); | 134 | struct rpc_auth * rpcauth_create(rpc_authflavor_t, struct rpc_clnt *); |
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index ad7bde2c437e..cf1198d10ee9 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); |
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index f7ff6ad3259e..205878a3caa5 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c | |||
@@ -213,6 +213,11 @@ unx_validate(struct rpc_task *task, __be32 *p) | |||
213 | return p; | 213 | return p; |
214 | } | 214 | } |
215 | 215 | ||
216 | void __init rpc_init_authunix(void) | ||
217 | { | ||
218 | spin_lock_init(&unix_cred_cache.lock); | ||
219 | } | ||
220 | |||
216 | const struct rpc_authops authunix_ops = { | 221 | const struct rpc_authops authunix_ops = { |
217 | .owner = THIS_MODULE, | 222 | .owner = THIS_MODULE, |
218 | .au_flavor = RPC_AUTH_UNIX, | 223 | .au_flavor = RPC_AUTH_UNIX, |
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 3e19e7af6799..018065fca84b 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c | |||
@@ -152,6 +152,7 @@ init_sunrpc(void) | |||
152 | cache_register(&ip_map_cache); | 152 | cache_register(&ip_map_cache); |
153 | cache_register(&unix_gid_cache); | 153 | cache_register(&unix_gid_cache); |
154 | init_socket_xprt(); | 154 | init_socket_xprt(); |
155 | rpc_init_authunix(); | ||
155 | out: | 156 | out: |
156 | return err; | 157 | return err; |
157 | } | 158 | } |