aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/lockd/mon.c2
-rw-r--r--fs/nfs/mount_clnt.c4
-rw-r--r--include/linux/sunrpc/clnt.h10
-rw-r--r--net/sunrpc/clnt.c10
-rw-r--r--net/sunrpc/rpcb_clnt.c6
-rw-r--r--net/sunrpc/sched.c14
6 files changed, 14 insertions, 32 deletions
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 2102e2d0134d..3353ed8421a7 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -61,6 +61,7 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res)
61 status); 61 status);
62 else 62 else
63 status = 0; 63 status = 0;
64 rpc_shutdown_client(clnt);
64 out: 65 out:
65 return status; 66 return status;
66} 67}
@@ -138,7 +139,6 @@ nsm_create(void)
138 .program = &nsm_program, 139 .program = &nsm_program,
139 .version = SM_VERSION, 140 .version = SM_VERSION,
140 .authflavor = RPC_AUTH_NULL, 141 .authflavor = RPC_AUTH_NULL,
141 .flags = (RPC_CLNT_CREATE_ONESHOT),
142 }; 142 };
143 143
144 return rpc_create(&args); 144 return rpc_create(&args);
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index ca5a266a3140..878d7a5cb6d4 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -69,6 +69,7 @@ nfsroot_mount(struct sockaddr_in *addr, char *path, struct nfs_fh *fh,
69 msg.rpc_proc = &mnt_clnt->cl_procinfo[MNTPROC_MNT]; 69 msg.rpc_proc = &mnt_clnt->cl_procinfo[MNTPROC_MNT];
70 70
71 status = rpc_call_sync(mnt_clnt, &msg, 0); 71 status = rpc_call_sync(mnt_clnt, &msg, 0);
72 rpc_shutdown_client(mnt_clnt);
72 return status < 0? status : (result.status? -EACCES : 0); 73 return status < 0? status : (result.status? -EACCES : 0);
73} 74}
74 75
@@ -84,8 +85,7 @@ mnt_create(char *hostname, struct sockaddr_in *srvaddr, int version,
84 .program = &mnt_program, 85 .program = &mnt_program,
85 .version = version, 86 .version = version,
86 .authflavor = RPC_AUTH_UNIX, 87 .authflavor = RPC_AUTH_UNIX,
87 .flags = (RPC_CLNT_CREATE_ONESHOT | 88 .flags = RPC_CLNT_CREATE_INTR,
88 RPC_CLNT_CREATE_INTR),
89 }; 89 };
90 90
91 return rpc_create(&args); 91 return rpc_create(&args);
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index ab3ef6d629a7..fe7ea65ed0ae 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -44,8 +44,7 @@ struct rpc_clnt {
44 unsigned int cl_softrtry : 1,/* soft timeouts */ 44 unsigned int cl_softrtry : 1,/* soft timeouts */
45 cl_intr : 1,/* interruptible */ 45 cl_intr : 1,/* interruptible */
46 cl_discrtry : 1,/* disconnect before retry */ 46 cl_discrtry : 1,/* disconnect before retry */
47 cl_autobind : 1,/* use getport() */ 47 cl_autobind : 1;/* use getport() */
48 cl_oneshot : 1;/* dispose after use */
49 48
50 struct rpc_rtt * cl_rtt; /* RTO estimator data */ 49 struct rpc_rtt * cl_rtt; /* RTO estimator data */
51 50
@@ -112,10 +111,9 @@ struct rpc_create_args {
112#define RPC_CLNT_CREATE_HARDRTRY (1UL << 0) 111#define RPC_CLNT_CREATE_HARDRTRY (1UL << 0)
113#define RPC_CLNT_CREATE_INTR (1UL << 1) 112#define RPC_CLNT_CREATE_INTR (1UL << 1)
114#define RPC_CLNT_CREATE_AUTOBIND (1UL << 2) 113#define RPC_CLNT_CREATE_AUTOBIND (1UL << 2)
115#define RPC_CLNT_CREATE_ONESHOT (1UL << 3) 114#define RPC_CLNT_CREATE_NONPRIVPORT (1UL << 3)
116#define RPC_CLNT_CREATE_NONPRIVPORT (1UL << 4) 115#define RPC_CLNT_CREATE_NOPING (1UL << 4)
117#define RPC_CLNT_CREATE_NOPING (1UL << 5) 116#define RPC_CLNT_CREATE_DISCRTRY (1UL << 5)
118#define RPC_CLNT_CREATE_DISCRTRY (1UL << 6)
119 117
120struct rpc_clnt *rpc_create(struct rpc_create_args *args); 118struct rpc_clnt *rpc_create(struct rpc_create_args *args);
121struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *, 119struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *,
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index fb65249538d4..34662dfa9cc0 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -249,8 +249,6 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
249 clnt->cl_intr = 1; 249 clnt->cl_intr = 1;
250 if (args->flags & RPC_CLNT_CREATE_AUTOBIND) 250 if (args->flags & RPC_CLNT_CREATE_AUTOBIND)
251 clnt->cl_autobind = 1; 251 clnt->cl_autobind = 1;
252 if (args->flags & RPC_CLNT_CREATE_ONESHOT)
253 clnt->cl_oneshot = 1;
254 if (args->flags & RPC_CLNT_CREATE_DISCRTRY) 252 if (args->flags & RPC_CLNT_CREATE_DISCRTRY)
255 clnt->cl_discrtry = 1; 253 clnt->cl_discrtry = 1;
256 254
@@ -285,7 +283,6 @@ rpc_clone_client(struct rpc_clnt *clnt)
285 new->cl_xprt = xprt_get(clnt->cl_xprt); 283 new->cl_xprt = xprt_get(clnt->cl_xprt);
286 /* Turn off autobind on clones */ 284 /* Turn off autobind on clones */
287 new->cl_autobind = 0; 285 new->cl_autobind = 0;
288 new->cl_oneshot = 0;
289 INIT_LIST_HEAD(&new->cl_tasks); 286 INIT_LIST_HEAD(&new->cl_tasks);
290 spin_lock_init(&new->cl_lock); 287 spin_lock_init(&new->cl_lock);
291 rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); 288 rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
@@ -304,8 +301,7 @@ out_no_clnt:
304 301
305/* 302/*
306 * Properly shut down an RPC client, terminating all outstanding 303 * Properly shut down an RPC client, terminating all outstanding
307 * requests. Note that we must be certain that cl_oneshot is cleared, 304 * requests.
308 * or else the client would be destroyed when the last task releases it.
309 */ 305 */
310int 306int
311rpc_shutdown_client(struct rpc_clnt *clnt) 307rpc_shutdown_client(struct rpc_clnt *clnt)
@@ -314,8 +310,6 @@ rpc_shutdown_client(struct rpc_clnt *clnt)
314 clnt->cl_protname, clnt->cl_server); 310 clnt->cl_protname, clnt->cl_server);
315 311
316 while (!list_empty(&clnt->cl_tasks)) { 312 while (!list_empty(&clnt->cl_tasks)) {
317 /* Don't let rpc_release_client destroy us */
318 clnt->cl_oneshot = 0;
319 rpc_killall_tasks(clnt); 313 rpc_killall_tasks(clnt);
320 wait_event_timeout(destroy_wait, 314 wait_event_timeout(destroy_wait,
321 list_empty(&clnt->cl_tasks), 1*HZ); 315 list_empty(&clnt->cl_tasks), 1*HZ);
@@ -366,8 +360,6 @@ rpc_release_client(struct rpc_clnt *clnt)
366 360
367 if (list_empty(&clnt->cl_tasks)) 361 if (list_empty(&clnt->cl_tasks))
368 wake_up(&destroy_wait); 362 wake_up(&destroy_wait);
369 if (clnt->cl_oneshot)
370 rpc_destroy_client(clnt);
371 kref_put(&clnt->cl_kref, rpc_free_client); 363 kref_put(&clnt->cl_kref, rpc_free_client);
372} 364}
373 365
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 6c7aa8a1f0c6..00853a326499 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -184,8 +184,7 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
184 .program = &rpcb_program, 184 .program = &rpcb_program,
185 .version = version, 185 .version = version,
186 .authflavor = RPC_AUTH_UNIX, 186 .authflavor = RPC_AUTH_UNIX,
187 .flags = (RPC_CLNT_CREATE_ONESHOT | 187 .flags = RPC_CLNT_CREATE_NOPING,
188 RPC_CLNT_CREATE_NOPING),
189 }; 188 };
190 189
191 ((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT); 190 ((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT);
@@ -238,6 +237,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
238 237
239 error = rpc_call_sync(rpcb_clnt, &msg, 0); 238 error = rpc_call_sync(rpcb_clnt, &msg, 0);
240 239
240 rpc_shutdown_client(rpcb_clnt);
241 if (error < 0) 241 if (error < 0)
242 printk(KERN_WARNING "RPC: failed to contact local rpcbind " 242 printk(KERN_WARNING "RPC: failed to contact local rpcbind "
243 "server (errno %d).\n", -error); 243 "server (errno %d).\n", -error);
@@ -286,6 +286,7 @@ int rpcb_getport_external(struct sockaddr_in *sin, __u32 prog,
286 return PTR_ERR(rpcb_clnt); 286 return PTR_ERR(rpcb_clnt);
287 287
288 status = rpc_call_sync(rpcb_clnt, &msg, 0); 288 status = rpc_call_sync(rpcb_clnt, &msg, 0);
289 rpc_shutdown_client(rpcb_clnt);
289 290
290 if (status >= 0) { 291 if (status >= 0) {
291 if (map.r_port != 0) 292 if (map.r_port != 0)
@@ -379,6 +380,7 @@ void rpcb_getport(struct rpc_task *task)
379 } 380 }
380 381
381 child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map); 382 child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map);
383 rpc_destroy_client(rpcb_clnt);
382 if (IS_ERR(child)) { 384 if (IS_ERR(child)) {
383 status = -EIO; 385 status = -EIO;
384 dprintk("RPC: %5u rpcb_getport rpc_run_task failed\n", 386 dprintk("RPC: %5u rpcb_getport rpc_run_task failed\n",
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index bb12983580a0..d95fe4e40eb4 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -876,9 +876,7 @@ static void rpc_free_task(struct rcu_head *rcu)
876} 876}
877 877
878/* 878/*
879 * Create a new task for the specified client. We have to 879 * Create a new task for the specified client.
880 * clean up after an allocation failure, as the client may
881 * have specified "oneshot".
882 */ 880 */
883struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *calldata) 881struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *calldata)
884{ 882{
@@ -886,7 +884,7 @@ struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc
886 884
887 task = rpc_alloc_task(); 885 task = rpc_alloc_task();
888 if (!task) 886 if (!task)
889 goto cleanup; 887 goto out;
890 888
891 rpc_init_task(task, clnt, flags, tk_ops, calldata); 889 rpc_init_task(task, clnt, flags, tk_ops, calldata);
892 890
@@ -894,14 +892,6 @@ struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc
894 task->tk_flags |= RPC_TASK_DYNAMIC; 892 task->tk_flags |= RPC_TASK_DYNAMIC;
895out: 893out:
896 return task; 894 return task;
897
898cleanup:
899 /* Check whether to release the client */
900 if (clnt) {
901 kref_get(&clnt->cl_kref); /* pretend we were used ... */
902 rpc_release_client(clnt);
903 }
904 goto out;
905} 895}
906 896
907 897