diff options
-rw-r--r-- | include/linux/sunrpc/sched.h | 1 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 4 | ||||
-rw-r--r-- | net/sunrpc/netns.h | 1 | ||||
-rw-r--r-- | net/sunrpc/rpcb_clnt.c | 40 |
4 files changed, 33 insertions, 13 deletions
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index 6d870353674a..1821445708d6 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h | |||
@@ -121,6 +121,7 @@ struct rpc_task_setup { | |||
121 | #define RPC_TASK_SOFTCONN 0x0400 /* Fail if can't connect */ | 121 | #define RPC_TASK_SOFTCONN 0x0400 /* Fail if can't connect */ |
122 | #define RPC_TASK_SENT 0x0800 /* message was sent */ | 122 | #define RPC_TASK_SENT 0x0800 /* message was sent */ |
123 | #define RPC_TASK_TIMEOUT 0x1000 /* fail with ETIMEDOUT on timeout */ | 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 | #define RPC_IS_ASYNC(t) ((t)->tk_flags & RPC_TASK_ASYNC) | 126 | #define RPC_IS_ASYNC(t) ((t)->tk_flags & RPC_TASK_ASYNC) |
126 | #define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER) | 127 | #define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER) |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 74f6a704e374..ecbc4e3d83ad 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -1660,6 +1660,10 @@ call_connect(struct rpc_task *task) | |||
1660 | task->tk_action = call_connect_status; | 1660 | task->tk_action = call_connect_status; |
1661 | if (task->tk_status < 0) | 1661 | if (task->tk_status < 0) |
1662 | return; | 1662 | return; |
1663 | if (task->tk_flags & RPC_TASK_NOCONNECT) { | ||
1664 | rpc_exit(task, -ENOTCONN); | ||
1665 | return; | ||
1666 | } | ||
1663 | xprt_connect(task); | 1667 | xprt_connect(task); |
1664 | } | 1668 | } |
1665 | } | 1669 | } |
diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h index 74d948f5d5a1..779742cfc1ff 100644 --- a/net/sunrpc/netns.h +++ b/net/sunrpc/netns.h | |||
@@ -23,6 +23,7 @@ struct sunrpc_net { | |||
23 | struct rpc_clnt *rpcb_local_clnt4; | 23 | struct rpc_clnt *rpcb_local_clnt4; |
24 | spinlock_t rpcb_clnt_lock; | 24 | spinlock_t rpcb_clnt_lock; |
25 | unsigned int rpcb_users; | 25 | unsigned int rpcb_users; |
26 | unsigned int rpcb_is_af_local : 1; | ||
26 | 27 | ||
27 | struct mutex gssp_lock; | 28 | struct mutex gssp_lock; |
28 | wait_queue_head_t gssp_wq; | 29 | wait_queue_head_t gssp_wq; |
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index b0f723227157..1891a1022c17 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c | |||
@@ -204,13 +204,15 @@ void rpcb_put_local(struct net *net) | |||
204 | } | 204 | } |
205 | 205 | ||
206 | static void rpcb_set_local(struct net *net, struct rpc_clnt *clnt, | 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 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 210 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
210 | 211 | ||
211 | /* Protected by rpcb_create_local_mutex */ | 212 | /* Protected by rpcb_create_local_mutex */ |
212 | sn->rpcb_local_clnt = clnt; | 213 | sn->rpcb_local_clnt = clnt; |
213 | sn->rpcb_local_clnt4 = clnt4; | 214 | sn->rpcb_local_clnt4 = clnt4; |
215 | sn->rpcb_is_af_local = is_af_local ? 1 : 0; | ||
214 | smp_wmb(); | 216 | smp_wmb(); |
215 | sn->rpcb_users = 1; | 217 | sn->rpcb_users = 1; |
216 | dprintk("RPC: created new rpcb local clients (rpcb_local_clnt: " | 218 | dprintk("RPC: created new rpcb local clients (rpcb_local_clnt: " |
@@ -271,7 +273,7 @@ static int rpcb_create_local_unix(struct net *net) | |||
271 | clnt4 = NULL; | 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 | out: | 278 | out: |
277 | return result; | 279 | return result; |
@@ -323,7 +325,7 @@ static int rpcb_create_local_net(struct net *net) | |||
323 | clnt4 = NULL; | 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 | out: | 330 | out: |
329 | return result; | 331 | return result; |
@@ -384,13 +386,16 @@ static struct rpc_clnt *rpcb_create(struct net *net, const char *hostname, | |||
384 | return rpc_create(&args); | 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 | msg->rpc_resp = &result; | 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 | if (error < 0) { | 399 | if (error < 0) { |
395 | dprintk("RPC: failed to contact local rpcbind " | 400 | dprintk("RPC: failed to contact local rpcbind " |
396 | "server (errno %d).\n", -error); | 401 | "server (errno %d).\n", -error); |
@@ -447,16 +452,19 @@ int rpcb_register(struct net *net, u32 prog, u32 vers, int prot, unsigned short | |||
447 | .rpc_argp = &map, | 452 | .rpc_argp = &map, |
448 | }; | 453 | }; |
449 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 454 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
455 | bool is_set = false; | ||
450 | 456 | ||
451 | dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " | 457 | dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " |
452 | "rpcbind\n", (port ? "" : "un"), | 458 | "rpcbind\n", (port ? "" : "un"), |
453 | prog, vers, prot, port); | 459 | prog, vers, prot, port); |
454 | 460 | ||
455 | msg.rpc_proc = &rpcb_procedures2[RPCBPROC_UNSET]; | 461 | msg.rpc_proc = &rpcb_procedures2[RPCBPROC_UNSET]; |
456 | if (port) | 462 | if (port != 0) { |
457 | msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET]; | 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 @@ static int rpcb_register_inet4(struct sunrpc_net *sn, | |||
469 | const struct sockaddr_in *sin = (const struct sockaddr_in *)sap; | 477 | const struct sockaddr_in *sin = (const struct sockaddr_in *)sap; |
470 | struct rpcbind_args *map = msg->rpc_argp; | 478 | struct rpcbind_args *map = msg->rpc_argp; |
471 | unsigned short port = ntohs(sin->sin_port); | 479 | unsigned short port = ntohs(sin->sin_port); |
480 | bool is_set = false; | ||
472 | int result; | 481 | int result; |
473 | 482 | ||
474 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL); | 483 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL); |
@@ -479,10 +488,12 @@ static int rpcb_register_inet4(struct sunrpc_net *sn, | |||
479 | map->r_addr, map->r_netid); | 488 | map->r_addr, map->r_netid); |
480 | 489 | ||
481 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; | 490 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; |
482 | if (port) | 491 | if (port != 0) { |
483 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; | 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 | kfree(map->r_addr); | 497 | kfree(map->r_addr); |
487 | return result; | 498 | return result; |
488 | } | 499 | } |
@@ -497,6 +508,7 @@ static int rpcb_register_inet6(struct sunrpc_net *sn, | |||
497 | const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap; | 508 | const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap; |
498 | struct rpcbind_args *map = msg->rpc_argp; | 509 | struct rpcbind_args *map = msg->rpc_argp; |
499 | unsigned short port = ntohs(sin6->sin6_port); | 510 | unsigned short port = ntohs(sin6->sin6_port); |
511 | bool is_set = false; | ||
500 | int result; | 512 | int result; |
501 | 513 | ||
502 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL); | 514 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL); |
@@ -507,10 +519,12 @@ static int rpcb_register_inet6(struct sunrpc_net *sn, | |||
507 | map->r_addr, map->r_netid); | 519 | map->r_addr, map->r_netid); |
508 | 520 | ||
509 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; | 521 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; |
510 | if (port) | 522 | if (port != 0) { |
511 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; | 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 | kfree(map->r_addr); | 528 | kfree(map->r_addr); |
515 | return result; | 529 | return result; |
516 | } | 530 | } |
@@ -527,7 +541,7 @@ static int rpcb_unregister_all_protofamilies(struct sunrpc_net *sn, | |||
527 | map->r_addr = ""; | 541 | map->r_addr = ""; |
528 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; | 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 | /** |