mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-19 19:29:02 +07:00
SUNRPC: Remove rpc_authflavor_lock in favour of RCU locking
Module removal is RCU safe by design, so we really have no need to lock the auth_flavors[] array. Substitute a lockless scheme to add/remove entries in the array, and then use rcu. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
This commit is contained in:
parent
1c6c4b740d
commit
4e4c3bef44
@ -30,10 +30,9 @@ struct rpc_cred_cache {
|
|||||||
|
|
||||||
static unsigned int auth_hashbits = RPC_CREDCACHE_DEFAULT_HASHBITS;
|
static unsigned int auth_hashbits = RPC_CREDCACHE_DEFAULT_HASHBITS;
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(rpc_authflavor_lock);
|
static const struct rpc_authops __rcu *auth_flavors[RPC_AUTH_MAXFLAVOR] = {
|
||||||
static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = {
|
[RPC_AUTH_NULL] = (const struct rpc_authops __force __rcu *)&authnull_ops,
|
||||||
&authnull_ops, /* AUTH_NULL */
|
[RPC_AUTH_UNIX] = (const struct rpc_authops __force __rcu *)&authunix_ops,
|
||||||
&authunix_ops, /* AUTH_UNIX */
|
|
||||||
NULL, /* others can be loadable modules */
|
NULL, /* others can be loadable modules */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -93,39 +92,65 @@ pseudoflavor_to_flavor(u32 flavor) {
|
|||||||
int
|
int
|
||||||
rpcauth_register(const struct rpc_authops *ops)
|
rpcauth_register(const struct rpc_authops *ops)
|
||||||
{
|
{
|
||||||
|
const struct rpc_authops *old;
|
||||||
rpc_authflavor_t flavor;
|
rpc_authflavor_t flavor;
|
||||||
int ret = -EPERM;
|
|
||||||
|
|
||||||
if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
|
if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
spin_lock(&rpc_authflavor_lock);
|
old = cmpxchg((const struct rpc_authops ** __force)&auth_flavors[flavor], NULL, ops);
|
||||||
if (auth_flavors[flavor] == NULL) {
|
if (old == NULL || old == ops)
|
||||||
auth_flavors[flavor] = ops;
|
return 0;
|
||||||
ret = 0;
|
return -EPERM;
|
||||||
}
|
|
||||||
spin_unlock(&rpc_authflavor_lock);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(rpcauth_register);
|
EXPORT_SYMBOL_GPL(rpcauth_register);
|
||||||
|
|
||||||
int
|
int
|
||||||
rpcauth_unregister(const struct rpc_authops *ops)
|
rpcauth_unregister(const struct rpc_authops *ops)
|
||||||
{
|
{
|
||||||
|
const struct rpc_authops *old;
|
||||||
rpc_authflavor_t flavor;
|
rpc_authflavor_t flavor;
|
||||||
int ret = -EPERM;
|
|
||||||
|
|
||||||
if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
|
if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
spin_lock(&rpc_authflavor_lock);
|
|
||||||
if (auth_flavors[flavor] == ops) {
|
old = cmpxchg((const struct rpc_authops ** __force)&auth_flavors[flavor], ops, NULL);
|
||||||
auth_flavors[flavor] = NULL;
|
if (old == ops || old == NULL)
|
||||||
ret = 0;
|
return 0;
|
||||||
}
|
return -EPERM;
|
||||||
spin_unlock(&rpc_authflavor_lock);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(rpcauth_unregister);
|
EXPORT_SYMBOL_GPL(rpcauth_unregister);
|
||||||
|
|
||||||
|
static const struct rpc_authops *
|
||||||
|
rpcauth_get_authops(rpc_authflavor_t flavor)
|
||||||
|
{
|
||||||
|
const struct rpc_authops *ops;
|
||||||
|
|
||||||
|
if (flavor >= RPC_AUTH_MAXFLAVOR)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
ops = rcu_dereference(auth_flavors[flavor]);
|
||||||
|
if (ops == NULL) {
|
||||||
|
rcu_read_unlock();
|
||||||
|
request_module("rpc-auth-%u", flavor);
|
||||||
|
rcu_read_lock();
|
||||||
|
ops = rcu_dereference(auth_flavors[flavor]);
|
||||||
|
if (ops == NULL)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (!try_module_get(ops->owner))
|
||||||
|
ops = NULL;
|
||||||
|
out:
|
||||||
|
rcu_read_unlock();
|
||||||
|
return ops;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rpcauth_put_authops(const struct rpc_authops *ops)
|
||||||
|
{
|
||||||
|
module_put(ops->owner);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rpcauth_get_pseudoflavor - check if security flavor is supported
|
* rpcauth_get_pseudoflavor - check if security flavor is supported
|
||||||
* @flavor: a security flavor
|
* @flavor: a security flavor
|
||||||
@ -138,25 +163,16 @@ EXPORT_SYMBOL_GPL(rpcauth_unregister);
|
|||||||
rpc_authflavor_t
|
rpc_authflavor_t
|
||||||
rpcauth_get_pseudoflavor(rpc_authflavor_t flavor, struct rpcsec_gss_info *info)
|
rpcauth_get_pseudoflavor(rpc_authflavor_t flavor, struct rpcsec_gss_info *info)
|
||||||
{
|
{
|
||||||
const struct rpc_authops *ops;
|
const struct rpc_authops *ops = rpcauth_get_authops(flavor);
|
||||||
rpc_authflavor_t pseudoflavor;
|
rpc_authflavor_t pseudoflavor;
|
||||||
|
|
||||||
ops = auth_flavors[flavor];
|
if (!ops)
|
||||||
if (ops == NULL)
|
|
||||||
request_module("rpc-auth-%u", flavor);
|
|
||||||
spin_lock(&rpc_authflavor_lock);
|
|
||||||
ops = auth_flavors[flavor];
|
|
||||||
if (ops == NULL || !try_module_get(ops->owner)) {
|
|
||||||
spin_unlock(&rpc_authflavor_lock);
|
|
||||||
return RPC_AUTH_MAXFLAVOR;
|
return RPC_AUTH_MAXFLAVOR;
|
||||||
}
|
|
||||||
spin_unlock(&rpc_authflavor_lock);
|
|
||||||
|
|
||||||
pseudoflavor = flavor;
|
pseudoflavor = flavor;
|
||||||
if (ops->info2flavor != NULL)
|
if (ops->info2flavor != NULL)
|
||||||
pseudoflavor = ops->info2flavor(info);
|
pseudoflavor = ops->info2flavor(info);
|
||||||
|
|
||||||
module_put(ops->owner);
|
rpcauth_put_authops(ops);
|
||||||
return pseudoflavor;
|
return pseudoflavor;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(rpcauth_get_pseudoflavor);
|
EXPORT_SYMBOL_GPL(rpcauth_get_pseudoflavor);
|
||||||
@ -176,25 +192,15 @@ rpcauth_get_gssinfo(rpc_authflavor_t pseudoflavor, struct rpcsec_gss_info *info)
|
|||||||
const struct rpc_authops *ops;
|
const struct rpc_authops *ops;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (flavor >= RPC_AUTH_MAXFLAVOR)
|
ops = rpcauth_get_authops(flavor);
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
ops = auth_flavors[flavor];
|
|
||||||
if (ops == NULL)
|
if (ops == NULL)
|
||||||
request_module("rpc-auth-%u", flavor);
|
|
||||||
spin_lock(&rpc_authflavor_lock);
|
|
||||||
ops = auth_flavors[flavor];
|
|
||||||
if (ops == NULL || !try_module_get(ops->owner)) {
|
|
||||||
spin_unlock(&rpc_authflavor_lock);
|
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
|
||||||
spin_unlock(&rpc_authflavor_lock);
|
|
||||||
|
|
||||||
result = -ENOENT;
|
result = -ENOENT;
|
||||||
if (ops->flavor2info != NULL)
|
if (ops->flavor2info != NULL)
|
||||||
result = ops->flavor2info(pseudoflavor, info);
|
result = ops->flavor2info(pseudoflavor, info);
|
||||||
|
|
||||||
module_put(ops->owner);
|
rpcauth_put_authops(ops);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(rpcauth_get_gssinfo);
|
EXPORT_SYMBOL_GPL(rpcauth_get_gssinfo);
|
||||||
@ -212,15 +218,13 @@ EXPORT_SYMBOL_GPL(rpcauth_get_gssinfo);
|
|||||||
int
|
int
|
||||||
rpcauth_list_flavors(rpc_authflavor_t *array, int size)
|
rpcauth_list_flavors(rpc_authflavor_t *array, int size)
|
||||||
{
|
{
|
||||||
rpc_authflavor_t flavor;
|
const struct rpc_authops *ops;
|
||||||
int result = 0;
|
rpc_authflavor_t flavor, pseudos[4];
|
||||||
|
int i, len, result = 0;
|
||||||
|
|
||||||
spin_lock(&rpc_authflavor_lock);
|
rcu_read_lock();
|
||||||
for (flavor = 0; flavor < RPC_AUTH_MAXFLAVOR; flavor++) {
|
for (flavor = 0; flavor < RPC_AUTH_MAXFLAVOR; flavor++) {
|
||||||
const struct rpc_authops *ops = auth_flavors[flavor];
|
ops = rcu_dereference(auth_flavors[flavor]);
|
||||||
rpc_authflavor_t pseudos[4];
|
|
||||||
int i, len;
|
|
||||||
|
|
||||||
if (result >= size) {
|
if (result >= size) {
|
||||||
result = -ENOMEM;
|
result = -ENOMEM;
|
||||||
break;
|
break;
|
||||||
@ -245,7 +249,7 @@ rpcauth_list_flavors(rpc_authflavor_t *array, int size)
|
|||||||
array[result++] = pseudos[i];
|
array[result++] = pseudos[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock(&rpc_authflavor_lock);
|
rcu_read_unlock();
|
||||||
|
|
||||||
dprintk("RPC: %s returns %d\n", __func__, result);
|
dprintk("RPC: %s returns %d\n", __func__, result);
|
||||||
return result;
|
return result;
|
||||||
@ -255,25 +259,17 @@ EXPORT_SYMBOL_GPL(rpcauth_list_flavors);
|
|||||||
struct rpc_auth *
|
struct rpc_auth *
|
||||||
rpcauth_create(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
|
rpcauth_create(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
|
||||||
{
|
{
|
||||||
struct rpc_auth *auth;
|
struct rpc_auth *auth = ERR_PTR(-EINVAL);
|
||||||
const struct rpc_authops *ops;
|
const struct rpc_authops *ops;
|
||||||
u32 flavor = pseudoflavor_to_flavor(args->pseudoflavor);
|
u32 flavor = pseudoflavor_to_flavor(args->pseudoflavor);
|
||||||
|
|
||||||
auth = ERR_PTR(-EINVAL);
|
ops = rpcauth_get_authops(flavor);
|
||||||
if (flavor >= RPC_AUTH_MAXFLAVOR)
|
if (ops == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if ((ops = auth_flavors[flavor]) == NULL)
|
|
||||||
request_module("rpc-auth-%u", flavor);
|
|
||||||
spin_lock(&rpc_authflavor_lock);
|
|
||||||
ops = auth_flavors[flavor];
|
|
||||||
if (ops == NULL || !try_module_get(ops->owner)) {
|
|
||||||
spin_unlock(&rpc_authflavor_lock);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
spin_unlock(&rpc_authflavor_lock);
|
|
||||||
auth = ops->create(args, clnt);
|
auth = ops->create(args, clnt);
|
||||||
module_put(ops->owner);
|
|
||||||
|
rpcauth_put_authops(ops);
|
||||||
if (IS_ERR(auth))
|
if (IS_ERR(auth))
|
||||||
return auth;
|
return auth;
|
||||||
if (clnt->cl_auth)
|
if (clnt->cl_auth)
|
||||||
|
Loading…
Reference in New Issue
Block a user