diff options
| -rw-r--r-- | include/linux/sunrpc/auth.h | 2 | ||||
| -rw-r--r-- | net/sunrpc/auth.c | 17 | ||||
| -rw-r--r-- | net/sunrpc/auth_generic.c | 6 | ||||
| -rw-r--r-- | net/sunrpc/auth_null.c | 2 |
4 files changed, 25 insertions, 2 deletions
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h index c683b9a06913..8e030075fe79 100644 --- a/include/linux/sunrpc/auth.h +++ b/include/linux/sunrpc/auth.h | |||
| @@ -103,6 +103,7 @@ struct rpc_auth_create_args { | |||
| 103 | 103 | ||
| 104 | /* Flags for rpcauth_lookupcred() */ | 104 | /* Flags for rpcauth_lookupcred() */ |
| 105 | #define RPCAUTH_LOOKUP_NEW 0x01 /* Accept an uninitialised cred */ | 105 | #define RPCAUTH_LOOKUP_NEW 0x01 /* Accept an uninitialised cred */ |
| 106 | #define RPCAUTH_LOOKUP_RCU 0x02 /* lock-less lookup */ | ||
| 106 | 107 | ||
| 107 | /* | 108 | /* |
| 108 | * Client authentication ops | 109 | * Client authentication ops |
| @@ -154,6 +155,7 @@ void rpc_destroy_generic_auth(void); | |||
| 154 | void rpc_destroy_authunix(void); | 155 | void rpc_destroy_authunix(void); |
| 155 | 156 | ||
| 156 | struct rpc_cred * rpc_lookup_cred(void); | 157 | struct rpc_cred * rpc_lookup_cred(void); |
| 158 | struct rpc_cred * rpc_lookup_cred_nonblock(void); | ||
| 157 | struct rpc_cred * rpc_lookup_machine_cred(const char *service_name); | 159 | struct rpc_cred * rpc_lookup_machine_cred(const char *service_name); |
| 158 | int rpcauth_register(const struct rpc_authops *); | 160 | int rpcauth_register(const struct rpc_authops *); |
| 159 | int rpcauth_unregister(const struct rpc_authops *); | 161 | int rpcauth_unregister(const struct rpc_authops *); |
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 360decdddc78..24fcbd23ae6c 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
| @@ -557,6 +557,12 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, | |||
| 557 | hlist_for_each_entry_rcu(entry, &cache->hashtable[nr], cr_hash) { | 557 | hlist_for_each_entry_rcu(entry, &cache->hashtable[nr], cr_hash) { |
| 558 | if (!entry->cr_ops->crmatch(acred, entry, flags)) | 558 | if (!entry->cr_ops->crmatch(acred, entry, flags)) |
| 559 | continue; | 559 | continue; |
| 560 | if (flags & RPCAUTH_LOOKUP_RCU) { | ||
| 561 | if (test_bit(RPCAUTH_CRED_HASHED, &entry->cr_flags) && | ||
| 562 | !test_bit(RPCAUTH_CRED_NEW, &entry->cr_flags)) | ||
| 563 | cred = entry; | ||
| 564 | break; | ||
| 565 | } | ||
| 560 | spin_lock(&cache->lock); | 566 | spin_lock(&cache->lock); |
| 561 | if (test_bit(RPCAUTH_CRED_HASHED, &entry->cr_flags) == 0) { | 567 | if (test_bit(RPCAUTH_CRED_HASHED, &entry->cr_flags) == 0) { |
| 562 | spin_unlock(&cache->lock); | 568 | spin_unlock(&cache->lock); |
| @@ -571,6 +577,9 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, | |||
| 571 | if (cred != NULL) | 577 | if (cred != NULL) |
| 572 | goto found; | 578 | goto found; |
| 573 | 579 | ||
| 580 | if (flags & RPCAUTH_LOOKUP_RCU) | ||
| 581 | return ERR_PTR(-ECHILD); | ||
| 582 | |||
| 574 | new = auth->au_ops->crcreate(auth, acred, flags); | 583 | new = auth->au_ops->crcreate(auth, acred, flags); |
| 575 | if (IS_ERR(new)) { | 584 | if (IS_ERR(new)) { |
| 576 | cred = new; | 585 | cred = new; |
| @@ -621,10 +630,14 @@ rpcauth_lookupcred(struct rpc_auth *auth, int flags) | |||
| 621 | memset(&acred, 0, sizeof(acred)); | 630 | memset(&acred, 0, sizeof(acred)); |
| 622 | acred.uid = cred->fsuid; | 631 | acred.uid = cred->fsuid; |
| 623 | acred.gid = cred->fsgid; | 632 | acred.gid = cred->fsgid; |
| 624 | acred.group_info = get_group_info(((struct cred *)cred)->group_info); | 633 | if (flags & RPCAUTH_LOOKUP_RCU) |
| 634 | acred.group_info = rcu_dereference(cred->group_info); | ||
| 635 | else | ||
| 636 | acred.group_info = get_group_info(((struct cred *)cred)->group_info); | ||
| 625 | 637 | ||
| 626 | ret = auth->au_ops->lookup_cred(auth, &acred, flags); | 638 | ret = auth->au_ops->lookup_cred(auth, &acred, flags); |
| 627 | put_group_info(acred.group_info); | 639 | if (!(flags & RPCAUTH_LOOKUP_RCU)) |
| 640 | put_group_info(acred.group_info); | ||
| 628 | return ret; | 641 | return ret; |
| 629 | } | 642 | } |
| 630 | EXPORT_SYMBOL_GPL(rpcauth_lookupcred); | 643 | EXPORT_SYMBOL_GPL(rpcauth_lookupcred); |
diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c index ed04869b2d4f..6f6b829c9e8e 100644 --- a/net/sunrpc/auth_generic.c +++ b/net/sunrpc/auth_generic.c | |||
| @@ -38,6 +38,12 @@ struct rpc_cred *rpc_lookup_cred(void) | |||
| 38 | } | 38 | } |
| 39 | EXPORT_SYMBOL_GPL(rpc_lookup_cred); | 39 | EXPORT_SYMBOL_GPL(rpc_lookup_cred); |
| 40 | 40 | ||
| 41 | struct rpc_cred *rpc_lookup_cred_nonblock(void) | ||
| 42 | { | ||
| 43 | return rpcauth_lookupcred(&generic_auth, RPCAUTH_LOOKUP_RCU); | ||
| 44 | } | ||
| 45 | EXPORT_SYMBOL_GPL(rpc_lookup_cred_nonblock); | ||
| 46 | |||
| 41 | /* | 47 | /* |
| 42 | * Public call interface for looking up machine creds. | 48 | * Public call interface for looking up machine creds. |
| 43 | */ | 49 | */ |
diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c index f0ebe07978a2..712c123e04e9 100644 --- a/net/sunrpc/auth_null.c +++ b/net/sunrpc/auth_null.c | |||
| @@ -35,6 +35,8 @@ nul_destroy(struct rpc_auth *auth) | |||
| 35 | static struct rpc_cred * | 35 | static struct rpc_cred * |
| 36 | nul_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) | 36 | nul_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) |
| 37 | { | 37 | { |
| 38 | if (flags & RPCAUTH_LOOKUP_RCU) | ||
| 39 | return &null_cred; | ||
| 38 | return get_rpccred(&null_cred); | 40 | return get_rpccred(&null_cred); |
| 39 | } | 41 | } |
| 40 | 42 | ||
