diff options
Diffstat (limited to 'fs/nfs/client.c')
-rw-r--r-- | fs/nfs/client.c | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index cb5e92463bdb..c08cab935ad5 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -51,6 +51,48 @@ static LIST_HEAD(nfs_client_list); | |||
51 | static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq); | 51 | static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq); |
52 | 52 | ||
53 | /* | 53 | /* |
54 | * RPC cruft for NFS | ||
55 | */ | ||
56 | static struct rpc_version *nfs_version[5] = { | ||
57 | [2] = &nfs_version2, | ||
58 | #ifdef CONFIG_NFS_V3 | ||
59 | [3] = &nfs_version3, | ||
60 | #endif | ||
61 | #ifdef CONFIG_NFS_V4 | ||
62 | [4] = &nfs_version4, | ||
63 | #endif | ||
64 | }; | ||
65 | |||
66 | struct rpc_program nfs_program = { | ||
67 | .name = "nfs", | ||
68 | .number = NFS_PROGRAM, | ||
69 | .nrvers = ARRAY_SIZE(nfs_version), | ||
70 | .version = nfs_version, | ||
71 | .stats = &nfs_rpcstat, | ||
72 | .pipe_dir_name = "/nfs", | ||
73 | }; | ||
74 | |||
75 | struct rpc_stat nfs_rpcstat = { | ||
76 | .program = &nfs_program | ||
77 | }; | ||
78 | |||
79 | |||
80 | #ifdef CONFIG_NFS_V3_ACL | ||
81 | static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program }; | ||
82 | static struct rpc_version * nfsacl_version[] = { | ||
83 | [3] = &nfsacl_version3, | ||
84 | }; | ||
85 | |||
86 | struct rpc_program nfsacl_program = { | ||
87 | .name = "nfsacl", | ||
88 | .number = NFS_ACL_PROGRAM, | ||
89 | .nrvers = ARRAY_SIZE(nfsacl_version), | ||
90 | .version = nfsacl_version, | ||
91 | .stats = &nfsacl_rpcstat, | ||
92 | }; | ||
93 | #endif /* CONFIG_NFS_V3_ACL */ | ||
94 | |||
95 | /* | ||
54 | * Allocate a shared client record | 96 | * Allocate a shared client record |
55 | * | 97 | * |
56 | * Since these are allocated/deallocated very rarely, we don't | 98 | * Since these are allocated/deallocated very rarely, we don't |
@@ -310,3 +352,80 @@ void nfs_mark_client_ready(struct nfs_client *clp, int state) | |||
310 | clp->cl_cons_state = state; | 352 | clp->cl_cons_state = state; |
311 | wake_up_all(&nfs_client_active_wq); | 353 | wake_up_all(&nfs_client_active_wq); |
312 | } | 354 | } |
355 | |||
356 | /* | ||
357 | * Initialise the timeout values for a connection | ||
358 | */ | ||
359 | static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, | ||
360 | unsigned int timeo, unsigned int retrans) | ||
361 | { | ||
362 | to->to_initval = timeo * HZ / 10; | ||
363 | to->to_retries = retrans; | ||
364 | if (!to->to_retries) | ||
365 | to->to_retries = 2; | ||
366 | |||
367 | switch (proto) { | ||
368 | case IPPROTO_TCP: | ||
369 | if (!to->to_initval) | ||
370 | to->to_initval = 60 * HZ; | ||
371 | if (to->to_initval > NFS_MAX_TCP_TIMEOUT) | ||
372 | to->to_initval = NFS_MAX_TCP_TIMEOUT; | ||
373 | to->to_increment = to->to_initval; | ||
374 | to->to_maxval = to->to_initval + (to->to_increment * to->to_retries); | ||
375 | to->to_exponential = 0; | ||
376 | break; | ||
377 | case IPPROTO_UDP: | ||
378 | default: | ||
379 | if (!to->to_initval) | ||
380 | to->to_initval = 11 * HZ / 10; | ||
381 | if (to->to_initval > NFS_MAX_UDP_TIMEOUT) | ||
382 | to->to_initval = NFS_MAX_UDP_TIMEOUT; | ||
383 | to->to_maxval = NFS_MAX_UDP_TIMEOUT; | ||
384 | to->to_exponential = 1; | ||
385 | break; | ||
386 | } | ||
387 | } | ||
388 | |||
389 | /* | ||
390 | * Create an RPC client handle | ||
391 | */ | ||
392 | int nfs_create_rpc_client(struct nfs_client *clp, int proto, | ||
393 | unsigned int timeo, | ||
394 | unsigned int retrans, | ||
395 | rpc_authflavor_t flavor) | ||
396 | { | ||
397 | struct rpc_timeout timeparms; | ||
398 | struct rpc_xprt *xprt = NULL; | ||
399 | struct rpc_clnt *clnt = NULL; | ||
400 | |||
401 | if (!IS_ERR(clp->cl_rpcclient)) | ||
402 | return 0; | ||
403 | |||
404 | nfs_init_timeout_values(&timeparms, proto, timeo, retrans); | ||
405 | clp->retrans_timeo = timeparms.to_initval; | ||
406 | clp->retrans_count = timeparms.to_retries; | ||
407 | |||
408 | /* create transport and client */ | ||
409 | xprt = xprt_create_proto(proto, &clp->cl_addr, &timeparms); | ||
410 | if (IS_ERR(xprt)) { | ||
411 | dprintk("%s: cannot create RPC transport. Error = %ld\n", | ||
412 | __FUNCTION__, PTR_ERR(xprt)); | ||
413 | return PTR_ERR(xprt); | ||
414 | } | ||
415 | |||
416 | /* Bind to a reserved port! */ | ||
417 | xprt->resvport = 1; | ||
418 | /* Create the client RPC handle */ | ||
419 | clnt = rpc_create_client(xprt, clp->cl_hostname, &nfs_program, | ||
420 | clp->rpc_ops->version, RPC_AUTH_UNIX); | ||
421 | if (IS_ERR(clnt)) { | ||
422 | dprintk("%s: cannot create RPC client. Error = %ld\n", | ||
423 | __FUNCTION__, PTR_ERR(clnt)); | ||
424 | return PTR_ERR(clnt); | ||
425 | } | ||
426 | |||
427 | clnt->cl_intr = 1; | ||
428 | clnt->cl_softrtry = 1; | ||
429 | clp->cl_rpcclient = clnt; | ||
430 | return 0; | ||
431 | } | ||