diff options
author | Andy Adamson <andros@netapp.com> | 2011-02-28 20:34:17 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-03-11 15:38:42 -0500 |
commit | d83217c13531fd59730d77b5c2284e90e56c0a50 (patch) | |
tree | e347037afc91fdb81e0e2fcf7225d30462fb90af /fs | |
parent | 64419a9b20938d9070fdd8c58c2fa23c911915f8 (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>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/client.c | 41 | ||||
-rw-r--r-- | fs/nfs/internal.h | 5 | ||||
-rw-r--r-- | fs/nfs/nfs4_fs.h | 12 | ||||
-rw-r--r-- | fs/nfs/nfs4filelayoutdev.c | 61 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 29 |
5 files changed, 146 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 | */ | ||
1430 | struct 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 | } | ||
1460 | EXPORT_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 *); |
149 | extern void nfs_mark_client_ready(struct nfs_client *clp, int state); | 149 | extern void nfs_mark_client_ready(struct nfs_client *clp, int state); |
150 | extern int nfs4_check_client_ready(struct nfs_client *clp); | 150 | extern int nfs4_check_client_ready(struct nfs_client *clp); |
151 | extern 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 |
152 | extern int __init nfs_fs_proc_init(void); | 155 | extern int __init nfs_fs_proc_init(void); |
153 | extern void nfs_fs_proc_exit(void); | 156 | extern void nfs_fs_proc_exit(void); |
@@ -213,6 +216,8 @@ extern const u32 nfs41_maxwrite_overhead; | |||
213 | extern struct rpc_procinfo nfs4_procedures[]; | 216 | extern struct rpc_procinfo nfs4_procedures[]; |
214 | #endif | 217 | #endif |
215 | 218 | ||
219 | extern int nfs4_init_ds_session(struct nfs_client *clp); | ||
220 | |||
216 | /* proc.c */ | 221 | /* proc.c */ |
217 | void nfs_close_context(struct nfs_open_context *ctx, int is_sync); | 222 | void nfs_close_context(struct nfs_open_context *ctx, int is_sync); |
218 | extern int nfs_init_client(struct nfs_client *clp, | 223 | extern 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 | |||
270 | static inline bool | ||
271 | is_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 */ |
270 | static inline struct nfs4_session *nfs4_get_session(const struct nfs_server *server) | 276 | static 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 | |||
299 | static inline bool | ||
300 | is_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 | ||
294 | extern const struct nfs4_minor_version_ops *nfs_v4_minor_ops[]; | 306 | extern 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 | */ | ||
111 | static int | ||
112 | nfs4_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)); | ||
161 | out: | ||
162 | return status; | ||
163 | out_put: | ||
164 | nfs_put_client(clp); | ||
165 | goto out; | ||
166 | } | ||
167 | |||
107 | static void | 168 | static void |
108 | destroy_ds(struct nfs4_pnfs_ds *ds) | 169 | destroy_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 | ||
1576 | static int nfs4_recover_expired_lease(struct nfs_server *server) | 1576 | static 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 | ||
1594 | static 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 | ||
5125 | int 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 | } | ||
5143 | EXPORT_SYMBOL_GPL(nfs4_init_ds_session); | ||
5144 | |||
5145 | |||
5121 | /* | 5146 | /* |
5122 | * Renew the cl_session lease. | 5147 | * Renew the cl_session lease. |
5123 | */ | 5148 | */ |