Skip to content

Commit 608a0ab

Browse files
trondmyJ. Bruce Fields
authored andcommitted
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>
1 parent 30382d6 commit 608a0ab

File tree

4 files changed

+36
-6
lines changed

4 files changed

+36
-6
lines changed

include/linux/sunrpc/svcauth.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ struct auth_domain {
8282
struct hlist_node hash;
8383
char *name;
8484
struct auth_ops *flavour;
85+
struct rcu_head rcu_head;
8586
};
8687

8788
/*

net/sunrpc/auth_gss/svcauth_gss.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1764,14 +1764,21 @@ svcauth_gss_release(struct svc_rqst *rqstp)
17641764
}
17651765

17661766
static void
1767-
svcauth_gss_domain_release(struct auth_domain *dom)
1767+
svcauth_gss_domain_release_rcu(struct rcu_head *head)
17681768
{
1769+
struct auth_domain *dom = container_of(head, struct auth_domain, rcu_head);
17691770
struct gss_domain *gd = container_of(dom, struct gss_domain, h);
17701771

17711772
kfree(dom->name);
17721773
kfree(gd);
17731774
}
17741775

1776+
static void
1777+
svcauth_gss_domain_release(struct auth_domain *dom)
1778+
{
1779+
call_rcu(&dom->rcu_head, svcauth_gss_domain_release_rcu);
1780+
}
1781+
17751782
static struct auth_ops svcauthops_gss = {
17761783
.name = "rpcsec_gss",
17771784
.owner = THIS_MODULE,

net/sunrpc/svcauth.c

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,11 @@ static struct hlist_head auth_domain_table[DN_HASHMAX];
143143
static DEFINE_SPINLOCK(auth_domain_lock);
144144

145145
static void auth_domain_release(struct kref *kref)
146+
__releases(&auth_domain_lock)
146147
{
147148
struct auth_domain *dom = container_of(kref, struct auth_domain, ref);
148149

149-
hlist_del(&dom->hash);
150+
hlist_del_rcu(&dom->hash);
150151
dom->flavour->domain_release(dom);
151152
spin_unlock(&auth_domain_lock);
152153
}
@@ -175,14 +176,29 @@ auth_domain_lookup(char *name, struct auth_domain *new)
175176
}
176177
}
177178
if (new)
178-
hlist_add_head(&new->hash, head);
179+
hlist_add_head_rcu(&new->hash, head);
179180
spin_unlock(&auth_domain_lock);
180181
return new;
181182
}
182183
EXPORT_SYMBOL_GPL(auth_domain_lookup);
183184

184185
struct auth_domain *auth_domain_find(char *name)
185186
{
186-
return auth_domain_lookup(name, NULL);
187+
struct auth_domain *hp;
188+
struct hlist_head *head;
189+
190+
head = &auth_domain_table[hash_str(name, DN_HASHBITS)];
191+
192+
rcu_read_lock();
193+
hlist_for_each_entry_rcu(hp, head, hash) {
194+
if (strcmp(hp->name, name)==0) {
195+
if (!kref_get_unless_zero(&hp->ref))
196+
hp = NULL;
197+
rcu_read_unlock();
198+
return hp;
199+
}
200+
}
201+
rcu_read_unlock();
202+
return NULL;
187203
}
188204
EXPORT_SYMBOL_GPL(auth_domain_find);

net/sunrpc/svcauth_unix.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,20 +37,26 @@ struct unix_domain {
3737
extern struct auth_ops svcauth_null;
3838
extern struct auth_ops svcauth_unix;
3939

40-
static void svcauth_unix_domain_release(struct auth_domain *dom)
40+
static void svcauth_unix_domain_release_rcu(struct rcu_head *head)
4141
{
42+
struct auth_domain *dom = container_of(head, struct auth_domain, rcu_head);
4243
struct unix_domain *ud = container_of(dom, struct unix_domain, h);
4344

4445
kfree(dom->name);
4546
kfree(ud);
4647
}
4748

49+
static void svcauth_unix_domain_release(struct auth_domain *dom)
50+
{
51+
call_rcu(&dom->rcu_head, svcauth_unix_domain_release_rcu);
52+
}
53+
4854
struct auth_domain *unix_domain_find(char *name)
4955
{
5056
struct auth_domain *rv;
5157
struct unix_domain *new = NULL;
5258

53-
rv = auth_domain_lookup(name, NULL);
59+
rv = auth_domain_find(name);
5460
while(1) {
5561
if (rv) {
5662
if (new && rv != &new->h)

0 commit comments

Comments
 (0)