mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 20:54:10 +08:00
SUNRPC: Add lockless lookup of the server's auth domain
Avoid taking the global auth_domain_lock in most lookups of the auth domain by adding an RCU protected lookup. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
parent
30382d6ce5
commit
608a0ab2f5
@ -82,6 +82,7 @@ struct auth_domain {
|
|||||||
struct hlist_node hash;
|
struct hlist_node hash;
|
||||||
char *name;
|
char *name;
|
||||||
struct auth_ops *flavour;
|
struct auth_ops *flavour;
|
||||||
|
struct rcu_head rcu_head;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1764,14 +1764,21 @@ out_err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
svcauth_gss_domain_release(struct auth_domain *dom)
|
svcauth_gss_domain_release_rcu(struct rcu_head *head)
|
||||||
{
|
{
|
||||||
|
struct auth_domain *dom = container_of(head, struct auth_domain, rcu_head);
|
||||||
struct gss_domain *gd = container_of(dom, struct gss_domain, h);
|
struct gss_domain *gd = container_of(dom, struct gss_domain, h);
|
||||||
|
|
||||||
kfree(dom->name);
|
kfree(dom->name);
|
||||||
kfree(gd);
|
kfree(gd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
svcauth_gss_domain_release(struct auth_domain *dom)
|
||||||
|
{
|
||||||
|
call_rcu(&dom->rcu_head, svcauth_gss_domain_release_rcu);
|
||||||
|
}
|
||||||
|
|
||||||
static struct auth_ops svcauthops_gss = {
|
static struct auth_ops svcauthops_gss = {
|
||||||
.name = "rpcsec_gss",
|
.name = "rpcsec_gss",
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
|
@ -143,10 +143,11 @@ static struct hlist_head auth_domain_table[DN_HASHMAX];
|
|||||||
static DEFINE_SPINLOCK(auth_domain_lock);
|
static DEFINE_SPINLOCK(auth_domain_lock);
|
||||||
|
|
||||||
static void auth_domain_release(struct kref *kref)
|
static void auth_domain_release(struct kref *kref)
|
||||||
|
__releases(&auth_domain_lock)
|
||||||
{
|
{
|
||||||
struct auth_domain *dom = container_of(kref, struct auth_domain, ref);
|
struct auth_domain *dom = container_of(kref, struct auth_domain, ref);
|
||||||
|
|
||||||
hlist_del(&dom->hash);
|
hlist_del_rcu(&dom->hash);
|
||||||
dom->flavour->domain_release(dom);
|
dom->flavour->domain_release(dom);
|
||||||
spin_unlock(&auth_domain_lock);
|
spin_unlock(&auth_domain_lock);
|
||||||
}
|
}
|
||||||
@ -175,7 +176,7 @@ auth_domain_lookup(char *name, struct auth_domain *new)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (new)
|
if (new)
|
||||||
hlist_add_head(&new->hash, head);
|
hlist_add_head_rcu(&new->hash, head);
|
||||||
spin_unlock(&auth_domain_lock);
|
spin_unlock(&auth_domain_lock);
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
@ -183,6 +184,21 @@ EXPORT_SYMBOL_GPL(auth_domain_lookup);
|
|||||||
|
|
||||||
struct auth_domain *auth_domain_find(char *name)
|
struct auth_domain *auth_domain_find(char *name)
|
||||||
{
|
{
|
||||||
return auth_domain_lookup(name, NULL);
|
struct auth_domain *hp;
|
||||||
|
struct hlist_head *head;
|
||||||
|
|
||||||
|
head = &auth_domain_table[hash_str(name, DN_HASHBITS)];
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
hlist_for_each_entry_rcu(hp, head, hash) {
|
||||||
|
if (strcmp(hp->name, name)==0) {
|
||||||
|
if (!kref_get_unless_zero(&hp->ref))
|
||||||
|
hp = NULL;
|
||||||
|
rcu_read_unlock();
|
||||||
|
return hp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(auth_domain_find);
|
EXPORT_SYMBOL_GPL(auth_domain_find);
|
||||||
|
@ -37,20 +37,26 @@ struct unix_domain {
|
|||||||
extern struct auth_ops svcauth_null;
|
extern struct auth_ops svcauth_null;
|
||||||
extern struct auth_ops svcauth_unix;
|
extern struct auth_ops svcauth_unix;
|
||||||
|
|
||||||
static void svcauth_unix_domain_release(struct auth_domain *dom)
|
static void svcauth_unix_domain_release_rcu(struct rcu_head *head)
|
||||||
{
|
{
|
||||||
|
struct auth_domain *dom = container_of(head, struct auth_domain, rcu_head);
|
||||||
struct unix_domain *ud = container_of(dom, struct unix_domain, h);
|
struct unix_domain *ud = container_of(dom, struct unix_domain, h);
|
||||||
|
|
||||||
kfree(dom->name);
|
kfree(dom->name);
|
||||||
kfree(ud);
|
kfree(ud);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void svcauth_unix_domain_release(struct auth_domain *dom)
|
||||||
|
{
|
||||||
|
call_rcu(&dom->rcu_head, svcauth_unix_domain_release_rcu);
|
||||||
|
}
|
||||||
|
|
||||||
struct auth_domain *unix_domain_find(char *name)
|
struct auth_domain *unix_domain_find(char *name)
|
||||||
{
|
{
|
||||||
struct auth_domain *rv;
|
struct auth_domain *rv;
|
||||||
struct unix_domain *new = NULL;
|
struct unix_domain *new = NULL;
|
||||||
|
|
||||||
rv = auth_domain_lookup(name, NULL);
|
rv = auth_domain_find(name);
|
||||||
while(1) {
|
while(1) {
|
||||||
if (rv) {
|
if (rv) {
|
||||||
if (new && rv != &new->h)
|
if (new && rv != &new->h)
|
||||||
|
Loading…
Reference in New Issue
Block a user