Home | History | Annotate | Download | only in nfs
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*
     27  *	Copyright (c) 1983,1984,1985,1986,1987,1988,1989  AT&T.
     28  *	All rights reserved.
     29  *	Use is subject to license terms.
     30  */
     31 
     32 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     33 
     34 #include <sys/param.h>
     35 #include <sys/types.h>
     36 #include <sys/systm.h>
     37 #include <sys/cred.h>
     38 #include <sys/proc.h>
     39 #include <sys/user.h>
     40 #include <sys/buf.h>
     41 #include <sys/vfs.h>
     42 #include <sys/vnode.h>
     43 #include <sys/pathname.h>
     44 #include <sys/uio.h>
     45 #include <sys/file.h>
     46 #include <sys/stat.h>
     47 #include <sys/errno.h>
     48 #include <sys/socket.h>
     49 #include <sys/sysmacros.h>
     50 #include <sys/siginfo.h>
     51 #include <sys/tiuser.h>
     52 #include <sys/statvfs.h>
     53 #include <sys/stream.h>
     54 #include <sys/strsubr.h>
     55 #include <sys/stropts.h>
     56 #include <sys/timod.h>
     57 #include <sys/t_kuser.h>
     58 #include <sys/kmem.h>
     59 #include <sys/kstat.h>
     60 #include <sys/dirent.h>
     61 #include <sys/cmn_err.h>
     62 #include <sys/debug.h>
     63 #include <sys/unistd.h>
     64 #include <sys/vtrace.h>
     65 #include <sys/mode.h>
     66 #include <sys/acl.h>
     67 #include <sys/sdt.h>
     68 
     69 #include <rpc/types.h>
     70 #include <rpc/auth.h>
     71 #include <rpc/auth_unix.h>
     72 #include <rpc/auth_des.h>
     73 #include <rpc/svc.h>
     74 #include <rpc/xdr.h>
     75 
     76 #include <nfs/nfs.h>
     77 #include <nfs/export.h>
     78 #include <nfs/nfssys.h>
     79 #include <nfs/nfs_clnt.h>
     80 #include <nfs/nfs_acl.h>
     81 #include <nfs/nfs_log.h>
     82 #include <nfs/lm.h>
     83 #include <nfs/nfs_dispatch.h>
     84 #include <nfs/nfs4_drc.h>
     85 
     86 #include <sys/modctl.h>
     87 #include <sys/cladm.h>
     88 #include <sys/clconf.h>
     89 
     90 #define	MAXHOST 32
     91 const char *kinet_ntop6(uchar_t *, char *, size_t);
     92 
     93 /*
     94  * Module linkage information.
     95  */
     96 
     97 static struct modlmisc modlmisc = {
     98 	&mod_miscops, "NFS server module"
     99 };
    100 
    101 static struct modlinkage modlinkage = {
    102 	MODREV_1, (void *)&modlmisc, NULL
    103 };
    104 
    105 char _depends_on[] = "misc/klmmod";
    106 
    107 int
    108 _init(void)
    109 {
    110 	int status;
    111 
    112 	if ((status = nfs_srvinit()) != 0) {
    113 		cmn_err(CE_WARN, "_init: nfs_srvinit failed");
    114 		return (status);
    115 	}
    116 
    117 	status = mod_install((struct modlinkage *)&modlinkage);
    118 	if (status != 0) {
    119 		/*
    120 		 * Could not load module, cleanup previous
    121 		 * initialization work.
    122 		 */
    123 		nfs_srvfini();
    124 	}
    125 
    126 	/*
    127 	 * Initialise some placeholders for nfssys() calls. These have
    128 	 * to be declared by the nfs module, since that handles nfssys()
    129 	 * calls - also used by NFS clients - but are provided by this
    130 	 * nfssrv module. These also then serve as confirmation to the
    131 	 * relevant code in nfs that nfssrv has been loaded, as they're
    132 	 * initially NULL.
    133 	 */
    134 	nfs_srv_quiesce_func = nfs_srv_quiesce_all;
    135 	nfs_srv_dss_func = rfs4_dss_setpaths;
    136 
    137 	/* setup DSS paths here; must be done before initial server startup */
    138 	rfs4_dss_paths = rfs4_dss_oldpaths = NULL;
    139 
    140 	return (status);
    141 }
    142 
    143 int
    144 _fini()
    145 {
    146 	return (EBUSY);
    147 }
    148 
    149 int
    150 _info(struct modinfo *modinfop)
    151 {
    152 	return (mod_info(&modlinkage, modinfop));
    153 }
    154 
    155 /*
    156  * PUBLICFH_CHECK() checks if the dispatch routine supports
    157  * RPC_PUBLICFH_OK, if the filesystem is exported public, and if the
    158  * incoming request is using the public filehandle. The check duplicates
    159  * the exportmatch() call done in checkexport(), and we should consider
    160  * modifying those routines to avoid the duplication. For now, we optimize
    161  * by calling exportmatch() only after checking that the dispatch routine
    162  * supports RPC_PUBLICFH_OK, and if the filesystem is explicitly exported
    163  * public (i.e., not the placeholder).
    164  */
    165 #define	PUBLICFH_CHECK(disp, exi, fsid, xfid) \
    166 		((disp->dis_flags & RPC_PUBLICFH_OK) && \
    167 		((exi->exi_export.ex_flags & EX_PUBLIC) || \
    168 		(exi == exi_public && exportmatch(exi_root, \
    169 		fsid, xfid))))
    170 
    171 static void	nfs_srv_shutdown_all(int);
    172 static void	rfs4_server_start(int);
    173 static void	nullfree(void);
    174 static void	rfs_dispatch(struct svc_req *, SVCXPRT *);
    175 static void	acl_dispatch(struct svc_req *, SVCXPRT *);
    176 static void	common_dispatch(struct svc_req *, SVCXPRT *,
    177 		rpcvers_t, rpcvers_t, char *,
    178 		struct rpc_disptable *);
    179 static void	hanfsv4_failover(void);
    180 static	int	checkauth(struct exportinfo *, struct svc_req *, cred_t *, int,
    181 			bool_t);
    182 static char	*client_name(struct svc_req *req);
    183 static char	*client_addr(struct svc_req *req, char *buf);
    184 extern	int	sec_svc_getcred(struct svc_req *, cred_t *cr, char **, int *);
    185 extern	bool_t	sec_svc_inrootlist(int, caddr_t, int, caddr_t *);
    186 
    187 #define	NFSLOG_COPY_NETBUF(exi, xprt, nb)	{		\
    188 	(nb)->maxlen = (xprt)->xp_rtaddr.maxlen;		\
    189 	(nb)->len = (xprt)->xp_rtaddr.len;			\
    190 	(nb)->buf = kmem_alloc((nb)->len, KM_SLEEP);		\
    191 	bcopy((xprt)->xp_rtaddr.buf, (nb)->buf, (nb)->len);	\
    192 	}
    193 
    194 /*
    195  * Public Filehandle common nfs routines
    196  */
    197 static int	MCLpath(char **);
    198 static void	URLparse(char *);
    199 
    200 /*
    201  * NFS callout table.
    202  * This table is used by svc_getreq() to dispatch a request with
    203  * a given prog/vers pair to an appropriate service provider
    204  * dispatch routine.
    205  *
    206  * NOTE: ordering is relied upon below when resetting the version min/max
    207  * for NFS_PROGRAM.  Careful, if this is ever changed.
    208  */
    209 static SVC_CALLOUT __nfs_sc_clts[] = {
    210 	{ NFS_PROGRAM,	   NFS_VERSMIN,	    NFS_VERSMAX,	rfs_dispatch },
    211 	{ NFS_ACL_PROGRAM, NFS_ACL_VERSMIN, NFS_ACL_VERSMAX,	acl_dispatch }
    212 };
    213 
    214 static SVC_CALLOUT_TABLE nfs_sct_clts = {
    215 	sizeof (__nfs_sc_clts) / sizeof (__nfs_sc_clts[0]), FALSE,
    216 	__nfs_sc_clts
    217 };
    218 
    219 static SVC_CALLOUT __nfs_sc_cots[] = {
    220 	{ NFS_PROGRAM,	   NFS_VERSMIN,	    NFS_VERSMAX,	rfs_dispatch },
    221 	{ NFS_ACL_PROGRAM, NFS_ACL_VERSMIN, NFS_ACL_VERSMAX,	acl_dispatch }
    222 };
    223 
    224 static SVC_CALLOUT_TABLE nfs_sct_cots = {
    225 	sizeof (__nfs_sc_cots) / sizeof (__nfs_sc_cots[0]), FALSE, __nfs_sc_cots
    226 };
    227 
    228 static SVC_CALLOUT __nfs_sc_rdma[] = {
    229 	{ NFS_PROGRAM,	   NFS_VERSMIN,	    NFS_VERSMAX,	rfs_dispatch },
    230 	{ NFS_ACL_PROGRAM, NFS_ACL_VERSMIN, NFS_ACL_VERSMAX,	acl_dispatch }
    231 };
    232 
    233 static SVC_CALLOUT_TABLE nfs_sct_rdma = {
    234 	sizeof (__nfs_sc_rdma) / sizeof (__nfs_sc_rdma[0]), FALSE, __nfs_sc_rdma
    235 };
    236 rpcvers_t nfs_versmin = NFS_VERSMIN_DEFAULT;
    237 rpcvers_t nfs_versmax = NFS_VERSMAX_DEFAULT;
    238 
    239 /*
    240  * Used to track the state of the server so that initialization
    241  * can be done properly.
    242  */
    243 typedef enum {
    244 	NFS_SERVER_STOPPED,	/* server state destroyed */
    245 	NFS_SERVER_STOPPING,	/* server state being destroyed */
    246 	NFS_SERVER_RUNNING,
    247 	NFS_SERVER_QUIESCED,	/* server state preserved */
    248 	NFS_SERVER_OFFLINE	/* server pool offline */
    249 } nfs_server_running_t;
    250 
    251 static nfs_server_running_t nfs_server_upordown;
    252 static kmutex_t nfs_server_upordown_lock;
    253 static	kcondvar_t nfs_server_upordown_cv;
    254 
    255 /*
    256  * DSS: distributed stable storage
    257  * lists of all DSS paths: current, and before last warmstart
    258  */
    259 nvlist_t *rfs4_dss_paths, *rfs4_dss_oldpaths;
    260 
    261 int rfs4_dispatch(struct rpcdisp *, struct svc_req *, SVCXPRT *, char *);
    262 bool_t rfs4_minorvers_mismatch(struct svc_req *, SVCXPRT *, void *);
    263 
    264 /*
    265  * RDMA wait variables.
    266  */
    267 static kcondvar_t rdma_wait_cv;
    268 static kmutex_t rdma_wait_mutex;
    269 
    270 /*
    271  * Will be called at the point the server pool is being unregistered
    272  * from the pool list. From that point onwards, the pool is waiting
    273  * to be drained and as such the server state is stale and pertains
    274  * to the old instantiation of the NFS server pool.
    275  */
    276 void
    277 nfs_srv_offline(void)
    278 {
    279 	mutex_enter(&nfs_server_upordown_lock);
    280 	if (nfs_server_upordown == NFS_SERVER_RUNNING) {
    281 		nfs_server_upordown = NFS_SERVER_OFFLINE;
    282 	}
    283 	mutex_exit(&nfs_server_upordown_lock);
    284 }
    285 
    286 /*
    287  * Will be called at the point the server pool is being destroyed so
    288  * all transports have been closed and no service threads are in
    289  * existence.
    290  *
    291  * If we quiesce the server, we're shutting it down without destroying the
    292  * server state. This allows it to warm start subsequently.
    293  */
    294 void
    295 nfs_srv_stop_all(void)
    296 {
    297 	int quiesce = 0;
    298 	nfs_srv_shutdown_all(quiesce);
    299 }
    300 
    301 /*
    302  * This alternative shutdown routine can be requested via nfssys()
    303  */
    304 void
    305 nfs_srv_quiesce_all(void)
    306 {
    307 	int quiesce = 1;
    308 	nfs_srv_shutdown_all(quiesce);
    309 }
    310 
    311 static void
    312 nfs_srv_shutdown_all(int quiesce) {
    313 	mutex_enter(&nfs_server_upordown_lock);
    314 	if (quiesce) {
    315 		if (nfs_server_upordown == NFS_SERVER_RUNNING ||
    316 			nfs_server_upordown == NFS_SERVER_OFFLINE) {
    317 			nfs_server_upordown = NFS_SERVER_QUIESCED;
    318 			cv_signal(&nfs_server_upordown_cv);
    319 
    320 			/* reset DSS state, for subsequent warm restart */
    321 			rfs4_dss_numnewpaths = 0;
    322 			rfs4_dss_newpaths = NULL;
    323 
    324 			cmn_err(CE_NOTE, "nfs_server: server is now quiesced; "
    325 			    "NFSv4 state has been preserved");
    326 		}
    327 	} else {
    328 		if (nfs_server_upordown == NFS_SERVER_OFFLINE) {
    329 			nfs_server_upordown = NFS_SERVER_STOPPING;
    330 			mutex_exit(&nfs_server_upordown_lock);
    331 			rfs4_state_fini();
    332 			rfs4_fini_drc(nfs4_drc);
    333 			mutex_enter(&nfs_server_upordown_lock);
    334 			nfs_server_upordown = NFS_SERVER_STOPPED;
    335 			cv_signal(&nfs_server_upordown_cv);
    336 		}
    337 	}
    338 	mutex_exit(&nfs_server_upordown_lock);
    339 }
    340 
    341 static int
    342 nfs_srv_set_sc_versions(struct file *fp, SVC_CALLOUT_TABLE **sctpp,
    343 			rpcvers_t versmin, rpcvers_t versmax)
    344 {
    345 	struct strioctl strioc;
    346 	struct T_info_ack tinfo;
    347 	int		error, retval;
    348 
    349 	/*
    350 	 * Find out what type of transport this is.
    351 	 */
    352 	strioc.ic_cmd = TI_GETINFO;
    353 	strioc.ic_timout = -1;
    354 	strioc.ic_len = sizeof (tinfo);
    355 	strioc.ic_dp = (char *)&tinfo;
    356 	tinfo.PRIM_type = T_INFO_REQ;
    357 
    358 	error = strioctl(fp->f_vnode, I_STR, (intptr_t)&strioc, 0, K_TO_K,
    359 	    CRED(), &retval);
    360 	if (error || retval)
    361 		return (error);
    362 
    363 	/*
    364 	 * Based on our query of the transport type...
    365 	 *
    366 	 * Reset the min/max versions based on the caller's request
    367 	 * NOTE: This assumes that NFS_PROGRAM is first in the array!!
    368 	 * And the second entry is the NFS_ACL_PROGRAM.
    369 	 */
    370 	switch (tinfo.SERV_type) {
    371 	case T_CLTS:
    372 		if (versmax == NFS_V4)
    373 			return (EINVAL);
    374 		__nfs_sc_clts[0].sc_versmin = versmin;
    375 		__nfs_sc_clts[0].sc_versmax = versmax;
    376 		__nfs_sc_clts[1].sc_versmin = versmin;
    377 		__nfs_sc_clts[1].sc_versmax = versmax;
    378 		*sctpp = &nfs_sct_clts;
    379 		break;
    380 	case T_COTS:
    381 	case T_COTS_ORD:
    382 		__nfs_sc_cots[0].sc_versmin = versmin;
    383 		__nfs_sc_cots[0].sc_versmax = versmax;
    384 		/* For the NFS_ACL program, check the max version */
    385 		if (versmax > NFS_ACL_VERSMAX)
    386 			versmax = NFS_ACL_VERSMAX;
    387 		__nfs_sc_cots[1].sc_versmin = versmin;
    388 		__nfs_sc_cots[1].sc_versmax = versmax;
    389 		*sctpp = &nfs_sct_cots;
    390 		break;
    391 	default:
    392 		error = EINVAL;
    393 	}
    394 
    395 	return (error);
    396 }
    397 
    398 /*
    399  * NFS Server system call.
    400  * Does all of the work of running a NFS server.
    401  * uap->fd is the fd of an open transport provider
    402  */
    403 int
    404 nfs_svc(struct nfs_svc_args *arg, model_t model)
    405 {
    406 	file_t *fp;
    407 	SVCMASTERXPRT *xprt;
    408 	int error;
    409 	int readsize;
    410 	char buf[KNC_STRSIZE];
    411 	size_t len;
    412 	STRUCT_HANDLE(nfs_svc_args, uap);
    413 	struct netbuf addrmask;
    414 	SVC_CALLOUT_TABLE *sctp = NULL;
    415 
    416 #ifdef lint
    417 	model = model;		/* STRUCT macros don't always refer to it */
    418 #endif
    419 
    420 	STRUCT_SET_HANDLE(uap, model, arg);
    421 
    422 	/* Check privileges in nfssys() */
    423 
    424 	if ((fp = getf(STRUCT_FGET(uap, fd))) == NULL)
    425 		return (EBADF);
    426 
    427 	/*
    428 	 * Set read buffer size to rsize
    429 	 * and add room for RPC headers.
    430 	 */
    431 	readsize = nfs3tsize() + (RPC_MAXDATASIZE - NFS_MAXDATA);
    432 	if (readsize < RPC_MAXDATASIZE)
    433 		readsize = RPC_MAXDATASIZE;
    434 
    435 	error = copyinstr((const char *)STRUCT_FGETP(uap, netid), buf,
    436 	    KNC_STRSIZE, &len);
    437 	if (error) {
    438 		releasef(STRUCT_FGET(uap, fd));
    439 		return (error);
    440 	}
    441 
    442 	addrmask.len = STRUCT_FGET(uap, addrmask.len);
    443 	addrmask.maxlen = STRUCT_FGET(uap, addrmask.maxlen);
    444 	addrmask.buf = kmem_alloc(addrmask.maxlen, KM_SLEEP);
    445 	error = copyin(STRUCT_FGETP(uap, addrmask.buf), addrmask.buf,
    446 	    addrmask.len);
    447 	if (error) {
    448 		releasef(STRUCT_FGET(uap, fd));
    449 		kmem_free(addrmask.buf, addrmask.maxlen);
    450 		return (error);
    451 	}
    452 
    453 	nfs_versmin = STRUCT_FGET(uap, versmin);
    454 	nfs_versmax = STRUCT_FGET(uap, versmax);
    455 
    456 	/* Double check the vers min/max ranges */
    457 	if ((nfs_versmin > nfs_versmax) ||
    458 		(nfs_versmin < NFS_VERSMIN) ||
    459 		(nfs_versmax > NFS_VERSMAX)) {
    460 		nfs_versmin = NFS_VERSMIN_DEFAULT;
    461 		nfs_versmax = NFS_VERSMAX_DEFAULT;
    462 	}
    463 
    464 	if (error =
    465 	    nfs_srv_set_sc_versions(fp, &sctp, nfs_versmin, nfs_versmax)) {
    466 		releasef(STRUCT_FGET(uap, fd));
    467 		kmem_free(addrmask.buf, addrmask.maxlen);
    468 		return (error);
    469 	}
    470 
    471 	/* Initialize nfsv4 server */
    472 	if (nfs_versmax == (rpcvers_t)NFS_V4)
    473 		rfs4_server_start(STRUCT_FGET(uap, delegation));
    474 
    475 	/* Create a transport handle. */
    476 	error = svc_tli_kcreate(fp, readsize, buf, &addrmask, &xprt,
    477 				sctp, NULL, NFS_SVCPOOL_ID, TRUE);
    478 
    479 	if (error)
    480 		kmem_free(addrmask.buf, addrmask.maxlen);
    481 
    482 	releasef(STRUCT_FGET(uap, fd));
    483 
    484 	/* HA-NFSv4: save the cluster nodeid */
    485 	if (cluster_bootflags & CLUSTER_BOOTED)
    486 		lm_global_nlmid = clconf_get_nodeid();
    487 
    488 	return (error);
    489 }
    490 
    491 static void
    492 rfs4_server_start(int nfs4_srv_delegation)
    493 {
    494 	/*
    495 	 * Determine if the server has previously been "started" and
    496 	 * if not, do the per instance initialization
    497 	 */
    498 	mutex_enter(&nfs_server_upordown_lock);
    499 
    500 	if (nfs_server_upordown != NFS_SERVER_RUNNING) {
    501 		/* Do we need to stop and wait on the previous server? */
    502 		while (nfs_server_upordown == NFS_SERVER_STOPPING ||
    503 			nfs_server_upordown == NFS_SERVER_OFFLINE)
    504 			cv_wait(&nfs_server_upordown_cv,
    505 			    &nfs_server_upordown_lock);
    506 
    507 		if (nfs_server_upordown != NFS_SERVER_RUNNING) {
    508 			(void) svc_pool_control(NFS_SVCPOOL_ID,
    509 			    SVCPSET_UNREGISTER_PROC, (void *)&nfs_srv_offline);
    510 			(void) svc_pool_control(NFS_SVCPOOL_ID,
    511 			    SVCPSET_SHUTDOWN_PROC, (void *)&nfs_srv_stop_all);
    512 
    513 			/* is this an nfsd warm start? */
    514 			if (nfs_server_upordown == NFS_SERVER_QUIESCED) {
    515 				cmn_err(CE_NOTE, "nfs_server: "
    516 				    "server was previously quiesced; "
    517 				    "existing NFSv4 state will be re-used");
    518 
    519 				/*
    520 				 * HA-NFSv4: this is also the signal
    521 				 * that a Resource Group failover has
    522 				 * occurred.
    523 				 */
    524 				if (cluster_bootflags & CLUSTER_BOOTED)
    525 					hanfsv4_failover();
    526 			} else {
    527 				/* cold start */
    528 				rfs4_state_init();
    529 				nfs4_drc = rfs4_init_drc(nfs4_drc_max,
    530 							nfs4_drc_hash);
    531 			}
    532 
    533 			/*
    534 			 * Check to see if delegation is to be
    535 			 * enabled at the server
    536 			 */
    537 			if (nfs4_srv_delegation != FALSE)
    538 				rfs4_set_deleg_policy(SRV_NORMAL_DELEGATE);
    539 
    540 			nfs_server_upordown = NFS_SERVER_RUNNING;
    541 		}
    542 		cv_signal(&nfs_server_upordown_cv);
    543 	}
    544 	mutex_exit(&nfs_server_upordown_lock);
    545 }
    546 
    547 /*
    548  * If RDMA device available,
    549  * start RDMA listener.
    550  */
    551 int
    552 rdma_start(struct rdma_svc_args *rsa)
    553 {
    554 	int error;
    555 	rdma_xprt_group_t started_rdma_xprts;
    556 
    557 	/* Double check the vers min/max ranges */
    558 	if ((rsa->nfs_versmin > rsa->nfs_versmax) ||
    559 		(rsa->nfs_versmin < NFS_VERSMIN) ||
    560 		(rsa->nfs_versmax > NFS_VERSMAX)) {
    561 		rsa->nfs_versmin = NFS_VERSMIN_DEFAULT;
    562 		rsa->nfs_versmax = NFS_VERSMAX_DEFAULT;
    563 	}
    564 	nfs_versmin = rsa->nfs_versmin;
    565 	nfs_versmax = rsa->nfs_versmax;
    566 
    567 	/* Set the versions in the callout table */
    568 	__nfs_sc_rdma[0].sc_versmin = rsa->nfs_versmin;
    569 	__nfs_sc_rdma[0].sc_versmax = rsa->nfs_versmax;
    570 	/* For the NFS_ACL program, check the max version */
    571 	__nfs_sc_rdma[1].sc_versmin = rsa->nfs_versmin;
    572 	if (rsa->nfs_versmax > NFS_ACL_VERSMAX)
    573 		__nfs_sc_rdma[1].sc_versmax = NFS_ACL_VERSMAX;
    574 	else
    575 		__nfs_sc_rdma[1].sc_versmax = rsa->nfs_versmax;
    576 
    577 	/* Initialize nfsv4 server */
    578 	if (rsa->nfs_versmax == (rpcvers_t)NFS_V4)
    579 		rfs4_server_start(rsa->delegation);
    580 
    581 	started_rdma_xprts.rtg_count = 0;
    582 	started_rdma_xprts.rtg_listhead = NULL;
    583 	started_rdma_xprts.rtg_poolid = rsa->poolid;
    584 	error = svc_rdma_kcreate(rsa->netid, &nfs_sct_rdma, rsa->poolid,
    585 	    &started_rdma_xprts);
    586 
    587 	if (error == 0) {
    588 		mutex_enter(&rdma_wait_mutex);
    589 		if (!cv_wait_sig(&rdma_wait_cv, &rdma_wait_mutex)) {
    590 			rdma_stop(started_rdma_xprts);
    591 		}
    592 		mutex_exit(&rdma_wait_mutex);
    593 	}
    594 
    595 	return (error);
    596 }
    597 
    598 /* ARGSUSED */
    599 void
    600 rpc_null(caddr_t *argp, caddr_t *resp)
    601 {
    602 }
    603 
    604 /* ARGSUSED */
    605 void
    606 rpc_null_v3(caddr_t *argp, caddr_t *resp, struct exportinfo *exi,
    607     struct svc_req *req, cred_t *cr)
    608 {
    609 	DTRACE_NFSV3_3(op__null__start, struct svc_req *, req,
    610 	    cred_t *, cr, vnode_t *, NULL);
    611 	DTRACE_NFSV3_3(op__null__done, struct svc_req *, req,
    612 	    cred_t *, cr, vnode_t *, NULL);
    613 }
    614 
    615 /* ARGSUSED */
    616 static void
    617 rfs_error(caddr_t *argp, caddr_t *resp)
    618 {
    619 	/* return (EOPNOTSUPP); */
    620 }
    621 
    622 static void
    623 nullfree(void)
    624 {
    625 }
    626 
    627 static char *rfscallnames_v2[] = {
    628 	"RFS2_NULL",
    629 	"RFS2_GETATTR",
    630 	"RFS2_SETATTR",
    631 	"RFS2_ROOT",
    632 	"RFS2_LOOKUP",
    633 	"RFS2_READLINK",
    634 	"RFS2_READ",
    635 	"RFS2_WRITECACHE",
    636 	"RFS2_WRITE",
    637 	"RFS2_CREATE",
    638 	"RFS2_REMOVE",
    639 	"RFS2_RENAME",
    640 	"RFS2_LINK",
    641 	"RFS2_SYMLINK",
    642 	"RFS2_MKDIR",
    643 	"RFS2_RMDIR",
    644 	"RFS2_READDIR",
    645 	"RFS2_STATFS"
    646 };
    647 
    648 static struct rpcdisp rfsdisptab_v2[] = {
    649 	/*
    650 	 * NFS VERSION 2
    651 	 */
    652 
    653 	/* RFS_NULL = 0 */
    654 	{rpc_null,
    655 	    xdr_void, NULL_xdrproc_t, 0,
    656 	    xdr_void, NULL_xdrproc_t, 0,
    657 	    nullfree, RPC_IDEMPOTENT,
    658 	    0},
    659 
    660 	/* RFS_GETATTR = 1 */
    661 	{rfs_getattr,
    662 	    xdr_fhandle, xdr_fastfhandle, sizeof (fhandle_t),
    663 	    xdr_attrstat, xdr_fastattrstat, sizeof (struct nfsattrstat),
    664 	    nullfree, RPC_IDEMPOTENT|RPC_ALLOWANON|RPC_MAPRESP,
    665 	    rfs_getattr_getfh},
    666 
    667 	/* RFS_SETATTR = 2 */
    668 	{rfs_setattr,
    669 	    xdr_saargs, NULL_xdrproc_t, sizeof (struct nfssaargs),
    670 	    xdr_attrstat, xdr_fastattrstat, sizeof (struct nfsattrstat),
    671 	    nullfree, RPC_MAPRESP,
    672 	    rfs_setattr_getfh},
    673 
    674 	/* RFS_ROOT = 3 *** NO LONGER SUPPORTED *** */
    675 	{rfs_error,
    676 	    xdr_void, NULL_xdrproc_t, 0,
    677 	    xdr_void, NULL_xdrproc_t, 0,
    678 	    nullfree, RPC_IDEMPOTENT,
    679 	    0},
    680 
    681 	/* RFS_LOOKUP = 4 */
    682 	{rfs_lookup,
    683 	    xdr_diropargs, NULL_xdrproc_t, sizeof (struct nfsdiropargs),
    684 	    xdr_diropres, xdr_fastdiropres, sizeof (struct nfsdiropres),
    685 	    nullfree, RPC_IDEMPOTENT|RPC_MAPRESP|RPC_PUBLICFH_OK,
    686 	    rfs_lookup_getfh},
    687 
    688 	/* RFS_READLINK = 5 */
    689 	{rfs_readlink,
    690 	    xdr_fhandle, xdr_fastfhandle, sizeof (fhandle_t),
    691 	    xdr_rdlnres, NULL_xdrproc_t, sizeof (struct nfsrdlnres),
    692 	    rfs_rlfree, RPC_IDEMPOTENT,
    693 	    rfs_readlink_getfh},
    694 
    695 	/* RFS_READ = 6 */
    696 	{rfs_read,
    697 	    xdr_readargs, NULL_xdrproc_t, sizeof (struct nfsreadargs),
    698 	    xdr_rdresult, NULL_xdrproc_t, sizeof (struct nfsrdresult),
    699 	    rfs_rdfree, RPC_IDEMPOTENT,
    700 	    rfs_read_getfh},
    701 
    702 	/* RFS_WRITECACHE = 7 *** NO LONGER SUPPORTED *** */
    703 	{rfs_error,
    704 	    xdr_void, NULL_xdrproc_t, 0,
    705 	    xdr_void, NULL_xdrproc_t, 0,
    706 	    nullfree, RPC_IDEMPOTENT,
    707 	    0},
    708 
    709 	/* RFS_WRITE = 8 */
    710 	{rfs_write,
    711 	    xdr_writeargs, NULL_xdrproc_t, sizeof (struct nfswriteargs),
    712 	    xdr_attrstat, xdr_fastattrstat, sizeof (struct nfsattrstat),
    713 	    nullfree, RPC_MAPRESP,
    714 	    rfs_write_getfh},
    715 
    716 	/* RFS_CREATE = 9 */
    717 	{rfs_create,
    718 	    xdr_creatargs, NULL_xdrproc_t, sizeof (struct nfscreatargs),
    719 	    xdr_diropres, xdr_fastdiropres, sizeof (struct nfsdiropres),
    720 	    nullfree, RPC_MAPRESP,
    721 	    rfs_create_getfh},
    722 
    723 	/* RFS_REMOVE = 10 */
    724 	{rfs_remove,
    725 	    xdr_diropargs, NULL_xdrproc_t, sizeof (struct nfsdiropargs),
    726 #ifdef _LITTLE_ENDIAN
    727 	    xdr_enum, xdr_fastenum, sizeof (enum nfsstat),
    728 #else
    729 	    xdr_enum, NULL_xdrproc_t, sizeof (enum nfsstat),
    730 #endif
    731 	    nullfree, RPC_MAPRESP,
    732 	    rfs_remove_getfh},
    733 
    734 	/* RFS_RENAME = 11 */
    735 	{rfs_rename,
    736 	    xdr_rnmargs, NULL_xdrproc_t, sizeof (struct nfsrnmargs),
    737 #ifdef _LITTLE_ENDIAN
    738 	    xdr_enum, xdr_fastenum, sizeof (enum nfsstat),
    739 #else
    740 	    xdr_enum, NULL_xdrproc_t, sizeof (enum nfsstat),
    741 #endif
    742 	    nullfree, RPC_MAPRESP,
    743 	    rfs_rename_getfh},
    744 
    745 	/* RFS_LINK = 12 */
    746 	{rfs_link,
    747 	    xdr_linkargs, NULL_xdrproc_t, sizeof (struct nfslinkargs),
    748 #ifdef _LITTLE_ENDIAN
    749 	    xdr_enum, xdr_fastenum, sizeof (enum nfsstat),
    750 #else
    751 	    xdr_enum, NULL_xdrproc_t, sizeof (enum nfsstat),
    752 #endif
    753 	    nullfree, RPC_MAPRESP,
    754 	    rfs_link_getfh},
    755 
    756 	/* RFS_SYMLINK = 13 */
    757 	{rfs_symlink,
    758 	    xdr_slargs, NULL_xdrproc_t, sizeof (struct nfsslargs),
    759 #ifdef _LITTLE_ENDIAN
    760 	    xdr_enum, xdr_fastenum, sizeof (enum nfsstat),
    761 #else
    762 	    xdr_enum, NULL_xdrproc_t, sizeof (enum nfsstat),
    763 #endif
    764 	    nullfree, RPC_MAPRESP,
    765 	    rfs_symlink_getfh},
    766 
    767 	/* RFS_MKDIR = 14 */
    768 	{rfs_mkdir,
    769 	    xdr_creatargs, NULL_xdrproc_t, sizeof (struct nfscreatargs),
    770 	    xdr_diropres, xdr_fastdiropres, sizeof (struct nfsdiropres),
    771 	    nullfree, RPC_MAPRESP,
    772 	    rfs_mkdir_getfh},
    773 
    774 	/* RFS_RMDIR = 15 */
    775 	{rfs_rmdir,
    776 	    xdr_diropargs, NULL_xdrproc_t, sizeof (struct nfsdiropargs),
    777 #ifdef _LITTLE_ENDIAN
    778 	    xdr_enum, xdr_fastenum, sizeof (enum nfsstat),
    779 #else
    780 	    xdr_enum, NULL_xdrproc_t, sizeof (enum nfsstat),
    781 #endif
    782 	    nullfree, RPC_MAPRESP,
    783 	    rfs_rmdir_getfh},
    784 
    785 	/* RFS_READDIR = 16 */
    786 	{rfs_readdir,
    787 	    xdr_rddirargs, NULL_xdrproc_t, sizeof (struct nfsrddirargs),
    788 	    xdr_putrddirres, NULL_xdrproc_t, sizeof (struct nfsrddirres),
    789 	    rfs_rddirfree, RPC_IDEMPOTENT,
    790 	    rfs_readdir_getfh},
    791 
    792 	/* RFS_STATFS = 17 */
    793 	{rfs_statfs,
    794 	    xdr_fhandle, xdr_fastfhandle, sizeof (fhandle_t),
    795 	    xdr_statfs, xdr_faststatfs, sizeof (struct nfsstatfs),
    796 	    nullfree, RPC_IDEMPOTENT|RPC_ALLOWANON|RPC_MAPRESP,
    797 	    rfs_statfs_getfh},
    798 };
    799 
    800 static char *rfscallnames_v3[] = {
    801 	"RFS3_NULL",
    802 	"RFS3_GETATTR",
    803 	"RFS3_SETATTR",
    804 	"RFS3_LOOKUP",
    805 	"RFS3_ACCESS",
    806 	"RFS3_READLINK",
    807 	"RFS3_READ",
    808 	"RFS3_WRITE",
    809 	"RFS3_CREATE",
    810 	"RFS3_MKDIR",
    811 	"RFS3_SYMLINK",
    812 	"RFS3_MKNOD",
    813 	"RFS3_REMOVE",
    814 	"RFS3_RMDIR",
    815 	"RFS3_RENAME",
    816 	"RFS3_LINK",
    817 	"RFS3_READDIR",
    818 	"RFS3_READDIRPLUS",
    819 	"RFS3_FSSTAT",
    820 	"RFS3_FSINFO",
    821 	"RFS3_PATHCONF",
    822 	"RFS3_COMMIT"
    823 };
    824 
    825 static struct rpcdisp rfsdisptab_v3[] = {
    826 	/*
    827 	 * NFS VERSION 3
    828 	 */
    829 
    830 	/* RFS_NULL = 0 */
    831 	{rpc_null_v3,
    832 	    xdr_void, NULL_xdrproc_t, 0,
    833 	    xdr_void, NULL_xdrproc_t, 0,
    834 	    nullfree, RPC_IDEMPOTENT,
    835 	    0},
    836 
    837 	/* RFS3_GETATTR = 1 */
    838 	{rfs3_getattr,
    839 	    xdr_nfs_fh3_server, NULL_xdrproc_t, sizeof (GETATTR3args),
    840 	    xdr_GETATTR3res, NULL_xdrproc_t, sizeof (GETATTR3res),
    841 	    nullfree, (RPC_IDEMPOTENT | RPC_ALLOWANON),
    842 	    rfs3_getattr_getfh},
    843 
    844 	/* RFS3_SETATTR = 2 */
    845 	{rfs3_setattr,
    846 	    xdr_SETATTR3args, NULL_xdrproc_t, sizeof (SETATTR3args),
    847 	    xdr_SETATTR3res, NULL_xdrproc_t, sizeof (SETATTR3res),
    848 	    nullfree, 0,
    849 	    rfs3_setattr_getfh},
    850 
    851 	/* RFS3_LOOKUP = 3 */
    852 	{rfs3_lookup,
    853 	    xdr_diropargs3, NULL_xdrproc_t, sizeof (LOOKUP3args),
    854 	    xdr_LOOKUP3res, NULL_xdrproc_t, sizeof (LOOKUP3res),
    855 	    nullfree, (RPC_IDEMPOTENT | RPC_PUBLICFH_OK),
    856 	    rfs3_lookup_getfh},
    857 
    858 	/* RFS3_ACCESS = 4 */
    859 	{rfs3_access,
    860 	    xdr_ACCESS3args, NULL_xdrproc_t, sizeof (ACCESS3args),
    861 	    xdr_ACCESS3res, NULL_xdrproc_t, sizeof (ACCESS3res),
    862 	    nullfree, RPC_IDEMPOTENT,
    863 	    rfs3_access_getfh},
    864 
    865 	/* RFS3_READLINK = 5 */
    866 	{rfs3_readlink,
    867 	    xdr_nfs_fh3_server, NULL_xdrproc_t, sizeof (READLINK3args),
    868 	    xdr_READLINK3res, NULL_xdrproc_t, sizeof (READLINK3res),
    869 	    rfs3_readlink_free, RPC_IDEMPOTENT,
    870 	    rfs3_readlink_getfh},
    871 
    872 	/* RFS3_READ = 6 */
    873 	{rfs3_read,
    874 	    xdr_READ3args, NULL_xdrproc_t, sizeof (READ3args),
    875 	    xdr_READ3res, NULL_xdrproc_t, sizeof (READ3res),
    876 	    rfs3_read_free, RPC_IDEMPOTENT,
    877 	    rfs3_read_getfh},
    878 
    879 	/* RFS3_WRITE = 7 */
    880 	{rfs3_write,
    881 	    xdr_WRITE3args, NULL_xdrproc_t, sizeof (WRITE3args),
    882 	    xdr_WRITE3res, NULL_xdrproc_t, sizeof (WRITE3res),
    883 	    nullfree, 0,
    884 	    rfs3_write_getfh},
    885 
    886 	/* RFS3_CREATE = 8 */
    887 	{rfs3_create,
    888 	    xdr_CREATE3args, NULL_xdrproc_t, sizeof (CREATE3args),
    889 	    xdr_CREATE3res, NULL_xdrproc_t, sizeof (CREATE3res),
    890 	    nullfree, 0,
    891 	    rfs3_create_getfh},
    892 
    893 	/* RFS3_MKDIR = 9 */
    894 	{rfs3_mkdir,
    895 	    xdr_MKDIR3args, NULL_xdrproc_t, sizeof (MKDIR3args),
    896 	    xdr_MKDIR3res, NULL_xdrproc_t, sizeof (MKDIR3res),
    897 	    nullfree, 0,
    898 	    rfs3_mkdir_getfh},
    899 
    900 	/* RFS3_SYMLINK = 10 */
    901 	{rfs3_symlink,
    902 	    xdr_SYMLINK3args, NULL_xdrproc_t, sizeof (SYMLINK3args),
    903 	    xdr_SYMLINK3res, NULL_xdrproc_t, sizeof (SYMLINK3res),
    904 	    nullfree, 0,
    905 	    rfs3_symlink_getfh},
    906 
    907 	/* RFS3_MKNOD = 11 */
    908 	{rfs3_mknod,
    909 	    xdr_MKNOD3args, NULL_xdrproc_t, sizeof (MKNOD3args),
    910 	    xdr_MKNOD3res, NULL_xdrproc_t, sizeof (MKNOD3res),
    911 	    nullfree, 0,
    912 	    rfs3_mknod_getfh},
    913 
    914 	/* RFS3_REMOVE = 12 */
    915 	{rfs3_remove,
    916 	    xdr_diropargs3, NULL_xdrproc_t, sizeof (REMOVE3args),
    917 	    xdr_REMOVE3res, NULL_xdrproc_t, sizeof (REMOVE3res),
    918 	    nullfree, 0,
    919 	    rfs3_remove_getfh},
    920 
    921 	/* RFS3_RMDIR = 13 */
    922 	{rfs3_rmdir,
    923 	    xdr_diropargs3, NULL_xdrproc_t, sizeof (RMDIR3args),
    924 	    xdr_RMDIR3res, NULL_xdrproc_t, sizeof (RMDIR3res),
    925 	    nullfree, 0,
    926 	    rfs3_rmdir_getfh},
    927 
    928 	/* RFS3_RENAME = 14 */
    929 	{rfs3_rename,
    930 	    xdr_RENAME3args, NULL_xdrproc_t, sizeof (RENAME3args),
    931 	    xdr_RENAME3res, NULL_xdrproc_t, sizeof (RENAME3res),
    932 	    nullfree, 0,
    933 	    rfs3_rename_getfh},
    934 
    935 	/* RFS3_LINK = 15 */
    936 	{rfs3_link,
    937 	    xdr_LINK3args, NULL_xdrproc_t, sizeof (LINK3args),
    938 	    xdr_LINK3res, NULL_xdrproc_t, sizeof (LINK3res),
    939 	    nullfree, 0,
    940 	    rfs3_link_getfh},
    941 
    942 	/* RFS3_READDIR = 16 */
    943 	{rfs3_readdir,
    944 	    xdr_READDIR3args, NULL_xdrproc_t, sizeof (READDIR3args),
    945 	    xdr_READDIR3res, NULL_xdrproc_t, sizeof (READDIR3res),
    946 	    rfs3_readdir_free, RPC_IDEMPOTENT,
    947 	    rfs3_readdir_getfh},
    948 
    949 	/* RFS3_READDIRPLUS = 17 */
    950 	{rfs3_readdirplus,
    951 	    xdr_READDIRPLUS3args, NULL_xdrproc_t, sizeof (READDIRPLUS3args),
    952 	    xdr_READDIRPLUS3res, NULL_xdrproc_t, sizeof (READDIRPLUS3res),
    953 	    rfs3_readdirplus_free, RPC_AVOIDWORK,
    954 	    rfs3_readdirplus_getfh},
    955 
    956 	/* RFS3_FSSTAT = 18 */
    957 	{rfs3_fsstat,
    958 	    xdr_nfs_fh3_server, NULL_xdrproc_t, sizeof (FSSTAT3args),
    959 	    xdr_FSSTAT3res, NULL_xdrproc_t, sizeof (FSSTAT3res),
    960 	    nullfree, RPC_IDEMPOTENT,
    961 	    rfs3_fsstat_getfh},
    962 
    963 	/* RFS3_FSINFO = 19 */
    964 	{rfs3_fsinfo,
    965 	    xdr_nfs_fh3_server, NULL_xdrproc_t, sizeof (FSINFO3args),
    966 	    xdr_FSINFO3res, NULL_xdrproc_t, sizeof (FSINFO3res),
    967 	    nullfree, RPC_IDEMPOTENT|RPC_ALLOWANON,
    968 	    rfs3_fsinfo_getfh},
    969 
    970 	/* RFS3_PATHCONF = 20 */
    971 	{rfs3_pathconf,
    972 	    xdr_nfs_fh3_server, NULL_xdrproc_t, sizeof (PATHCONF3args),
    973 	    xdr_PATHCONF3res, NULL_xdrproc_t, sizeof (PATHCONF3res),
    974 	    nullfree, RPC_IDEMPOTENT,
    975 	    rfs3_pathconf_getfh},
    976 
    977 	/* RFS3_COMMIT = 21 */
    978 	{rfs3_commit,
    979 	    xdr_COMMIT3args, NULL_xdrproc_t, sizeof (COMMIT3args),
    980 	    xdr_COMMIT3res, NULL_xdrproc_t, sizeof (COMMIT3res),
    981 	    nullfree, RPC_IDEMPOTENT,
    982 	    rfs3_commit_getfh},
    983 };
    984 
    985 static char *rfscallnames_v4[] = {
    986 	"RFS4_NULL",
    987 	"RFS4_COMPOUND",
    988 	"RFS4_NULL",
    989 	"RFS4_NULL",
    990 	"RFS4_NULL",
    991 	"RFS4_NULL",
    992 	"RFS4_NULL",
    993 	"RFS4_NULL",
    994 	"RFS4_CREATE"
    995 };
    996 
    997 static struct rpcdisp rfsdisptab_v4[] = {
    998 	/*
    999 	 * NFS VERSION 4
   1000 	 */
   1001 
   1002 	/* RFS_NULL = 0 */
   1003 	{rpc_null,
   1004 	    xdr_void, NULL_xdrproc_t, 0,
   1005 	    xdr_void, NULL_xdrproc_t, 0,
   1006 	    nullfree, RPC_IDEMPOTENT, 0},
   1007 
   1008 	/* RFS4_compound = 1 */
   1009 	{rfs4_compound,
   1010 	    xdr_COMPOUND4args_srv, NULL_xdrproc_t, sizeof (COMPOUND4args),
   1011 	    xdr_COMPOUND4res_srv, NULL_xdrproc_t, sizeof (COMPOUND4res),
   1012 	    rfs4_compound_free, 0, 0},
   1013 };
   1014 
   1015 union rfs_args {
   1016 	/*
   1017 	 * NFS VERSION 2
   1018 	 */
   1019 
   1020 	/* RFS_NULL = 0 */
   1021 
   1022 	/* RFS_GETATTR = 1 */
   1023 	fhandle_t nfs2_getattr_args;
   1024 
   1025 	/* RFS_SETATTR = 2 */
   1026 	struct nfssaargs nfs2_setattr_args;
   1027 
   1028 	/* RFS_ROOT = 3 *** NO LONGER SUPPORTED *** */
   1029 
   1030 	/* RFS_LOOKUP = 4 */
   1031 	struct nfsdiropargs nfs2_lookup_args;
   1032 
   1033 	/* RFS_READLINK = 5 */
   1034 	fhandle_t nfs2_readlink_args;
   1035 
   1036 	/* RFS_READ = 6 */
   1037 	struct nfsreadargs nfs2_read_args;
   1038 
   1039 	/* RFS_WRITECACHE = 7 *** NO LONGER SUPPORTED *** */
   1040 
   1041 	/* RFS_WRITE = 8 */
   1042 	struct nfswriteargs nfs2_write_args;
   1043 
   1044 	/* RFS_CREATE = 9 */
   1045 	struct nfscreatargs nfs2_create_args;
   1046 
   1047 	/* RFS_REMOVE = 10 */
   1048 	struct nfsdiropargs nfs2_remove_args;
   1049 
   1050 	/* RFS_RENAME = 11 */
   1051 	struct nfsrnmargs nfs2_rename_args;
   1052 
   1053 	/* RFS_LINK = 12 */
   1054 	struct nfslinkargs nfs2_link_args;
   1055 
   1056 	/* RFS_SYMLINK = 13 */
   1057 	struct nfsslargs nfs2_symlink_args;
   1058 
   1059 	/* RFS_MKDIR = 14 */
   1060 	struct nfscreatargs nfs2_mkdir_args;
   1061 
   1062 	/* RFS_RMDIR = 15 */
   1063 	struct nfsdiropargs nfs2_rmdir_args;
   1064 
   1065 	/* RFS_READDIR = 16 */
   1066 	struct nfsrddirargs nfs2_readdir_args;
   1067 
   1068 	/* RFS_STATFS = 17 */
   1069 	fhandle_t nfs2_statfs_args;
   1070 
   1071 	/*
   1072 	 * NFS VERSION 3
   1073 	 */
   1074 
   1075 	/* RFS_NULL = 0 */
   1076 
   1077 	/* RFS3_GETATTR = 1 */
   1078 	GETATTR3arg