File Index
Files and directories
Sign in
FILE

nfs4client.c

File preview with syntax highlighting.

linux-6.19.14/fs/nfs/nfs4client.c C
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
   4 * Written by David Howells (dhowells@redhat.com)
   5 */
   6#include <linux/module.h>
   7#include <linux/nfs_fs.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 <linux/sunrpc/rpc_pipe_fs.h>
  14#include <net/handshake.h>
  15#include "internal.h"
  16#include "callback.h"
  17#include "delegation.h"
  18#include "nfs4session.h"
  19#include "nfs4idmap.h"
  20#include "pnfs.h"
  21#include "netns.h"
  22#include "sysfs.h"
  23
  24#define NFSDBG_FACILITY		NFSDBG_CLIENT
  25
  26/*
  27 * Get a unique NFSv4.0 callback identifier which will be used
  28 * by the V4.0 callback service to lookup the nfs_client struct
  29 */
  30static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion)
  31{
  32	int ret = 0;
  33	struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
  34
  35	if (clp->rpc_ops->version != 4 || minorversion != 0)
  36		return ret;
  37	idr_preload(GFP_KERNEL);
  38	spin_lock(&nn->nfs_client_lock);
  39	ret = idr_alloc(&nn->cb_ident_idr, clp, 1, 0, GFP_NOWAIT);
  40	if (ret >= 0)
  41		clp->cl_cb_ident = ret;
  42	spin_unlock(&nn->nfs_client_lock);
  43	idr_preload_end();
  44	return ret < 0 ? ret : 0;
  45}
  46
  47#ifdef CONFIG_NFS_V4_1
  48/*
  49 * Per auth flavor data server rpc clients
  50 */
  51struct nfs4_ds_server {
  52	struct list_head	list;   /* ds_clp->cl_ds_clients */
  53	struct rpc_clnt		*rpc_clnt;
  54};
  55
  56/**
  57 * nfs4_find_ds_client - Common lookup case for DS I/O
  58 * @ds_clp: pointer to the DS's nfs_client
  59 * @flavor: rpc auth flavour to match
  60 */
  61static struct nfs4_ds_server *
  62nfs4_find_ds_client(struct nfs_client *ds_clp, rpc_authflavor_t flavor)
  63{
  64	struct nfs4_ds_server *dss;
  65
  66	rcu_read_lock();
  67	list_for_each_entry_rcu(dss, &ds_clp->cl_ds_clients, list) {
  68		if (dss->rpc_clnt->cl_auth->au_flavor != flavor)
  69			continue;
  70		goto out;
  71	}
  72	dss = NULL;
  73out:
  74	rcu_read_unlock();
  75	return dss;
  76}
  77
  78static struct nfs4_ds_server *
  79nfs4_add_ds_client(struct nfs_client *ds_clp, rpc_authflavor_t flavor,
  80			   struct nfs4_ds_server *new)
  81{
  82	struct nfs4_ds_server *dss;
  83
  84	spin_lock(&ds_clp->cl_lock);
  85	list_for_each_entry(dss, &ds_clp->cl_ds_clients, list) {
  86		if (dss->rpc_clnt->cl_auth->au_flavor != flavor)
  87			continue;
  88		goto out;
  89	}
  90	if (new)
  91		list_add_rcu(&new->list, &ds_clp->cl_ds_clients);
  92	dss = new;
  93out:
  94	spin_unlock(&ds_clp->cl_lock); /* need some lock to protect list */
  95	return dss;
  96}
  97
  98static struct nfs4_ds_server *
  99nfs4_alloc_ds_server(struct nfs_client *ds_clp, rpc_authflavor_t flavor)
 100{
 101	struct nfs4_ds_server *dss;
 102
 103	dss = kmalloc(sizeof(*dss), GFP_NOFS);
 104	if (dss == NULL)
 105		return ERR_PTR(-ENOMEM);
 106
 107	dss->rpc_clnt = rpc_clone_client_set_auth(ds_clp->cl_rpcclient, flavor);
 108	if (IS_ERR(dss->rpc_clnt)) {
 109		int err = PTR_ERR(dss->rpc_clnt);
 110		kfree (dss);
 111		return ERR_PTR(err);
 112	}
 113	INIT_LIST_HEAD(&dss->list);
 114
 115	return dss;
 116}
 117
 118static void
 119nfs4_free_ds_server(struct nfs4_ds_server *dss)
 120{
 121	rpc_release_client(dss->rpc_clnt);
 122	kfree(dss);
 123}
 124
 125/**
 126 * nfs4_find_or_create_ds_client - Find or create a DS rpc client
 127 * @ds_clp: pointer to the DS's nfs_client
 128 * @inode: pointer to the inode
 129 *
 130 * Find or create a DS rpc client with th MDS server rpc client auth flavor
 131 * in the nfs_client cl_ds_clients list.
 132 */
 133struct rpc_clnt *
 134nfs4_find_or_create_ds_client(struct nfs_client *ds_clp, struct inode *inode)
 135{
 136	struct nfs4_ds_server *dss, *new;
 137	rpc_authflavor_t flavor = NFS_SERVER(inode)->client->cl_auth->au_flavor;
 138
 139	dss = nfs4_find_ds_client(ds_clp, flavor);
 140	if (dss != NULL)
 141		goto out;
 142	new = nfs4_alloc_ds_server(ds_clp, flavor);
 143	if (IS_ERR(new))
 144		return ERR_CAST(new);
 145	dss = nfs4_add_ds_client(ds_clp, flavor, new);
 146	if (dss != new)
 147		nfs4_free_ds_server(new);
 148out:
 149	return dss->rpc_clnt;
 150}
 151EXPORT_SYMBOL_GPL(nfs4_find_or_create_ds_client);
 152
 153static void
 154nfs4_shutdown_ds_clients(struct nfs_client *clp)
 155{
 156	struct nfs4_ds_server *dss;
 157
 158	while (!list_empty(&clp->cl_ds_clients)) {
 159		dss = list_entry(clp->cl_ds_clients.next,
 160					struct nfs4_ds_server, list);
 161		list_del(&dss->list);
 162		rpc_shutdown_client(dss->rpc_clnt);
 163		kfree (dss);
 164	}
 165}
 166
 167static void
 168nfs4_cleanup_callback(struct nfs_client *clp)
 169{
 170	struct nfs4_copy_state *cp_state;
 171
 172	while (!list_empty(&clp->pending_cb_stateids)) {
 173		cp_state = list_entry(clp->pending_cb_stateids.next,
 174					struct nfs4_copy_state, copies);
 175		list_del(&cp_state->copies);
 176		kfree(cp_state);
 177	}
 178}
 179
 180void nfs41_shutdown_client(struct nfs_client *clp)
 181{
 182	if (nfs4_has_session(clp)) {
 183		nfs4_cleanup_callback(clp);
 184		nfs4_shutdown_ds_clients(clp);
 185		nfs4_destroy_session(clp->cl_session);
 186		nfs4_destroy_clientid(clp);
 187	}
 188
 189}
 190#endif	/* CONFIG_NFS_V4_1 */
 191
 192void nfs40_shutdown_client(struct nfs_client *clp)
 193{
 194	if (clp->cl_slot_tbl) {
 195		nfs4_shutdown_slot_table(clp->cl_slot_tbl);
 196		kfree(clp->cl_slot_tbl);
 197	}
 198}
 199
 200struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init)
 201{
 202	char buf[INET6_ADDRSTRLEN + 1];
 203	const char *ip_addr = cl_init->ip_addr;
 204	struct nfs_client *clp = nfs_alloc_client(cl_init);
 205	int err;
 206
 207	if (IS_ERR(clp))
 208		return clp;
 209
 210	err = nfs_get_cb_ident_idr(clp, cl_init->minorversion);
 211	if (err)
 212		goto error;
 213
 214	if (cl_init->minorversion > NFS4_MAX_MINOR_VERSION) {
 215		err = -EINVAL;
 216		goto error;
 217	}
 218
 219	spin_lock_init(&clp->cl_lock);
 220	INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
 221	INIT_LIST_HEAD(&clp->cl_ds_clients);
 222	rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
 223	clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
 224	clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion];
 225	clp->cl_mig_gen = 1;
 226	clp->cl_last_renewal = jiffies;
 227#if IS_ENABLED(CONFIG_NFS_V4_1)
 228	init_waitqueue_head(&clp->cl_lock_waitq);
 229#endif
 230	INIT_LIST_HEAD(&clp->pending_cb_stateids);
 231
 232	if (cl_init->minorversion != 0)
 233		__set_bit(NFS_CS_INFINITE_SLOTS, &clp->cl_flags);
 234	__set_bit(NFS_CS_DISCRTRY, &clp->cl_flags);
 235	__set_bit(NFS_CS_NO_RETRANS_TIMEOUT, &clp->cl_flags);
 236	if (test_bit(NFS_CS_PNFS, &cl_init->init_flags))
 237		__set_bit(NFS_CS_PNFS, &clp->cl_flags);
 238	if (test_bit(NFS_CS_NETUNREACH_FATAL, &cl_init->init_flags))
 239		__set_bit(NFS_CS_NETUNREACH_FATAL, &clp->cl_flags);
 240	/*
 241	 * Set up the connection to the server before we add add to the
 242	 * global list.
 243	 */
 244	err = nfs_create_rpc_client(clp, cl_init, RPC_AUTH_GSS_KRB5I);
 245	if (err == -EINVAL)
 246		err = nfs_create_rpc_client(clp, cl_init, RPC_AUTH_UNIX);
 247	if (err < 0)
 248		goto error;
 249
 250	/* If no clientaddr= option was specified, find a usable cb address */
 251	if (ip_addr == NULL) {
 252		struct sockaddr_storage cb_addr;
 253		struct sockaddr *sap = (struct sockaddr *)&cb_addr;
 254
 255		err = rpc_localaddr(clp->cl_rpcclient, sap, sizeof(cb_addr));
 256		if (err < 0)
 257			goto error;
 258		err = rpc_ntop(sap, buf, sizeof(buf));
 259		if (err < 0)
 260			goto error;
 261		ip_addr = (const char *)buf;
 262	}
 263	strscpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
 264
 265	err = nfs_idmap_new(clp);
 266	if (err < 0) {
 267		dprintk("%s: failed to create idmapper. Error = %d\n",
 268			__func__, err);
 269		goto error;
 270	}
 271	__set_bit(NFS_CS_IDMAP, &clp->cl_res_state);
 272	return clp;
 273
 274error:
 275	nfs_free_client(clp);
 276	return ERR_PTR(err);
 277}
 278
 279/*
 280 * Destroy the NFS4 callback service
 281 */
 282static void nfs4_destroy_callback(struct nfs_client *clp)
 283{
 284	if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) {
 285		struct rpc_xprt *xprt;
 286
 287		xprt = rcu_dereference_raw(clp->cl_rpcclient->cl_xprt);
 288		nfs_callback_down(clp->cl_mvops->minor_version, clp->cl_net,
 289				  xprt);
 290	}
 291}
 292
 293static void nfs4_shutdown_client(struct nfs_client *clp)
 294{
 295	if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
 296		nfs4_kill_renewd(clp);
 297	clp->cl_mvops->shutdown_client(clp);
 298	nfs4_destroy_callback(clp);
 299	if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
 300		nfs_idmap_delete(clp);
 301
 302	rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
 303	kfree(clp->cl_serverowner);
 304	kfree(clp->cl_serverscope);
 305	kfree(clp->cl_implid);
 306	kfree(clp->cl_owner_id);
 307}
 308
 309void nfs4_free_client(struct nfs_client *clp)
 310{
 311	nfs4_shutdown_client(clp);
 312	nfs_free_client(clp);
 313}
 314
 315/*
 316 * Initialize the NFS4 callback service
 317 */
 318static int nfs4_init_callback(struct nfs_client *clp)
 319{
 320	struct rpc_xprt *xprt;
 321	int error;
 322
 323	xprt = rcu_dereference_raw(clp->cl_rpcclient->cl_xprt);
 324
 325	if (nfs4_has_session(clp)) {
 326		error = xprt_setup_backchannel(xprt, NFS41_BC_MIN_CALLBACKS);
 327		if (error < 0)
 328			return error;
 329	}
 330
 331	error = nfs_callback_up(clp->cl_mvops->minor_version, xprt);
 332	if (error < 0) {
 333		dprintk("%s: failed to start callback. Error = %d\n",
 334			__func__, error);
 335		return error;
 336	}
 337	__set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
 338
 339	return 0;
 340}
 341
 342/**
 343 * nfs40_init_client - nfs_client initialization tasks for NFSv4.0
 344 * @clp: nfs_client to initialize
 345 *
 346 * Returns zero on success, or a negative errno if some error occurred.
 347 */
 348int nfs40_init_client(struct nfs_client *clp)
 349{
 350	struct nfs4_slot_table *tbl;
 351	int ret;
 352
 353	tbl = kzalloc(sizeof(*tbl), GFP_NOFS);
 354	if (tbl == NULL)
 355		return -ENOMEM;
 356
 357	ret = nfs4_setup_slot_table(tbl, NFS4_MAX_SLOT_TABLE,
 358					"NFSv4.0 transport Slot table");
 359	if (ret) {
 360		nfs4_shutdown_slot_table(tbl);
 361		kfree(tbl);
 362		return ret;
 363	}
 364
 365	clp->cl_slot_tbl = tbl;
 366	return 0;
 367}
 368
 369#if defined(CONFIG_NFS_V4_1)
 370
 371/**
 372 * nfs41_init_client - nfs_client initialization tasks for NFSv4.1+
 373 * @clp: nfs_client to initialize
 374 *
 375 * Returns zero on success, or a negative errno if some error occurred.
 376 */
 377int nfs41_init_client(struct nfs_client *clp)
 378{
 379	struct nfs4_session *session = NULL;
 380
 381	/*
 382	 * Create the session and mark it expired.
 383	 * When a SEQUENCE operation encounters the expired session
 384	 * it will do session recovery to initialize it.
 385	 */
 386	session = nfs4_alloc_session(clp);
 387	if (!session)
 388		return -ENOMEM;
 389
 390	clp->cl_session = session;
 391
 392	/*
 393	 * The create session reply races with the server back
 394	 * channel probe. Mark the client NFS_CS_SESSION_INITING
 395	 * so that the client back channel can find the
 396	 * nfs_client struct
 397	 */
 398	nfs_mark_client_ready(clp, NFS_CS_SESSION_INITING);
 399	return 0;
 400}
 401
 402#endif	/* CONFIG_NFS_V4_1 */
 403
 404/*
 405 * Initialize the minor version specific parts of an NFS4 client record
 406 */
 407static int nfs4_init_client_minor_version(struct nfs_client *clp)
 408{
 409	int ret;
 410
 411	ret = clp->cl_mvops->init_client(clp);
 412	if (ret)
 413		return ret;
 414	return nfs4_init_callback(clp);
 415}
 416
 417static void nfs4_add_trunk(struct nfs_client *clp, struct nfs_client *old)
 418{
 419	struct sockaddr_storage clp_addr, old_addr;
 420	struct sockaddr *clp_sap = (struct sockaddr *)&clp_addr;
 421	struct sockaddr *old_sap = (struct sockaddr *)&old_addr;
 422	size_t clp_salen;
 423	struct xprt_create xprt_args = {
 424		.ident = old->cl_proto,
 425		.net = old->cl_net,
 426		.servername = old->cl_hostname,
 427	};
 428	int max_connect = test_bit(NFS_CS_PNFS, &clp->cl_flags) ?
 429		clp->cl_max_connect : old->cl_max_connect;
 430
 431	if (clp->cl_proto != old->cl_proto)
 432		return;
 433	clp_salen = rpc_peeraddr(clp->cl_rpcclient, clp_sap, sizeof(clp_addr));
 434	rpc_peeraddr(old->cl_rpcclient, old_sap, sizeof(old_addr));
 435
 436	if (clp_addr.ss_family != old_addr.ss_family)
 437		return;
 438
 439	xprt_args.dstaddr = clp_sap;
 440	xprt_args.addrlen = clp_salen;
 441
 442	rpc_clnt_add_xprt(old->cl_rpcclient, &xprt_args,
 443			  rpc_clnt_test_and_add_xprt, &max_connect);
 444}
 445
 446/**
 447 * nfs4_init_client - Initialise an NFS4 client record
 448 *
 449 * @clp: nfs_client to initialise
 450 * @cl_init: pointer to nfs_client_initdata
 451 *
 452 * Returns pointer to an NFS client, or an ERR_PTR value.
 453 */
 454struct nfs_client *nfs4_init_client(struct nfs_client *clp,
 455				    const struct nfs_client_initdata *cl_init)
 456{
 457	struct nfs_client *old;
 458	int error;
 459
 460	if (clp->cl_cons_state == NFS_CS_READY)
 461		/* the client is initialised already */
 462		return clp;
 463
 464	error = nfs4_init_client_minor_version(clp);
 465	if (error < 0)
 466		goto error;
 467
 468	error = nfs4_discover_server_trunking(clp, &old);
 469	if (error < 0)
 470		goto error;
 471
 472	if (clp != old) {
 473		clp->cl_preserve_clid = true;
 474		/*
 475		 * Mark the client as having failed initialization so other
 476		 * processes walking the nfs_client_list in nfs_match_client()
 477		 * won't try to use it.
 478		 */
 479		nfs_mark_client_ready(clp, -EPERM);
 480		if (old->cl_mvops->session_trunk)
 481			nfs4_add_trunk(clp, old);
 482	}
 483	clear_bit(NFS_CS_TSM_POSSIBLE, &clp->cl_flags);
 484	nfs_put_client(clp);
 485	return old;
 486
 487error:
 488	nfs_mark_client_ready(clp, error);
 489	nfs_put_client(clp);
 490	return ERR_PTR(error);
 491}
 492
 493/*
 494 * SETCLIENTID just did a callback update with the callback ident in
 495 * "drop," but server trunking discovery claims "drop" and "keep" are
 496 * actually the same server.  Swap the callback IDs so that "keep"
 497 * will continue to use the callback ident the server now knows about,
 498 * and so that "keep"'s original callback ident is destroyed when
 499 * "drop" is freed.
 500 */
 501static void nfs4_swap_callback_idents(struct nfs_client *keep,
 502				      struct nfs_client *drop)
 503{
 504	struct nfs_net *nn = net_generic(keep->cl_net, nfs_net_id);
 505	unsigned int save = keep->cl_cb_ident;
 506
 507	if (keep->cl_cb_ident == drop->cl_cb_ident)
 508		return;
 509
 510	dprintk("%s: keeping callback ident %u and dropping ident %u\n",
 511		__func__, keep->cl_cb_ident, drop->cl_cb_ident);
 512
 513	spin_lock(&nn->nfs_client_lock);
 514
 515	idr_replace(&nn->cb_ident_idr, keep, drop->cl_cb_ident);
 516	keep->cl_cb_ident = drop->cl_cb_ident;
 517
 518	idr_replace(&nn->cb_ident_idr, drop, save);
 519	drop->cl_cb_ident = save;
 520
 521	spin_unlock(&nn->nfs_client_lock);
 522}
 523
 524static bool nfs4_match_client_owner_id(const struct nfs_client *clp1,
 525		const struct nfs_client *clp2)
 526{
 527	if (clp1->cl_owner_id == NULL || clp2->cl_owner_id == NULL)
 528		return true;
 529	return strcmp(clp1->cl_owner_id, clp2->cl_owner_id) == 0;
 530}
 531
 532static bool nfs4_same_verifier(nfs4_verifier *v1, nfs4_verifier *v2)
 533{
 534	return memcmp(v1->data, v2->data, sizeof(v1->data)) == 0;
 535}
 536
 537static int nfs4_match_client(struct nfs_client  *pos,  struct nfs_client *new,
 538			     struct nfs_client **prev, struct nfs_net *nn)
 539{
 540	int status;
 541
 542	if (pos->rpc_ops != new->rpc_ops)
 543		return 1;
 544
 545	if (pos->cl_minorversion != new->cl_minorversion)
 546		return 1;
 547
 548	/* If "pos" isn't marked ready, we can't trust the
 549	 * remaining fields in "pos", especially the client
 550	 * ID and serverowner fields.  Wait for CREATE_SESSION
 551	 * to finish. */
 552	if (pos->cl_cons_state > NFS_CS_READY) {
 553		refcount_inc(&pos->cl_count);
 554		spin_unlock(&nn->nfs_client_lock);
 555
 556		nfs_put_client(*prev);
 557		*prev = pos;
 558
 559		status = nfs_wait_client_init_complete(pos);
 560		spin_lock(&nn->nfs_client_lock);
 561
 562		if (status < 0)
 563			return status;
 564	}
 565
 566	if (pos->cl_cons_state != NFS_CS_READY)
 567		return 1;
 568
 569	if (pos->cl_clientid != new->cl_clientid)
 570		return 1;
 571
 572	/* NFSv4.1 always uses the uniform string, however someone
 573	 * might switch the uniquifier string on us.
 574	 */
 575	if (!nfs4_match_client_owner_id(pos, new))
 576		return 1;
 577
 578	return 0;
 579}
 580
 581/**
 582 * nfs40_walk_client_list - Find server that recognizes a client ID
 583 *
 584 * @new: nfs_client with client ID to test
 585 * @result: OUT: found nfs_client, or new
 586 * @cred: credential to use for trunking test
 587 *
 588 * Returns zero, a negative errno, or a negative NFS4ERR status.
 589 * If zero is returned, an nfs_client pointer is planted in "result."
 590 *
 591 * NB: nfs40_walk_client_list() relies on the new nfs_client being
 592 *     the last nfs_client on the list.
 593 */
 594int nfs40_walk_client_list(struct nfs_client *new,
 595			   struct nfs_client **result,
 596			   const struct cred *cred)
 597{
 598	struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id);
 599	struct nfs_client *pos, *prev = NULL;
 600	struct nfs4_setclientid_res clid = {
 601		.clientid	= new->cl_clientid,
 602		.confirm	= new->cl_confirm,
 603	};
 604	int status = -NFS4ERR_STALE_CLIENTID;
 605
 606	spin_lock(&nn->nfs_client_lock);
 607	list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) {
 608
 609		if (pos == new)
 610			goto found;
 611
 612		status = nfs4_match_client(pos, new, &prev, nn);
 613		if (status < 0)
 614			goto out_unlock;
 615		if (status != 0)
 616			continue;
 617		/*
 618		 * We just sent a new SETCLIENTID, which should have
 619		 * caused the server to return a new cl_confirm.  So if
 620		 * cl_confirm is the same, then this is a different
 621		 * server that just returned the same cl_confirm by
 622		 * coincidence:
 623		 */
 624		if ((new != pos) && nfs4_same_verifier(&pos->cl_confirm,
 625						       &new->cl_confirm))
 626			continue;
 627		/*
 628		 * But if the cl_confirm's are different, then the only
 629		 * way that a SETCLIENTID_CONFIRM to pos can succeed is
 630		 * if new and pos point to the same server:
 631		 */
 632found:
 633		refcount_inc(&pos->cl_count);
 634		spin_unlock(&nn->nfs_client_lock);
 635
 636		nfs_put_client(prev);
 637		prev = pos;
 638
 639		status = nfs4_proc_setclientid_confirm(pos, &clid, cred);
 640		switch (status) {
 641		case -NFS4ERR_STALE_CLIENTID:
 642			break;
 643		case 0:
 644			nfs4_swap_callback_idents(pos, new);
 645			pos->cl_confirm = new->cl_confirm;
 646			nfs_mark_client_ready(pos, NFS_CS_READY);
 647
 648			prev = NULL;
 649			*result = pos;
 650			goto out;
 651		case -ERESTARTSYS:
 652		case -ETIMEDOUT:
 653			/* The callback path may have been inadvertently
 654			 * changed. Schedule recovery!
 655			 */
 656			nfs4_schedule_path_down_recovery(pos);
 657			goto out;
 658		default:
 659			goto out;
 660		}
 661
 662		spin_lock(&nn->nfs_client_lock);
 663	}
 664out_unlock:
 665	spin_unlock(&nn->nfs_client_lock);
 666
 667	/* No match found. The server lost our clientid */
 668out:
 669	nfs_put_client(prev);
 670	return status;
 671}
 672
 673#ifdef CONFIG_NFS_V4_1
 674/*
 675 * Returns true if the server major ids match
 676 */
 677bool
 678nfs4_check_serverowner_major_id(struct nfs41_server_owner *o1,
 679				struct nfs41_server_owner *o2)
 680{
 681	if (o1->major_id_sz != o2->major_id_sz)
 682		return false;
 683	return memcmp(o1->major_id, o2->major_id, o1->major_id_sz) == 0;
 684}
 685
 686/*
 687 * Returns true if the server scopes match
 688 */
 689static bool
 690nfs4_check_server_scope(struct nfs41_server_scope *s1,
 691			struct nfs41_server_scope *s2)
 692{
 693	if (s1->server_scope_sz != s2->server_scope_sz)
 694		return false;
 695	return memcmp(s1->server_scope, s2->server_scope,
 696					s1->server_scope_sz) == 0;
 697}
 698
 699/**
 700 * nfs4_detect_session_trunking - Checks for session trunking.
 701 * @clp:    original mount nfs_client
 702 * @res:    result structure from an exchange_id using the original mount
 703 *          nfs_client with a new multi_addr transport
 704 * @xprt:   pointer to the transport to add.
 705 *
 706 * Called after a successful EXCHANGE_ID on a multi-addr connection.
 707 * Upon success, add the transport.
 708 *
 709 * Returns zero on success, otherwise -EINVAL
 710 *
 711 * Note: since the exchange_id for the new multi_addr transport uses the
 712 * same nfs_client from the original mount, the cl_owner_id is reused,
 713 * so eir_clientowner is the same.
 714 */
 715int nfs4_detect_session_trunking(struct nfs_client *clp,
 716				 struct nfs41_exchange_id_res *res,
 717				 struct rpc_xprt *xprt)
 718{
 719	/* Check eir_clientid */
 720	if (clp->cl_clientid != res->clientid)
 721		goto out_err;
 722
 723	/* Check eir_server_owner so_major_id */
 724	if (!nfs4_check_serverowner_major_id(clp->cl_serverowner,
 725					     res->server_owner))
 726		goto out_err;
 727
 728	/* Check eir_server_owner so_minor_id */
 729	if (clp->cl_serverowner->minor_id != res->server_owner->minor_id)
 730		goto out_err;
 731
 732	/* Check eir_server_scope */
 733	if (!nfs4_check_server_scope(clp->cl_serverscope, res->server_scope))
 734		goto out_err;
 735
 736	pr_info("NFS:  %s: Session trunking succeeded for %s\n",
 737		clp->cl_hostname,
 738		xprt->address_strings[RPC_DISPLAY_ADDR]);
 739
 740	return 0;
 741out_err:
 742	pr_info("NFS:  %s: Session trunking failed for %s\n", clp->cl_hostname,
 743		xprt->address_strings[RPC_DISPLAY_ADDR]);
 744
 745	return -EINVAL;
 746}
 747
 748/**
 749 * nfs41_walk_client_list - Find nfs_client that matches a client/server owner
 750 *
 751 * @new: nfs_client with client ID to test
 752 * @result: OUT: found nfs_client, or new
 753 * @cred: credential to use for trunking test
 754 *
 755 * Returns zero, a negative errno, or a negative NFS4ERR status.
 756 * If zero is returned, an nfs_client pointer is planted in "result."
 757 *
 758 * NB: nfs41_walk_client_list() relies on the new nfs_client being
 759 *     the last nfs_client on the list.
 760 */
 761int nfs41_walk_client_list(struct nfs_client *new,
 762			   struct nfs_client **result,
 763			   const struct cred *cred)
 764{
 765	struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id);
 766	struct nfs_client *pos, *prev = NULL;
 767	int status = -NFS4ERR_STALE_CLIENTID;
 768
 769	spin_lock(&nn->nfs_client_lock);
 770	list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) {
 771
 772		if (pos == new)
 773			goto found;
 774
 775		status = nfs4_match_client(pos, new, &prev, nn);
 776		if (status < 0)
 777			goto out;
 778		if (status != 0)
 779			continue;
 780
 781		/*
 782		 * Note that session trunking is just a special subcase of
 783		 * client id trunking. In either case, we want to fall back
 784		 * to using the existing nfs_client.
 785		 */
 786		if (!nfs4_check_serverowner_major_id(pos->cl_serverowner,
 787						     new->cl_serverowner))
 788			continue;
 789
 790found:
 791		refcount_inc(&pos->cl_count);
 792		*result = pos;
 793		status = 0;
 794		break;
 795	}
 796
 797out:
 798	spin_unlock(&nn->nfs_client_lock);
 799	nfs_put_client(prev);
 800	return status;
 801}
 802#endif	/* CONFIG_NFS_V4_1 */
 803
 804static void nfs4_destroy_server(struct nfs_server *server)
 805{
 806	LIST_HEAD(freeme);
 807
 808	nfs_server_return_all_delegations(server);
 809	unset_pnfs_layoutdriver(server);
 810	nfs4_purge_state_owners(server, &freeme);
 811	nfs4_free_state_owners(&freeme);
 812	kfree(server->delegation_hash_table);
 813}
 814
 815/*
 816 * NFSv4.0 callback thread helper
 817 *
 818 * Find a client by callback identifier
 819 */
 820struct nfs_client *
 821nfs4_find_client_ident(struct net *net, int cb_ident)
 822{
 823	struct nfs_client *clp;
 824	struct nfs_net *nn = net_generic(net, nfs_net_id);
 825
 826	spin_lock(&nn->nfs_client_lock);
 827	clp = idr_find(&nn->cb_ident_idr, cb_ident);
 828	if (clp)
 829		refcount_inc(&clp->cl_count);
 830	spin_unlock(&nn->nfs_client_lock);
 831	return clp;
 832}
 833
 834#if defined(CONFIG_NFS_V4_1)
 835/* Common match routine for v4.0 and v4.1 callback services */
 836static bool nfs4_cb_match_client(const struct sockaddr *addr,
 837		struct nfs_client *clp, u32 minorversion)
 838{
 839	struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
 840
 841	/* Don't match clients that failed to initialise */
 842	if (!(clp->cl_cons_state == NFS_CS_READY ||
 843	    clp->cl_cons_state == NFS_CS_SESSION_INITING))
 844		return false;
 845
 846	smp_rmb();
 847
 848	/* Match the version and minorversion */
 849	if (clp->rpc_ops->version != 4 ||
 850	    clp->cl_minorversion != minorversion)
 851		return false;
 852
 853	/* Match only the IP address, not the port number */
 854	return rpc_cmp_addr(addr, clap);
 855}
 856
 857/*
 858 * NFSv4.1 callback thread helper
 859 * For CB_COMPOUND calls, find a client by IP address, protocol version,
 860 * minorversion, and sessionID
 861 *
 862 * Returns NULL if no such client
 863 */
 864struct nfs_client *
 865nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr,
 866			   struct nfs4_sessionid *sid, u32 minorversion)
 867{
 868	struct nfs_client *clp;
 869	struct nfs_net *nn = net_generic(net, nfs_net_id);
 870
 871	spin_lock(&nn->nfs_client_lock);
 872	list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) {
 873		if (!nfs4_cb_match_client(addr, clp, minorversion))
 874			continue;
 875
 876		if (!nfs4_has_session(clp))
 877			continue;
 878
 879		/* Match sessionid*/
 880		if (memcmp(clp->cl_session->sess_id.data,
 881		    sid->data, NFS4_MAX_SESSIONID_LEN) != 0)
 882			continue;
 883
 884		refcount_inc(&clp->cl_count);
 885		spin_unlock(&nn->nfs_client_lock);
 886		return clp;
 887	}
 888	spin_unlock(&nn->nfs_client_lock);
 889	return NULL;
 890}
 891
 892#else /* CONFIG_NFS_V4_1 */
 893
 894struct nfs_client *
 895nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr,
 896			   struct nfs4_sessionid *sid, u32 minorversion)
 897{
 898	return NULL;
 899}
 900#endif /* CONFIG_NFS_V4_1 */
 901
 902/*
 903 * Set up an NFS4 client
 904 */
 905static int nfs4_set_client(struct nfs_server *server,
 906		struct nfs_client_initdata *cl_init)
 907{
 908	struct nfs_client *clp;
 909
 910	cl_init->nfs_mod = &nfs_v4;
 911	cl_init->cred = server->cred;
 912
 913	if (cl_init->minorversion == 0) {
 914		__set_bit(NFS_CS_REUSEPORT, &cl_init->init_flags);
 915		cl_init->max_connect = 0;
 916	}
 917
 918	switch (cl_init->proto) {
 919	case XPRT_TRANSPORT_RDMA:
 920	case XPRT_TRANSPORT_TCP:
 921	case XPRT_TRANSPORT_TCP_TLS:
 922		break;
 923	default:
 924		cl_init->nconnect = 0;
 925	}
 926
 927	if (server->flags & NFS_MOUNT_NORESVPORT)
 928		__set_bit(NFS_CS_NORESVPORT, &cl_init->init_flags);
 929	if (server->options & NFS_OPTION_MIGRATION)
 930		__set_bit(NFS_CS_MIGRATION, &cl_init->init_flags);
 931	if (test_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status))
 932		__set_bit(NFS_CS_TSM_POSSIBLE, &cl_init->init_flags);
 933	server->port = rpc_get_port((struct sockaddr *)cl_init->addr);
 934
 935	if (server->flags & NFS_MOUNT_NETUNREACH_FATAL)
 936		__set_bit(NFS_CS_NETUNREACH_FATAL, &cl_init->init_flags);
 937
 938	/* Allocate or find a client reference we can use */
 939	clp = nfs_get_client(cl_init);
 940	if (IS_ERR(clp))
 941		return PTR_ERR(clp);
 942
 943	if (server->nfs_client == clp) {
 944		nfs_put_client(clp);
 945		return -ELOOP;
 946	}
 947
 948	/*
 949	 * Query for the lease time on clientid setup or renewal
 950	 *
 951	 * Note that this will be set on nfs_clients that were created
 952	 * only for the DS role and did not set this bit, but now will
 953	 * serve a dual role.
 954	 */
 955	set_bit(NFS_CS_CHECK_LEASE_TIME, &clp->cl_res_state);
 956
 957	server->nfs_client = clp;
 958	nfs_sysfs_add_server(server);
 959	nfs_sysfs_link_rpc_client(server, clp->cl_rpcclient, "_state");
 960
 961	return 0;
 962}
 963
 964/*
 965 * Set up a pNFS Data Server client.
 966 *
 967 * Return any existing nfs_client that matches server address,port,version
 968 * and minorversion.
 969 *
 970 * For a new nfs_client, use a soft mount (default), a low retrans and a
 971 * low timeout interval so that if a connection is lost, we retry through
 972 * the MDS.
 973 */
 974struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv,
 975		const struct sockaddr_storage *ds_addr, int ds_addrlen,
 976		int ds_proto, unsigned int ds_timeo, unsigned int ds_retrans,
 977		u32 minor_version)
 978{
 979	struct rpc_timeout ds_timeout;
 980	struct nfs_client *mds_clp = mds_srv->nfs_client;
 981	struct nfs_client_initdata cl_init = {
 982		.addr = ds_addr,
 983		.addrlen = ds_addrlen,
 984		.nodename = mds_clp->cl_rpcclient->cl_nodename,
 985		.ip_addr = mds_clp->cl_ipaddr,
 986		.nfs_mod = &nfs_v4,
 987		.proto = ds_proto,
 988		.minorversion = minor_version,
 989		.net = mds_clp->cl_net,
 990		.timeparms = &ds_timeout,
 991		.cred = mds_srv->cred,
 992		.xprtsec = {
 993			.policy = RPC_XPRTSEC_NONE,
 994			.cert_serial = TLS_NO_CERT,
 995			.privkey_serial = TLS_NO_PRIVKEY,
 996		},
 997	};
 998	char buf[INET6_ADDRSTRLEN + 1];
 999
1000	if (rpc_ntop((struct sockaddr *)ds_addr, buf, sizeof(buf)) <= 0)
1001		return ERR_PTR(-EINVAL);
1002	cl_init.hostname = buf;
1003
1004	switch (ds_proto) {
1005	case XPRT_TRANSPORT_TCP_TLS:
1006		if (mds_srv->nfs_client->cl_xprtsec.policy != RPC_XPRTSEC_NONE)
1007			cl_init.xprtsec = mds_srv->nfs_client->cl_xprtsec;
1008		else
1009			ds_proto = XPRT_TRANSPORT_TCP;
1010		fallthrough;
1011	case XPRT_TRANSPORT_RDMA:
1012	case XPRT_TRANSPORT_TCP:
1013		if (mds_clp->cl_nconnect > 1) {
1014			cl_init.nconnect = mds_clp->cl_nconnect;
1015			cl_init.max_connect = NFS_MAX_TRANSPORTS;
1016		}
1017	}
1018
1019	if (mds_srv->flags & NFS_MOUNT_NORESVPORT)
1020		__set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
1021	if (test_bit(NFS_CS_NETUNREACH_FATAL, &mds_clp->cl_flags))
1022		__set_bit(NFS_CS_NETUNREACH_FATAL, &cl_init.init_flags);
1023
1024	__set_bit(NFS_CS_PNFS, &cl_init.init_flags);
1025	cl_init.max_connect = NFS_MAX_TRANSPORTS;
1026	/*
1027	 * Set an authflavor equual to the MDS value. Use the MDS nfs_client
1028	 * cl_ipaddr so as to use the same EXCHANGE_ID co_ownerid as the MDS
1029	 * (section 13.1 RFC 5661).
1030	 */
1031	nfs_init_timeout_values(&ds_timeout, ds_proto, ds_timeo, ds_retrans);
1032	return nfs_get_client(&cl_init);
1033}
1034EXPORT_SYMBOL_GPL(nfs4_set_ds_client);
1035
1036/*
1037 * Session has been established, and the client marked ready.
1038 * Limit the mount rsize, wsize and dtsize using negotiated fore
1039 * channel attributes.
1040 */
1041static void nfs4_session_limit_rwsize(struct nfs_server *server)
1042{
1043#ifdef CONFIG_NFS_V4_1
1044	struct nfs4_session *sess;
1045	u32 server_resp_sz;
1046	u32 server_rqst_sz;
1047
1048	if (!nfs4_has_session(server->nfs_client))
1049		return;
1050	sess = server->nfs_client->cl_session;
1051	server_resp_sz = sess->fc_attrs.max_resp_sz - nfs41_maxread_overhead;
1052	server_rqst_sz = sess->fc_attrs.max_rqst_sz - nfs41_maxwrite_overhead;
1053
1054	if (server->dtsize > server_resp_sz)
1055		server->dtsize = server_resp_sz;
1056	if (server->rsize > server_resp_sz)
1057		server->rsize = server_resp_sz;
1058	if (server->wsize > server_rqst_sz)
1059		server->wsize = server_rqst_sz;
1060#endif /* CONFIG_NFS_V4_1 */
1061}
1062
1063/*
1064 * Limit xattr sizes using the channel attributes.
1065 */
1066static void nfs4_session_limit_xasize(struct nfs_server *server)
1067{
1068#ifdef CONFIG_NFS_V4_2
1069	struct nfs4_session *sess;
1070	u32 server_gxa_sz;
1071	u32 server_sxa_sz;
1072	u32 server_lxa_sz;
1073
1074	if (!nfs4_has_session(server->nfs_client))
1075		return;
1076
1077	sess = server->nfs_client->cl_session;
1078
1079	server_gxa_sz = sess->fc_attrs.max_resp_sz - nfs42_maxgetxattr_overhead;
1080	server_sxa_sz = sess->fc_attrs.max_rqst_sz - nfs42_maxsetxattr_overhead;
1081	server_lxa_sz = sess->fc_attrs.max_resp_sz -
1082	    nfs42_maxlistxattrs_overhead;
1083
1084	if (server->gxasize > server_gxa_sz)
1085		server->gxasize = server_gxa_sz;
1086	if (server->sxasize > server_sxa_sz)
1087		server->sxasize = server_sxa_sz;
1088	if (server->lxasize > server_lxa_sz)
1089		server->lxasize = server_lxa_sz;
1090#endif
1091}
1092
1093static int nfs4_server_common_setup(struct nfs_server *server,
1094		struct nfs_fh *mntfh, bool auth_probe)
1095{
1096	int error;
1097
1098	error = nfs4_delegation_hash_alloc(server);
1099	if (error)
1100		return error;
1101
1102	/* data servers support only a subset of NFSv4.1 */
1103	if (is_ds_only_client(server->nfs_client))
1104		return -EPROTONOSUPPORT;
1105
1106	/* We must ensure the session is initialised first */
1107	error = nfs4_init_session(server->nfs_client);
1108	if (error < 0)
1109		return error;
1110
1111	nfs_server_set_init_caps(server);
1112
1113	/* Probe the root fh to retrieve its FSID and filehandle */
1114	error = nfs4_get_rootfh(server, mntfh, auth_probe);
1115	if (error < 0)
1116		return error;
1117
1118	dprintk("Server FSID: %llx:%llx\n",
1119			(unsigned long long) server->fsid.major,
1120			(unsigned long long) server->fsid.minor);
1121	nfs_display_fhandle(mntfh, "Pseudo-fs root FH");
1122
1123	error = nfs_probe_server(server, mntfh);
1124	if (error < 0)
1125		return error;
1126
1127	nfs4_session_limit_rwsize(server);
1128	nfs4_session_limit_xasize(server);
1129
1130	if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
1131		server->namelen = NFS4_MAXNAMLEN;
1132
1133	nfs_server_insert_lists(server);
1134	server->mount_time = jiffies;
1135	server->destroy = nfs4_destroy_server;
1136	return 0;
1137}
1138
1139/*
1140 * Create a version 4 volume record
1141 */
1142static int nfs4_init_server(struct nfs_server *server, struct fs_context *fc)
1143{
1144	struct nfs_fs_context *ctx = nfs_fc2context(fc);
1145	struct rpc_timeout timeparms;
1146	struct nfs_client_initdata cl_init = {
1147		.hostname = ctx->nfs_server.hostname,
1148		.addr = &ctx->nfs_server._address,
1149		.addrlen = ctx->nfs_server.addrlen,
1150		.ip_addr = ctx->client_address,
1151		.proto = ctx->nfs_server.protocol,
1152		.minorversion = ctx->minorversion,
1153		.net = fc->net_ns,
1154		.timeparms = &timeparms,
1155		.xprtsec = ctx->xprtsec,
1156		.nconnect = ctx->nfs_server.nconnect,
1157		.max_connect = ctx->nfs_server.max_connect,
1158	};
1159	int error;
1160
1161	nfs_init_timeout_values(&timeparms, ctx->nfs_server.protocol,
1162				ctx->timeo, ctx->retrans);
1163
1164	/* Initialise the client representation from the mount data */
1165	server->flags = ctx->flags;
1166	server->options = ctx->options;
1167	server->auth_info = ctx->auth_info;
1168
1169	/* Use the first specified auth flavor. If this flavor isn't
1170	 * allowed by the server, use the SECINFO path to try the
1171	 * other specified flavors */
1172	if (ctx->auth_info.flavor_len >= 1)
1173		ctx->selected_flavor = ctx->auth_info.flavors[0];
1174	else
1175		ctx->selected_flavor = RPC_AUTH_UNIX;
1176
1177	/* Get a client record */
1178	error = nfs4_set_client(server, &cl_init);
1179	if (error < 0)
1180		return error;
1181
1182	if (ctx->bsize) {
1183		server->bsize = ctx->bsize;
1184		server->automount_inherit |= NFS_AUTOMOUNT_INHERIT_BSIZE;
1185	}
1186	if (ctx->rsize) {
1187		server->rsize =
1188			nfs_io_size(ctx->rsize, server->nfs_client->cl_proto);
1189		server->automount_inherit |= NFS_AUTOMOUNT_INHERIT_RSIZE;
1190	}
1191	if (ctx->wsize) {
1192		server->wsize =
1193			nfs_io_size(ctx->wsize, server->nfs_client->cl_proto);
1194		server->automount_inherit |= NFS_AUTOMOUNT_INHERIT_WSIZE;
1195	}
1196
1197	server->acregmin = ctx->acregmin * HZ;
1198	server->acregmax = ctx->acregmax * HZ;
1199	server->acdirmin = ctx->acdirmin * HZ;
1200	server->acdirmax = ctx->acdirmax * HZ;
1201	server->port     = ctx->nfs_server.port;
1202
1203	return nfs_init_server_rpcclient(server, &timeparms,
1204					 ctx->selected_flavor);
1205}
1206
1207/*
1208 * Create a version 4 volume record
1209 * - keyed on server and FSID
1210 */
1211struct nfs_server *nfs4_create_server(struct fs_context *fc)
1212{
1213	struct nfs_fs_context *ctx = nfs_fc2context(fc);
1214	struct nfs_server *server;
1215	bool auth_probe;
1216	int error;
1217
1218	server = nfs_alloc_server();
1219	if (!server)
1220		return ERR_PTR(-ENOMEM);
1221
1222	server->cred = get_cred(fc->cred);
1223
1224	auth_probe = ctx->auth_info.flavor_len < 1;
1225
1226	/* set up the general RPC client */
1227	error = nfs4_init_server(server, fc);
1228	if (error < 0)
1229		goto error;
1230
1231	error = nfs4_server_common_setup(server, ctx->mntfh, auth_probe);
1232	if (error < 0)
1233		goto error;
1234
1235	return server;
1236
1237error:
1238	nfs_free_server(server);
1239	return ERR_PTR(error);
1240}
1241
1242/*
1243 * Create an NFS4 referral server record
1244 */
1245struct nfs_server *nfs4_create_referral_server(struct fs_context *fc)
1246{
1247	struct nfs_fs_context *ctx = nfs_fc2context(fc);
1248	struct nfs_server *parent_server = NFS_SB(ctx->clone_data.sb);
1249	struct nfs_client *parent_client = parent_server->nfs_client;
1250	struct nfs_client_initdata cl_init = {
1251		.hostname = ctx->nfs_server.hostname,
1252		.addr = &ctx->nfs_server._address,
1253		.addrlen = ctx->nfs_server.addrlen,
1254		.ip_addr = parent_client->cl_ipaddr,
1255		.minorversion = parent_client->cl_mvops->minor_version,
1256		.net = parent_client->cl_net,
1257		.timeparms = parent_server->client->cl_timeout,
1258		.xprtsec = parent_client->cl_xprtsec,
1259		.nconnect = parent_client->cl_nconnect,
1260		.max_connect = parent_client->cl_max_connect,
1261	};
1262	struct nfs_server *server;
1263	bool auth_probe;
1264	int error;
1265
1266	server = nfs_alloc_server();
1267	if (!server)
1268		return ERR_PTR(-ENOMEM);
1269
1270	server->cred = get_cred(parent_server->cred);
1271
1272	/* Initialise the client representation from the parent server */
1273	nfs_server_copy_userdata(server, parent_server);
1274
1275	/* Get a client representation */
1276#if IS_ENABLED(CONFIG_SUNRPC_XPRT_RDMA)
1277	rpc_set_port(&ctx->nfs_server.address, NFS_RDMA_PORT);
1278	cl_init.proto = XPRT_TRANSPORT_RDMA;
1279	error = nfs4_set_client(server, &cl_init);
1280	if (!error)
1281		goto init_server;
1282#endif	/* IS_ENABLED(CONFIG_SUNRPC_XPRT_RDMA) */
1283
1284	cl_init.proto = XPRT_TRANSPORT_TCP;
1285	if (parent_client->cl_xprtsec.policy != RPC_XPRTSEC_NONE)
1286		cl_init.proto = XPRT_TRANSPORT_TCP_TLS;
1287	rpc_set_port(&ctx->nfs_server.address, NFS_PORT);
1288	error = nfs4_set_client(server, &cl_init);
1289	if (error < 0)
1290		goto error;
1291
1292#if IS_ENABLED(CONFIG_SUNRPC_XPRT_RDMA)
1293init_server:
1294#endif
1295	error = nfs_init_server_rpcclient(server, parent_server->client->cl_timeout,
1296					  ctx->selected_flavor);
1297	if (error < 0)
1298		goto error;
1299
1300	auth_probe = parent_server->auth_info.flavor_len < 1;
1301
1302	error = nfs4_server_common_setup(server, ctx->mntfh, auth_probe);
1303	if (error < 0)
1304		goto error;
1305
1306	return server;
1307
1308error:
1309	nfs_free_server(server);
1310	return ERR_PTR(error);
1311}
1312
1313/**
1314 * nfs4_update_server - Move an nfs_server to a different nfs_client
1315 *
1316 * @server: represents FSID to be moved
1317 * @hostname: new end-point's hostname
1318 * @sap: new end-point's socket address
1319 * @salen: size of "sap"
1320 * @net: net namespace
1321 *
1322 * The nfs_server must be quiescent before this function is invoked.
1323 * Either its session is drained (NFSv4.1+), or its transport is
1324 * plugged and drained (NFSv4.0).
1325 *
1326 * Returns zero on success, or a negative errno value.
1327 */
1328int nfs4_update_server(struct nfs_server *server, const char *hostname,
1329		       struct sockaddr_storage *sap, size_t salen, struct net *net)
1330{
1331	struct nfs_client *clp = server->nfs_client;
1332	struct rpc_clnt *clnt = server->client;
1333	struct xprt_create xargs = {
1334		.ident		= clp->cl_proto,
1335		.net		= net,
1336		.dstaddr	= (struct sockaddr *)sap,
1337		.addrlen	= salen,
1338		.servername	= hostname,
1339		/* cel: bleh. We might need to pass TLS parameters here */
1340	};
1341	char buf[INET6_ADDRSTRLEN + 1];
1342	struct sockaddr_storage address;
1343	struct sockaddr *localaddr = (struct sockaddr *)&address;
1344	struct nfs_client_initdata cl_init = {
1345		.hostname = hostname,
1346		.addr = sap,
1347		.addrlen = salen,
1348		.ip_addr = buf,
1349		.proto = clp->cl_proto,
1350		.minorversion = clp->cl_minorversion,
1351		.net = net,
1352		.timeparms = clnt->cl_timeout,
1353		.xprtsec = clp->cl_xprtsec,
1354		.nconnect = clp->cl_nconnect,
1355		.max_connect = clp->cl_max_connect,
1356	};
1357	int error;
1358
1359	error = rpc_switch_client_transport(clnt, &xargs, clnt->cl_timeout);
1360	if (error != 0)
1361		return error;
1362
1363	error = rpc_localaddr(clnt, localaddr, sizeof(address));
1364	if (error != 0)
1365		return error;
1366
1367	if (rpc_ntop(localaddr, buf, sizeof(buf)) == 0)
1368		return -EAFNOSUPPORT;
1369
1370	nfs_server_remove_lists(server);
1371	set_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status);
1372	error = nfs4_set_client(server, &cl_init);
1373	clear_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status);
1374	if (error != 0) {
1375		nfs_server_insert_lists(server);
1376		return error;
1377	}
1378	nfs_put_client(clp);
1379
1380	if (server->nfs_client->cl_hostname == NULL) {
1381		server->nfs_client->cl_hostname = kstrdup(hostname, GFP_KERNEL);
1382		if (server->nfs_client->cl_hostname == NULL)
1383			return -ENOMEM;
1384	}
1385	nfs_server_insert_lists(server);
1386
1387	return nfs_probe_server(server, NFS_FH(d_inode(server->super->s_root)));
1388}
~/ Read-only file preview.