aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Adamson <andros@netapp.com>2011-02-28 20:34:17 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-03-11 15:38:42 -0500
commitd83217c13531fd59730d77b5c2284e90e56c0a50 (patch)
treee347037afc91fdb81e0e2fcf7225d30462fb90af
parent64419a9b20938d9070fdd8c58c2fa23c911915f8 (diff)
NFSv4.1: data server connection
Introduce a data server set_client and init session following the nfs4_set_client and nfs4_init_session convention. Once a new nfs_client is on the nfs_client_list, the nfs_client cl_cons_state serializes access to creating an nfs_client struct with matching properties. Use the new nfs_get_client() that initializes new clients. Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/client.c41
-rw-r--r--fs/nfs/internal.h5
-rw-r--r--fs/nfs/nfs4_fs.h12
-rw-r--r--fs/nfs/nfs4filelayoutdev.c61
-rw-r--r--fs/nfs/nfs4proc.c29
-rw-r--r--include/linux/nfs_xdr.h1
6 files changed, 147 insertions, 2 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index d5c5bdfa4231..6dd50ac5b545 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -1417,6 +1417,47 @@ error:
1417 return error; 1417 return error;
1418} 1418}
1419 1419
1420/*
1421 * Set up a pNFS Data Server client.
1422 *
1423 * Return any existing nfs_client that matches server address,port,version
1424 * and minorversion.
1425 *
1426 * For a new nfs_client, use a soft mount (default), a low retrans and a
1427 * low timeout interval so that if a connection is lost, we retry through
1428 * the MDS.
1429 */
1430struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp,
1431 const struct sockaddr *ds_addr,
1432 int ds_addrlen, int ds_proto)
1433{
1434 struct nfs_client_initdata cl_init = {
1435 .addr = ds_addr,
1436 .addrlen = ds_addrlen,
1437 .rpc_ops = &nfs_v4_clientops,
1438 .proto = ds_proto,
1439 .minorversion = mds_clp->cl_minorversion,
1440 };
1441 struct rpc_timeout ds_timeout = {
1442 .to_initval = 15 * HZ,
1443 .to_maxval = 15 * HZ,
1444 .to_retries = 1,
1445 .to_exponential = 1,
1446 };
1447 struct nfs_client *clp;
1448
1449 /*
1450 * Set an authflavor equual to the MDS value. Use the MDS nfs_client
1451 * cl_ipaddr so as to use the same EXCHANGE_ID co_ownerid as the MDS
1452 * (section 13.1 RFC 5661).
1453 */
1454 clp = nfs_get_client(&cl_init, &ds_timeout, mds_clp->cl_ipaddr,
1455 mds_clp->cl_rpcclient->cl_auth->au_flavor, 0);
1456
1457 dprintk("<-- %s %p\n", __func__, clp);
1458 return clp;
1459}
1460EXPORT_SYMBOL(nfs4_set_ds_client);
1420 1461
1421/* 1462/*
1422 * Session has been established, and the client marked ready. 1463 * Session has been established, and the client marked ready.
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 4d7b3a97e522..5cc92014259e 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -148,6 +148,9 @@ extern struct nfs_server *nfs_clone_server(struct nfs_server *,
148 struct nfs_fattr *); 148 struct nfs_fattr *);
149extern void nfs_mark_client_ready(struct nfs_client *clp, int state); 149extern void nfs_mark_client_ready(struct nfs_client *clp, int state);
150extern int nfs4_check_client_ready(struct nfs_client *clp); 150extern int nfs4_check_client_ready(struct nfs_client *clp);
151extern struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp,
152 const struct sockaddr *ds_addr,
153 int ds_addrlen, int ds_proto);
151#ifdef CONFIG_PROC_FS 154#ifdef CONFIG_PROC_FS
152extern int __init nfs_fs_proc_init(void); 155extern int __init nfs_fs_proc_init(void);
153extern void nfs_fs_proc_exit(void); 156extern void nfs_fs_proc_exit(void);
@@ -213,6 +216,8 @@ extern const u32 nfs41_maxwrite_overhead;
213extern struct rpc_procinfo nfs4_procedures[]; 216extern struct rpc_procinfo nfs4_procedures[];
214#endif 217#endif
215 218
219extern int nfs4_init_ds_session(struct nfs_client *clp);
220
216/* proc.c */ 221/* proc.c */
217void nfs_close_context(struct nfs_open_context *ctx, int is_sync); 222void nfs_close_context(struct nfs_open_context *ctx, int is_sync);
218extern int nfs_init_client(struct nfs_client *clp, 223extern int nfs_init_client(struct nfs_client *clp,
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index d4cfacc40003..7058a9f75e7f 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -266,6 +266,12 @@ is_ds_only_client(struct nfs_client *clp)
266 return (clp->cl_exchange_flags & EXCHGID4_FLAG_MASK_PNFS) == 266 return (clp->cl_exchange_flags & EXCHGID4_FLAG_MASK_PNFS) ==
267 EXCHGID4_FLAG_USE_PNFS_DS; 267 EXCHGID4_FLAG_USE_PNFS_DS;
268} 268}
269
270static inline bool
271is_ds_client(struct nfs_client *clp)
272{
273 return clp->cl_exchange_flags & EXCHGID4_FLAG_USE_PNFS_DS;
274}
269#else /* CONFIG_NFS_v4_1 */ 275#else /* CONFIG_NFS_v4_1 */
270static inline struct nfs4_session *nfs4_get_session(const struct nfs_server *server) 276static inline struct nfs4_session *nfs4_get_session(const struct nfs_server *server)
271{ 277{
@@ -289,6 +295,12 @@ is_ds_only_client(struct nfs_client *clp)
289{ 295{
290 return false; 296 return false;
291} 297}
298
299static inline bool
300is_ds_client(struct nfs_client *clp)
301{
302 return false;
303}
292#endif /* CONFIG_NFS_V4_1 */ 304#endif /* CONFIG_NFS_V4_1 */
293 305
294extern const struct nfs4_minor_version_ops *nfs_v4_minor_ops[]; 306extern const struct nfs4_minor_version_ops *nfs_v4_minor_ops[];
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c
index b73c34375f60..8bc91fb8b6fa 100644
--- a/fs/nfs/nfs4filelayoutdev.c
+++ b/fs/nfs/nfs4filelayoutdev.c
@@ -104,6 +104,67 @@ _data_server_lookup_locked(u32 ip_addr, u32 port)
104 return NULL; 104 return NULL;
105} 105}
106 106
107/*
108 * Create an rpc connection to the nfs4_pnfs_ds data server
109 * Currently only support IPv4
110 */
111static int
112nfs4_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds)
113{
114 struct nfs_client *clp;
115 struct sockaddr_in sin;
116 int status = 0;
117
118 dprintk("--> %s ip:port %x:%hu au_flavor %d\n", __func__,
119 ntohl(ds->ds_ip_addr), ntohs(ds->ds_port),
120 mds_srv->nfs_client->cl_rpcclient->cl_auth->au_flavor);
121
122 sin.sin_family = AF_INET;
123 sin.sin_addr.s_addr = ds->ds_ip_addr;
124 sin.sin_port = ds->ds_port;
125
126 clp = nfs4_set_ds_client(mds_srv->nfs_client, (struct sockaddr *)&sin,
127 sizeof(sin), IPPROTO_TCP);
128 if (IS_ERR(clp)) {
129 status = PTR_ERR(clp);
130 goto out;
131 }
132
133 if ((clp->cl_exchange_flags & EXCHGID4_FLAG_MASK_PNFS) != 0) {
134 if (!is_ds_client(clp)) {
135 status = -ENODEV;
136 goto out_put;
137 }
138 ds->ds_clp = clp;
139 dprintk("%s [existing] ip=%x, port=%hu\n", __func__,
140 ntohl(ds->ds_ip_addr), ntohs(ds->ds_port));
141 goto out;
142 }
143
144 /*
145 * Do not set NFS_CS_CHECK_LEASE_TIME instead set the DS lease to
146 * be equal to the MDS lease. Renewal is scheduled in create_session.
147 */
148 spin_lock(&mds_srv->nfs_client->cl_lock);
149 clp->cl_lease_time = mds_srv->nfs_client->cl_lease_time;
150 spin_unlock(&mds_srv->nfs_client->cl_lock);
151 clp->cl_last_renewal = jiffies;
152
153 /* New nfs_client */
154 status = nfs4_init_ds_session(clp);
155 if (status)
156 goto out_put;
157
158 ds->ds_clp = clp;
159 dprintk("%s [new] ip=%x, port=%hu\n", __func__, ntohl(ds->ds_ip_addr),
160 ntohs(ds->ds_port));
161out:
162 return status;
163out_put:
164 nfs_put_client(clp);
165 goto out;
166}
167
107static void 168static void
108destroy_ds(struct nfs4_pnfs_ds *ds) 169destroy_ds(struct nfs4_pnfs_ds *ds)
109{ 170{
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 55a8fc2f3df4..07d1a43f40f5 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1573,9 +1573,8 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
1573 return 0; 1573 return 0;
1574} 1574}
1575 1575
1576static int nfs4_recover_expired_lease(struct nfs_server *server) 1576static int nfs4_client_recover_expired_lease(struct nfs_client *clp)
1577{ 1577{
1578 struct nfs_client *clp = server->nfs_client;
1579 unsigned int loop; 1578 unsigned int loop;
1580 int ret; 1579 int ret;
1581 1580
@@ -1592,6 +1591,11 @@ static int nfs4_recover_expired_lease(struct nfs_server *server)
1592 return ret; 1591 return ret;
1593} 1592}
1594 1593
1594static int nfs4_recover_expired_lease(struct nfs_server *server)
1595{
1596 return nfs4_client_recover_expired_lease(server->nfs_client);
1597}
1598
1595/* 1599/*
1596 * OPEN_EXPIRED: 1600 * OPEN_EXPIRED:
1597 * reclaim state on the server after a network partition. 1601 * reclaim state on the server after a network partition.
@@ -5118,6 +5122,27 @@ int nfs4_init_session(struct nfs_server *server)
5118 return ret; 5122 return ret;
5119} 5123}
5120 5124
5125int nfs4_init_ds_session(struct nfs_client *clp)
5126{
5127 struct nfs4_session *session = clp->cl_session;
5128 int ret;
5129
5130 if (!test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state))
5131 return 0;
5132
5133 ret = nfs4_client_recover_expired_lease(clp);
5134 if (!ret)
5135 /* Test for the DS role */
5136 if (!is_ds_client(clp))
5137 ret = -ENODEV;
5138 if (!ret)
5139 ret = nfs4_check_client_ready(clp);
5140 return ret;
5141
5142}
5143EXPORT_SYMBOL_GPL(nfs4_init_ds_session);
5144
5145
5121/* 5146/*
5122 * Renew the cl_session lease. 5147 * Renew the cl_session lease.
5123 */ 5148 */
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 9d2b9dae277d..c66ff7fe1b6b 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1018,6 +1018,7 @@ struct nfs_read_data {
1018 struct nfs_readres res; 1018 struct nfs_readres res;
1019 unsigned long timestamp; /* For lease renewal */ 1019 unsigned long timestamp; /* For lease renewal */
1020 struct pnfs_layout_segment *lseg; 1020 struct pnfs_layout_segment *lseg;
1021 struct nfs_client *ds_clp; /* pNFS data server */
1021 const struct rpc_call_ops *mds_ops; 1022 const struct rpc_call_ops *mds_ops;
1022 struct page *page_array[NFS_PAGEVEC_SIZE]; 1023 struct page *page_array[NFS_PAGEVEC_SIZE];
1023}; 1024};