diff options
Diffstat (limited to 'net/sunrpc')
| -rw-r--r-- | net/sunrpc/auth_unix.c | 3 | ||||
| -rw-r--r-- | net/sunrpc/rpcb_clnt.c | 88 | ||||
| -rw-r--r-- | net/sunrpc/sunrpc_syms.c | 3 | ||||
| -rw-r--r-- | net/sunrpc/svc.c | 48 |
4 files changed, 106 insertions, 36 deletions
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index 4cb70dc6e7ad..e50502d8ceb7 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c | |||
| @@ -129,6 +129,9 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags) | |||
| 129 | for (i = 0; i < groups ; i++) | 129 | for (i = 0; i < groups ; i++) |
| 130 | if (cred->uc_gids[i] != GROUP_AT(acred->group_info, i)) | 130 | if (cred->uc_gids[i] != GROUP_AT(acred->group_info, i)) |
| 131 | return 0; | 131 | return 0; |
| 132 | if (groups < NFS_NGROUPS && | ||
| 133 | cred->uc_gids[groups] != NOGROUP) | ||
| 134 | return 0; | ||
| 132 | return 1; | 135 | return 1; |
| 133 | } | 136 | } |
| 134 | 137 | ||
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 | } | ||
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 9d0809160994..8ec9778c3f4a 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c | |||
| @@ -61,8 +61,6 @@ static struct pernet_operations sunrpc_net_ops = { | |||
| 61 | 61 | ||
| 62 | extern struct cache_detail unix_gid_cache; | 62 | extern struct cache_detail unix_gid_cache; |
| 63 | 63 | ||
| 64 | extern void cleanup_rpcb_clnt(void); | ||
| 65 | |||
| 66 | static int __init | 64 | static int __init |
| 67 | init_sunrpc(void) | 65 | init_sunrpc(void) |
| 68 | { | 66 | { |
| @@ -102,7 +100,6 @@ out: | |||
| 102 | static void __exit | 100 | static void __exit |
| 103 | cleanup_sunrpc(void) | 101 | cleanup_sunrpc(void) |
| 104 | { | 102 | { |
| 105 | cleanup_rpcb_clnt(); | ||
| 106 | rpcauth_remove_module(); | 103 | rpcauth_remove_module(); |
| 107 | cleanup_socket_xprt(); | 104 | cleanup_socket_xprt(); |
| 108 | svc_cleanup_xprt_sock(); | 105 | svc_cleanup_xprt_sock(); |
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index dd5cc00ed559..6e038884ae0c 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
| @@ -366,6 +366,42 @@ svc_pool_for_cpu(struct svc_serv *serv, int cpu) | |||
| 366 | return &serv->sv_pools[pidx % serv->sv_nrpools]; | 366 | return &serv->sv_pools[pidx % serv->sv_nrpools]; |
| 367 | } | 367 | } |
| 368 | 368 | ||
| 369 | static int svc_rpcb_setup(struct svc_serv *serv) | ||
| 370 | { | ||
| 371 | int err; | ||
| 372 | |||
| 373 | err = rpcb_create_local(); | ||
| 374 | if (err) | ||
| 375 | return err; | ||
| 376 | |||
| 377 | /* Remove any stale portmap registrations */ | ||
| 378 | svc_unregister(serv); | ||
| 379 | return 0; | ||
| 380 | } | ||
| 381 | |||
| 382 | void svc_rpcb_cleanup(struct svc_serv *serv) | ||
| 383 | { | ||
| 384 | svc_unregister(serv); | ||
| 385 | rpcb_put_local(); | ||
| 386 | } | ||
| 387 | EXPORT_SYMBOL_GPL(svc_rpcb_cleanup); | ||
| 388 | |||
| 389 | static int svc_uses_rpcbind(struct svc_serv *serv) | ||
| 390 | { | ||
| 391 | struct svc_program *progp; | ||
| 392 | unsigned int i; | ||
| 393 | |||
| 394 | for (progp = serv->sv_program; progp; progp = progp->pg_next) { | ||
| 395 | for (i = 0; i < progp->pg_nvers; i++) { | ||
| 396 | if (progp->pg_vers[i] == NULL) | ||
| 397 | continue; | ||
| 398 | if (progp->pg_vers[i]->vs_hidden == 0) | ||
| 399 | return 1; | ||
| 400 | } | ||
| 401 | } | ||
| 402 | |||
| 403 | return 0; | ||
| 404 | } | ||
| 369 | 405 | ||
| 370 | /* | 406 | /* |
| 371 | * Create an RPC service | 407 | * Create an RPC service |
| @@ -431,8 +467,15 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, | |||
| 431 | spin_lock_init(&pool->sp_lock); | 467 | spin_lock_init(&pool->sp_lock); |
| 432 | } | 468 | } |
| 433 | 469 | ||
| 434 | /* Remove any stale portmap registrations */ | 470 | if (svc_uses_rpcbind(serv)) { |
| 435 | svc_unregister(serv); | 471 | if (svc_rpcb_setup(serv) < 0) { |
| 472 | kfree(serv->sv_pools); | ||
| 473 | kfree(serv); | ||
| 474 | return NULL; | ||
| 475 | } | ||
| 476 | if (!serv->sv_shutdown) | ||
| 477 | serv->sv_shutdown = svc_rpcb_cleanup; | ||
| 478 | } | ||
| 436 | 479 | ||
| 437 | return serv; | 480 | return serv; |
| 438 | } | 481 | } |
| @@ -500,7 +543,6 @@ svc_destroy(struct svc_serv *serv) | |||
| 500 | if (svc_serv_is_pooled(serv)) | 543 | if (svc_serv_is_pooled(serv)) |
| 501 | svc_pool_map_put(); | 544 | svc_pool_map_put(); |
| 502 | 545 | ||
| 503 | svc_unregister(serv); | ||
| 504 | kfree(serv->sv_pools); | 546 | kfree(serv->sv_pools); |
| 505 | kfree(serv); | 547 | kfree(serv); |
| 506 | } | 548 | } |
