@@ -30,10 +30,9 @@ struct rpc_cred_cache {
30
30
31
31
static unsigned int auth_hashbits = RPC_CREDCACHE_DEFAULT_HASHBITS ;
32
32
33
- static DEFINE_SPINLOCK (rpc_authflavor_lock );
34
- static const struct rpc_authops * auth_flavors [RPC_AUTH_MAXFLAVOR ] = {
35
- & authnull_ops , /* AUTH_NULL */
36
- & authunix_ops , /* AUTH_UNIX */
33
+ static const struct rpc_authops __rcu * auth_flavors [RPC_AUTH_MAXFLAVOR ] = {
34
+ [RPC_AUTH_NULL ] = (const struct rpc_authops __force __rcu * )& authnull_ops ,
35
+ [RPC_AUTH_UNIX ] = (const struct rpc_authops __force __rcu * )& authunix_ops ,
37
36
NULL , /* others can be loadable modules */
38
37
};
39
38
@@ -93,39 +92,65 @@ pseudoflavor_to_flavor(u32 flavor) {
93
92
int
94
93
rpcauth_register (const struct rpc_authops * ops )
95
94
{
95
+ const struct rpc_authops * old ;
96
96
rpc_authflavor_t flavor ;
97
- int ret = - EPERM ;
98
97
99
98
if ((flavor = ops -> au_flavor ) >= RPC_AUTH_MAXFLAVOR )
100
99
return - EINVAL ;
101
- spin_lock (& rpc_authflavor_lock );
102
- if (auth_flavors [flavor ] == NULL ) {
103
- auth_flavors [flavor ] = ops ;
104
- ret = 0 ;
105
- }
106
- spin_unlock (& rpc_authflavor_lock );
107
- return ret ;
100
+ old = cmpxchg ((const struct rpc_authops * * __force )& auth_flavors [flavor ], NULL , ops );
101
+ if (old == NULL || old == ops )
102
+ return 0 ;
103
+ return - EPERM ;
108
104
}
109
105
EXPORT_SYMBOL_GPL (rpcauth_register );
110
106
111
107
int
112
108
rpcauth_unregister (const struct rpc_authops * ops )
113
109
{
110
+ const struct rpc_authops * old ;
114
111
rpc_authflavor_t flavor ;
115
- int ret = - EPERM ;
116
112
117
113
if ((flavor = ops -> au_flavor ) >= RPC_AUTH_MAXFLAVOR )
118
114
return - EINVAL ;
119
- spin_lock (& rpc_authflavor_lock );
120
- if (auth_flavors [flavor ] == ops ) {
121
- auth_flavors [flavor ] = NULL ;
122
- ret = 0 ;
123
- }
124
- spin_unlock (& rpc_authflavor_lock );
125
- return ret ;
115
+
116
+ old = cmpxchg ((const struct rpc_authops * * __force )& auth_flavors [flavor ], ops , NULL );
117
+ if (old == ops || old == NULL )
118
+ return 0 ;
119
+ return - EPERM ;
126
120
}
127
121
EXPORT_SYMBOL_GPL (rpcauth_unregister );
128
122
123
+ static const struct rpc_authops *
124
+ rpcauth_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 ;
143
+ out :
144
+ rcu_read_unlock ();
145
+ return ops ;
146
+ }
147
+
148
+ static void
149
+ rpcauth_put_authops (const struct rpc_authops * ops )
150
+ {
151
+ module_put (ops -> owner );
152
+ }
153
+
129
154
/**
130
155
* rpcauth_get_pseudoflavor - check if security flavor is supported
131
156
* @flavor: a security flavor
@@ -138,25 +163,16 @@ EXPORT_SYMBOL_GPL(rpcauth_unregister);
138
163
rpc_authflavor_t
139
164
rpcauth_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
167
rpc_authflavor_t pseudoflavor ;
143
168
144
- ops = auth_flavors [flavor ];
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 );
169
+ if (!ops )
151
170
return RPC_AUTH_MAXFLAVOR ;
152
- }
153
- spin_unlock (& rpc_authflavor_lock );
154
-
155
171
pseudoflavor = flavor ;
156
172
if (ops -> info2flavor != NULL )
157
173
pseudoflavor = ops -> info2flavor (info );
158
174
159
- module_put (ops -> owner );
175
+ rpcauth_put_authops (ops );
160
176
return pseudoflavor ;
161
177
}
162
178
EXPORT_SYMBOL_GPL (rpcauth_get_pseudoflavor );
@@ -176,25 +192,15 @@ rpcauth_get_gssinfo(rpc_authflavor_t pseudoflavor, struct rpcsec_gss_info *info)
176
192
const struct rpc_authops * ops ;
177
193
int result ;
178
194
179
- if (flavor >= RPC_AUTH_MAXFLAVOR )
180
- return - EINVAL ;
181
-
182
- ops = auth_flavors [flavor ];
195
+ ops = rpcauth_get_authops (flavor );
183
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
197
return - ENOENT ;
190
- }
191
- spin_unlock (& rpc_authflavor_lock );
192
198
193
199
result = - ENOENT ;
194
200
if (ops -> flavor2info != NULL )
195
201
result = ops -> flavor2info (pseudoflavor , info );
196
202
197
- module_put (ops -> owner );
203
+ rpcauth_put_authops (ops );
198
204
return result ;
199
205
}
200
206
EXPORT_SYMBOL_GPL (rpcauth_get_gssinfo );
@@ -212,15 +218,13 @@ EXPORT_SYMBOL_GPL(rpcauth_get_gssinfo);
212
218
int
213
219
rpcauth_list_flavors (rpc_authflavor_t * array , int size )
214
220
{
215
- rpc_authflavor_t flavor ;
216
- int result = 0 ;
221
+ const struct rpc_authops * ops ;
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
226
for (flavor = 0 ; flavor < RPC_AUTH_MAXFLAVOR ; flavor ++ ) {
220
- const struct rpc_authops * ops = auth_flavors [flavor ];
221
- rpc_authflavor_t pseudos [4 ];
222
- int i , len ;
223
-
227
+ ops = rcu_dereference (auth_flavors [flavor ]);
224
228
if (result >= size ) {
225
229
result = - ENOMEM ;
226
230
break ;
@@ -245,7 +249,7 @@ rpcauth_list_flavors(rpc_authflavor_t *array, int size)
245
249
array [result ++ ] = pseudos [i ];
246
250
}
247
251
}
248
- spin_unlock ( & rpc_authflavor_lock );
252
+ rcu_read_unlock ( );
249
253
250
254
dprintk ("RPC: %s returns %d\n" , __func__ , result );
251
255
return result ;
@@ -255,25 +259,17 @@ EXPORT_SYMBOL_GPL(rpcauth_list_flavors);
255
259
struct rpc_auth *
256
260
rpcauth_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
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 );
263
- if (flavor >= RPC_AUTH_MAXFLAVOR )
266
+ ops = rpcauth_get_authops ( flavor );
267
+ if (ops == NULL )
264
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
270
auth = ops -> create (args , clnt );
276
- module_put (ops -> owner );
271
+
272
+ rpcauth_put_authops (ops );
277
273
if (IS_ERR (auth ))
278
274
return auth ;
279
275
if (clnt -> cl_auth )
0 commit comments