aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/addr.c10
-rw-r--r--net/sunrpc/auth.c39
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c6
-rw-r--r--net/sunrpc/clnt.c54
-rw-r--r--net/sunrpc/rpcb_clnt.c104
-rw-r--r--net/sunrpc/sunrpc_syms.c3
-rw-r--r--net/sunrpc/xprt.c4
-rw-r--r--net/sunrpc/xprtsock.c2
8 files changed, 162 insertions, 60 deletions
diff --git a/net/sunrpc/addr.c b/net/sunrpc/addr.c
index c7450c8f0a7c..6dcdd2517819 100644
--- a/net/sunrpc/addr.c
+++ b/net/sunrpc/addr.c
@@ -55,16 +55,8 @@ static size_t rpc_ntop6_noscopeid(const struct sockaddr *sap,
55 55
56 /* 56 /*
57 * RFC 4291, Section 2.2.1 57 * RFC 4291, Section 2.2.1
58 *
59 * To keep the result as short as possible, especially
60 * since we don't shorthand, we don't want leading zeros
61 * in each halfword, so avoid %pI6.
62 */ 58 */
63 return snprintf(buf, buflen, "%x:%x:%x:%x:%x:%x:%x:%x", 59 return snprintf(buf, buflen, "%pI6c", addr);
64 ntohs(addr->s6_addr16[0]), ntohs(addr->s6_addr16[1]),
65 ntohs(addr->s6_addr16[2]), ntohs(addr->s6_addr16[3]),
66 ntohs(addr->s6_addr16[4]), ntohs(addr->s6_addr16[5]),
67 ntohs(addr->s6_addr16[6]), ntohs(addr->s6_addr16[7]));
68} 60}
69 61
70static size_t rpc_ntop6(const struct sockaddr *sap, 62static size_t rpc_ntop6(const struct sockaddr *sap,
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 7535a7bed2fa..f394fc190a49 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -123,16 +123,19 @@ rpcauth_unhash_cred_locked(struct rpc_cred *cred)
123 clear_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags); 123 clear_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags);
124} 124}
125 125
126static void 126static int
127rpcauth_unhash_cred(struct rpc_cred *cred) 127rpcauth_unhash_cred(struct rpc_cred *cred)
128{ 128{
129 spinlock_t *cache_lock; 129 spinlock_t *cache_lock;
130 int ret;
130 131
131 cache_lock = &cred->cr_auth->au_credcache->lock; 132 cache_lock = &cred->cr_auth->au_credcache->lock;
132 spin_lock(cache_lock); 133 spin_lock(cache_lock);
133 if (atomic_read(&cred->cr_count) == 0) 134 ret = atomic_read(&cred->cr_count) == 0;
135 if (ret)
134 rpcauth_unhash_cred_locked(cred); 136 rpcauth_unhash_cred_locked(cred);
135 spin_unlock(cache_lock); 137 spin_unlock(cache_lock);
138 return ret;
136} 139}
137 140
138/* 141/*
@@ -446,31 +449,35 @@ void
446put_rpccred(struct rpc_cred *cred) 449put_rpccred(struct rpc_cred *cred)
447{ 450{
448 /* Fast path for unhashed credentials */ 451 /* Fast path for unhashed credentials */
449 if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) 452 if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) == 0) {
450 goto need_lock; 453 if (atomic_dec_and_test(&cred->cr_count))
451 454 cred->cr_ops->crdestroy(cred);
452 if (!atomic_dec_and_test(&cred->cr_count))
453 return; 455 return;
454 goto out_destroy; 456 }
455need_lock: 457
456 if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock)) 458 if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock))
457 return; 459 return;
458 if (!list_empty(&cred->cr_lru)) { 460 if (!list_empty(&cred->cr_lru)) {
459 number_cred_unused--; 461 number_cred_unused--;
460 list_del_init(&cred->cr_lru); 462 list_del_init(&cred->cr_lru);
461 } 463 }
462 if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0)
463 rpcauth_unhash_cred(cred);
464 if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) { 464 if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) {
465 cred->cr_expire = jiffies; 465 if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0) {
466 list_add_tail(&cred->cr_lru, &cred_unused); 466 cred->cr_expire = jiffies;
467 number_cred_unused++; 467 list_add_tail(&cred->cr_lru, &cred_unused);
468 spin_unlock(&rpc_credcache_lock); 468 number_cred_unused++;
469 return; 469 goto out_nodestroy;
470 }
471 if (!rpcauth_unhash_cred(cred)) {
472 /* We were hashed and someone looked us up... */
473 goto out_nodestroy;
474 }
470 } 475 }
471 spin_unlock(&rpc_credcache_lock); 476 spin_unlock(&rpc_credcache_lock);
472out_destroy:
473 cred->cr_ops->crdestroy(cred); 477 cred->cr_ops->crdestroy(cred);
478 return;
479out_nodestroy:
480 spin_unlock(&rpc_credcache_lock);
474} 481}
475EXPORT_SYMBOL_GPL(put_rpccred); 482EXPORT_SYMBOL_GPL(put_rpccred);
476 483
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index fc6a43ccd950..3c3c50f38a1c 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -304,7 +304,7 @@ __gss_find_upcall(struct rpc_inode *rpci, uid_t uid)
304 * to that upcall instead of adding the new upcall. 304 * to that upcall instead of adding the new upcall.
305 */ 305 */
306static inline struct gss_upcall_msg * 306static inline struct gss_upcall_msg *
307gss_add_msg(struct gss_auth *gss_auth, struct gss_upcall_msg *gss_msg) 307gss_add_msg(struct gss_upcall_msg *gss_msg)
308{ 308{
309 struct rpc_inode *rpci = gss_msg->inode; 309 struct rpc_inode *rpci = gss_msg->inode;
310 struct inode *inode = &rpci->vfs_inode; 310 struct inode *inode = &rpci->vfs_inode;
@@ -445,7 +445,7 @@ gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cr
445 gss_new = gss_alloc_msg(gss_auth, uid, clnt, gss_cred->gc_machine_cred); 445 gss_new = gss_alloc_msg(gss_auth, uid, clnt, gss_cred->gc_machine_cred);
446 if (IS_ERR(gss_new)) 446 if (IS_ERR(gss_new))
447 return gss_new; 447 return gss_new;
448 gss_msg = gss_add_msg(gss_auth, gss_new); 448 gss_msg = gss_add_msg(gss_new);
449 if (gss_msg == gss_new) { 449 if (gss_msg == gss_new) {
450 struct inode *inode = &gss_new->inode->vfs_inode; 450 struct inode *inode = &gss_new->inode->vfs_inode;
451 int res = rpc_queue_upcall(inode, &gss_new->msg); 451 int res = rpc_queue_upcall(inode, &gss_new->msg);
@@ -485,7 +485,7 @@ gss_refresh_upcall(struct rpc_task *task)
485 dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid, 485 dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid,
486 cred->cr_uid); 486 cred->cr_uid);
487 gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred); 487 gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred);
488 if (IS_ERR(gss_msg) == -EAGAIN) { 488 if (PTR_ERR(gss_msg) == -EAGAIN) {
489 /* XXX: warning on the first, under the assumption we 489 /* XXX: warning on the first, under the assumption we
490 * shouldn't normally hit this case on a refresh. */ 490 * shouldn't normally hit this case on a refresh. */
491 warn_gssd(); 491 warn_gssd();
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 38829e20500b..154034b675bd 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -79,7 +79,7 @@ static void call_connect_status(struct rpc_task *task);
79 79
80static __be32 *rpc_encode_header(struct rpc_task *task); 80static __be32 *rpc_encode_header(struct rpc_task *task);
81static __be32 *rpc_verify_header(struct rpc_task *task); 81static __be32 *rpc_verify_header(struct rpc_task *task);
82static int rpc_ping(struct rpc_clnt *clnt, int flags); 82static int rpc_ping(struct rpc_clnt *clnt);
83 83
84static void rpc_register_client(struct rpc_clnt *clnt) 84static void rpc_register_client(struct rpc_clnt *clnt)
85{ 85{
@@ -340,7 +340,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
340 return clnt; 340 return clnt;
341 341
342 if (!(args->flags & RPC_CLNT_CREATE_NOPING)) { 342 if (!(args->flags & RPC_CLNT_CREATE_NOPING)) {
343 int err = rpc_ping(clnt, RPC_TASK_SOFT); 343 int err = rpc_ping(clnt);
344 if (err != 0) { 344 if (err != 0) {
345 rpc_shutdown_client(clnt); 345 rpc_shutdown_client(clnt);
346 return ERR_PTR(err); 346 return ERR_PTR(err);
@@ -528,7 +528,7 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old,
528 clnt->cl_prog = program->number; 528 clnt->cl_prog = program->number;
529 clnt->cl_vers = version->number; 529 clnt->cl_vers = version->number;
530 clnt->cl_stats = program->stats; 530 clnt->cl_stats = program->stats;
531 err = rpc_ping(clnt, RPC_TASK_SOFT); 531 err = rpc_ping(clnt);
532 if (err != 0) { 532 if (err != 0) {
533 rpc_shutdown_client(clnt); 533 rpc_shutdown_client(clnt);
534 clnt = ERR_PTR(err); 534 clnt = ERR_PTR(err);
@@ -1060,7 +1060,7 @@ call_bind_status(struct rpc_task *task)
1060 goto retry_timeout; 1060 goto retry_timeout;
1061 case -EPFNOSUPPORT: 1061 case -EPFNOSUPPORT:
1062 /* server doesn't support any rpcbind version we know of */ 1062 /* server doesn't support any rpcbind version we know of */
1063 dprintk("RPC: %5u remote rpcbind service unavailable\n", 1063 dprintk("RPC: %5u unrecognized remote rpcbind service\n",
1064 task->tk_pid); 1064 task->tk_pid);
1065 break; 1065 break;
1066 case -EPROTONOSUPPORT: 1066 case -EPROTONOSUPPORT:
@@ -1069,6 +1069,21 @@ call_bind_status(struct rpc_task *task)
1069 task->tk_status = 0; 1069 task->tk_status = 0;
1070 task->tk_action = call_bind; 1070 task->tk_action = call_bind;
1071 return; 1071 return;
1072 case -ECONNREFUSED: /* connection problems */
1073 case -ECONNRESET:
1074 case -ENOTCONN:
1075 case -EHOSTDOWN:
1076 case -EHOSTUNREACH:
1077 case -ENETUNREACH:
1078 case -EPIPE:
1079 dprintk("RPC: %5u remote rpcbind unreachable: %d\n",
1080 task->tk_pid, task->tk_status);
1081 if (!RPC_IS_SOFTCONN(task)) {
1082 rpc_delay(task, 5*HZ);
1083 goto retry_timeout;
1084 }
1085 status = task->tk_status;
1086 break;
1072 default: 1087 default:
1073 dprintk("RPC: %5u unrecognized rpcbind error (%d)\n", 1088 dprintk("RPC: %5u unrecognized rpcbind error (%d)\n",
1074 task->tk_pid, -task->tk_status); 1089 task->tk_pid, -task->tk_status);
@@ -1180,11 +1195,25 @@ static void
1180call_transmit_status(struct rpc_task *task) 1195call_transmit_status(struct rpc_task *task)
1181{ 1196{
1182 task->tk_action = call_status; 1197 task->tk_action = call_status;
1198
1199 /*
1200 * Common case: success. Force the compiler to put this
1201 * test first.
1202 */
1203 if (task->tk_status == 0) {
1204 xprt_end_transmit(task);
1205 rpc_task_force_reencode(task);
1206 return;
1207 }
1208
1183 switch (task->tk_status) { 1209 switch (task->tk_status) {
1184 case -EAGAIN: 1210 case -EAGAIN:
1185 break; 1211 break;
1186 default: 1212 default:
1213 dprint_status(task);
1187 xprt_end_transmit(task); 1214 xprt_end_transmit(task);
1215 rpc_task_force_reencode(task);
1216 break;
1188 /* 1217 /*
1189 * Special cases: if we've been waiting on the 1218 * Special cases: if we've been waiting on the
1190 * socket's write_space() callback, or if the 1219 * socket's write_space() callback, or if the
@@ -1192,11 +1221,16 @@ call_transmit_status(struct rpc_task *task)
1192 * then hold onto the transport lock. 1221 * then hold onto the transport lock.
1193 */ 1222 */
1194 case -ECONNREFUSED: 1223 case -ECONNREFUSED:
1195 case -ECONNRESET:
1196 case -ENOTCONN:
1197 case -EHOSTDOWN: 1224 case -EHOSTDOWN:
1198 case -EHOSTUNREACH: 1225 case -EHOSTUNREACH:
1199 case -ENETUNREACH: 1226 case -ENETUNREACH:
1227 if (RPC_IS_SOFTCONN(task)) {
1228 xprt_end_transmit(task);
1229 rpc_exit(task, task->tk_status);
1230 break;
1231 }
1232 case -ECONNRESET:
1233 case -ENOTCONN:
1200 case -EPIPE: 1234 case -EPIPE:
1201 rpc_task_force_reencode(task); 1235 rpc_task_force_reencode(task);
1202 } 1236 }
@@ -1346,6 +1380,10 @@ call_timeout(struct rpc_task *task)
1346 dprintk("RPC: %5u call_timeout (major)\n", task->tk_pid); 1380 dprintk("RPC: %5u call_timeout (major)\n", task->tk_pid);
1347 task->tk_timeouts++; 1381 task->tk_timeouts++;
1348 1382
1383 if (RPC_IS_SOFTCONN(task)) {
1384 rpc_exit(task, -ETIMEDOUT);
1385 return;
1386 }
1349 if (RPC_IS_SOFT(task)) { 1387 if (RPC_IS_SOFT(task)) {
1350 if (clnt->cl_chatty) 1388 if (clnt->cl_chatty)
1351 printk(KERN_NOTICE "%s: server %s not responding, timed out\n", 1389 printk(KERN_NOTICE "%s: server %s not responding, timed out\n",
@@ -1675,14 +1713,14 @@ static struct rpc_procinfo rpcproc_null = {
1675 .p_decode = rpcproc_decode_null, 1713 .p_decode = rpcproc_decode_null,
1676}; 1714};
1677 1715
1678static int rpc_ping(struct rpc_clnt *clnt, int flags) 1716static int rpc_ping(struct rpc_clnt *clnt)
1679{ 1717{
1680 struct rpc_message msg = { 1718 struct rpc_message msg = {
1681 .rpc_proc = &rpcproc_null, 1719 .rpc_proc = &rpcproc_null,
1682 }; 1720 };
1683 int err; 1721 int err;
1684 msg.rpc_cred = authnull_ops.lookup_cred(NULL, NULL, 0); 1722 msg.rpc_cred = authnull_ops.lookup_cred(NULL, NULL, 0);
1685 err = rpc_call_sync(clnt, &msg, flags); 1723 err = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN);
1686 put_rpccred(msg.rpc_cred); 1724 put_rpccred(msg.rpc_cred);
1687 return err; 1725 return err;
1688} 1726}
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 830faf4d9997..3e3772d8eb92 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -20,6 +20,7 @@
20#include <linux/in6.h> 20#include <linux/in6.h>
21#include <linux/kernel.h> 21#include <linux/kernel.h>
22#include <linux/errno.h> 22#include <linux/errno.h>
23#include <linux/mutex.h>
23#include <net/ipv6.h> 24#include <net/ipv6.h>
24 25
25#include <linux/sunrpc/clnt.h> 26#include <linux/sunrpc/clnt.h>
@@ -110,6 +111,9 @@ static void rpcb_getport_done(struct rpc_task *, void *);
110static void rpcb_map_release(void *data); 111static void rpcb_map_release(void *data);
111static struct rpc_program rpcb_program; 112static struct rpc_program rpcb_program;
112 113
114static struct rpc_clnt * rpcb_local_clnt;
115static struct rpc_clnt * rpcb_local_clnt4;
116
113struct rpcbind_args { 117struct rpcbind_args {
114 struct rpc_xprt * r_xprt; 118 struct rpc_xprt * r_xprt;
115 119
@@ -163,21 +167,60 @@ static const struct sockaddr_in rpcb_inaddr_loopback = {
163 .sin_port = htons(RPCBIND_PORT), 167 .sin_port = htons(RPCBIND_PORT),
164}; 168};
165 169
166static struct rpc_clnt *rpcb_create_local(struct sockaddr *addr, 170static DEFINE_MUTEX(rpcb_create_local_mutex);
167 size_t addrlen, u32 version) 171
172/*
173 * Returns zero on success, otherwise a negative errno value
174 * is returned.
175 */
176static int rpcb_create_local(void)
168{ 177{
169 struct rpc_create_args args = { 178 struct rpc_create_args args = {
170 .protocol = XPRT_TRANSPORT_UDP, 179 .protocol = XPRT_TRANSPORT_TCP,
171 .address = addr, 180 .address = (struct sockaddr *)&rpcb_inaddr_loopback,
172 .addrsize = addrlen, 181 .addrsize = sizeof(rpcb_inaddr_loopback),
173 .servername = "localhost", 182 .servername = "localhost",
174 .program = &rpcb_program, 183 .program = &rpcb_program,
175 .version = version, 184 .version = RPCBVERS_2,
176 .authflavor = RPC_AUTH_UNIX, 185 .authflavor = RPC_AUTH_UNIX,
177 .flags = RPC_CLNT_CREATE_NOPING, 186 .flags = RPC_CLNT_CREATE_NOPING,
178 }; 187 };
188 struct rpc_clnt *clnt, *clnt4;
189 int result = 0;
190
191 if (rpcb_local_clnt)
192 return result;
193
194 mutex_lock(&rpcb_create_local_mutex);
195 if (rpcb_local_clnt)
196 goto out;
197
198 clnt = rpc_create(&args);
199 if (IS_ERR(clnt)) {
200 dprintk("RPC: failed to create local rpcbind "
201 "client (errno %ld).\n", PTR_ERR(clnt));
202 result = -PTR_ERR(clnt);
203 goto out;
204 }
179 205
180 return rpc_create(&args); 206 /*
207 * This results in an RPC ping. On systems running portmapper,
208 * the v4 ping will fail. Proceed anyway, but disallow rpcb
209 * v4 upcalls.
210 */
211 clnt4 = rpc_bind_new_program(clnt, &rpcb_program, RPCBVERS_4);
212 if (IS_ERR(clnt4)) {
213 dprintk("RPC: failed to create local rpcbind v4 "
214 "cleint (errno %ld).\n", PTR_ERR(clnt4));
215 clnt4 = NULL;
216 }
217
218 rpcb_local_clnt = clnt;
219 rpcb_local_clnt4 = clnt4;
220
221out:
222 mutex_unlock(&rpcb_create_local_mutex);
223 return result;
181} 224}
182 225
183static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, 226static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
@@ -209,22 +252,13 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
209 return rpc_create(&args); 252 return rpc_create(&args);
210} 253}
211 254
212static int rpcb_register_call(const u32 version, struct rpc_message *msg) 255static int rpcb_register_call(struct rpc_clnt *clnt, struct rpc_message *msg)
213{ 256{
214 struct sockaddr *addr = (struct sockaddr *)&rpcb_inaddr_loopback;
215 size_t addrlen = sizeof(rpcb_inaddr_loopback);
216 struct rpc_clnt *rpcb_clnt;
217 int result, error = 0; 257 int result, error = 0;
218 258
219 msg->rpc_resp = &result; 259 msg->rpc_resp = &result;
220 260
221 rpcb_clnt = rpcb_create_local(addr, addrlen, version); 261 error = rpc_call_sync(clnt, msg, RPC_TASK_SOFTCONN);
222 if (!IS_ERR(rpcb_clnt)) {
223 error = rpc_call_sync(rpcb_clnt, msg, 0);
224 rpc_shutdown_client(rpcb_clnt);
225 } else
226 error = PTR_ERR(rpcb_clnt);
227
228 if (error < 0) { 262 if (error < 0) {
229 dprintk("RPC: failed to contact local rpcbind " 263 dprintk("RPC: failed to contact local rpcbind "
230 "server (errno %d).\n", -error); 264 "server (errno %d).\n", -error);
@@ -279,6 +313,11 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port)
279 struct rpc_message msg = { 313 struct rpc_message msg = {
280 .rpc_argp = &map, 314 .rpc_argp = &map,
281 }; 315 };
316 int error;
317
318 error = rpcb_create_local();
319 if (error)
320 return error;
282 321
283 dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " 322 dprintk("RPC: %sregistering (%u, %u, %d, %u) with local "
284 "rpcbind\n", (port ? "" : "un"), 323 "rpcbind\n", (port ? "" : "un"),
@@ -288,7 +327,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port)
288 if (port) 327 if (port)
289 msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET]; 328 msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET];
290 329
291 return rpcb_register_call(RPCBVERS_2, &msg); 330 return rpcb_register_call(rpcb_local_clnt, &msg);
292} 331}
293 332
294/* 333/*
@@ -313,7 +352,7 @@ static int rpcb_register_inet4(const struct sockaddr *sap,
313 if (port) 352 if (port)
314 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; 353 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
315 354
316 result = rpcb_register_call(RPCBVERS_4, msg); 355 result = rpcb_register_call(rpcb_local_clnt4, msg);
317 kfree(map->r_addr); 356 kfree(map->r_addr);
318 return result; 357 return result;
319} 358}
@@ -340,7 +379,7 @@ static int rpcb_register_inet6(const struct sockaddr *sap,
340 if (port) 379 if (port)
341 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; 380 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
342 381
343 result = rpcb_register_call(RPCBVERS_4, msg); 382 result = rpcb_register_call(rpcb_local_clnt4, msg);
344 kfree(map->r_addr); 383 kfree(map->r_addr);
345 return result; 384 return result;
346} 385}
@@ -356,7 +395,7 @@ static int rpcb_unregister_all_protofamilies(struct rpc_message *msg)
356 map->r_addr = ""; 395 map->r_addr = "";
357 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; 396 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
358 397
359 return rpcb_register_call(RPCBVERS_4, msg); 398 return rpcb_register_call(rpcb_local_clnt4, msg);
360} 399}
361 400
362/** 401/**
@@ -414,6 +453,13 @@ int rpcb_v4_register(const u32 program, const u32 version,
414 struct rpc_message msg = { 453 struct rpc_message msg = {
415 .rpc_argp = &map, 454 .rpc_argp = &map,
416 }; 455 };
456 int error;
457
458 error = rpcb_create_local();
459 if (error)
460 return error;
461 if (rpcb_local_clnt4 == NULL)
462 return -EPROTONOSUPPORT;
417 463
418 if (address == NULL) 464 if (address == NULL)
419 return rpcb_unregister_all_protofamilies(&msg); 465 return rpcb_unregister_all_protofamilies(&msg);
@@ -491,7 +537,7 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi
491 .rpc_message = &msg, 537 .rpc_message = &msg,
492 .callback_ops = &rpcb_getport_ops, 538 .callback_ops = &rpcb_getport_ops,
493 .callback_data = map, 539 .callback_data = map,
494 .flags = RPC_TASK_ASYNC, 540 .flags = RPC_TASK_ASYNC | RPC_TASK_SOFTCONN,
495 }; 541 };
496 542
497 return rpc_run_task(&task_setup_data); 543 return rpc_run_task(&task_setup_data);
@@ -1027,3 +1073,15 @@ static struct rpc_program rpcb_program = {
1027 .version = rpcb_version, 1073 .version = rpcb_version,
1028 .stats = &rpcb_stats, 1074 .stats = &rpcb_stats,
1029}; 1075};
1076
1077/**
1078 * cleanup_rpcb_clnt - remove xprtsock's sysctls, unregister
1079 *
1080 */
1081void cleanup_rpcb_clnt(void)
1082{
1083 if (rpcb_local_clnt4)
1084 rpc_shutdown_client(rpcb_local_clnt4);
1085 if (rpcb_local_clnt)
1086 rpc_shutdown_client(rpcb_local_clnt);
1087}
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index 8cce92189019..f438347d817b 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -24,6 +24,8 @@
24 24
25extern struct cache_detail ip_map_cache, unix_gid_cache; 25extern struct cache_detail ip_map_cache, unix_gid_cache;
26 26
27extern void cleanup_rpcb_clnt(void);
28
27static int __init 29static int __init
28init_sunrpc(void) 30init_sunrpc(void)
29{ 31{
@@ -53,6 +55,7 @@ out:
53static void __exit 55static void __exit
54cleanup_sunrpc(void) 56cleanup_sunrpc(void)
55{ 57{
58 cleanup_rpcb_clnt();
56 rpcauth_remove_module(); 59 rpcauth_remove_module();
57 cleanup_socket_xprt(); 60 cleanup_socket_xprt();
58 svc_cleanup_xprt_sock(); 61 svc_cleanup_xprt_sock();
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index fd46d42afa89..469de292c23c 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -700,6 +700,10 @@ void xprt_connect(struct rpc_task *task)
700 } 700 }
701 if (!xprt_lock_write(xprt, task)) 701 if (!xprt_lock_write(xprt, task))
702 return; 702 return;
703
704 if (test_and_clear_bit(XPRT_CLOSE_WAIT, &xprt->state))
705 xprt->ops->close(xprt);
706
703 if (xprt_connected(xprt)) 707 if (xprt_connected(xprt))
704 xprt_release_write(xprt, task); 708 xprt_release_write(xprt, task);
705 else { 709 else {
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 04732d09013e..3d739e5d15d8 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -2019,7 +2019,7 @@ static void xs_connect(struct rpc_task *task)
2019 if (xprt_test_and_set_connecting(xprt)) 2019 if (xprt_test_and_set_connecting(xprt))
2020 return; 2020 return;
2021 2021
2022 if (transport->sock != NULL) { 2022 if (transport->sock != NULL && !RPC_IS_SOFTCONN(task)) {
2023 dprintk("RPC: xs_connect delayed xprt %p for %lu " 2023 dprintk("RPC: xs_connect delayed xprt %p for %lu "
2024 "seconds\n", 2024 "seconds\n",
2025 xprt, xprt->reestablish_timeout / HZ); 2025 xprt, xprt->reestablish_timeout / HZ);