aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorBryan Schumaker <bjschuma@netapp.com>2012-07-16 16:39:17 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-07-17 13:33:52 -0400
commit428360d77c801932e4b28f15160aebbdb5f5a03e (patch)
tree2e96be9e5f6d1d75009c11e0adfad16a29595851 /fs
parenta38a9eac75f0d09f1941a6e85e291c8e96bc8375 (diff)
NFS: Initialize the NFS v4 client from init_nfs_v4()
And split these functions out of the generic client into a v4 specific file. Signed-off-by: Bryan Schumaker <bjschuma@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/Makefile2
-rw-r--r--fs/nfs/client.c137
-rw-r--r--fs/nfs/internal.h1
-rw-r--r--fs/nfs/nfs4client.c144
4 files changed, 149 insertions, 135 deletions
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index ec13afe2619a..0b96c2038346 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -15,7 +15,7 @@ nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o
15nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \ 15nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
16 nfs4super.o nfs4file.o delegation.o idmap.o \ 16 nfs4super.o nfs4file.o delegation.o idmap.o \
17 callback.o callback_xdr.o callback_proc.o \ 17 callback.o callback_xdr.o callback_proc.o \
18 nfs4namespace.o nfs4getroot.o 18 nfs4namespace.o nfs4getroot.o nfs4client.o
19nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o 19nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o
20 20
21ifeq ($(CONFIG_SYSCTL), y) 21ifeq ($(CONFIG_SYSCTL), y)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 254719c4a575..5664c7bbe50d 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -662,9 +662,9 @@ static void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
662/* 662/*
663 * Create an RPC client handle 663 * Create an RPC client handle
664 */ 664 */
665static int nfs_create_rpc_client(struct nfs_client *clp, 665int nfs_create_rpc_client(struct nfs_client *clp,
666 const struct rpc_timeout *timeparms, 666 const struct rpc_timeout *timeparms,
667 rpc_authflavor_t flavor) 667 rpc_authflavor_t flavor)
668{ 668{
669 struct rpc_clnt *clnt = NULL; 669 struct rpc_clnt *clnt = NULL;
670 struct rpc_create_args args = { 670 struct rpc_create_args args = {
@@ -1305,137 +1305,6 @@ nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr,
1305#endif /* CONFIG_NFS_V4_1 */ 1305#endif /* CONFIG_NFS_V4_1 */
1306 1306
1307/* 1307/*
1308 * Initialize the NFS4 callback service
1309 */
1310static int nfs4_init_callback(struct nfs_client *clp)
1311{
1312 int error;
1313
1314 if (clp->rpc_ops->version == 4) {
1315 struct rpc_xprt *xprt;
1316
1317 xprt = rcu_dereference_raw(clp->cl_rpcclient->cl_xprt);
1318
1319 if (nfs4_has_session(clp)) {
1320 error = xprt_setup_backchannel(xprt,
1321 NFS41_BC_MIN_CALLBACKS);
1322 if (error < 0)
1323 return error;
1324 }
1325
1326 error = nfs_callback_up(clp->cl_mvops->minor_version, xprt);
1327 if (error < 0) {
1328 dprintk("%s: failed to start callback. Error = %d\n",
1329 __func__, error);
1330 return error;
1331 }
1332 __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
1333 }
1334 return 0;
1335}
1336
1337/*
1338 * Initialize the minor version specific parts of an NFS4 client record
1339 */
1340static int nfs4_init_client_minor_version(struct nfs_client *clp)
1341{
1342#if defined(CONFIG_NFS_V4_1)
1343 if (clp->cl_mvops->minor_version) {
1344 struct nfs4_session *session = NULL;
1345 /*
1346 * Create the session and mark it expired.
1347 * When a SEQUENCE operation encounters the expired session
1348 * it will do session recovery to initialize it.
1349 */
1350 session = nfs4_alloc_session(clp);
1351 if (!session)
1352 return -ENOMEM;
1353
1354 clp->cl_session = session;
1355 /*
1356 * The create session reply races with the server back
1357 * channel probe. Mark the client NFS_CS_SESSION_INITING
1358 * so that the client back channel can find the
1359 * nfs_client struct
1360 */
1361 nfs_mark_client_ready(clp, NFS_CS_SESSION_INITING);
1362 }
1363#endif /* CONFIG_NFS_V4_1 */
1364
1365 return nfs4_init_callback(clp);
1366}
1367
1368/**
1369 * nfs4_init_client - Initialise an NFS4 client record
1370 *
1371 * @clp: nfs_client to initialise
1372 * @timeparms: timeout parameters for underlying RPC transport
1373 * @ip_addr: callback IP address in presentation format
1374 * @authflavor: authentication flavor for underlying RPC transport
1375 *
1376 * Returns pointer to an NFS client, or an ERR_PTR value.
1377 */
1378struct nfs_client *nfs4_init_client(struct nfs_client *clp,
1379 const struct rpc_timeout *timeparms,
1380 const char *ip_addr,
1381 rpc_authflavor_t authflavour)
1382{
1383 char buf[INET6_ADDRSTRLEN + 1];
1384 int error;
1385
1386 if (clp->cl_cons_state == NFS_CS_READY) {
1387 /* the client is initialised already */
1388 dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp);
1389 return clp;
1390 }
1391
1392 /* Check NFS protocol revision and initialize RPC op vector */
1393 clp->rpc_ops = &nfs_v4_clientops;
1394
1395 __set_bit(NFS_CS_DISCRTRY, &clp->cl_flags);
1396 error = nfs_create_rpc_client(clp, timeparms, authflavour);
1397 if (error < 0)
1398 goto error;
1399
1400 /* If no clientaddr= option was specified, find a usable cb address */
1401 if (ip_addr == NULL) {
1402 struct sockaddr_storage cb_addr;
1403 struct sockaddr *sap = (struct sockaddr *)&cb_addr;
1404
1405 error = rpc_localaddr(clp->cl_rpcclient, sap, sizeof(cb_addr));
1406 if (error < 0)
1407 goto error;
1408 error = rpc_ntop(sap, buf, sizeof(buf));
1409 if (error < 0)
1410 goto error;
1411 ip_addr = (const char *)buf;
1412 }
1413 strlcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
1414
1415 error = nfs_idmap_new(clp);
1416 if (error < 0) {
1417 dprintk("%s: failed to create idmapper. Error = %d\n",
1418 __func__, error);
1419 goto error;
1420 }
1421 __set_bit(NFS_CS_IDMAP, &clp->cl_res_state);
1422
1423 error = nfs4_init_client_minor_version(clp);
1424 if (error < 0)
1425 goto error;
1426
1427 if (!nfs4_has_session(clp))
1428 nfs_mark_client_ready(clp, NFS_CS_READY);
1429 return clp;
1430
1431error:
1432 nfs_mark_client_ready(clp, error);
1433 nfs_put_client(clp);
1434 dprintk("<-- nfs4_init_client() = xerror %d\n", error);
1435 return ERR_PTR(error);
1436}
1437
1438/*
1439 * Set up an NFS4 client 1308 * Set up an NFS4 client
1440 */ 1309 */
1441static int nfs4_set_client(struct nfs_server *server, 1310static int nfs4_set_client(struct nfs_server *server,
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index ca7200a53caf..10df28d14f83 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -149,6 +149,7 @@ extern void nfs_umount(const struct nfs_mount_request *info);
149extern const struct rpc_program nfs_program; 149extern const struct rpc_program nfs_program;
150extern void nfs_clients_init(struct net *net); 150extern void nfs_clients_init(struct net *net);
151extern struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *); 151extern struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *);
152int nfs_create_rpc_client(struct nfs_client *, const struct rpc_timeout *, rpc_authflavor_t);
152 153
153extern void nfs_cleanup_cb_ident_idr(struct net *); 154extern void nfs_cleanup_cb_ident_idr(struct net *);
154extern void nfs_put_client(struct nfs_client *); 155extern void nfs_put_client(struct nfs_client *);
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
new file mode 100644
index 000000000000..c5234b589907
--- /dev/null
+++ b/fs/nfs/nfs4client.c
@@ -0,0 +1,144 @@
1/*
2 * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
3 * Written by David Howells (dhowells@redhat.com)
4 */
5#include <linux/nfs_fs.h>
6#include <linux/nfs_idmap.h>
7#include <linux/sunrpc/auth.h>
8#include <linux/sunrpc/xprt.h>
9#include <linux/sunrpc/bc_xprt.h>
10#include "internal.h"
11#include "callback.h"
12
13#define NFSDBG_FACILITY NFSDBG_CLIENT
14
15/*
16 * Initialize the NFS4 callback service
17 */
18static int nfs4_init_callback(struct nfs_client *clp)
19{
20 int error;
21
22 if (clp->rpc_ops->version == 4) {
23 struct rpc_xprt *xprt;
24
25 xprt = rcu_dereference_raw(clp->cl_rpcclient->cl_xprt);
26
27 if (nfs4_has_session(clp)) {
28 error = xprt_setup_backchannel(xprt,
29 NFS41_BC_MIN_CALLBACKS);
30 if (error < 0)
31 return error;
32 }
33
34 error = nfs_callback_up(clp->cl_mvops->minor_version, xprt);
35 if (error < 0) {
36 dprintk("%s: failed to start callback. Error = %d\n",
37 __func__, error);
38 return error;
39 }
40 __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
41 }
42 return 0;
43}
44
45/*
46 * Initialize the minor version specific parts of an NFS4 client record
47 */
48static int nfs4_init_client_minor_version(struct nfs_client *clp)
49{
50#if defined(CONFIG_NFS_V4_1)
51 if (clp->cl_mvops->minor_version) {
52 struct nfs4_session *session = NULL;
53 /*
54 * Create the session and mark it expired.
55 * When a SEQUENCE operation encounters the expired session
56 * it will do session recovery to initialize it.
57 */
58 session = nfs4_alloc_session(clp);
59 if (!session)
60 return -ENOMEM;
61
62 clp->cl_session = session;
63 /*
64 * The create session reply races with the server back
65 * channel probe. Mark the client NFS_CS_SESSION_INITING
66 * so that the client back channel can find the
67 * nfs_client struct
68 */
69 nfs_mark_client_ready(clp, NFS_CS_SESSION_INITING);
70 }
71#endif /* CONFIG_NFS_V4_1 */
72
73 return nfs4_init_callback(clp);
74}
75
76/**
77 * nfs4_init_client - Initialise an NFS4 client record
78 *
79 * @clp: nfs_client to initialise
80 * @timeparms: timeout parameters for underlying RPC transport
81 * @ip_addr: callback IP address in presentation format
82 * @authflavor: authentication flavor for underlying RPC transport
83 *
84 * Returns pointer to an NFS client, or an ERR_PTR value.
85 */
86struct nfs_client *nfs4_init_client(struct nfs_client *clp,
87 const struct rpc_timeout *timeparms,
88 const char *ip_addr,
89 rpc_authflavor_t authflavour)
90{
91 char buf[INET6_ADDRSTRLEN + 1];
92 int error;
93
94 if (clp->cl_cons_state == NFS_CS_READY) {
95 /* the client is initialised already */
96 dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp);
97 return clp;
98 }
99
100 /* Check NFS protocol revision and initialize RPC op vector */
101 clp->rpc_ops = &nfs_v4_clientops;
102
103 __set_bit(NFS_CS_DISCRTRY, &clp->cl_flags);
104 error = nfs_create_rpc_client(clp, timeparms, authflavour);
105 if (error < 0)
106 goto error;
107
108 /* If no clientaddr= option was specified, find a usable cb address */
109 if (ip_addr == NULL) {
110 struct sockaddr_storage cb_addr;
111 struct sockaddr *sap = (struct sockaddr *)&cb_addr;
112
113 error = rpc_localaddr(clp->cl_rpcclient, sap, sizeof(cb_addr));
114 if (error < 0)
115 goto error;
116 error = rpc_ntop(sap, buf, sizeof(buf));
117 if (error < 0)
118 goto error;
119 ip_addr = (const char *)buf;
120 }
121 strlcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
122
123 error = nfs_idmap_new(clp);
124 if (error < 0) {
125 dprintk("%s: failed to create idmapper. Error = %d\n",
126 __func__, error);
127 goto error;
128 }
129 __set_bit(NFS_CS_IDMAP, &clp->cl_res_state);
130
131 error = nfs4_init_client_minor_version(clp);
132 if (error < 0)
133 goto error;
134
135 if (!nfs4_has_session(clp))
136 nfs_mark_client_ready(clp, NFS_CS_READY);
137 return clp;
138
139error:
140 nfs_mark_client_ready(clp, error);
141 nfs_put_client(clp);
142 dprintk("<-- nfs4_init_client() = xerror %d\n", error);
143 return ERR_PTR(error);
144}