Commit 786615bc1ce84150ded80daea6bd9f6297f48e73
1 parent
00326ed644
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
SUNRPC: If the rpcbind channel is disconnected, fail the call to unregister
If rpcbind causes our connection to the AF_LOCAL socket to close after we've registered a service, then we want to be careful about reconnecting since the mount namespace may have changed. By simply refusing to reconnect the AF_LOCAL socket in the case of unregister, we avoid the need to somehow save the mount namespace. While this may lead to some services not unregistering properly, it should be safe. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> Cc: Nix <nix@esperi.org.uk> Cc: Jeff Layton <jlayton@redhat.com> Cc: stable@vger.kernel.org # 3.9.x
Showing 4 changed files with 33 additions and 13 deletions Side-by-side Diff
include/linux/sunrpc/sched.h
... | ... | @@ -121,6 +121,7 @@ |
121 | 121 | #define RPC_TASK_SOFTCONN 0x0400 /* Fail if can't connect */ |
122 | 122 | #define RPC_TASK_SENT 0x0800 /* message was sent */ |
123 | 123 | #define RPC_TASK_TIMEOUT 0x1000 /* fail with ETIMEDOUT on timeout */ |
124 | +#define RPC_TASK_NOCONNECT 0x2000 /* return ENOTCONN if not connected */ | |
124 | 125 | |
125 | 126 | #define RPC_IS_ASYNC(t) ((t)->tk_flags & RPC_TASK_ASYNC) |
126 | 127 | #define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER) |
net/sunrpc/clnt.c
net/sunrpc/netns.h
net/sunrpc/rpcb_clnt.c
... | ... | @@ -204,13 +204,15 @@ |
204 | 204 | } |
205 | 205 | |
206 | 206 | static void rpcb_set_local(struct net *net, struct rpc_clnt *clnt, |
207 | - struct rpc_clnt *clnt4) | |
207 | + struct rpc_clnt *clnt4, | |
208 | + bool is_af_local) | |
208 | 209 | { |
209 | 210 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
210 | 211 | |
211 | 212 | /* Protected by rpcb_create_local_mutex */ |
212 | 213 | sn->rpcb_local_clnt = clnt; |
213 | 214 | sn->rpcb_local_clnt4 = clnt4; |
215 | + sn->rpcb_is_af_local = is_af_local ? 1 : 0; | |
214 | 216 | smp_wmb(); |
215 | 217 | sn->rpcb_users = 1; |
216 | 218 | dprintk("RPC: created new rpcb local clients (rpcb_local_clnt: " |
... | ... | @@ -271,7 +273,7 @@ |
271 | 273 | clnt4 = NULL; |
272 | 274 | } |
273 | 275 | |
274 | - rpcb_set_local(net, clnt, clnt4); | |
276 | + rpcb_set_local(net, clnt, clnt4, true); | |
275 | 277 | |
276 | 278 | out: |
277 | 279 | return result; |
... | ... | @@ -323,7 +325,7 @@ |
323 | 325 | clnt4 = NULL; |
324 | 326 | } |
325 | 327 | |
326 | - rpcb_set_local(net, clnt, clnt4); | |
328 | + rpcb_set_local(net, clnt, clnt4, false); | |
327 | 329 | |
328 | 330 | out: |
329 | 331 | return result; |
330 | 332 | |
331 | 333 | |
332 | 334 | |
... | ... | @@ -384,13 +386,16 @@ |
384 | 386 | return rpc_create(&args); |
385 | 387 | } |
386 | 388 | |
387 | -static int rpcb_register_call(struct rpc_clnt *clnt, struct rpc_message *msg) | |
389 | +static int rpcb_register_call(struct sunrpc_net *sn, struct rpc_clnt *clnt, struct rpc_message *msg, bool is_set) | |
388 | 390 | { |
389 | - int result, error = 0; | |
391 | + int flags = RPC_TASK_NOCONNECT; | |
392 | + int error, result = 0; | |
390 | 393 | |
394 | + if (is_set || !sn->rpcb_is_af_local) | |
395 | + flags = RPC_TASK_SOFTCONN; | |
391 | 396 | msg->rpc_resp = &result; |
392 | 397 | |
393 | - error = rpc_call_sync(clnt, msg, RPC_TASK_SOFTCONN); | |
398 | + error = rpc_call_sync(clnt, msg, flags); | |
394 | 399 | if (error < 0) { |
395 | 400 | dprintk("RPC: failed to contact local rpcbind " |
396 | 401 | "server (errno %d).\n", -error); |
397 | 402 | |
398 | 403 | |
399 | 404 | |
... | ... | @@ -447,16 +452,19 @@ |
447 | 452 | .rpc_argp = &map, |
448 | 453 | }; |
449 | 454 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
455 | + bool is_set = false; | |
450 | 456 | |
451 | 457 | dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " |
452 | 458 | "rpcbind\n", (port ? "" : "un"), |
453 | 459 | prog, vers, prot, port); |
454 | 460 | |
455 | 461 | msg.rpc_proc = &rpcb_procedures2[RPCBPROC_UNSET]; |
456 | - if (port) | |
462 | + if (port != 0) { | |
457 | 463 | msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET]; |
464 | + is_set = true; | |
465 | + } | |
458 | 466 | |
459 | - return rpcb_register_call(sn->rpcb_local_clnt, &msg); | |
467 | + return rpcb_register_call(sn, sn->rpcb_local_clnt, &msg, is_set); | |
460 | 468 | } |
461 | 469 | |
462 | 470 | /* |
... | ... | @@ -469,6 +477,7 @@ |
469 | 477 | const struct sockaddr_in *sin = (const struct sockaddr_in *)sap; |
470 | 478 | struct rpcbind_args *map = msg->rpc_argp; |
471 | 479 | unsigned short port = ntohs(sin->sin_port); |
480 | + bool is_set = false; | |
472 | 481 | int result; |
473 | 482 | |
474 | 483 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL); |
475 | 484 | |
476 | 485 | |
... | ... | @@ -479,10 +488,12 @@ |
479 | 488 | map->r_addr, map->r_netid); |
480 | 489 | |
481 | 490 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; |
482 | - if (port) | |
491 | + if (port != 0) { | |
483 | 492 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; |
493 | + is_set = true; | |
494 | + } | |
484 | 495 | |
485 | - result = rpcb_register_call(sn->rpcb_local_clnt4, msg); | |
496 | + result = rpcb_register_call(sn, sn->rpcb_local_clnt4, msg, is_set); | |
486 | 497 | kfree(map->r_addr); |
487 | 498 | return result; |
488 | 499 | } |
... | ... | @@ -497,6 +508,7 @@ |
497 | 508 | const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap; |
498 | 509 | struct rpcbind_args *map = msg->rpc_argp; |
499 | 510 | unsigned short port = ntohs(sin6->sin6_port); |
511 | + bool is_set = false; | |
500 | 512 | int result; |
501 | 513 | |
502 | 514 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL); |
503 | 515 | |
504 | 516 | |
... | ... | @@ -507,10 +519,12 @@ |
507 | 519 | map->r_addr, map->r_netid); |
508 | 520 | |
509 | 521 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; |
510 | - if (port) | |
522 | + if (port != 0) { | |
511 | 523 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; |
524 | + is_set = true; | |
525 | + } | |
512 | 526 | |
513 | - result = rpcb_register_call(sn->rpcb_local_clnt4, msg); | |
527 | + result = rpcb_register_call(sn, sn->rpcb_local_clnt4, msg, is_set); | |
514 | 528 | kfree(map->r_addr); |
515 | 529 | return result; |
516 | 530 | } |
... | ... | @@ -527,7 +541,7 @@ |
527 | 541 | map->r_addr = ""; |
528 | 542 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; |
529 | 543 | |
530 | - return rpcb_register_call(sn->rpcb_local_clnt4, msg); | |
544 | + return rpcb_register_call(sn, sn->rpcb_local_clnt4, msg, false); | |
531 | 545 | } |
532 | 546 | |
533 | 547 | /** |