aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/rpcb_clnt.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/rpcb_clnt.c')
-rw-r--r--net/sunrpc/rpcb_clnt.c65
1 files changed, 35 insertions, 30 deletions
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 6c7aa8a1f0c6..d1740dbab991 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -12,6 +12,8 @@
12 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> 12 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
13 */ 13 */
14 14
15#include <linux/module.h>
16
15#include <linux/types.h> 17#include <linux/types.h>
16#include <linux/socket.h> 18#include <linux/socket.h>
17#include <linux/kernel.h> 19#include <linux/kernel.h>
@@ -184,8 +186,8 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
184 .program = &rpcb_program, 186 .program = &rpcb_program,
185 .version = version, 187 .version = version,
186 .authflavor = RPC_AUTH_UNIX, 188 .authflavor = RPC_AUTH_UNIX,
187 .flags = (RPC_CLNT_CREATE_ONESHOT | 189 .flags = (RPC_CLNT_CREATE_NOPING |
188 RPC_CLNT_CREATE_NOPING), 190 RPC_CLNT_CREATE_INTR),
189 }; 191 };
190 192
191 ((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT); 193 ((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT);
@@ -238,6 +240,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
238 240
239 error = rpc_call_sync(rpcb_clnt, &msg, 0); 241 error = rpc_call_sync(rpcb_clnt, &msg, 0);
240 242
243 rpc_shutdown_client(rpcb_clnt);
241 if (error < 0) 244 if (error < 0)
242 printk(KERN_WARNING "RPC: failed to contact local rpcbind " 245 printk(KERN_WARNING "RPC: failed to contact local rpcbind "
243 "server (errno %d).\n", -error); 246 "server (errno %d).\n", -error);
@@ -246,21 +249,20 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
246 return error; 249 return error;
247} 250}
248 251
249#ifdef CONFIG_ROOT_NFS
250/** 252/**
251 * rpcb_getport_external - obtain the port for an RPC service on a given host 253 * rpcb_getport_sync - obtain the port for an RPC service on a given host
252 * @sin: address of remote peer 254 * @sin: address of remote peer
253 * @prog: RPC program number to bind 255 * @prog: RPC program number to bind
254 * @vers: RPC version number to bind 256 * @vers: RPC version number to bind
255 * @prot: transport protocol to use to make this request 257 * @prot: transport protocol to use to make this request
256 * 258 *
257 * Called from outside the RPC client in a synchronous task context. 259 * Called from outside the RPC client in a synchronous task context.
260 * Uses default timeout parameters specified by underlying transport.
258 * 261 *
259 * For now, this supports only version 2 queries, but is used only by 262 * XXX: Needs to support IPv6, and rpcbind versions 3 and 4
260 * mount_clnt for NFS_ROOT.
261 */ 263 */
262int rpcb_getport_external(struct sockaddr_in *sin, __u32 prog, 264int rpcb_getport_sync(struct sockaddr_in *sin, __u32 prog,
263 __u32 vers, int prot) 265 __u32 vers, int prot)
264{ 266{
265 struct rpcbind_args map = { 267 struct rpcbind_args map = {
266 .r_prog = prog, 268 .r_prog = prog,
@@ -277,15 +279,16 @@ int rpcb_getport_external(struct sockaddr_in *sin, __u32 prog,
277 char hostname[40]; 279 char hostname[40];
278 int status; 280 int status;
279 281
280 dprintk("RPC: rpcb_getport_external(%u.%u.%u.%u, %u, %u, %d)\n", 282 dprintk("RPC: %s(" NIPQUAD_FMT ", %u, %u, %d)\n",
281 NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot); 283 __FUNCTION__, NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
282 284
283 sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr)); 285 sprintf(hostname, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr));
284 rpcb_clnt = rpcb_create(hostname, (struct sockaddr *)sin, prot, 2, 0); 286 rpcb_clnt = rpcb_create(hostname, (struct sockaddr *)sin, prot, 2, 0);
285 if (IS_ERR(rpcb_clnt)) 287 if (IS_ERR(rpcb_clnt))
286 return PTR_ERR(rpcb_clnt); 288 return PTR_ERR(rpcb_clnt);
287 289
288 status = rpc_call_sync(rpcb_clnt, &msg, 0); 290 status = rpc_call_sync(rpcb_clnt, &msg, 0);
291 rpc_shutdown_client(rpcb_clnt);
289 292
290 if (status >= 0) { 293 if (status >= 0) {
291 if (map.r_port != 0) 294 if (map.r_port != 0)
@@ -294,16 +297,16 @@ int rpcb_getport_external(struct sockaddr_in *sin, __u32 prog,
294 } 297 }
295 return status; 298 return status;
296} 299}
297#endif 300EXPORT_SYMBOL_GPL(rpcb_getport_sync);
298 301
299/** 302/**
300 * rpcb_getport - obtain the port for a given RPC service on a given host 303 * rpcb_getport_async - obtain the port for a given RPC service on a given host
301 * @task: task that is waiting for portmapper request 304 * @task: task that is waiting for portmapper request
302 * 305 *
303 * This one can be called for an ongoing RPC request, and can be used in 306 * This one can be called for an ongoing RPC request, and can be used in
304 * an async (rpciod) context. 307 * an async (rpciod) context.
305 */ 308 */
306void rpcb_getport(struct rpc_task *task) 309void rpcb_getport_async(struct rpc_task *task)
307{ 310{
308 struct rpc_clnt *clnt = task->tk_client; 311 struct rpc_clnt *clnt = task->tk_client;
309 int bind_version; 312 int bind_version;
@@ -314,17 +317,17 @@ void rpcb_getport(struct rpc_task *task)
314 struct sockaddr addr; 317 struct sockaddr addr;
315 int status; 318 int status;
316 319
317 dprintk("RPC: %5u rpcb_getport(%s, %u, %u, %d)\n", 320 dprintk("RPC: %5u %s(%s, %u, %u, %d)\n",
318 task->tk_pid, clnt->cl_server, 321 task->tk_pid, __FUNCTION__,
319 clnt->cl_prog, clnt->cl_vers, xprt->prot); 322 clnt->cl_server, clnt->cl_prog, clnt->cl_vers, xprt->prot);
320 323
321 /* Autobind on cloned rpc clients is discouraged */ 324 /* Autobind on cloned rpc clients is discouraged */
322 BUG_ON(clnt->cl_parent != clnt); 325 BUG_ON(clnt->cl_parent != clnt);
323 326
324 if (xprt_test_and_set_binding(xprt)) { 327 if (xprt_test_and_set_binding(xprt)) {
325 status = -EACCES; /* tell caller to check again */ 328 status = -EACCES; /* tell caller to check again */
326 dprintk("RPC: %5u rpcb_getport waiting for another binder\n", 329 dprintk("RPC: %5u %s: waiting for another binder\n",
327 task->tk_pid); 330 task->tk_pid, __FUNCTION__);
328 goto bailout_nowake; 331 goto bailout_nowake;
329 } 332 }
330 333
@@ -335,27 +338,28 @@ void rpcb_getport(struct rpc_task *task)
335 /* Someone else may have bound if we slept */ 338 /* Someone else may have bound if we slept */
336 if (xprt_bound(xprt)) { 339 if (xprt_bound(xprt)) {
337 status = 0; 340 status = 0;
338 dprintk("RPC: %5u rpcb_getport already bound\n", task->tk_pid); 341 dprintk("RPC: %5u %s: already bound\n",
342 task->tk_pid, __FUNCTION__);
339 goto bailout_nofree; 343 goto bailout_nofree;
340 } 344 }
341 345
342 if (rpcb_next_version[xprt->bind_index].rpc_proc == NULL) { 346 if (rpcb_next_version[xprt->bind_index].rpc_proc == NULL) {
343 xprt->bind_index = 0; 347 xprt->bind_index = 0;
344 status = -EACCES; /* tell caller to try again later */ 348 status = -EACCES; /* tell caller to try again later */
345 dprintk("RPC: %5u rpcb_getport no more getport versions " 349 dprintk("RPC: %5u %s: no more getport versions available\n",
346 "available\n", task->tk_pid); 350 task->tk_pid, __FUNCTION__);
347 goto bailout_nofree; 351 goto bailout_nofree;
348 } 352 }
349 bind_version = rpcb_next_version[xprt->bind_index].rpc_vers; 353 bind_version = rpcb_next_version[xprt->bind_index].rpc_vers;
350 354
351 dprintk("RPC: %5u rpcb_getport trying rpcbind version %u\n", 355 dprintk("RPC: %5u %s: trying rpcbind version %u\n",
352 task->tk_pid, bind_version); 356 task->tk_pid, __FUNCTION__, bind_version);
353 357
354 map = kzalloc(sizeof(struct rpcbind_args), GFP_ATOMIC); 358 map = kzalloc(sizeof(struct rpcbind_args), GFP_ATOMIC);
355 if (!map) { 359 if (!map) {
356 status = -ENOMEM; 360 status = -ENOMEM;
357 dprintk("RPC: %5u rpcb_getport no memory available\n", 361 dprintk("RPC: %5u %s: no memory available\n",
358 task->tk_pid); 362 task->tk_pid, __FUNCTION__);
359 goto bailout_nofree; 363 goto bailout_nofree;
360 } 364 }
361 map->r_prog = clnt->cl_prog; 365 map->r_prog = clnt->cl_prog;
@@ -373,16 +377,17 @@ void rpcb_getport(struct rpc_task *task)
373 rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot, bind_version, 0); 377 rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot, bind_version, 0);
374 if (IS_ERR(rpcb_clnt)) { 378 if (IS_ERR(rpcb_clnt)) {
375 status = PTR_ERR(rpcb_clnt); 379 status = PTR_ERR(rpcb_clnt);
376 dprintk("RPC: %5u rpcb_getport rpcb_create failed, error %ld\n", 380 dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n",
377 task->tk_pid, PTR_ERR(rpcb_clnt)); 381 task->tk_pid, __FUNCTION__, PTR_ERR(rpcb_clnt));
378 goto bailout; 382 goto bailout;
379 } 383 }
380 384
381 child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map); 385 child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map);
386 rpc_release_client(rpcb_clnt);
382 if (IS_ERR(child)) { 387 if (IS_ERR(child)) {
383 status = -EIO; 388 status = -EIO;
384 dprintk("RPC: %5u rpcb_getport rpc_run_task failed\n", 389 dprintk("RPC: %5u %s: rpc_run_task failed\n",
385 task->tk_pid); 390 task->tk_pid, __FUNCTION__);
386 goto bailout_nofree; 391 goto bailout_nofree;
387 } 392 }
388 rpc_put_task(child); 393 rpc_put_task(child);