aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@hammerspace.com>2018-09-27 13:12:44 -0400
committerTrond Myklebust <trond.myklebust@hammerspace.com>2018-09-30 15:35:17 -0400
commit4e4c3bef4471c8a06406abd2e3d9493e8478feff (patch)
tree1d1a2a56b701a76caa61545969f08cdbe2d5af61
parent1c6c4b740df12f2162ae5c3fac337137e2776236 (diff)
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>
-rw-r--r--net/sunrpc/auth.c128
1 files changed, 62 insertions, 66 deletions
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 59df5cdba0ac..32985aa515be 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -30,10 +30,9 @@ struct rpc_cred_cache {
30 30
31static unsigned int auth_hashbits = RPC_CREDCACHE_DEFAULT_HASHBITS; 31static unsigned int auth_hashbits = RPC_CREDCACHE_DEFAULT_HASHBITS;
32 32
33static DEFINE_SPINLOCK(rpc_authflavor_lock); 33static const struct rpc_authops __rcu *auth_flavors[RPC_AUTH_MAXFLAVOR] = {
34static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = { 34 [RPC_AUTH_NULL] = (const struct rpc_authops __force __rcu *)&authnull_ops,
35 &authnull_ops, /* AUTH_NULL */ 35 [RPC_AUTH_UNIX] = (const struct rpc_authops __force __rcu *)&authunix_ops,
36 &authunix_ops, /* AUTH_UNIX */
37 NULL, /* others can be loadable modules */ 36 NULL, /* others can be loadable modules */
38}; 37};
39 38
@@ -93,39 +92,65 @@ pseudoflavor_to_flavor(u32 flavor) {
93int 92int
94rpcauth_register(const struct rpc_authops *ops) 93rpcauth_register(const struct rpc_authops *ops)
95{ 94{
95 const struct rpc_authops *old;
96 rpc_authflavor_t flavor; 96 rpc_authflavor_t flavor;
97 int ret = -EPERM;
98 97
99 if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR) 98 if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
100 return -EINVAL; 99 return -EINVAL;
101 spin_lock(&rpc_authflavor_lock); 100 old = cmpxchg((const struct rpc_authops ** __force)&auth_flavors[flavor], NULL, ops);
102 if (auth_flavors[flavor] == NULL) { 101 if (old == NULL || old == ops)
103 auth_flavors[flavor] = ops; 102 return 0;
104 ret = 0; 103 return -EPERM;
105 }
106 spin_unlock(&rpc_authflavor_lock);
107 return ret;
108} 104}
109EXPORT_SYMBOL_GPL(rpcauth_register); 105EXPORT_SYMBOL_GPL(rpcauth_register);
110 106
111int 107int
112rpcauth_unregister(const struct rpc_authops *ops) 108rpcauth_unregister(const struct rpc_authops *ops)
113{ 109{
110 const struct rpc_authops *old;
114 rpc_authflavor_t flavor; 111 rpc_authflavor_t flavor;
115 int ret = -EPERM;
116 112
117 if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR) 113 if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
118 return -EINVAL; 114 return -EINVAL;
119 spin_lock(&rpc_authflavor_lock); 115
120 if (auth_flavors[flavor] == ops) { 116 old = cmpxchg((const struct rpc_authops ** __force)&auth_flavors[flavor], ops, NULL);
121 auth_flavors[flavor] = NULL; 117 if (old == ops || old == NULL)
122 ret = 0; 118 return 0;
123 } 119 return -EPERM;
124 spin_unlock(&rpc_authflavor_lock);
125 return ret;
126} 120}
127EXPORT_SYMBOL_GPL(rpcauth_unregister); 121EXPORT_SYMBOL_GPL(rpcauth_unregister);
128 122
123static const struct rpc_authops *
124rpcauth_get_authops(rpc_authflavor_t flavor)
125{
126 const struct rpc_authops *ops;
127
128 if (flavor >= RPC_AUTH_MAXFLAVOR)
129 return NULL;
130
131 rcu_read_lock();
132 ops = rcu_dereference(auth_flavors[flavor]);
133 if (ops == NULL) {
134 rcu_read_unlock();
135 request_module("rpc-auth-%u", flavor);
136 rcu_read_lock();
137 ops = rcu_dereference(auth_flavors[flavor]);
138 if (ops == NULL)
139 goto out;
140 }
141 if (!try_module_get(ops->owner))
142 ops = NULL;
143out:
144 rcu_read_unlock();
145 return ops;
146}
147
148static void
149rpcauth_put_authops(const struct rpc_authops *ops)
150{
151 module_put(ops->owner);
152}
153
129/** 154/**
130 * rpcauth_get_pseudoflavor - check if security flavor is supported 155 * rpcauth_get_pseudoflavor - check if security flavor is supported
131 * @flavor: a security flavor 156 * @flavor: a security flavor
@@ -138,25 +163,16 @@ EXPORT_SYMBOL_GPL(rpcauth_unregister);
138rpc_authflavor_t 163rpc_authflavor_t
139rpcauth_get_pseudoflavor(rpc_authflavor_t flavor, struct rpcsec_gss_info *info) 164rpcauth_get_pseudoflavor(rpc_authflavor_t flavor, struct rpcsec_gss_info *info)
140{ 165{
141 const struct rpc_authops *ops; 166 const struct rpc_authops *ops = rpcauth_get_authops(flavor);
142 rpc_authflavor_t pseudoflavor; 167 rpc_authflavor_t pseudoflavor;
143 168
144 ops = auth_flavors[flavor]; 169 if (!ops)
145 if (ops == NULL)
146 request_module("rpc-auth-%u", flavor);
147 spin_lock(&rpc_authflavor_lock);
148 ops = auth_flavors[flavor];
149 if (ops == NULL || !try_module_get(ops->owner)) {
150 spin_unlock(&rpc_authflavor_lock);
151 return RPC_AUTH_MAXFLAVOR; 170 return RPC_AUTH_MAXFLAVOR;
152 }
153 spin_unlock(&rpc_authflavor_lock);
154
155 pseudoflavor = flavor; 171 pseudoflavor = flavor;
156 if (ops->info2flavor != NULL) 172 if (ops->info2flavor != NULL)
157 pseudoflavor = ops->info2flavor(info); 173 pseudoflavor = ops->info2flavor(info);
158 174
159 module_put(ops->owner); 175 rpcauth_put_authops(ops);
160 return pseudoflavor; 176 return pseudoflavor;
161} 177}
162EXPORT_SYMBOL_GPL(rpcauth_get_pseudoflavor); 178EXPORT_SYMBOL_GPL(rpcauth_get_pseudoflavor);
@@ -176,25 +192,15 @@ rpcauth_get_gssinfo(rpc_authflavor_t pseudoflavor, struct rpcsec_gss_info *info)
176 const struct rpc_authops *ops; 192 const struct rpc_authops *ops;
177 int result; 193 int result;
178 194
179 if (flavor >= RPC_AUTH_MAXFLAVOR) 195 ops = rpcauth_get_authops(flavor);
180 return -EINVAL;
181
182 ops = auth_flavors[flavor];
183 if (ops == NULL) 196 if (ops == NULL)
184 request_module("rpc-auth-%u", flavor);
185 spin_lock(&rpc_authflavor_lock);
186 ops = auth_flavors[flavor];
187 if (ops == NULL || !try_module_get(ops->owner)) {
188 spin_unlock(&rpc_authflavor_lock);
189 return -ENOENT; 197 return -ENOENT;
190 }
191 spin_unlock(&rpc_authflavor_lock);
192 198
193 result = -ENOENT; 199 result = -ENOENT;
194 if (ops->flavor2info != NULL) 200 if (ops->flavor2info != NULL)
195 result = ops->flavor2info(pseudoflavor, info); 201 result = ops->flavor2info(pseudoflavor, info);
196 202
197 module_put(ops->owner); 203 rpcauth_put_authops(ops);
198 return result; 204 return result;
199} 205}
200EXPORT_SYMBOL_GPL(rpcauth_get_gssinfo); 206EXPORT_SYMBOL_GPL(rpcauth_get_gssinfo);
@@ -212,15 +218,13 @@ EXPORT_SYMBOL_GPL(rpcauth_get_gssinfo);
212int 218int
213rpcauth_list_flavors(rpc_authflavor_t *array, int size) 219rpcauth_list_flavors(rpc_authflavor_t *array, int size)
214{ 220{
215 rpc_authflavor_t flavor; 221 const struct rpc_authops *ops;
216 int result = 0; 222 rpc_authflavor_t flavor, pseudos[4];
223 int i, len, result = 0;
217 224
218 spin_lock(&rpc_authflavor_lock); 225 rcu_read_lock();
219 for (flavor = 0; flavor < RPC_AUTH_MAXFLAVOR; flavor++) { 226 for (flavor = 0; flavor < RPC_AUTH_MAXFLAVOR; flavor++) {
220 const struct rpc_authops *ops = auth_flavors[flavor]; 227 ops = rcu_dereference(auth_flavors[flavor]);
221 rpc_authflavor_t pseudos[4];
222 int i, len;
223
224 if (result >= size) { 228 if (result >= size) {
225 result = -ENOMEM; 229 result = -ENOMEM;
226 break; 230 break;
@@ -245,7 +249,7 @@ rpcauth_list_flavors(rpc_authflavor_t *array, int size)
245 array[result++] = pseudos[i]; 249 array[result++] = pseudos[i];
246 } 250 }
247 } 251 }
248 spin_unlock(&rpc_authflavor_lock); 252 rcu_read_unlock();
249 253
250 dprintk("RPC: %s returns %d\n", __func__, result); 254 dprintk("RPC: %s returns %d\n", __func__, result);
251 return result; 255 return result;
@@ -255,25 +259,17 @@ EXPORT_SYMBOL_GPL(rpcauth_list_flavors);
255struct rpc_auth * 259struct rpc_auth *
256rpcauth_create(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt) 260rpcauth_create(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
257{ 261{
258 struct rpc_auth *auth; 262 struct rpc_auth *auth = ERR_PTR(-EINVAL);
259 const struct rpc_authops *ops; 263 const struct rpc_authops *ops;
260 u32 flavor = pseudoflavor_to_flavor(args->pseudoflavor); 264 u32 flavor = pseudoflavor_to_flavor(args->pseudoflavor);
261 265
262 auth = ERR_PTR(-EINVAL); 266 ops = rpcauth_get_authops(flavor);
263 if (flavor >= RPC_AUTH_MAXFLAVOR) 267 if (ops == NULL)
264 goto out; 268 goto out;
265 269
266 if ((ops = auth_flavors[flavor]) == NULL)
267 request_module("rpc-auth-%u", flavor);
268 spin_lock(&rpc_authflavor_lock);
269 ops = auth_flavors[flavor];
270 if (ops == NULL || !try_module_get(ops->owner)) {
271 spin_unlock(&rpc_authflavor_lock);
272 goto out;
273 }
274 spin_unlock(&rpc_authflavor_lock);
275 auth = ops->create(args, clnt); 270 auth = ops->create(args, clnt);
276 module_put(ops->owner); 271
272 rpcauth_put_authops(ops);
277 if (IS_ERR(auth)) 273 if (IS_ERR(auth))
278 return auth; 274 return auth;
279 if (clnt->cl_auth) 275 if (clnt->cl_auth)