diff options
author | Trond Myklebust <trondmy@gmail.com> | 2018-10-01 10:41:48 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2018-10-29 16:58:04 -0400 |
commit | 6d1616b26cd91f2502111d098cd9c288dbafe5c8 (patch) | |
tree | 85d9039a2c1288cdbccafa18f387bcfb40ae441e | |
parent | 9ceddd9da13434a5906255c0fc528c385aded283 (diff) |
SUNRPC: Lockless server RPCSEC_GSS context lookup
Use RCU protection for looking up the RPCSEC_GSS context.
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r-- | net/sunrpc/auth_gss/svcauth_gss.c | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 87c71fb0f0ea..1ece4bc3eb8d 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
@@ -76,6 +76,7 @@ struct rsi { | |||
76 | struct xdr_netobj in_handle, in_token; | 76 | struct xdr_netobj in_handle, in_token; |
77 | struct xdr_netobj out_handle, out_token; | 77 | struct xdr_netobj out_handle, out_token; |
78 | int major_status, minor_status; | 78 | int major_status, minor_status; |
79 | struct rcu_head rcu_head; | ||
79 | }; | 80 | }; |
80 | 81 | ||
81 | static struct rsi *rsi_update(struct cache_detail *cd, struct rsi *new, struct rsi *old); | 82 | static struct rsi *rsi_update(struct cache_detail *cd, struct rsi *new, struct rsi *old); |
@@ -89,13 +90,21 @@ static void rsi_free(struct rsi *rsii) | |||
89 | kfree(rsii->out_token.data); | 90 | kfree(rsii->out_token.data); |
90 | } | 91 | } |
91 | 92 | ||
92 | static void rsi_put(struct kref *ref) | 93 | static void rsi_free_rcu(struct rcu_head *head) |
93 | { | 94 | { |
94 | struct rsi *rsii = container_of(ref, struct rsi, h.ref); | 95 | struct rsi *rsii = container_of(head, struct rsi, rcu_head); |
96 | |||
95 | rsi_free(rsii); | 97 | rsi_free(rsii); |
96 | kfree(rsii); | 98 | kfree(rsii); |
97 | } | 99 | } |
98 | 100 | ||
101 | static void rsi_put(struct kref *ref) | ||
102 | { | ||
103 | struct rsi *rsii = container_of(ref, struct rsi, h.ref); | ||
104 | |||
105 | call_rcu(&rsii->rcu_head, rsi_free_rcu); | ||
106 | } | ||
107 | |||
99 | static inline int rsi_hash(struct rsi *item) | 108 | static inline int rsi_hash(struct rsi *item) |
100 | { | 109 | { |
101 | return hash_mem(item->in_handle.data, item->in_handle.len, RSI_HASHBITS) | 110 | return hash_mem(item->in_handle.data, item->in_handle.len, RSI_HASHBITS) |
@@ -282,7 +291,7 @@ static struct rsi *rsi_lookup(struct cache_detail *cd, struct rsi *item) | |||
282 | struct cache_head *ch; | 291 | struct cache_head *ch; |
283 | int hash = rsi_hash(item); | 292 | int hash = rsi_hash(item); |
284 | 293 | ||
285 | ch = sunrpc_cache_lookup(cd, &item->h, hash); | 294 | ch = sunrpc_cache_lookup_rcu(cd, &item->h, hash); |
286 | if (ch) | 295 | if (ch) |
287 | return container_of(ch, struct rsi, h); | 296 | return container_of(ch, struct rsi, h); |
288 | else | 297 | else |
@@ -330,6 +339,7 @@ struct rsc { | |||
330 | struct svc_cred cred; | 339 | struct svc_cred cred; |
331 | struct gss_svc_seq_data seqdata; | 340 | struct gss_svc_seq_data seqdata; |
332 | struct gss_ctx *mechctx; | 341 | struct gss_ctx *mechctx; |
342 | struct rcu_head rcu_head; | ||
333 | }; | 343 | }; |
334 | 344 | ||
335 | static struct rsc *rsc_update(struct cache_detail *cd, struct rsc *new, struct rsc *old); | 345 | static struct rsc *rsc_update(struct cache_detail *cd, struct rsc *new, struct rsc *old); |
@@ -343,12 +353,22 @@ static void rsc_free(struct rsc *rsci) | |||
343 | free_svc_cred(&rsci->cred); | 353 | free_svc_cred(&rsci->cred); |
344 | } | 354 | } |
345 | 355 | ||
356 | static void rsc_free_rcu(struct rcu_head *head) | ||
357 | { | ||
358 | struct rsc *rsci = container_of(head, struct rsc, rcu_head); | ||
359 | |||
360 | kfree(rsci->handle.data); | ||
361 | kfree(rsci); | ||
362 | } | ||
363 | |||
346 | static void rsc_put(struct kref *ref) | 364 | static void rsc_put(struct kref *ref) |
347 | { | 365 | { |
348 | struct rsc *rsci = container_of(ref, struct rsc, h.ref); | 366 | struct rsc *rsci = container_of(ref, struct rsc, h.ref); |
349 | 367 | ||
350 | rsc_free(rsci); | 368 | if (rsci->mechctx) |
351 | kfree(rsci); | 369 | gss_delete_sec_context(&rsci->mechctx); |
370 | free_svc_cred(&rsci->cred); | ||
371 | call_rcu(&rsci->rcu_head, rsc_free_rcu); | ||
352 | } | 372 | } |
353 | 373 | ||
354 | static inline int | 374 | static inline int |
@@ -542,7 +562,7 @@ static struct rsc *rsc_lookup(struct cache_detail *cd, struct rsc *item) | |||
542 | struct cache_head *ch; | 562 | struct cache_head *ch; |
543 | int hash = rsc_hash(item); | 563 | int hash = rsc_hash(item); |
544 | 564 | ||
545 | ch = sunrpc_cache_lookup(cd, &item->h, hash); | 565 | ch = sunrpc_cache_lookup_rcu(cd, &item->h, hash); |
546 | if (ch) | 566 | if (ch) |
547 | return container_of(ch, struct rsc, h); | 567 | return container_of(ch, struct rsc, h); |
548 | else | 568 | else |