xref: /openbmc/linux/fs/nfs/nfs4client.c (revision ca79522c)
1 /*
2  * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
3  * Written by David Howells (dhowells@redhat.com)
4  */
5 #include <linux/module.h>
6 #include <linux/nfs_fs.h>
7 #include <linux/nfs_idmap.h>
8 #include <linux/nfs_mount.h>
9 #include <linux/sunrpc/addr.h>
10 #include <linux/sunrpc/auth.h>
11 #include <linux/sunrpc/xprt.h>
12 #include <linux/sunrpc/bc_xprt.h>
13 #include "internal.h"
14 #include "callback.h"
15 #include "delegation.h"
16 #include "nfs4session.h"
17 #include "pnfs.h"
18 #include "netns.h"
19 
20 #define NFSDBG_FACILITY		NFSDBG_CLIENT
21 
22 /*
23  * Get a unique NFSv4.0 callback identifier which will be used
24  * by the V4.0 callback service to lookup the nfs_client struct
25  */
26 static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion)
27 {
28 	int ret = 0;
29 	struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
30 
31 	if (clp->rpc_ops->version != 4 || minorversion != 0)
32 		return ret;
33 	idr_preload(GFP_KERNEL);
34 	spin_lock(&nn->nfs_client_lock);
35 	ret = idr_alloc(&nn->cb_ident_idr, clp, 0, 0, GFP_NOWAIT);
36 	if (ret >= 0)
37 		clp->cl_cb_ident = ret;
38 	spin_unlock(&nn->nfs_client_lock);
39 	idr_preload_end();
40 	return ret < 0 ? ret : 0;
41 }
42 
43 #ifdef CONFIG_NFS_V4_1
44 static void nfs4_shutdown_session(struct nfs_client *clp)
45 {
46 	if (nfs4_has_session(clp)) {
47 		nfs4_destroy_session(clp->cl_session);
48 		nfs4_destroy_clientid(clp);
49 	}
50 
51 }
52 #else /* CONFIG_NFS_V4_1 */
53 static void nfs4_shutdown_session(struct nfs_client *clp)
54 {
55 }
56 #endif /* CONFIG_NFS_V4_1 */
57 
58 struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init)
59 {
60 	int err;
61 	struct nfs_client *clp = nfs_alloc_client(cl_init);
62 	if (IS_ERR(clp))
63 		return clp;
64 
65 	err = nfs_get_cb_ident_idr(clp, cl_init->minorversion);
66 	if (err)
67 		goto error;
68 
69 	spin_lock_init(&clp->cl_lock);
70 	INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
71 	rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
72 	clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
73 	clp->cl_minorversion = cl_init->minorversion;
74 	clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion];
75 	return clp;
76 
77 error:
78 	nfs_free_client(clp);
79 	return ERR_PTR(err);
80 }
81 
82 /*
83  * Destroy the NFS4 callback service
84  */
85 static void nfs4_destroy_callback(struct nfs_client *clp)
86 {
87 	if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
88 		nfs_callback_down(clp->cl_mvops->minor_version, clp->cl_net);
89 }
90 
91 static void nfs4_shutdown_client(struct nfs_client *clp)
92 {
93 	if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
94 		nfs4_kill_renewd(clp);
95 	nfs4_shutdown_session(clp);
96 	nfs4_destroy_callback(clp);
97 	if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
98 		nfs_idmap_delete(clp);
99 
100 	rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
101 	kfree(clp->cl_serverowner);
102 	kfree(clp->cl_serverscope);
103 	kfree(clp->cl_implid);
104 }
105 
106 void nfs4_free_client(struct nfs_client *clp)
107 {
108 	nfs4_shutdown_client(clp);
109 	nfs_free_client(clp);
110 }
111 
112 /*
113  * Initialize the NFS4 callback service
114  */
115 static int nfs4_init_callback(struct nfs_client *clp)
116 {
117 	int error;
118 
119 	if (clp->rpc_ops->version == 4) {
120 		struct rpc_xprt *xprt;
121 
122 		xprt = rcu_dereference_raw(clp->cl_rpcclient->cl_xprt);
123 
124 		if (nfs4_has_session(clp)) {
125 			error = xprt_setup_backchannel(xprt,
126 						NFS41_BC_MIN_CALLBACKS);
127 			if (error < 0)
128 				return error;
129 		}
130 
131 		error = nfs_callback_up(clp->cl_mvops->minor_version, xprt);
132 		if (error < 0) {
133 			dprintk("%s: failed to start callback. Error = %d\n",
134 				__func__, error);
135 			return error;
136 		}
137 		__set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
138 	}
139 	return 0;
140 }
141 
142 /*
143  * Initialize the minor version specific parts of an NFS4 client record
144  */
145 static int nfs4_init_client_minor_version(struct nfs_client *clp)
146 {
147 #if defined(CONFIG_NFS_V4_1)
148 	if (clp->cl_mvops->minor_version) {
149 		struct nfs4_session *session = NULL;
150 		/*
151 		 * Create the session and mark it expired.
152 		 * When a SEQUENCE operation encounters the expired session
153 		 * it will do session recovery to initialize it.
154 		 */
155 		session = nfs4_alloc_session(clp);
156 		if (!session)
157 			return -ENOMEM;
158 
159 		clp->cl_session = session;
160 		/*
161 		 * The create session reply races with the server back
162 		 * channel probe. Mark the client NFS_CS_SESSION_INITING
163 		 * so that the client back channel can find the
164 		 * nfs_client struct
165 		 */
166 		nfs_mark_client_ready(clp, NFS_CS_SESSION_INITING);
167 	}
168 #endif /* CONFIG_NFS_V4_1 */
169 
170 	return nfs4_init_callback(clp);
171 }
172 
173 /**
174  * nfs4_init_client - Initialise an NFS4 client record
175  *
176  * @clp: nfs_client to initialise
177  * @timeparms: timeout parameters for underlying RPC transport
178  * @ip_addr: callback IP address in presentation format
179  * @authflavor: authentication flavor for underlying RPC transport
180  *
181  * Returns pointer to an NFS client, or an ERR_PTR value.
182  */
183 struct nfs_client *nfs4_init_client(struct nfs_client *clp,
184 				    const struct rpc_timeout *timeparms,
185 				    const char *ip_addr,
186 				    rpc_authflavor_t authflavour)
187 {
188 	char buf[INET6_ADDRSTRLEN + 1];
189 	struct nfs_client *old;
190 	int error;
191 
192 	if (clp->cl_cons_state == NFS_CS_READY) {
193 		/* the client is initialised already */
194 		dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp);
195 		return clp;
196 	}
197 
198 	/* Check NFS protocol revision and initialize RPC op vector */
199 	clp->rpc_ops = &nfs_v4_clientops;
200 
201 	if (clp->cl_minorversion != 0)
202 		__set_bit(NFS_CS_INFINITE_SLOTS, &clp->cl_flags);
203 	__set_bit(NFS_CS_DISCRTRY, &clp->cl_flags);
204 	error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_GSS_KRB5I);
205 	if (error == -EINVAL)
206 		error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_NULL);
207 	if (error < 0)
208 		goto error;
209 
210 	/* If no clientaddr= option was specified, find a usable cb address */
211 	if (ip_addr == NULL) {
212 		struct sockaddr_storage cb_addr;
213 		struct sockaddr *sap = (struct sockaddr *)&cb_addr;
214 
215 		error = rpc_localaddr(clp->cl_rpcclient, sap, sizeof(cb_addr));
216 		if (error < 0)
217 			goto error;
218 		error = rpc_ntop(sap, buf, sizeof(buf));
219 		if (error < 0)
220 			goto error;
221 		ip_addr = (const char *)buf;
222 	}
223 	strlcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
224 
225 	error = nfs_idmap_new(clp);
226 	if (error < 0) {
227 		dprintk("%s: failed to create idmapper. Error = %d\n",
228 			__func__, error);
229 		goto error;
230 	}
231 	__set_bit(NFS_CS_IDMAP, &clp->cl_res_state);
232 
233 	error = nfs4_init_client_minor_version(clp);
234 	if (error < 0)
235 		goto error;
236 
237 	if (!nfs4_has_session(clp))
238 		nfs_mark_client_ready(clp, NFS_CS_READY);
239 
240 	error = nfs4_discover_server_trunking(clp, &old);
241 	if (error < 0)
242 		goto error;
243 	nfs_put_client(clp);
244 	if (clp != old) {
245 		clp->cl_preserve_clid = true;
246 		clp = old;
247 	}
248 
249 	return clp;
250 
251 error:
252 	nfs_mark_client_ready(clp, error);
253 	nfs_put_client(clp);
254 	dprintk("<-- nfs4_init_client() = xerror %d\n", error);
255 	return ERR_PTR(error);
256 }
257 
258 /*
259  * SETCLIENTID just did a callback update with the callback ident in
260  * "drop," but server trunking discovery claims "drop" and "keep" are
261  * actually the same server.  Swap the callback IDs so that "keep"
262  * will continue to use the callback ident the server now knows about,
263  * and so that "keep"'s original callback ident is destroyed when
264  * "drop" is freed.
265  */
266 static void nfs4_swap_callback_idents(struct nfs_client *keep,
267 				      struct nfs_client *drop)
268 {
269 	struct nfs_net *nn = net_generic(keep->cl_net, nfs_net_id);
270 	unsigned int save = keep->cl_cb_ident;
271 
272 	if (keep->cl_cb_ident == drop->cl_cb_ident)
273 		return;
274 
275 	dprintk("%s: keeping callback ident %u and dropping ident %u\n",
276 		__func__, keep->cl_cb_ident, drop->cl_cb_ident);
277 
278 	spin_lock(&nn->nfs_client_lock);
279 
280 	idr_replace(&nn->cb_ident_idr, keep, drop->cl_cb_ident);
281 	keep->cl_cb_ident = drop->cl_cb_ident;
282 
283 	idr_replace(&nn->cb_ident_idr, drop, save);
284 	drop->cl_cb_ident = save;
285 
286 	spin_unlock(&nn->nfs_client_lock);
287 }
288 
289 /**
290  * nfs40_walk_client_list - Find server that recognizes a client ID
291  *
292  * @new: nfs_client with client ID to test
293  * @result: OUT: found nfs_client, or new
294  * @cred: credential to use for trunking test
295  *
296  * Returns zero, a negative errno, or a negative NFS4ERR status.
297  * If zero is returned, an nfs_client pointer is planted in "result."
298  *
299  * NB: nfs40_walk_client_list() relies on the new nfs_client being
300  *     the last nfs_client on the list.
301  */
302 int nfs40_walk_client_list(struct nfs_client *new,
303 			   struct nfs_client **result,
304 			   struct rpc_cred *cred)
305 {
306 	struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id);
307 	struct nfs_client *pos, *prev = NULL;
308 	struct nfs4_setclientid_res clid = {
309 		.clientid	= new->cl_clientid,
310 		.confirm	= new->cl_confirm,
311 	};
312 	int status = -NFS4ERR_STALE_CLIENTID;
313 
314 	spin_lock(&nn->nfs_client_lock);
315 	list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) {
316 		/* If "pos" isn't marked ready, we can't trust the
317 		 * remaining fields in "pos" */
318 		if (pos->cl_cons_state > NFS_CS_READY) {
319 			atomic_inc(&pos->cl_count);
320 			spin_unlock(&nn->nfs_client_lock);
321 
322 			if (prev)
323 				nfs_put_client(prev);
324 			prev = pos;
325 
326 			status = nfs_wait_client_init_complete(pos);
327 			spin_lock(&nn->nfs_client_lock);
328 			if (status < 0)
329 				continue;
330 		}
331 		if (pos->cl_cons_state != NFS_CS_READY)
332 			continue;
333 
334 		if (pos->rpc_ops != new->rpc_ops)
335 			continue;
336 
337 		if (pos->cl_proto != new->cl_proto)
338 			continue;
339 
340 		if (pos->cl_minorversion != new->cl_minorversion)
341 			continue;
342 
343 		if (pos->cl_clientid != new->cl_clientid)
344 			continue;
345 
346 		atomic_inc(&pos->cl_count);
347 		spin_unlock(&nn->nfs_client_lock);
348 
349 		if (prev)
350 			nfs_put_client(prev);
351 		prev = pos;
352 
353 		status = nfs4_proc_setclientid_confirm(pos, &clid, cred);
354 		switch (status) {
355 		case -NFS4ERR_STALE_CLIENTID:
356 			break;
357 		case 0:
358 			nfs4_swap_callback_idents(pos, new);
359 
360 			prev = NULL;
361 			*result = pos;
362 			dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n",
363 				__func__, pos, atomic_read(&pos->cl_count));
364 		default:
365 			goto out;
366 		}
367 
368 		spin_lock(&nn->nfs_client_lock);
369 	}
370 	spin_unlock(&nn->nfs_client_lock);
371 
372 	/* No match found. The server lost our clientid */
373 out:
374 	if (prev)
375 		nfs_put_client(prev);
376 	dprintk("NFS: <-- %s status = %d\n", __func__, status);
377 	return status;
378 }
379 
380 #ifdef CONFIG_NFS_V4_1
381 /*
382  * Returns true if the client IDs match
383  */
384 static bool nfs4_match_clientids(struct nfs_client *a, struct nfs_client *b)
385 {
386 	if (a->cl_clientid != b->cl_clientid) {
387 		dprintk("NFS: --> %s client ID %llx does not match %llx\n",
388 			__func__, a->cl_clientid, b->cl_clientid);
389 		return false;
390 	}
391 	dprintk("NFS: --> %s client ID %llx matches %llx\n",
392 		__func__, a->cl_clientid, b->cl_clientid);
393 	return true;
394 }
395 
396 /*
397  * Returns true if the server owners match
398  */
399 static bool
400 nfs4_match_serverowners(struct nfs_client *a, struct nfs_client *b)
401 {
402 	struct nfs41_server_owner *o1 = a->cl_serverowner;
403 	struct nfs41_server_owner *o2 = b->cl_serverowner;
404 
405 	if (o1->minor_id != o2->minor_id) {
406 		dprintk("NFS: --> %s server owner minor IDs do not match\n",
407 			__func__);
408 		return false;
409 	}
410 
411 	if (o1->major_id_sz != o2->major_id_sz)
412 		goto out_major_mismatch;
413 	if (memcmp(o1->major_id, o2->major_id, o1->major_id_sz) != 0)
414 		goto out_major_mismatch;
415 
416 	dprintk("NFS: --> %s server owners match\n", __func__);
417 	return true;
418 
419 out_major_mismatch:
420 	dprintk("NFS: --> %s server owner major IDs do not match\n",
421 		__func__);
422 	return false;
423 }
424 
425 /**
426  * nfs41_walk_client_list - Find nfs_client that matches a client/server owner
427  *
428  * @new: nfs_client with client ID to test
429  * @result: OUT: found nfs_client, or new
430  * @cred: credential to use for trunking test
431  *
432  * Returns zero, a negative errno, or a negative NFS4ERR status.
433  * If zero is returned, an nfs_client pointer is planted in "result."
434  *
435  * NB: nfs41_walk_client_list() relies on the new nfs_client being
436  *     the last nfs_client on the list.
437  */
438 int nfs41_walk_client_list(struct nfs_client *new,
439 			   struct nfs_client **result,
440 			   struct rpc_cred *cred)
441 {
442 	struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id);
443 	struct nfs_client *pos, *prev = NULL;
444 	int status = -NFS4ERR_STALE_CLIENTID;
445 
446 	spin_lock(&nn->nfs_client_lock);
447 	list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) {
448 		/* If "pos" isn't marked ready, we can't trust the
449 		 * remaining fields in "pos", especially the client
450 		 * ID and serverowner fields.  Wait for CREATE_SESSION
451 		 * to finish. */
452 		if (pos->cl_cons_state > NFS_CS_READY) {
453 			atomic_inc(&pos->cl_count);
454 			spin_unlock(&nn->nfs_client_lock);
455 
456 			if (prev)
457 				nfs_put_client(prev);
458 			prev = pos;
459 
460 			status = nfs_wait_client_init_complete(pos);
461 			if (status == 0) {
462 				nfs4_schedule_lease_recovery(pos);
463 				status = nfs4_wait_clnt_recover(pos);
464 			}
465 			spin_lock(&nn->nfs_client_lock);
466 			if (status < 0)
467 				continue;
468 		}
469 		if (pos->cl_cons_state != NFS_CS_READY)
470 			continue;
471 
472 		if (pos->rpc_ops != new->rpc_ops)
473 			continue;
474 
475 		if (pos->cl_proto != new->cl_proto)
476 			continue;
477 
478 		if (pos->cl_minorversion != new->cl_minorversion)
479 			continue;
480 
481 		if (!nfs4_match_clientids(pos, new))
482 			continue;
483 
484 		if (!nfs4_match_serverowners(pos, new))
485 			continue;
486 
487 		atomic_inc(&pos->cl_count);
488 		*result = pos;
489 		status = 0;
490 		dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n",
491 			__func__, pos, atomic_read(&pos->cl_count));
492 		break;
493 	}
494 
495 	/* No matching nfs_client found. */
496 	spin_unlock(&nn->nfs_client_lock);
497 	dprintk("NFS: <-- %s status = %d\n", __func__, status);
498 	if (prev)
499 		nfs_put_client(prev);
500 	return status;
501 }
502 #endif	/* CONFIG_NFS_V4_1 */
503 
504 static void nfs4_destroy_server(struct nfs_server *server)
505 {
506 	nfs_server_return_all_delegations(server);
507 	unset_pnfs_layoutdriver(server);
508 	nfs4_purge_state_owners(server);
509 }
510 
511 /*
512  * NFSv4.0 callback thread helper
513  *
514  * Find a client by callback identifier
515  */
516 struct nfs_client *
517 nfs4_find_client_ident(struct net *net, int cb_ident)
518 {
519 	struct nfs_client *clp;
520 	struct nfs_net *nn = net_generic(net, nfs_net_id);
521 
522 	spin_lock(&nn->nfs_client_lock);
523 	clp = idr_find(&nn->cb_ident_idr, cb_ident);
524 	if (clp)
525 		atomic_inc(&clp->cl_count);
526 	spin_unlock(&nn->nfs_client_lock);
527 	return clp;
528 }
529 
530 #if defined(CONFIG_NFS_V4_1)
531 /* Common match routine for v4.0 and v4.1 callback services */
532 static bool nfs4_cb_match_client(const struct sockaddr *addr,
533 		struct nfs_client *clp, u32 minorversion)
534 {
535 	struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
536 
537 	/* Don't match clients that failed to initialise */
538 	if (!(clp->cl_cons_state == NFS_CS_READY ||
539 	    clp->cl_cons_state == NFS_CS_SESSION_INITING))
540 		return false;
541 
542 	smp_rmb();
543 
544 	/* Match the version and minorversion */
545 	if (clp->rpc_ops->version != 4 ||
546 	    clp->cl_minorversion != minorversion)
547 		return false;
548 
549 	/* Match only the IP address, not the port number */
550 	if (!nfs_sockaddr_match_ipaddr(addr, clap))
551 		return false;
552 
553 	return true;
554 }
555 
556 /*
557  * NFSv4.1 callback thread helper
558  * For CB_COMPOUND calls, find a client by IP address, protocol version,
559  * minorversion, and sessionID
560  *
561  * Returns NULL if no such client
562  */
563 struct nfs_client *
564 nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr,
565 			   struct nfs4_sessionid *sid)
566 {
567 	struct nfs_client *clp;
568 	struct nfs_net *nn = net_generic(net, nfs_net_id);
569 
570 	spin_lock(&nn->nfs_client_lock);
571 	list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) {
572 		if (nfs4_cb_match_client(addr, clp, 1) == false)
573 			continue;
574 
575 		if (!nfs4_has_session(clp))
576 			continue;
577 
578 		/* Match sessionid*/
579 		if (memcmp(clp->cl_session->sess_id.data,
580 		    sid->data, NFS4_MAX_SESSIONID_LEN) != 0)
581 			continue;
582 
583 		atomic_inc(&clp->cl_count);
584 		spin_unlock(&nn->nfs_client_lock);
585 		return clp;
586 	}
587 	spin_unlock(&nn->nfs_client_lock);
588 	return NULL;
589 }
590 
591 #else /* CONFIG_NFS_V4_1 */
592 
593 struct nfs_client *
594 nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr,
595 			   struct nfs4_sessionid *sid)
596 {
597 	return NULL;
598 }
599 #endif /* CONFIG_NFS_V4_1 */
600 
601 /*
602  * Set up an NFS4 client
603  */
604 static int nfs4_set_client(struct nfs_server *server,
605 		const char *hostname,
606 		const struct sockaddr *addr,
607 		const size_t addrlen,
608 		const char *ip_addr,
609 		rpc_authflavor_t authflavour,
610 		int proto, const struct rpc_timeout *timeparms,
611 		u32 minorversion, struct net *net)
612 {
613 	struct nfs_client_initdata cl_init = {
614 		.hostname = hostname,
615 		.addr = addr,
616 		.addrlen = addrlen,
617 		.nfs_mod = &nfs_v4,
618 		.proto = proto,
619 		.minorversion = minorversion,
620 		.net = net,
621 	};
622 	struct nfs_client *clp;
623 	int error;
624 
625 	dprintk("--> nfs4_set_client()\n");
626 
627 	if (server->flags & NFS_MOUNT_NORESVPORT)
628 		set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
629 
630 	/* Allocate or find a client reference we can use */
631 	clp = nfs_get_client(&cl_init, timeparms, ip_addr, authflavour);
632 	if (IS_ERR(clp)) {
633 		error = PTR_ERR(clp);
634 		goto error;
635 	}
636 
637 	/*
638 	 * Query for the lease time on clientid setup or renewal
639 	 *
640 	 * Note that this will be set on nfs_clients that were created
641 	 * only for the DS role and did not set this bit, but now will
642 	 * serve a dual role.
643 	 */
644 	set_bit(NFS_CS_CHECK_LEASE_TIME, &clp->cl_res_state);
645 
646 	server->nfs_client = clp;
647 	dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp);
648 	return 0;
649 error:
650 	dprintk("<-- nfs4_set_client() = xerror %d\n", error);
651 	return error;
652 }
653 
654 /*
655  * Set up a pNFS Data Server client.
656  *
657  * Return any existing nfs_client that matches server address,port,version
658  * and minorversion.
659  *
660  * For a new nfs_client, use a soft mount (default), a low retrans and a
661  * low timeout interval so that if a connection is lost, we retry through
662  * the MDS.
663  */
664 struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp,
665 		const struct sockaddr *ds_addr, int ds_addrlen,
666 		int ds_proto, unsigned int ds_timeo, unsigned int ds_retrans)
667 {
668 	struct nfs_client_initdata cl_init = {
669 		.addr = ds_addr,
670 		.addrlen = ds_addrlen,
671 		.nfs_mod = &nfs_v4,
672 		.proto = ds_proto,
673 		.minorversion = mds_clp->cl_minorversion,
674 		.net = mds_clp->cl_net,
675 	};
676 	struct rpc_timeout ds_timeout;
677 	struct nfs_client *clp;
678 
679 	/*
680 	 * Set an authflavor equual to the MDS value. Use the MDS nfs_client
681 	 * cl_ipaddr so as to use the same EXCHANGE_ID co_ownerid as the MDS
682 	 * (section 13.1 RFC 5661).
683 	 */
684 	nfs_init_timeout_values(&ds_timeout, ds_proto, ds_timeo, ds_retrans);
685 	clp = nfs_get_client(&cl_init, &ds_timeout, mds_clp->cl_ipaddr,
686 			     mds_clp->cl_rpcclient->cl_auth->au_flavor);
687 
688 	dprintk("<-- %s %p\n", __func__, clp);
689 	return clp;
690 }
691 EXPORT_SYMBOL_GPL(nfs4_set_ds_client);
692 
693 /*
694  * Session has been established, and the client marked ready.
695  * Set the mount rsize and wsize with negotiated fore channel
696  * attributes which will be bound checked in nfs_server_set_fsinfo.
697  */
698 static void nfs4_session_set_rwsize(struct nfs_server *server)
699 {
700 #ifdef CONFIG_NFS_V4_1
701 	struct nfs4_session *sess;
702 	u32 server_resp_sz;
703 	u32 server_rqst_sz;
704 
705 	if (!nfs4_has_session(server->nfs_client))
706 		return;
707 	sess = server->nfs_client->cl_session;
708 	server_resp_sz = sess->fc_attrs.max_resp_sz - nfs41_maxread_overhead;
709 	server_rqst_sz = sess->fc_attrs.max_rqst_sz - nfs41_maxwrite_overhead;
710 
711 	if (server->rsize > server_resp_sz)
712 		server->rsize = server_resp_sz;
713 	if (server->wsize > server_rqst_sz)
714 		server->wsize = server_rqst_sz;
715 #endif /* CONFIG_NFS_V4_1 */
716 }
717 
718 static int nfs4_server_common_setup(struct nfs_server *server,
719 		struct nfs_fh *mntfh)
720 {
721 	struct nfs_fattr *fattr;
722 	int error;
723 
724 	/* data servers support only a subset of NFSv4.1 */
725 	if (is_ds_only_client(server->nfs_client))
726 		return -EPROTONOSUPPORT;
727 
728 	fattr = nfs_alloc_fattr();
729 	if (fattr == NULL)
730 		return -ENOMEM;
731 
732 	/* We must ensure the session is initialised first */
733 	error = nfs4_init_session(server);
734 	if (error < 0)
735 		goto out;
736 
737 	/* Set the basic capabilities */
738 	server->caps |= server->nfs_client->cl_mvops->init_caps;
739 	if (server->flags & NFS_MOUNT_NORDIRPLUS)
740 			server->caps &= ~NFS_CAP_READDIRPLUS;
741 	/*
742 	 * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower
743 	 * authentication.
744 	 */
745 	if (nfs4_disable_idmapping &&
746 			server->client->cl_auth->au_flavor == RPC_AUTH_UNIX)
747 		server->caps |= NFS_CAP_UIDGID_NOMAP;
748 
749 
750 	/* Probe the root fh to retrieve its FSID and filehandle */
751 	error = nfs4_get_rootfh(server, mntfh);
752 	if (error < 0)
753 		goto out;
754 
755 	dprintk("Server FSID: %llx:%llx\n",
756 			(unsigned long long) server->fsid.major,
757 			(unsigned long long) server->fsid.minor);
758 	dprintk("Mount FH: %d\n", mntfh->size);
759 
760 	nfs4_session_set_rwsize(server);
761 
762 	error = nfs_probe_fsinfo(server, mntfh, fattr);
763 	if (error < 0)
764 		goto out;
765 
766 	if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
767 		server->namelen = NFS4_MAXNAMLEN;
768 
769 	nfs_server_insert_lists(server);
770 	server->mount_time = jiffies;
771 	server->destroy = nfs4_destroy_server;
772 out:
773 	nfs_free_fattr(fattr);
774 	return error;
775 }
776 
777 /*
778  * Create a version 4 volume record
779  */
780 static int nfs4_init_server(struct nfs_server *server,
781 		const struct nfs_parsed_mount_data *data)
782 {
783 	struct rpc_timeout timeparms;
784 	int error;
785 
786 	dprintk("--> nfs4_init_server()\n");
787 
788 	nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
789 			data->timeo, data->retrans);
790 
791 	/* Initialise the client representation from the mount data */
792 	server->flags = data->flags;
793 	server->options = data->options;
794 
795 	/* Get a client record */
796 	error = nfs4_set_client(server,
797 			data->nfs_server.hostname,
798 			(const struct sockaddr *)&data->nfs_server.address,
799 			data->nfs_server.addrlen,
800 			data->client_address,
801 			data->auth_flavors[0],
802 			data->nfs_server.protocol,
803 			&timeparms,
804 			data->minorversion,
805 			data->net);
806 	if (error < 0)
807 		goto error;
808 
809 	if (data->rsize)
810 		server->rsize = nfs_block_size(data->rsize, NULL);
811 	if (data->wsize)
812 		server->wsize = nfs_block_size(data->wsize, NULL);
813 
814 	server->acregmin = data->acregmin * HZ;
815 	server->acregmax = data->acregmax * HZ;
816 	server->acdirmin = data->acdirmin * HZ;
817 	server->acdirmax = data->acdirmax * HZ;
818 
819 	server->port = data->nfs_server.port;
820 
821 	error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]);
822 
823 error:
824 	/* Done */
825 	dprintk("<-- nfs4_init_server() = %d\n", error);
826 	return error;
827 }
828 
829 /*
830  * Create a version 4 volume record
831  * - keyed on server and FSID
832  */
833 /*struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
834 				      struct nfs_fh *mntfh)*/
835 struct nfs_server *nfs4_create_server(struct nfs_mount_info *mount_info,
836 				      struct nfs_subversion *nfs_mod)
837 {
838 	struct nfs_server *server;
839 	int error;
840 
841 	dprintk("--> nfs4_create_server()\n");
842 
843 	server = nfs_alloc_server();
844 	if (!server)
845 		return ERR_PTR(-ENOMEM);
846 
847 	/* set up the general RPC client */
848 	error = nfs4_init_server(server, mount_info->parsed);
849 	if (error < 0)
850 		goto error;
851 
852 	error = nfs4_server_common_setup(server, mount_info->mntfh);
853 	if (error < 0)
854 		goto error;
855 
856 	dprintk("<-- nfs4_create_server() = %p\n", server);
857 	return server;
858 
859 error:
860 	nfs_free_server(server);
861 	dprintk("<-- nfs4_create_server() = error %d\n", error);
862 	return ERR_PTR(error);
863 }
864 
865 /*
866  * Create an NFS4 referral server record
867  */
868 struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
869 					       struct nfs_fh *mntfh)
870 {
871 	struct nfs_client *parent_client;
872 	struct nfs_server *server, *parent_server;
873 	int error;
874 
875 	dprintk("--> nfs4_create_referral_server()\n");
876 
877 	server = nfs_alloc_server();
878 	if (!server)
879 		return ERR_PTR(-ENOMEM);
880 
881 	parent_server = NFS_SB(data->sb);
882 	parent_client = parent_server->nfs_client;
883 
884 	/* Initialise the client representation from the parent server */
885 	nfs_server_copy_userdata(server, parent_server);
886 
887 	/* Get a client representation.
888 	 * Note: NFSv4 always uses TCP, */
889 	error = nfs4_set_client(server, data->hostname,
890 				data->addr,
891 				data->addrlen,
892 				parent_client->cl_ipaddr,
893 				data->authflavor,
894 				rpc_protocol(parent_server->client),
895 				parent_server->client->cl_timeout,
896 				parent_client->cl_mvops->minor_version,
897 				parent_client->cl_net);
898 	if (error < 0)
899 		goto error;
900 
901 	error = nfs_init_server_rpcclient(server, parent_server->client->cl_timeout, data->authflavor);
902 	if (error < 0)
903 		goto error;
904 
905 	error = nfs4_server_common_setup(server, mntfh);
906 	if (error < 0)
907 		goto error;
908 
909 	dprintk("<-- nfs_create_referral_server() = %p\n", server);
910 	return server;
911 
912 error:
913 	nfs_free_server(server);
914 	dprintk("<-- nfs4_create_referral_server() = error %d\n", error);
915 	return ERR_PTR(error);
916 }
917