diff options
Diffstat (limited to 'net/sunrpc/rpcb_clnt.c')
-rw-r--r-- | net/sunrpc/rpcb_clnt.c | 88 |
1 files changed, 58 insertions, 30 deletions
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index f588b852d41c..8761bf8e36fc 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c | |||
@@ -114,6 +114,9 @@ static struct rpc_program rpcb_program; | |||
114 | static struct rpc_clnt * rpcb_local_clnt; | 114 | static struct rpc_clnt * rpcb_local_clnt; |
115 | static struct rpc_clnt * rpcb_local_clnt4; | 115 | static struct rpc_clnt * rpcb_local_clnt4; |
116 | 116 | ||
117 | DEFINE_SPINLOCK(rpcb_clnt_lock); | ||
118 | unsigned int rpcb_users; | ||
119 | |||
117 | struct rpcbind_args { | 120 | struct rpcbind_args { |
118 | struct rpc_xprt * r_xprt; | 121 | struct rpc_xprt * r_xprt; |
119 | 122 | ||
@@ -161,6 +164,56 @@ static void rpcb_map_release(void *data) | |||
161 | kfree(map); | 164 | kfree(map); |
162 | } | 165 | } |
163 | 166 | ||
167 | static int rpcb_get_local(void) | ||
168 | { | ||
169 | int cnt; | ||
170 | |||
171 | spin_lock(&rpcb_clnt_lock); | ||
172 | if (rpcb_users) | ||
173 | rpcb_users++; | ||
174 | cnt = rpcb_users; | ||
175 | spin_unlock(&rpcb_clnt_lock); | ||
176 | |||
177 | return cnt; | ||
178 | } | ||
179 | |||
180 | void rpcb_put_local(void) | ||
181 | { | ||
182 | struct rpc_clnt *clnt = rpcb_local_clnt; | ||
183 | struct rpc_clnt *clnt4 = rpcb_local_clnt4; | ||
184 | int shutdown; | ||
185 | |||
186 | spin_lock(&rpcb_clnt_lock); | ||
187 | if (--rpcb_users == 0) { | ||
188 | rpcb_local_clnt = NULL; | ||
189 | rpcb_local_clnt4 = NULL; | ||
190 | } | ||
191 | shutdown = !rpcb_users; | ||
192 | spin_unlock(&rpcb_clnt_lock); | ||
193 | |||
194 | if (shutdown) { | ||
195 | /* | ||
196 | * cleanup_rpcb_clnt - remove xprtsock's sysctls, unregister | ||
197 | */ | ||
198 | if (clnt4) | ||
199 | rpc_shutdown_client(clnt4); | ||
200 | if (clnt) | ||
201 | rpc_shutdown_client(clnt); | ||
202 | } | ||
203 | } | ||
204 | |||
205 | static void rpcb_set_local(struct rpc_clnt *clnt, struct rpc_clnt *clnt4) | ||
206 | { | ||
207 | /* Protected by rpcb_create_local_mutex */ | ||
208 | rpcb_local_clnt = clnt; | ||
209 | rpcb_local_clnt4 = clnt4; | ||
210 | smp_wmb(); | ||
211 | rpcb_users = 1; | ||
212 | dprintk("RPC: created new rpcb local clients (rpcb_local_clnt: " | ||
213 | "%p, rpcb_local_clnt4: %p)\n", rpcb_local_clnt, | ||
214 | rpcb_local_clnt4); | ||
215 | } | ||
216 | |||
164 | /* | 217 | /* |
165 | * Returns zero on success, otherwise a negative errno value | 218 | * Returns zero on success, otherwise a negative errno value |
166 | * is returned. | 219 | * is returned. |
@@ -205,9 +258,7 @@ static int rpcb_create_local_unix(void) | |||
205 | clnt4 = NULL; | 258 | clnt4 = NULL; |
206 | } | 259 | } |
207 | 260 | ||
208 | /* Protected by rpcb_create_local_mutex */ | 261 | rpcb_set_local(clnt, clnt4); |
209 | rpcb_local_clnt = clnt; | ||
210 | rpcb_local_clnt4 = clnt4; | ||
211 | 262 | ||
212 | out: | 263 | out: |
213 | return result; | 264 | return result; |
@@ -259,9 +310,7 @@ static int rpcb_create_local_net(void) | |||
259 | clnt4 = NULL; | 310 | clnt4 = NULL; |
260 | } | 311 | } |
261 | 312 | ||
262 | /* Protected by rpcb_create_local_mutex */ | 313 | rpcb_set_local(clnt, clnt4); |
263 | rpcb_local_clnt = clnt; | ||
264 | rpcb_local_clnt4 = clnt4; | ||
265 | 314 | ||
266 | out: | 315 | out: |
267 | return result; | 316 | return result; |
@@ -271,16 +320,16 @@ out: | |||
271 | * Returns zero on success, otherwise a negative errno value | 320 | * Returns zero on success, otherwise a negative errno value |
272 | * is returned. | 321 | * is returned. |
273 | */ | 322 | */ |
274 | static int rpcb_create_local(void) | 323 | int rpcb_create_local(void) |
275 | { | 324 | { |
276 | static DEFINE_MUTEX(rpcb_create_local_mutex); | 325 | static DEFINE_MUTEX(rpcb_create_local_mutex); |
277 | int result = 0; | 326 | int result = 0; |
278 | 327 | ||
279 | if (rpcb_local_clnt) | 328 | if (rpcb_get_local()) |
280 | return result; | 329 | return result; |
281 | 330 | ||
282 | mutex_lock(&rpcb_create_local_mutex); | 331 | mutex_lock(&rpcb_create_local_mutex); |
283 | if (rpcb_local_clnt) | 332 | if (rpcb_get_local()) |
284 | goto out; | 333 | goto out; |
285 | 334 | ||
286 | if (rpcb_create_local_unix() != 0) | 335 | if (rpcb_create_local_unix() != 0) |
@@ -382,11 +431,6 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port) | |||
382 | struct rpc_message msg = { | 431 | struct rpc_message msg = { |
383 | .rpc_argp = &map, | 432 | .rpc_argp = &map, |
384 | }; | 433 | }; |
385 | int error; | ||
386 | |||
387 | error = rpcb_create_local(); | ||
388 | if (error) | ||
389 | return error; | ||
390 | 434 | ||
391 | dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " | 435 | dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " |
392 | "rpcbind\n", (port ? "" : "un"), | 436 | "rpcbind\n", (port ? "" : "un"), |
@@ -522,11 +566,7 @@ int rpcb_v4_register(const u32 program, const u32 version, | |||
522 | struct rpc_message msg = { | 566 | struct rpc_message msg = { |
523 | .rpc_argp = &map, | 567 | .rpc_argp = &map, |
524 | }; | 568 | }; |
525 | int error; | ||
526 | 569 | ||
527 | error = rpcb_create_local(); | ||
528 | if (error) | ||
529 | return error; | ||
530 | if (rpcb_local_clnt4 == NULL) | 570 | if (rpcb_local_clnt4 == NULL) |
531 | return -EPROTONOSUPPORT; | 571 | return -EPROTONOSUPPORT; |
532 | 572 | ||
@@ -1060,15 +1100,3 @@ static struct rpc_program rpcb_program = { | |||
1060 | .version = rpcb_version, | 1100 | .version = rpcb_version, |
1061 | .stats = &rpcb_stats, | 1101 | .stats = &rpcb_stats, |
1062 | }; | 1102 | }; |
1063 | |||
1064 | /** | ||
1065 | * cleanup_rpcb_clnt - remove xprtsock's sysctls, unregister | ||
1066 | * | ||
1067 | */ | ||
1068 | void cleanup_rpcb_clnt(void) | ||
1069 | { | ||
1070 | if (rpcb_local_clnt4) | ||
1071 | rpc_shutdown_client(rpcb_local_clnt4); | ||
1072 | if (rpcb_local_clnt) | ||
1073 | rpc_shutdown_client(rpcb_local_clnt); | ||
1074 | } | ||