aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/sunrpc/auth.h3
-rw-r--r--net/sunrpc/auth.c46
-rw-r--r--net/sunrpc/auth_unix.c5
-rw-r--r--net/sunrpc/sunrpc_syms.c1
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)
64struct rpc_cred_cache { 64struct 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 {
126extern const struct rpc_authops authunix_ops; 127extern const struct rpc_authops authunix_ops;
127extern const struct rpc_authops authnull_ops; 128extern const struct rpc_authops authnull_ops;
128 129
130void __init rpc_init_authunix(void);
131
129int rpcauth_register(const struct rpc_authops *); 132int rpcauth_register(const struct rpc_authops *);
130int rpcauth_unregister(const struct rpc_authops *); 133int rpcauth_unregister(const struct rpc_authops *);
131struct rpc_auth * rpcauth_create(rpc_authflavor_t, struct rpc_clnt *); 134struct 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
123static void
124rpcauth_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)
202static void 217static void
203rpcauth_prune_expired(struct list_head *free) 218rpcauth_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);
294found: 311found:
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);
305out: 323out:
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
216void __init rpc_init_authunix(void)
217{
218 spin_lock_init(&unix_cred_cache.lock);
219}
220
216const struct rpc_authops authunix_ops = { 221const 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();
155out: 156out:
156 return err; 157 return err;
157} 158}