aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/client.c')
-rw-r--r--fs/nfs/client.c119
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);
51static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq); 51static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);
52 52
53/* 53/*
54 * RPC cruft for NFS
55 */
56static 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
66struct 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
75struct rpc_stat nfs_rpcstat = {
76 .program = &nfs_program
77};
78
79
80#ifdef CONFIG_NFS_V3_ACL
81static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program };
82static struct rpc_version * nfsacl_version[] = {
83 [3] = &nfsacl_version3,
84};
85
86struct 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 */
359static 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 */
392int 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}