aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/sunrpc/sched.h1
-rw-r--r--net/sunrpc/clnt.c4
-rw-r--r--net/sunrpc/netns.h1
-rw-r--r--net/sunrpc/rpcb_clnt.c40
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
206static void rpcb_set_local(struct net *net, struct rpc_clnt *clnt, 206static 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
276out: 278out:
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
328out: 330out:
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
387static int rpcb_register_call(struct rpc_clnt *clnt, struct rpc_message *msg) 389static 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/**