diff options
Diffstat (limited to 'net/sunrpc/rpcb_clnt.c')
| -rw-r--r-- | net/sunrpc/rpcb_clnt.c | 65 |
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 | */ |
| 262 | int rpcb_getport_external(struct sockaddr_in *sin, __u32 prog, | 264 | int 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 | 300 | EXPORT_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 | */ |
| 306 | void rpcb_getport(struct rpc_task *task) | 309 | void 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); |
