Commit 9499b434 authored by Trond Myklebust's avatar Trond Myklebust

SUNRPC: Give credential cache a local spinlock

Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 31be5bf1
...@@ -63,6 +63,7 @@ struct rpc_cred { ...@@ -63,6 +63,7 @@ struct rpc_cred {
#define RPC_CREDCACHE_MASK (RPC_CREDCACHE_NR - 1) #define RPC_CREDCACHE_MASK (RPC_CREDCACHE_NR - 1)
struct rpc_cred_cache { struct rpc_cred_cache {
struct hlist_head hashtable[RPC_CREDCACHE_NR]; struct hlist_head hashtable[RPC_CREDCACHE_NR];
spinlock_t lock;
unsigned long nextgc; /* next garbage collection */ unsigned long nextgc; /* next garbage collection */
unsigned long expire; /* cache expiry interval */ unsigned long expire; /* cache expiry interval */
}; };
...@@ -126,6 +127,8 @@ struct rpc_credops { ...@@ -126,6 +127,8 @@ struct rpc_credops {
extern const struct rpc_authops authunix_ops; extern const struct rpc_authops authunix_ops;
extern const struct rpc_authops authnull_ops; extern const struct rpc_authops authnull_ops;
void __init rpc_init_authunix(void);
int rpcauth_register(const struct rpc_authops *); int rpcauth_register(const struct rpc_authops *);
int rpcauth_unregister(const struct rpc_authops *); int rpcauth_unregister(const struct rpc_authops *);
struct rpc_auth * rpcauth_create(rpc_authflavor_t, struct rpc_clnt *); struct rpc_auth * rpcauth_create(rpc_authflavor_t, struct rpc_clnt *);
......
...@@ -120,6 +120,18 @@ rpcauth_unhash_cred_locked(struct rpc_cred *cred) ...@@ -120,6 +120,18 @@ rpcauth_unhash_cred_locked(struct rpc_cred *cred)
clear_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags); clear_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags);
} }
static void
rpcauth_unhash_cred(struct rpc_cred *cred)
{
spinlock_t *cache_lock;
cache_lock = &cred->cr_auth->au_credcache->lock;
spin_lock(cache_lock);
if (atomic_read(&cred->cr_count) == 0)
rpcauth_unhash_cred_locked(cred);
spin_unlock(cache_lock);
}
/* /*
* Initialize RPC credential cache * Initialize RPC credential cache
*/ */
...@@ -134,6 +146,7 @@ rpcauth_init_credcache(struct rpc_auth *auth, unsigned long expire) ...@@ -134,6 +146,7 @@ rpcauth_init_credcache(struct rpc_auth *auth, unsigned long expire)
return -ENOMEM; return -ENOMEM;
for (i = 0; i < RPC_CREDCACHE_NR; i++) for (i = 0; i < RPC_CREDCACHE_NR; i++)
INIT_HLIST_HEAD(&new->hashtable[i]); INIT_HLIST_HEAD(&new->hashtable[i]);
spin_lock_init(&new->lock);
new->expire = expire; new->expire = expire;
new->nextgc = jiffies + (expire >> 1); new->nextgc = jiffies + (expire >> 1);
auth->au_credcache = new; auth->au_credcache = new;
...@@ -168,6 +181,7 @@ rpcauth_clear_credcache(struct rpc_cred_cache *cache) ...@@ -168,6 +181,7 @@ rpcauth_clear_credcache(struct rpc_cred_cache *cache)
int i; int i;
spin_lock(&rpc_credcache_lock); spin_lock(&rpc_credcache_lock);
spin_lock(&cache->lock);
for (i = 0; i < RPC_CREDCACHE_NR; i++) { for (i = 0; i < RPC_CREDCACHE_NR; i++) {
head = &cache->hashtable[i]; head = &cache->hashtable[i];
while (!hlist_empty(head)) { while (!hlist_empty(head)) {
...@@ -177,6 +191,7 @@ rpcauth_clear_credcache(struct rpc_cred_cache *cache) ...@@ -177,6 +191,7 @@ rpcauth_clear_credcache(struct rpc_cred_cache *cache)
rpcauth_unhash_cred_locked(cred); rpcauth_unhash_cred_locked(cred);
} }
} }
spin_unlock(&cache->lock);
spin_unlock(&rpc_credcache_lock); spin_unlock(&rpc_credcache_lock);
rpcauth_destroy_credlist(&free); rpcauth_destroy_credlist(&free);
} }
...@@ -202,6 +217,7 @@ rpcauth_destroy_credcache(struct rpc_auth *auth) ...@@ -202,6 +217,7 @@ rpcauth_destroy_credcache(struct rpc_auth *auth)
static void static void
rpcauth_prune_expired(struct list_head *free) rpcauth_prune_expired(struct list_head *free)
{ {
spinlock_t *cache_lock;
struct rpc_cred *cred; struct rpc_cred *cred;
while (!list_empty(&cred_unused)) { while (!list_empty(&cred_unused)) {
...@@ -212,9 +228,14 @@ rpcauth_prune_expired(struct list_head *free) ...@@ -212,9 +228,14 @@ rpcauth_prune_expired(struct list_head *free)
list_del_init(&cred->cr_lru); list_del_init(&cred->cr_lru);
if (atomic_read(&cred->cr_count) != 0) if (atomic_read(&cred->cr_count) != 0)
continue; continue;
get_rpccred(cred); cache_lock = &cred->cr_auth->au_credcache->lock;
list_add_tail(&cred->cr_lru, free); spin_lock(cache_lock);
rpcauth_unhash_cred_locked(cred); if (atomic_read(&cred->cr_count) == 0) {
get_rpccred(cred);
list_add_tail(&cred->cr_lru, free);
rpcauth_unhash_cred_locked(cred);
}
spin_unlock(cache_lock);
} }
} }
...@@ -253,21 +274,19 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, ...@@ -253,21 +274,19 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) { hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) {
if (!entry->cr_ops->crmatch(acred, entry, flags)) if (!entry->cr_ops->crmatch(acred, entry, flags))
continue; continue;
spin_lock(&rpc_credcache_lock); spin_lock(&cache->lock);
if (test_bit(RPCAUTH_CRED_HASHED, &entry->cr_flags) == 0) { if (test_bit(RPCAUTH_CRED_HASHED, &entry->cr_flags) == 0) {
spin_unlock(&rpc_credcache_lock); spin_unlock(&cache->lock);
continue; continue;
} }
cred = get_rpccred(entry); cred = get_rpccred(entry);
spin_unlock(&rpc_credcache_lock); spin_unlock(&cache->lock);
break; break;
} }
rcu_read_unlock(); rcu_read_unlock();
if (cred != NULL) { if (cred != NULL)
rpcauth_gc_credcache(cache, &free);
goto found; goto found;
}
new = auth->au_ops->crcreate(auth, acred, flags); new = auth->au_ops->crcreate(auth, acred, flags);
if (IS_ERR(new)) { if (IS_ERR(new)) {
...@@ -275,7 +294,7 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, ...@@ -275,7 +294,7 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
goto out; goto out;
} }
spin_lock(&rpc_credcache_lock); spin_lock(&cache->lock);
hlist_for_each_entry(entry, pos, &cache->hashtable[nr], cr_hash) { hlist_for_each_entry(entry, pos, &cache->hashtable[nr], cr_hash) {
if (!entry->cr_ops->crmatch(acred, entry, flags)) if (!entry->cr_ops->crmatch(acred, entry, flags))
continue; continue;
...@@ -288,9 +307,7 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, ...@@ -288,9 +307,7 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
hlist_add_head_rcu(&cred->cr_hash, &cache->hashtable[nr]); hlist_add_head_rcu(&cred->cr_hash, &cache->hashtable[nr]);
} else } else
list_add_tail(&new->cr_lru, &free); list_add_tail(&new->cr_lru, &free);
rpcauth_prune_expired(&free); spin_unlock(&cache->lock);
cache->nextgc = jiffies + cache->expire;
spin_unlock(&rpc_credcache_lock);
found: found:
if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags) if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags)
&& cred->cr_ops->cr_init != NULL && cred->cr_ops->cr_init != NULL
...@@ -301,6 +318,7 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, ...@@ -301,6 +318,7 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
cred = ERR_PTR(res); cred = ERR_PTR(res);
} }
} }
rpcauth_gc_credcache(cache, &free);
rpcauth_destroy_credlist(&free); rpcauth_destroy_credlist(&free);
out: out:
return cred; return cred;
...@@ -393,7 +411,7 @@ put_rpccred(struct rpc_cred *cred) ...@@ -393,7 +411,7 @@ put_rpccred(struct rpc_cred *cred)
if (!list_empty(&cred->cr_lru)) if (!list_empty(&cred->cr_lru))
list_del_init(&cred->cr_lru); list_del_init(&cred->cr_lru);
if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0) if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0)
rpcauth_unhash_cred_locked(cred); rpcauth_unhash_cred(cred);
else if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) { else if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) {
cred->cr_expire = jiffies; cred->cr_expire = jiffies;
list_add_tail(&cred->cr_lru, &cred_unused); list_add_tail(&cred->cr_lru, &cred_unused);
......
...@@ -213,6 +213,11 @@ unx_validate(struct rpc_task *task, __be32 *p) ...@@ -213,6 +213,11 @@ unx_validate(struct rpc_task *task, __be32 *p)
return p; return p;
} }
void __init rpc_init_authunix(void)
{
spin_lock_init(&unix_cred_cache.lock);
}
const struct rpc_authops authunix_ops = { const struct rpc_authops authunix_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.au_flavor = RPC_AUTH_UNIX, .au_flavor = RPC_AUTH_UNIX,
......
...@@ -152,6 +152,7 @@ init_sunrpc(void) ...@@ -152,6 +152,7 @@ init_sunrpc(void)
cache_register(&ip_map_cache); cache_register(&ip_map_cache);
cache_register(&unix_gid_cache); cache_register(&unix_gid_cache);
init_socket_xprt(); init_socket_xprt();
rpc_init_authunix();
out: out:
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment