diff options
author | Trond Myklebust <trondmy@gmail.com> | 2018-10-01 10:41:46 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2018-10-29 16:58:04 -0400 |
commit | fd5d2f78261bedd3a40feb1474323fddb88398b8 (patch) | |
tree | de1a93af7e4de2f134640a10f8e1bdc42bb106fe | |
parent | ae74136b4bb64440a55117e12065b8c282ab6c1a (diff) |
SUNRPC: Make server side AUTH_UNIX use lockless lookups
Convert structs ip_map and unix_gid to use RCU protected lookups.
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r-- | net/sunrpc/svcauth_unix.c | 14 |
1 files changed, 8 insertions, 6 deletions
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 84cf39021a03..fb9041b92f72 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c | |||
@@ -97,6 +97,7 @@ struct ip_map { | |||
97 | char m_class[8]; /* e.g. "nfsd" */ | 97 | char m_class[8]; /* e.g. "nfsd" */ |
98 | struct in6_addr m_addr; | 98 | struct in6_addr m_addr; |
99 | struct unix_domain *m_client; | 99 | struct unix_domain *m_client; |
100 | struct rcu_head m_rcu; | ||
100 | }; | 101 | }; |
101 | 102 | ||
102 | static void ip_map_put(struct kref *kref) | 103 | static void ip_map_put(struct kref *kref) |
@@ -107,7 +108,7 @@ static void ip_map_put(struct kref *kref) | |||
107 | if (test_bit(CACHE_VALID, &item->flags) && | 108 | if (test_bit(CACHE_VALID, &item->flags) && |
108 | !test_bit(CACHE_NEGATIVE, &item->flags)) | 109 | !test_bit(CACHE_NEGATIVE, &item->flags)) |
109 | auth_domain_put(&im->m_client->h); | 110 | auth_domain_put(&im->m_client->h); |
110 | kfree(im); | 111 | kfree_rcu(im, m_rcu); |
111 | } | 112 | } |
112 | 113 | ||
113 | static inline int hash_ip6(const struct in6_addr *ip) | 114 | static inline int hash_ip6(const struct in6_addr *ip) |
@@ -286,9 +287,9 @@ static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class, | |||
286 | 287 | ||
287 | strcpy(ip.m_class, class); | 288 | strcpy(ip.m_class, class); |
288 | ip.m_addr = *addr; | 289 | ip.m_addr = *addr; |
289 | ch = sunrpc_cache_lookup(cd, &ip.h, | 290 | ch = sunrpc_cache_lookup_rcu(cd, &ip.h, |
290 | hash_str(class, IP_HASHBITS) ^ | 291 | hash_str(class, IP_HASHBITS) ^ |
291 | hash_ip6(addr)); | 292 | hash_ip6(addr)); |
292 | 293 | ||
293 | if (ch) | 294 | if (ch) |
294 | return container_of(ch, struct ip_map, h); | 295 | return container_of(ch, struct ip_map, h); |
@@ -418,6 +419,7 @@ struct unix_gid { | |||
418 | struct cache_head h; | 419 | struct cache_head h; |
419 | kuid_t uid; | 420 | kuid_t uid; |
420 | struct group_info *gi; | 421 | struct group_info *gi; |
422 | struct rcu_head rcu; | ||
421 | }; | 423 | }; |
422 | 424 | ||
423 | static int unix_gid_hash(kuid_t uid) | 425 | static int unix_gid_hash(kuid_t uid) |
@@ -432,7 +434,7 @@ static void unix_gid_put(struct kref *kref) | |||
432 | if (test_bit(CACHE_VALID, &item->flags) && | 434 | if (test_bit(CACHE_VALID, &item->flags) && |
433 | !test_bit(CACHE_NEGATIVE, &item->flags)) | 435 | !test_bit(CACHE_NEGATIVE, &item->flags)) |
434 | put_group_info(ug->gi); | 436 | put_group_info(ug->gi); |
435 | kfree(ug); | 437 | kfree_rcu(ug, rcu); |
436 | } | 438 | } |
437 | 439 | ||
438 | static int unix_gid_match(struct cache_head *corig, struct cache_head *cnew) | 440 | static int unix_gid_match(struct cache_head *corig, struct cache_head *cnew) |
@@ -625,7 +627,7 @@ static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, kuid_t uid) | |||
625 | struct cache_head *ch; | 627 | struct cache_head *ch; |
626 | 628 | ||
627 | ug.uid = uid; | 629 | ug.uid = uid; |
628 | ch = sunrpc_cache_lookup(cd, &ug.h, unix_gid_hash(uid)); | 630 | ch = sunrpc_cache_lookup_rcu(cd, &ug.h, unix_gid_hash(uid)); |
629 | if (ch) | 631 | if (ch) |
630 | return container_of(ch, struct unix_gid, h); | 632 | return container_of(ch, struct unix_gid, h); |
631 | else | 633 | else |