xref: /illumos-gate/usr/src/uts/common/fs/nfs/nfs4_srv.c (revision 0dfe541e)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
545916cd2Sjpk  * Common Development and Distribution License (the "License").
645916cd2Sjpk  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
216e062f4aSMarcel Telka 
227c478bd9Sstevel@tonic-gate /*
23bffeae97SMarcel Telka  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
2415721462SDaniil Lunev  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  *	Copyright (c) 1983,1984,1985,1986,1987,1988,1989  AT&T.
287c478bd9Sstevel@tonic-gate  *	All Rights Reserved
297c478bd9Sstevel@tonic-gate  */
307c478bd9Sstevel@tonic-gate 
31*0dfe541eSEvan Layton /*
32*0dfe541eSEvan Layton  * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
33*0dfe541eSEvan Layton  * Copyright 2019 Nexenta Systems, Inc.
34*0dfe541eSEvan Layton  * Copyright 2019 Nexenta by DDN, Inc.
35*0dfe541eSEvan Layton  */
36*0dfe541eSEvan Layton 
377c478bd9Sstevel@tonic-gate #include <sys/param.h>
387c478bd9Sstevel@tonic-gate #include <sys/types.h>
397c478bd9Sstevel@tonic-gate #include <sys/systm.h>
407c478bd9Sstevel@tonic-gate #include <sys/cred.h>
417c478bd9Sstevel@tonic-gate #include <sys/buf.h>
427c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
43aa59c4cbSrsb #include <sys/vfs_opreg.h>
447c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
457c478bd9Sstevel@tonic-gate #include <sys/uio.h>
467c478bd9Sstevel@tonic-gate #include <sys/errno.h>
477c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
487c478bd9Sstevel@tonic-gate #include <sys/statvfs.h>
497c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
507c478bd9Sstevel@tonic-gate #include <sys/dirent.h>
517c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
527c478bd9Sstevel@tonic-gate #include <sys/debug.h>
537c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
547c478bd9Sstevel@tonic-gate #include <sys/flock.h>
557c478bd9Sstevel@tonic-gate #include <sys/pathname.h>
567c478bd9Sstevel@tonic-gate #include <sys/nbmlock.h>
577c478bd9Sstevel@tonic-gate #include <sys/share.h>
587c478bd9Sstevel@tonic-gate #include <sys/atomic.h>
597c478bd9Sstevel@tonic-gate #include <sys/policy.h>
607c478bd9Sstevel@tonic-gate #include <sys/fem.h>
6145916cd2Sjpk #include <sys/sdt.h>
62cee86682Scalum #include <sys/ddi.h>
635679c89fSjv #include <sys/zone.h>
647c478bd9Sstevel@tonic-gate 
652f172c55SRobert Thurlow #include <fs/fs_reparse.h>
662f172c55SRobert Thurlow 
677c478bd9Sstevel@tonic-gate #include <rpc/types.h>
687c478bd9Sstevel@tonic-gate #include <rpc/auth.h>
697c478bd9Sstevel@tonic-gate #include <rpc/rpcsec_gss.h>
707c478bd9Sstevel@tonic-gate #include <rpc/svc.h>
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate #include <nfs/nfs.h>
73*0dfe541eSEvan Layton #include <nfs/nfssys.h>
747c478bd9Sstevel@tonic-gate #include <nfs/export.h>
75b89a8333Snatalie li - Sun Microsystems - Irvine United States #include <nfs/nfs_cmd.h>
767c478bd9Sstevel@tonic-gate #include <nfs/lm.h>
777c478bd9Sstevel@tonic-gate #include <nfs/nfs4.h>
78*0dfe541eSEvan Layton #include <nfs/nfs4_drc.h>
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate #include <sys/strsubr.h>
817c478bd9Sstevel@tonic-gate #include <sys/strsun.h>
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate #include <inet/common.h>
847c478bd9Sstevel@tonic-gate #include <inet/ip.h>
857c478bd9Sstevel@tonic-gate #include <inet/ip6.h>
867c478bd9Sstevel@tonic-gate 
8745916cd2Sjpk #include <sys/tsol/label.h>
8845916cd2Sjpk #include <sys/tsol/tndb.h>
8945916cd2Sjpk 
907c478bd9Sstevel@tonic-gate #define	RFS4_MAXLOCK_TRIES 4	/* Try to get the lock this many times */
917c478bd9Sstevel@tonic-gate static int rfs4_maxlock_tries = RFS4_MAXLOCK_TRIES;
927c478bd9Sstevel@tonic-gate #define	RFS4_LOCK_DELAY 10	/* Milliseconds */
930a701b1eSRobert Gordon static clock_t  rfs4_lock_delay = RFS4_LOCK_DELAY;
940a701b1eSRobert Gordon extern struct svc_ops rdma_svc_ops;
95c242f9a0Schunli zhang - Sun Microsystems - Irvine United States extern int nfs_loaned_buffers;
96c242f9a0Schunli zhang - Sun Microsystems - Irvine United States /* End of Tunables */
977c478bd9Sstevel@tonic-gate 
980a701b1eSRobert Gordon static int rdma_setup_read_data4(READ4args *, READ4res *);
990a701b1eSRobert Gordon 
1007c478bd9Sstevel@tonic-gate /*
1017c478bd9Sstevel@tonic-gate  * Used to bump the stateid4.seqid value and show changes in the stateid
1027c478bd9Sstevel@tonic-gate  */
1037c478bd9Sstevel@tonic-gate #define	next_stateid(sp) (++(sp)->bits.chgseq)
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate /*
1067c478bd9Sstevel@tonic-gate  * RFS4_MINLEN_ENTRY4: XDR-encoded size of smallest possible dirent.
1077c478bd9Sstevel@tonic-gate  *	This is used to return NFS4ERR_TOOSMALL when clients specify
1087c478bd9Sstevel@tonic-gate  *	maxcount that isn't large enough to hold the smallest possible
1097c478bd9Sstevel@tonic-gate  *	XDR encoded dirent.
1107c478bd9Sstevel@tonic-gate  *
1117c478bd9Sstevel@tonic-gate  *	    sizeof cookie (8 bytes) +
1127c478bd9Sstevel@tonic-gate  *	    sizeof name_len (4 bytes) +
1137c478bd9Sstevel@tonic-gate  *	    sizeof smallest (padded) name (4 bytes) +
1147c478bd9Sstevel@tonic-gate  *	    sizeof bitmap4_len (12 bytes) +   NOTE: we always encode len=2 bm4
1157c478bd9Sstevel@tonic-gate  *	    sizeof attrlist4_len (4 bytes) +
1167c478bd9Sstevel@tonic-gate  *	    sizeof next boolean (4 bytes)
1177c478bd9Sstevel@tonic-gate  *
1187c478bd9Sstevel@tonic-gate  * RFS4_MINLEN_RDDIR4: XDR-encoded size of READDIR op reply containing
1197c478bd9Sstevel@tonic-gate  * the smallest possible entry4 (assumes no attrs requested).
1207c478bd9Sstevel@tonic-gate  *	sizeof nfsstat4 (4 bytes) +
1217c478bd9Sstevel@tonic-gate  *	sizeof verifier4 (8 bytes) +
1227c478bd9Sstevel@tonic-gate  *	sizeof entry4list bool (4 bytes) +
123*0dfe541eSEvan Layton  *	sizeof entry4 (36 bytes) +
124*0dfe541eSEvan Layton  *	sizeof eof bool (4 bytes)
1257c478bd9Sstevel@tonic-gate  *
1267c478bd9Sstevel@tonic-gate  * RFS4_MINLEN_RDDIR_BUF: minimum length of buffer server will provide to
1277c478bd9Sstevel@tonic-gate  *	VOP_READDIR.  Its value is the size of the maximum possible dirent
1287c478bd9Sstevel@tonic-gate  *	for solaris.  The DIRENT64_RECLEN macro returns	the size of dirent
1297c478bd9Sstevel@tonic-gate  *	required for a given name length.  MAXNAMELEN is the maximum
1307c478bd9Sstevel@tonic-gate  *	filename length allowed in Solaris.  The first two DIRENT64_RECLEN()
1317c478bd9Sstevel@tonic-gate  *	macros are to allow for . and .. entries -- just a minor tweak to try
1327c478bd9Sstevel@tonic-gate  *	and guarantee that buffer we give to VOP_READDIR will be large enough
1337c478bd9Sstevel@tonic-gate  *	to hold ., .., and the largest possible solaris dirent64.
1347c478bd9Sstevel@tonic-gate  */
1357c478bd9Sstevel@tonic-gate #define	RFS4_MINLEN_ENTRY4 36
1367c478bd9Sstevel@tonic-gate #define	RFS4_MINLEN_RDDIR4 (4 + NFS4_VERIFIER_SIZE + 4 + RFS4_MINLEN_ENTRY4 + 4)
1377c478bd9Sstevel@tonic-gate #define	RFS4_MINLEN_RDDIR_BUF \
1387c478bd9Sstevel@tonic-gate 	(DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2) + DIRENT64_RECLEN(MAXNAMELEN))
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate /*
1417c478bd9Sstevel@tonic-gate  * It would be better to pad to 4 bytes since that's what XDR would do,
1427c478bd9Sstevel@tonic-gate  * but the dirents UFS gives us are already padded to 8, so just take
1437c478bd9Sstevel@tonic-gate  * what we're given.  Dircount is only a hint anyway.  Currently the
1447c478bd9Sstevel@tonic-gate  * solaris kernel is ASCII only, so there's no point in calling the
1457c478bd9Sstevel@tonic-gate  * UTF8 functions.
1467c478bd9Sstevel@tonic-gate  *
1477c478bd9Sstevel@tonic-gate  * dirent64: named padded to provide 8 byte struct alignment
1487c478bd9Sstevel@tonic-gate  *	d_ino(8) + d_off(8) + d_reclen(2) + d_name(namelen + null(1) + pad)
1497c478bd9Sstevel@tonic-gate  *
1507c478bd9Sstevel@tonic-gate  * cookie: uint64_t   +  utf8namelen: uint_t  +   utf8name padded to 8 bytes
1517c478bd9Sstevel@tonic-gate  *
1527c478bd9Sstevel@tonic-gate  */
1537c478bd9Sstevel@tonic-gate #define	DIRENT64_TO_DIRCOUNT(dp) \
1547c478bd9Sstevel@tonic-gate 	(3 * BYTES_PER_XDR_UNIT + DIRENT64_NAMELEN((dp)->d_reclen))
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 
157*0dfe541eSEvan Layton static sysid_t		lockt_sysid;	/* dummy sysid for all LOCKT calls */
1587c478bd9Sstevel@tonic-gate 
1590a701b1eSRobert Gordon u_longlong_t	nfs4_srv_caller_id;
1600a701b1eSRobert Gordon uint_t		nfs4_srv_vkey = 0;
1617c478bd9Sstevel@tonic-gate 
1620a701b1eSRobert Gordon void	rfs4_init_compound_state(struct compound_state *);
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate static void	nullfree(caddr_t);
1657c478bd9Sstevel@tonic-gate static void	rfs4_op_inval(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
166*0dfe541eSEvan Layton 		    struct compound_state *);
1677c478bd9Sstevel@tonic-gate static void	rfs4_op_access(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
168*0dfe541eSEvan Layton 		    struct compound_state *);
1697c478bd9Sstevel@tonic-gate static void	rfs4_op_close(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
170*0dfe541eSEvan Layton 		    struct compound_state *);
1717c478bd9Sstevel@tonic-gate static void	rfs4_op_commit(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
172*0dfe541eSEvan Layton 		    struct compound_state *);
1737c478bd9Sstevel@tonic-gate static void	rfs4_op_create(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
174*0dfe541eSEvan Layton 		    struct compound_state *);
1757c478bd9Sstevel@tonic-gate static void	rfs4_op_create_free(nfs_resop4 *resop);
1767c478bd9Sstevel@tonic-gate static void	rfs4_op_delegreturn(nfs_argop4 *, nfs_resop4 *,
177*0dfe541eSEvan Layton 		    struct svc_req *, struct compound_state *);
178f3b585ceSsamf static void	rfs4_op_delegpurge(nfs_argop4 *, nfs_resop4 *,
179*0dfe541eSEvan Layton 		    struct svc_req *, struct compound_state *);
1807c478bd9Sstevel@tonic-gate static void	rfs4_op_getattr(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
181*0dfe541eSEvan Layton 		    struct compound_state *);
1827c478bd9Sstevel@tonic-gate static void	rfs4_op_getattr_free(nfs_resop4 *);
1837c478bd9Sstevel@tonic-gate static void	rfs4_op_getfh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
184*0dfe541eSEvan Layton 		    struct compound_state *);
1857c478bd9Sstevel@tonic-gate static void	rfs4_op_getfh_free(nfs_resop4 *);
1867c478bd9Sstevel@tonic-gate static void	rfs4_op_illegal(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
187*0dfe541eSEvan Layton 		    struct compound_state *);
1887c478bd9Sstevel@tonic-gate static void	rfs4_op_link(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
189*0dfe541eSEvan Layton 		    struct compound_state *);
1907c478bd9Sstevel@tonic-gate static void	rfs4_op_lock(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
191*0dfe541eSEvan Layton 		    struct compound_state *);
1927c478bd9Sstevel@tonic-gate static void	lock_denied_free(nfs_resop4 *);
1937c478bd9Sstevel@tonic-gate static void	rfs4_op_locku(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
194*0dfe541eSEvan Layton 		    struct compound_state *);
1957c478bd9Sstevel@tonic-gate static void	rfs4_op_lockt(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
196*0dfe541eSEvan Layton 		    struct compound_state *);
1977c478bd9Sstevel@tonic-gate static void	rfs4_op_lookup(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
198*0dfe541eSEvan Layton 		    struct compound_state *);
1997c478bd9Sstevel@tonic-gate static void	rfs4_op_lookupp(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
200*0dfe541eSEvan Layton 		    struct compound_state *);
2017c478bd9Sstevel@tonic-gate static void	rfs4_op_openattr(nfs_argop4 *argop, nfs_resop4 *resop,
202*0dfe541eSEvan Layton 		    struct svc_req *req, struct compound_state *cs);
2037c478bd9Sstevel@tonic-gate static void	rfs4_op_nverify(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
204*0dfe541eSEvan Layton 		    struct compound_state *);
2057c478bd9Sstevel@tonic-gate static void	rfs4_op_open(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
206*0dfe541eSEvan Layton 		    struct compound_state *);
2077c478bd9Sstevel@tonic-gate static void	rfs4_op_open_confirm(nfs_argop4 *, nfs_resop4 *,
208*0dfe541eSEvan Layton 		    struct svc_req *, struct compound_state *);
2097c478bd9Sstevel@tonic-gate static void	rfs4_op_open_downgrade(nfs_argop4 *, nfs_resop4 *,
210*0dfe541eSEvan Layton 		    struct svc_req *, struct compound_state *);
2117c478bd9Sstevel@tonic-gate static void	rfs4_op_putfh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
212*0dfe541eSEvan Layton 		    struct compound_state *);
2137c478bd9Sstevel@tonic-gate static void	rfs4_op_putpubfh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
214*0dfe541eSEvan Layton 		    struct compound_state *);
2157c478bd9Sstevel@tonic-gate static void	rfs4_op_putrootfh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
216*0dfe541eSEvan Layton 		    struct compound_state *);
2177c478bd9Sstevel@tonic-gate static void	rfs4_op_read(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
218*0dfe541eSEvan Layton 		    struct compound_state *);
2197c478bd9Sstevel@tonic-gate static void	rfs4_op_read_free(nfs_resop4 *);
2207c478bd9Sstevel@tonic-gate static void	rfs4_op_readdir_free(nfs_resop4 *resop);
2217c478bd9Sstevel@tonic-gate static void	rfs4_op_readlink(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
222*0dfe541eSEvan Layton 		    struct compound_state *);
2237c478bd9Sstevel@tonic-gate static void	rfs4_op_readlink_free(nfs_resop4 *);
2247c478bd9Sstevel@tonic-gate static void	rfs4_op_release_lockowner(nfs_argop4 *, nfs_resop4 *,
225*0dfe541eSEvan Layton 		    struct svc_req *, struct compound_state *);
2267c478bd9Sstevel@tonic-gate static void	rfs4_op_remove(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
227*0dfe541eSEvan Layton 		    struct compound_state *);
2287c478bd9Sstevel@tonic-gate static void	rfs4_op_rename(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
229*0dfe541eSEvan Layton 		    struct compound_state *);
2307c478bd9Sstevel@tonic-gate static void	rfs4_op_renew(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
231*0dfe541eSEvan Layton 		    struct compound_state *);
2327c478bd9Sstevel@tonic-gate static void	rfs4_op_restorefh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
233*0dfe541eSEvan Layton 		    struct compound_state *);
2347c478bd9Sstevel@tonic-gate static void	rfs4_op_savefh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
235*0dfe541eSEvan Layton 		    struct compound_state *);
2367c478bd9Sstevel@tonic-gate static void	rfs4_op_setattr(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
237*0dfe541eSEvan Layton 		    struct compound_state *);
2387c478bd9Sstevel@tonic-gate static void	rfs4_op_verify(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
239*0dfe541eSEvan Layton 		    struct compound_state *);
2407c478bd9Sstevel@tonic-gate static void	rfs4_op_write(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
241*0dfe541eSEvan Layton 		    struct compound_state *);
2427c478bd9Sstevel@tonic-gate static void	rfs4_op_setclientid(nfs_argop4 *, nfs_resop4 *,
243*0dfe541eSEvan Layton 		    struct svc_req *, struct compound_state *);
2447c478bd9Sstevel@tonic-gate static void	rfs4_op_setclientid_confirm(nfs_argop4 *, nfs_resop4 *,
245*0dfe541eSEvan Layton 		    struct svc_req *req, struct compound_state *);
2467c478bd9Sstevel@tonic-gate static void	rfs4_op_secinfo(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
247*0dfe541eSEvan Layton 		    struct compound_state *);
2487c478bd9Sstevel@tonic-gate static void	rfs4_op_secinfo_free(nfs_resop4 *);
2497c478bd9Sstevel@tonic-gate 
250*0dfe541eSEvan Layton static nfsstat4 check_open_access(uint32_t, struct compound_state *,
251*0dfe541eSEvan Layton 		    struct svc_req *);
252*0dfe541eSEvan Layton nfsstat4	rfs4_client_sysid(rfs4_client_t *, sysid_t *);
253*0dfe541eSEvan Layton void		rfs4_ss_clid(nfs4_srv_t *, rfs4_client_t *);
254*0dfe541eSEvan Layton 
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate /*
2577c478bd9Sstevel@tonic-gate  * translation table for attrs
2587c478bd9Sstevel@tonic-gate  */
2597c478bd9Sstevel@tonic-gate struct nfs4_ntov_table {
2607c478bd9Sstevel@tonic-gate 	union nfs4_attr_u *na;
2617c478bd9Sstevel@tonic-gate 	uint8_t amap[NFS4_MAXNUM_ATTRS];
2627c478bd9Sstevel@tonic-gate 	int attrcnt;
2637c478bd9Sstevel@tonic-gate 	bool_t vfsstat;
2647c478bd9Sstevel@tonic-gate };
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate static void	nfs4_ntov_table_init(struct nfs4_ntov_table *ntovp);
2677c478bd9Sstevel@tonic-gate static void	nfs4_ntov_table_free(struct nfs4_ntov_table *ntovp,
268*0dfe541eSEvan Layton 		    struct nfs4_svgetit_arg *sargp);
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate static nfsstat4	do_rfs4_set_attrs(bitmap4 *resp, fattr4 *fattrp,
2717c478bd9Sstevel@tonic-gate 		    struct compound_state *cs, struct nfs4_svgetit_arg *sargp,
2727c478bd9Sstevel@tonic-gate 		    struct nfs4_ntov_table *ntovp, nfs4_attr_cmd_t cmd);
2737c478bd9Sstevel@tonic-gate 
274*0dfe541eSEvan Layton static void	hanfsv4_failover(nfs4_srv_t *);
275*0dfe541eSEvan Layton 
2760a701b1eSRobert Gordon fem_t		*deleg_rdops;
2770a701b1eSRobert Gordon fem_t		*deleg_wrops;
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate /*
2807c478bd9Sstevel@tonic-gate  * NFS4 op dispatch table
2817c478bd9Sstevel@tonic-gate  */
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate struct rfsv4disp {
2847c478bd9Sstevel@tonic-gate 	void	(*dis_proc)();		/* proc to call */
2857c478bd9Sstevel@tonic-gate 	void	(*dis_resfree)();	/* frees space allocated by proc */
2867c478bd9Sstevel@tonic-gate 	int	dis_flags;		/* RPC_IDEMPOTENT, etc... */
2877c478bd9Sstevel@tonic-gate };
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate static struct rfsv4disp rfsv4disptab[] = {
2907c478bd9Sstevel@tonic-gate 	/*
2917c478bd9Sstevel@tonic-gate 	 * NFS VERSION 4
2927c478bd9Sstevel@tonic-gate 	 */
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 	/* RFS_NULL = 0 */
295f7877f5dSDan McDonald 	{rfs4_op_illegal, nullfree, 0},
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	/* UNUSED = 1 */
298f7877f5dSDan McDonald 	{rfs4_op_illegal, nullfree, 0},
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 	/* UNUSED = 2 */
301f7877f5dSDan McDonald 	{rfs4_op_illegal, nullfree, 0},
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	/* OP_ACCESS = 3 */
304f7877f5dSDan McDonald 	{rfs4_op_access, nullfree, RPC_IDEMPOTENT},
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 	/* OP_CLOSE = 4 */
307f7877f5dSDan McDonald 	{rfs4_op_close, nullfree, 0},
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	/* OP_COMMIT = 5 */
310f7877f5dSDan McDonald 	{rfs4_op_commit, nullfree, RPC_IDEMPOTENT},
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 	/* OP_CREATE = 6 */
313f7877f5dSDan McDonald 	{rfs4_op_create, nullfree, 0},
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 	/* OP_DELEGPURGE = 7 */
316f7877f5dSDan McDonald 	{rfs4_op_delegpurge, nullfree, 0},
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 	/* OP_DELEGRETURN = 8 */
319f7877f5dSDan McDonald 	{rfs4_op_delegreturn, nullfree, 0},
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate 	/* OP_GETATTR = 9 */
322f7877f5dSDan McDonald 	{rfs4_op_getattr, rfs4_op_getattr_free, RPC_IDEMPOTENT},
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 	/* OP_GETFH = 10 */
325f7877f5dSDan McDonald 	{rfs4_op_getfh, rfs4_op_getfh_free, RPC_ALL},
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 	/* OP_LINK = 11 */
328f7877f5dSDan McDonald 	{rfs4_op_link, nullfree, 0},
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 	/* OP_LOCK = 12 */
331f7877f5dSDan McDonald 	{rfs4_op_lock, lock_denied_free, 0},
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 	/* OP_LOCKT = 13 */
334f7877f5dSDan McDonald 	{rfs4_op_lockt, lock_denied_free, 0},
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 	/* OP_LOCKU = 14 */
337f7877f5dSDan McDonald 	{rfs4_op_locku, nullfree, 0},
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 	/* OP_LOOKUP = 15 */
340f7877f5dSDan McDonald 	{rfs4_op_lookup, nullfree, (RPC_IDEMPOTENT | RPC_PUBLICFH_OK)},
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 	/* OP_LOOKUPP = 16 */
343f7877f5dSDan McDonald 	{rfs4_op_lookupp, nullfree, (RPC_IDEMPOTENT | RPC_PUBLICFH_OK)},
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 	/* OP_NVERIFY = 17 */
346f7877f5dSDan McDonald 	{rfs4_op_nverify, nullfree, RPC_IDEMPOTENT},
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	/* OP_OPEN = 18 */
349f7877f5dSDan McDonald 	{rfs4_op_open, rfs4_free_reply, 0},
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate 	/* OP_OPENATTR = 19 */
352f7877f5dSDan McDonald 	{rfs4_op_openattr, nullfree, 0},
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 	/* OP_OPEN_CONFIRM = 20 */
355f7877f5dSDan McDonald 	{rfs4_op_open_confirm, nullfree, 0},
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate 	/* OP_OPEN_DOWNGRADE = 21 */
358f7877f5dSDan McDonald 	{rfs4_op_open_downgrade, nullfree, 0},
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 	/* OP_OPEN_PUTFH = 22 */
361f7877f5dSDan McDonald 	{rfs4_op_putfh, nullfree, RPC_ALL},
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 	/* OP_PUTPUBFH = 23 */
364f7877f5dSDan McDonald 	{rfs4_op_putpubfh, nullfree, RPC_ALL},
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	/* OP_PUTROOTFH = 24 */
367f7877f5dSDan McDonald 	{rfs4_op_putrootfh, nullfree, RPC_ALL},
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	/* OP_READ = 25 */
370f7877f5dSDan McDonald 	{rfs4_op_read, rfs4_op_read_free, RPC_IDEMPOTENT},
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 	/* OP_READDIR = 26 */
373f7877f5dSDan McDonald 	{rfs4_op_readdir, rfs4_op_readdir_free, RPC_IDEMPOTENT},
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate 	/* OP_READLINK = 27 */
376f7877f5dSDan McDonald 	{rfs4_op_readlink, rfs4_op_readlink_free, RPC_IDEMPOTENT},
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	/* OP_REMOVE = 28 */
379f7877f5dSDan McDonald 	{rfs4_op_remove, nullfree, 0},
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 	/* OP_RENAME = 29 */
382f7877f5dSDan McDonald 	{rfs4_op_rename, nullfree, 0},
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 	/* OP_RENEW = 30 */
385f7877f5dSDan McDonald 	{rfs4_op_renew, nullfree, 0},
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	/* OP_RESTOREFH = 31 */
388f7877f5dSDan McDonald 	{rfs4_op_restorefh, nullfree, RPC_ALL},
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 	/* OP_SAVEFH = 32 */
391f7877f5dSDan McDonald 	{rfs4_op_savefh, nullfree, RPC_ALL},
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 	/* OP_SECINFO = 33 */
394f7877f5dSDan McDonald 	{rfs4_op_secinfo, rfs4_op_secinfo_free, 0},
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	/* OP_SETATTR = 34 */
397f7877f5dSDan McDonald 	{rfs4_op_setattr, nullfree, 0},
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 	/* OP_SETCLIENTID = 35 */
400f7877f5dSDan McDonald 	{rfs4_op_setclientid, nullfree, 0},
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 	/* OP_SETCLIENTID_CONFIRM = 36 */
403f7877f5dSDan McDonald 	{rfs4_op_setclientid_confirm, nullfree, 0},
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 	/* OP_VERIFY = 37 */
406f7877f5dSDan McDonald 	{rfs4_op_verify, nullfree, RPC_IDEMPOTENT},
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate 	/* OP_WRITE = 38 */
409f7877f5dSDan McDonald 	{rfs4_op_write, nullfree, 0},
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 	/* OP_RELEASE_LOCKOWNER = 39 */
412f7877f5dSDan McDonald 	{rfs4_op_release_lockowner, nullfree, 0},
4137c478bd9Sstevel@tonic-gate };
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate static uint_t rfsv4disp_cnt = sizeof (rfsv4disptab) / sizeof (rfsv4disptab[0]);
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate #define	OP_ILLEGAL_IDX (rfsv4disp_cnt)
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate #ifdef DEBUG
4207c478bd9Sstevel@tonic-gate 
4210a701b1eSRobert Gordon int		rfs4_fillone_debug = 0;
4220a701b1eSRobert Gordon int		rfs4_no_stub_access = 1;
4230a701b1eSRobert Gordon int		rfs4_rddir_debug = 0;
4247c478bd9Sstevel@tonic-gate 
4250a701b1eSRobert Gordon static char    *rfs4_op_string[] = {
4267c478bd9Sstevel@tonic-gate 	"rfs4_op_null",
4277c478bd9Sstevel@tonic-gate 	"rfs4_op_1 unused",
4287c478bd9Sstevel@tonic-gate 	"rfs4_op_2 unused",
4297c478bd9Sstevel@tonic-gate 	"rfs4_op_access",
4307c478bd9Sstevel@tonic-gate 	"rfs4_op_close",
4317c478bd9Sstevel@tonic-gate 	"rfs4_op_commit",
4327c478bd9Sstevel@tonic-gate 	"rfs4_op_create",
4337c478bd9Sstevel@tonic-gate 	"rfs4_op_delegpurge",
4347c478bd9Sstevel@tonic-gate 	"rfs4_op_delegreturn",
4357c478bd9Sstevel@tonic-gate 	"rfs4_op_getattr",
4367c478bd9Sstevel@tonic-gate 	"rfs4_op_getfh",
4377c478bd9Sstevel@tonic-gate 	"rfs4_op_link",
4387c478bd9Sstevel@tonic-gate 	"rfs4_op_lock",
4397c478bd9Sstevel@tonic-gate 	"rfs4_op_lockt",
4407c478bd9Sstevel@tonic-gate 	"rfs4_op_locku",
4417c478bd9Sstevel@tonic-gate 	"rfs4_op_lookup",
4427c478bd9Sstevel@tonic-gate 	"rfs4_op_lookupp",
4437c478bd9Sstevel@tonic-gate 	"rfs4_op_nverify",
4447c478bd9Sstevel@tonic-gate 	"rfs4_op_open",
4457c478bd9Sstevel@tonic-gate 	"rfs4_op_openattr",
4467c478bd9Sstevel@tonic-gate 	"rfs4_op_open_confirm",
4477c478bd9Sstevel@tonic-gate 	"rfs4_op_open_downgrade",
4487c478bd9Sstevel@tonic-gate 	"rfs4_op_putfh",
4497c478bd9Sstevel@tonic-gate 	"rfs4_op_putpubfh",
4507c478bd9Sstevel@tonic-gate 	"rfs4_op_putrootfh",
4517c478bd9Sstevel@tonic-gate 	"rfs4_op_read",
4527c478bd9Sstevel@tonic-gate 	"rfs4_op_readdir",
4537c478bd9Sstevel@tonic-gate 	"rfs4_op_readlink",
4547c478bd9Sstevel@tonic-gate 	"rfs4_op_remove",
4557c478bd9Sstevel@tonic-gate 	"rfs4_op_rename",
4567c478bd9Sstevel@tonic-gate 	"rfs4_op_renew",
4577c478bd9Sstevel@tonic-gate 	"rfs4_op_restorefh",
4587c478bd9Sstevel@tonic-gate 	"rfs4_op_savefh",
4597c478bd9Sstevel@tonic-gate 	"rfs4_op_secinfo",
4607c478bd9Sstevel@tonic-gate 	"rfs4_op_setattr",
4617c478bd9Sstevel@tonic-gate 	"rfs4_op_setclientid",
4627c478bd9Sstevel@tonic-gate 	"rfs4_op_setclient_confirm",
4637c478bd9Sstevel@tonic-gate 	"rfs4_op_verify",
4647c478bd9Sstevel@tonic-gate 	"rfs4_op_write",
4657c478bd9Sstevel@tonic-gate 	"rfs4_op_release_lockowner",
4667c478bd9Sstevel@tonic-gate 	"rfs4_op_illegal"
4677c478bd9Sstevel@tonic-gate };
4687c478bd9Sstevel@tonic-gate #endif
4697c478bd9Sstevel@tonic-gate 
470*0dfe541eSEvan Layton void	rfs4_ss_chkclid(nfs4_srv_t *, rfs4_client_t *);
4717c478bd9Sstevel@tonic-gate 
4720a701b1eSRobert Gordon extern size_t   strlcpy(char *dst, const char *src, size_t dstsize);
473cee86682Scalum 
4742f172c55SRobert Thurlow extern void	rfs4_free_fs_locations4(fs_locations4 *);
4752f172c55SRobert Thurlow 
4767c478bd9Sstevel@tonic-gate #ifdef	nextdp
4777c478bd9Sstevel@tonic-gate #undef nextdp
4787c478bd9Sstevel@tonic-gate #endif
4797c478bd9Sstevel@tonic-gate #define	nextdp(dp)	((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate static const fs_operation_def_t nfs4_rd_deleg_tmpl[] = {
482cfae96c2Sjwahlig 	VOPNAME_OPEN,		{ .femop_open = deleg_rd_open },
483cfae96c2Sjwahlig 	VOPNAME_WRITE,		{ .femop_write = deleg_rd_write },
484cfae96c2Sjwahlig 	VOPNAME_SETATTR,	{ .femop_setattr = deleg_rd_setattr },
485aa59c4cbSrsb 	VOPNAME_RWLOCK,		{ .femop_rwlock = deleg_rd_rwlock },
486cfae96c2Sjwahlig 	VOPNAME_SPACE,		{ .femop_space = deleg_rd_space },
487cfae96c2Sjwahlig 	VOPNAME_SETSECATTR,	{ .femop_setsecattr = deleg_rd_setsecattr },
488cfae96c2Sjwahlig 	VOPNAME_VNEVENT,	{ .femop_vnevent = deleg_rd_vnevent },
489aa59c4cbSrsb 	NULL,			NULL
4907c478bd9Sstevel@tonic-gate };
4917c478bd9Sstevel@tonic-gate static const fs_operation_def_t nfs4_wr_deleg_tmpl[] = {
492cfae96c2Sjwahlig 	VOPNAME_OPEN,		{ .femop_open = deleg_wr_open },
493cfae96c2Sjwahlig 	VOPNAME_READ,		{ .femop_read = deleg_wr_read },
494cfae96c2Sjwahlig 	VOPNAME_WRITE,		{ .femop_write = deleg_wr_write },
495cfae96c2Sjwahlig 	VOPNAME_SETATTR,	{ .femop_setattr = deleg_wr_setattr },
496aa59c4cbSrsb 	VOPNAME_RWLOCK,		{ .femop_rwlock = deleg_wr_rwlock },
497cfae96c2Sjwahlig 	VOPNAME_SPACE,		{ .femop_space = deleg_wr_space },
498cfae96c2Sjwahlig 	VOPNAME_SETSECATTR,	{ .femop_setsecattr = deleg_wr_setsecattr },
499cfae96c2Sjwahlig 	VOPNAME_VNEVENT,	{ .femop_vnevent = deleg_wr_vnevent },
500aa59c4cbSrsb 	NULL,			NULL
5017c478bd9Sstevel@tonic-gate };
5027c478bd9Sstevel@tonic-gate 
503*0dfe541eSEvan Layton nfs4_srv_t *
nfs4_get_srv(void)504*0dfe541eSEvan Layton nfs4_get_srv(void)
505*0dfe541eSEvan Layton {
506*0dfe541eSEvan Layton 	nfs_globals_t *ng = nfs_srv_getzg();
507*0dfe541eSEvan Layton 	nfs4_srv_t *srv = ng->nfs4_srv;
508*0dfe541eSEvan Layton 	ASSERT(srv != NULL);
509*0dfe541eSEvan Layton 	return (srv);
510*0dfe541eSEvan Layton }
511*0dfe541eSEvan Layton 
512*0dfe541eSEvan Layton void
rfs4_srv_zone_init(nfs_globals_t * ng)513*0dfe541eSEvan Layton rfs4_srv_zone_init(nfs_globals_t *ng)
5147c478bd9Sstevel@tonic-gate {
515*0dfe541eSEvan Layton 	nfs4_srv_t *nsrv4;
5167c478bd9Sstevel@tonic-gate 	timespec32_t verf;
517*0dfe541eSEvan Layton 
518*0dfe541eSEvan Layton 	nsrv4 = kmem_zalloc(sizeof (*nsrv4), KM_SLEEP);
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate 	/*
5217c478bd9Sstevel@tonic-gate 	 * The following algorithm attempts to find a unique verifier
5227c478bd9Sstevel@tonic-gate 	 * to be used as the write verifier returned from the server
5237c478bd9Sstevel@tonic-gate 	 * to the client.  It is important that this verifier change
5247c478bd9Sstevel@tonic-gate 	 * whenever the server reboots.  Of secondary importance, it
5257c478bd9Sstevel@tonic-gate 	 * is important for the verifier to be unique between two
5267c478bd9Sstevel@tonic-gate 	 * different servers.
5277c478bd9Sstevel@tonic-gate 	 *
5287c478bd9Sstevel@tonic-gate 	 * Thus, an attempt is made to use the system hostid and the
5297c478bd9Sstevel@tonic-gate 	 * current time in seconds when the nfssrv kernel module is
5307c478bd9Sstevel@tonic-gate 	 * loaded.  It is assumed that an NFS server will not be able
5317c478bd9Sstevel@tonic-gate 	 * to boot and then to reboot in less than a second.  If the
5327c478bd9Sstevel@tonic-gate 	 * hostid has not been set, then the current high resolution
5337c478bd9Sstevel@tonic-gate 	 * time is used.  This will ensure different verifiers each
5347c478bd9Sstevel@tonic-gate 	 * time the server reboots and minimize the chances that two
5357c478bd9Sstevel@tonic-gate 	 * different servers will have the same verifier.
5367c478bd9Sstevel@tonic-gate 	 * XXX - this is broken on LP64 kernels.
5377c478bd9Sstevel@tonic-gate 	 */
5385679c89fSjv 	verf.tv_sec = (time_t)zone_get_hostid(NULL);
5397c478bd9Sstevel@tonic-gate 	if (verf.tv_sec != 0) {
5407c478bd9Sstevel@tonic-gate 		verf.tv_nsec = gethrestime_sec();
5417c478bd9Sstevel@tonic-gate 	} else {
5427c478bd9Sstevel@tonic-gate 		timespec_t tverf;
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate 		gethrestime(&tverf);
5457c478bd9Sstevel@tonic-gate 		verf.tv_sec = (time_t)tverf.tv_sec;
5467c478bd9Sstevel@tonic-gate 		verf.tv_nsec = tverf.tv_nsec;
5477c478bd9Sstevel@tonic-gate 	}
548*0dfe541eSEvan Layton 	nsrv4->write4verf = *(uint64_t *)&verf;
549*0dfe541eSEvan Layton 
550*0dfe541eSEvan Layton 	/* Used to manage create/destroy of server state */
551*0dfe541eSEvan Layton 	nsrv4->nfs4_server_state = NULL;
552*0dfe541eSEvan Layton 	nsrv4->nfs4_cur_servinst = NULL;
553*0dfe541eSEvan Layton 	nsrv4->nfs4_deleg_policy = SRV_NEVER_DELEGATE;
554*0dfe541eSEvan Layton 	mutex_init(&nsrv4->deleg_lock, NULL, MUTEX_DEFAULT, NULL);
555*0dfe541eSEvan Layton 	mutex_init(&nsrv4->state_lock, NULL, MUTEX_DEFAULT, NULL);
556*0dfe541eSEvan Layton 	mutex_init(&nsrv4->servinst_lock, NULL, MUTEX_DEFAULT, NULL);
557*0dfe541eSEvan Layton 	rw_init(&nsrv4->deleg_policy_lock, NULL, RW_DEFAULT, NULL);
558*0dfe541eSEvan Layton 
559*0dfe541eSEvan Layton 	ng->nfs4_srv = nsrv4;
560*0dfe541eSEvan Layton }
5617c478bd9Sstevel@tonic-gate 
562*0dfe541eSEvan Layton void
rfs4_srv_zone_fini(nfs_globals_t * ng)563*0dfe541eSEvan Layton rfs4_srv_zone_fini(nfs_globals_t *ng)
564*0dfe541eSEvan Layton {
565*0dfe541eSEvan Layton 	nfs4_srv_t *nsrv4 = ng->nfs4_srv;
5667c478bd9Sstevel@tonic-gate 
567*0dfe541eSEvan Layton 	ng->nfs4_srv = NULL;
5687c478bd9Sstevel@tonic-gate 
569*0dfe541eSEvan Layton 	mutex_destroy(&nsrv4->deleg_lock);
570*0dfe541eSEvan Layton 	mutex_destroy(&nsrv4->state_lock);
571*0dfe541eSEvan Layton 	mutex_destroy(&nsrv4->servinst_lock);
572*0dfe541eSEvan Layton 	rw_destroy(&nsrv4->deleg_policy_lock);
5737c478bd9Sstevel@tonic-gate 
574*0dfe541eSEvan Layton 	kmem_free(nsrv4, sizeof (*nsrv4));
575*0dfe541eSEvan Layton }
5767c478bd9Sstevel@tonic-gate 
577*0dfe541eSEvan Layton void
rfs4_srvrinit(void)578*0dfe541eSEvan Layton rfs4_srvrinit(void)
579*0dfe541eSEvan Layton {
580*0dfe541eSEvan Layton 	extern void rfs4_attr_init();
5817c478bd9Sstevel@tonic-gate 
582*0dfe541eSEvan Layton 	rfs4_attr_init();
583*0dfe541eSEvan Layton 
584*0dfe541eSEvan Layton 	if (fem_create("deleg_rdops", nfs4_rd_deleg_tmpl, &deleg_rdops) != 0) {
5857c478bd9Sstevel@tonic-gate 		rfs4_disable_delegation();
586*0dfe541eSEvan Layton 	} else if (fem_create("deleg_wrops", nfs4_wr_deleg_tmpl,
587*0dfe541eSEvan Layton 	    &deleg_wrops) != 0) {
588*0dfe541eSEvan Layton 		rfs4_disable_delegation();
589*0dfe541eSEvan Layton 		fem_free(deleg_rdops);
5907c478bd9Sstevel@tonic-gate 	}
5917c478bd9Sstevel@tonic-gate 
5927c478bd9Sstevel@tonic-gate 	nfs4_srv_caller_id = fs_new_caller_id();
5937c478bd9Sstevel@tonic-gate 	lockt_sysid = lm_alloc_sysidt();
5941b300de9Sjwahlig 	vsd_create(&nfs4_srv_vkey, NULL);
595*0dfe541eSEvan Layton 	rfs4_state_g_init();
5967c478bd9Sstevel@tonic-gate }
5977c478bd9Sstevel@tonic-gate 
5987c478bd9Sstevel@tonic-gate void
rfs4_srvrfini(void)5997c478bd9Sstevel@tonic-gate rfs4_srvrfini(void)
6007c478bd9Sstevel@tonic-gate {
6017c478bd9Sstevel@tonic-gate 	if (lockt_sysid != LM_NOSYSID) {
6027c478bd9Sstevel@tonic-gate 		lm_free_sysidt(lockt_sysid);
6037c478bd9Sstevel@tonic-gate 		lockt_sysid = LM_NOSYSID;
6047c478bd9Sstevel@tonic-gate 	}
6057c478bd9Sstevel@tonic-gate 
606*0dfe541eSEvan Layton 	rfs4_state_g_fini();
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 	fem_free(deleg_rdops);
6097c478bd9Sstevel@tonic-gate 	fem_free(deleg_wrops);
6107c478bd9Sstevel@tonic-gate }
6117c478bd9Sstevel@tonic-gate 
612*0dfe541eSEvan Layton void
rfs4_do_server_start(int server_upordown,int srv_delegation,int cluster_booted)613*0dfe541eSEvan Layton rfs4_do_server_start(int server_upordown,
614*0dfe541eSEvan Layton     int srv_delegation, int cluster_booted)
615*0dfe541eSEvan Layton {
616*0dfe541eSEvan Layton 	nfs4_srv_t *nsrv4 = nfs4_get_srv();
617*0dfe541eSEvan Layton 
618*0dfe541eSEvan Layton 	/* Is this a warm start? */
619*0dfe541eSEvan Layton 	if (server_upordown == NFS_SERVER_QUIESCED) {
620*0dfe541eSEvan Layton 		cmn_err(CE_NOTE, "nfs4_srv: "
621*0dfe541eSEvan Layton 		    "server was previously quiesced; "
622*0dfe541eSEvan Layton 		    "existing NFSv4 state will be re-used");
623*0dfe541eSEvan Layton 
624*0dfe541eSEvan Layton 		/*
625*0dfe541eSEvan Layton 		 * HA-NFSv4: this is also the signal
626*0dfe541eSEvan Layton 		 * that a Resource Group failover has
627*0dfe541eSEvan Layton 		 * occurred.
628*0dfe541eSEvan Layton 		 */
629*0dfe541eSEvan Layton 		if (cluster_booted)
630*0dfe541eSEvan Layton 			hanfsv4_failover(nsrv4);
631*0dfe541eSEvan Layton 	} else {
632*0dfe541eSEvan Layton 		/* Cold start */
633*0dfe541eSEvan Layton 		nsrv4->rfs4_start_time = 0;
634*0dfe541eSEvan Layton 		rfs4_state_zone_init(nsrv4);
635*0dfe541eSEvan Layton 		nsrv4->nfs4_drc = rfs4_init_drc(nfs4_drc_max,
636*0dfe541eSEvan Layton 		    nfs4_drc_hash);
637*0dfe541eSEvan Layton 
638*0dfe541eSEvan Layton 		/*
639*0dfe541eSEvan Layton 		 * The nfsd service was started with the -s option
640*0dfe541eSEvan Layton 		 * we need to pull in any state from the paths indicated.
641*0dfe541eSEvan Layton 		 */
642*0dfe541eSEvan Layton 		if (curzone == global_zone && rfs4_dss_numnewpaths > 0) {
643*0dfe541eSEvan Layton 			/* read in the stable storage state from these paths */
644*0dfe541eSEvan Layton 			rfs4_dss_readstate(nsrv4, rfs4_dss_numnewpaths,
645*0dfe541eSEvan Layton 			    rfs4_dss_newpaths);
646*0dfe541eSEvan Layton 		}
647*0dfe541eSEvan Layton 	}
648*0dfe541eSEvan Layton 
649*0dfe541eSEvan Layton 	/* Check if delegation is to be enabled */
650*0dfe541eSEvan Layton 	if (srv_delegation != FALSE)
651*0dfe541eSEvan Layton 		rfs4_set_deleg_policy(nsrv4, SRV_NORMAL_DELEGATE);
652*0dfe541eSEvan Layton }
653*0dfe541eSEvan Layton 
6547c478bd9Sstevel@tonic-gate void
rfs4_init_compound_state(struct compound_state * cs)6557c478bd9Sstevel@tonic-gate rfs4_init_compound_state(struct compound_state *cs)
6567c478bd9Sstevel@tonic-gate {
6577c478bd9Sstevel@tonic-gate 	bzero(cs, sizeof (*cs));
6587c478bd9Sstevel@tonic-gate 	cs->cont = TRUE;
6597c478bd9Sstevel@tonic-gate 	cs->access = CS_ACCESS_DENIED;
6607c478bd9Sstevel@tonic-gate 	cs->deleg = FALSE;
6617c478bd9Sstevel@tonic-gate 	cs->mandlock = FALSE;
6627c478bd9Sstevel@tonic-gate 	cs->fh.nfs_fh4_val = cs->fhbuf;
6637c478bd9Sstevel@tonic-gate }
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate void
rfs4_grace_start(rfs4_servinst_t * sip)6667c478bd9Sstevel@tonic-gate rfs4_grace_start(rfs4_servinst_t *sip)
6677c478bd9Sstevel@tonic-gate {
6687c478bd9Sstevel@tonic-gate 	rw_enter(&sip->rwlock, RW_WRITER);
669d3d50737SRafael Vanoni 	sip->start_time = (time_t)TICK_TO_SEC(ddi_get_lbolt());
6707c478bd9Sstevel@tonic-gate 	sip->grace_period = rfs4_grace_period;
6717c478bd9Sstevel@tonic-gate 	rw_exit(&sip->rwlock);
6727c478bd9Sstevel@tonic-gate }
6737c478bd9Sstevel@tonic-gate 
6747c478bd9Sstevel@tonic-gate /*
6757c478bd9Sstevel@tonic-gate  * returns true if the instance's grace period has never been started
6767c478bd9Sstevel@tonic-gate  */
6777c478bd9Sstevel@tonic-gate int
rfs4_servinst_grace_new(rfs4_servinst_t * sip)6787c478bd9Sstevel@tonic-gate rfs4_servinst_grace_new(rfs4_servinst_t *sip)
6797c478bd9Sstevel@tonic-gate {
6807c478bd9Sstevel@tonic-gate 	time_t start_time;
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate 	rw_enter(&sip->rwlock, RW_READER);
6837c478bd9Sstevel@tonic-gate 	start_time = sip->start_time;
6847c478bd9Sstevel@tonic-gate 	rw_exit(&sip->rwlock);
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate 	return (start_time == 0);
6877c478bd9Sstevel@tonic-gate }
6887c478bd9Sstevel@tonic-gate 
6897c478bd9Sstevel@tonic-gate /*
6907c478bd9Sstevel@tonic-gate  * Indicates if server instance is within the
6917c478bd9Sstevel@tonic-gate  * grace period.
6927c478bd9Sstevel@tonic-gate  */
6937c478bd9Sstevel@tonic-gate int
rfs4_servinst_in_grace(rfs4_servinst_t * sip)6947c478bd9Sstevel@tonic-gate rfs4_servinst_in_grace(rfs4_servinst_t *sip)
6957c478bd9Sstevel@tonic-gate {
6967c478bd9Sstevel@tonic-gate 	time_t grace_expiry;
6977c478bd9Sstevel@tonic-gate 
6987c478bd9Sstevel@tonic-gate 	rw_enter(&sip->rwlock, RW_READER);
6997c478bd9Sstevel@tonic-gate 	grace_expiry = sip->start_time + sip->grace_period;
7007c478bd9Sstevel@tonic-gate 	rw_exit(&sip->rwlock);
7017c478bd9Sstevel@tonic-gate 
702d3d50737SRafael Vanoni 	return (((time_t)TICK_TO_SEC(ddi_get_lbolt())) < grace_expiry);
7037c478bd9Sstevel@tonic-gate }
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate int
rfs4_clnt_in_grace(rfs4_client_t * cp)7067c478bd9Sstevel@tonic-gate rfs4_clnt_in_grace(rfs4_client_t *cp)
7077c478bd9Sstevel@tonic-gate {
708d216dff5SRobert Mastors 	ASSERT(rfs4_dbe_refcnt(cp->rc_dbe) > 0);
7097c478bd9Sstevel@tonic-gate 
710d216dff5SRobert Mastors 	return (rfs4_servinst_in_grace(cp->rc_server_instance));
7117c478bd9Sstevel@tonic-gate }
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate /*
7147c478bd9Sstevel@tonic-gate  * reset all currently active grace periods
7157c478bd9Sstevel@tonic-gate  */
7167c478bd9Sstevel@tonic-gate void
rfs4_grace_reset_all(nfs4_srv_t * nsrv4)717*0dfe541eSEvan Layton rfs4_grace_reset_all(nfs4_srv_t *nsrv4)
7187c478bd9Sstevel@tonic-gate {
7197c478bd9Sstevel@tonic-gate 	rfs4_servinst_t *sip;
7207c478bd9Sstevel@tonic-gate 
721*0dfe541eSEvan Layton 	mutex_enter(&nsrv4->servinst_lock);
722*0dfe541eSEvan Layton 	for (sip = nsrv4->nfs4_cur_servinst; sip != NULL; sip = sip->prev)
723cee86682Scalum 		if (rfs4_servinst_in_grace(sip))
7247c478bd9Sstevel@tonic-gate 			rfs4_grace_start(sip);
725*0dfe541eSEvan Layton 	mutex_exit(&nsrv4->servinst_lock);
7267c478bd9Sstevel@tonic-gate }
7277c478bd9Sstevel@tonic-gate 
7287c478bd9Sstevel@tonic-gate /*
7297c478bd9Sstevel@tonic-gate  * start any new instances' grace periods
7307c478bd9Sstevel@tonic-gate  */
7317c478bd9Sstevel@tonic-gate void
rfs4_grace_start_new(nfs4_srv_t * nsrv4)732*0dfe541eSEvan Layton rfs4_grace_start_new(nfs4_srv_t *nsrv4)
7337c478bd9Sstevel@tonic-gate {
7347c478bd9Sstevel@tonic-gate 	rfs4_servinst_t *sip;
7357c478bd9Sstevel@tonic-gate 
736*0dfe541eSEvan Layton 	mutex_enter(&nsrv4->servinst_lock);
737*0dfe541eSEvan Layton 	for (sip = nsrv4->nfs4_cur_servinst; sip != NULL; sip = sip->prev)
7387c478bd9Sstevel@tonic-gate 		if (rfs4_servinst_grace_new(sip))
7397c478bd9Sstevel@tonic-gate 			rfs4_grace_start(sip);
740*0dfe541eSEvan Layton 	mutex_exit(&nsrv4->servinst_lock);
741cee86682Scalum }
742cee86682Scalum 
743cee86682Scalum static rfs4_dss_path_t *
rfs4_dss_newpath(nfs4_srv_t * nsrv4,rfs4_servinst_t * sip,char * path,unsigned index)744*0dfe541eSEvan Layton rfs4_dss_newpath(nfs4_srv_t *nsrv4, rfs4_servinst_t *sip,
745*0dfe541eSEvan Layton     char *path, unsigned index)
746cee86682Scalum {
747cee86682Scalum 	size_t len;
748cee86682Scalum 	rfs4_dss_path_t *dss_path;
749cee86682Scalum 
750cee86682Scalum 	dss_path = kmem_alloc(sizeof (rfs4_dss_path_t), KM_SLEEP);
751cee86682Scalum 
752cee86682Scalum 	/*
753cee86682Scalum 	 * Take a copy of the string, since the original may be overwritten.
754cee86682Scalum 	 * Sadly, no strdup() in the kernel.
755cee86682Scalum 	 */
756cee86682Scalum 	/* allow for NUL */
757cee86682Scalum 	len = strlen(path) + 1;
758cee86682Scalum 	dss_path->path = kmem_alloc(len, KM_SLEEP);
759cee86682Scalum 	(void) strlcpy(dss_path->path, path, len);
760cee86682Scalum 
761cee86682Scalum 	/* associate with servinst */
762cee86682Scalum 	dss_path->sip = sip;
763cee86682Scalum 	dss_path->index = index;
764cee86682Scalum 
765cee86682Scalum 	/*
766cee86682Scalum 	 * Add to list of served paths.
767cee86682Scalum 	 * No locking required, as we're only ever called at startup.
768cee86682Scalum 	 */
769*0dfe541eSEvan Layton 	if (nsrv4->dss_pathlist == NULL) {
770cee86682Scalum 		/* this is the first dss_path_t */
7717c478bd9Sstevel@tonic-gate 
772cee86682Scalum 		/* needed for insque/remque */
773cee86682Scalum 		dss_path->next = dss_path->prev = dss_path;
774cee86682Scalum 
775*0dfe541eSEvan Layton 		nsrv4->dss_pathlist = dss_path;
776cee86682Scalum 	} else {
777*0dfe541eSEvan Layton 		insque(dss_path, nsrv4->dss_pathlist);
778cee86682Scalum 	}
779cee86682Scalum 
780cee86682Scalum 	return (dss_path);
7817c478bd9Sstevel@tonic-gate }
7827c478bd9Sstevel@tonic-gate 
7837c478bd9Sstevel@tonic-gate /*
7847c478bd9Sstevel@tonic-gate  * Create a new server instance, and make it the currently active instance.
7857c478bd9Sstevel@tonic-gate  * Note that starting the grace period too early will reduce the clients'
7867c478bd9Sstevel@tonic-gate  * recovery window.
7877c478bd9Sstevel@tonic-gate  */
7887c478bd9Sstevel@tonic-gate void
rfs4_servinst_create(nfs4_srv_t * nsrv4,int start_grace,int dss_npaths,char ** dss_paths)789*0dfe541eSEvan Layton rfs4_servinst_create(nfs4_srv_t *nsrv4, int start_grace,
790*0dfe541eSEvan Layton     int dss_npaths, char **dss_paths)
7917c478bd9Sstevel@tonic-gate {
792cee86682Scalum 	unsigned i;
7937c478bd9Sstevel@tonic-gate 	rfs4_servinst_t *sip;
794cee86682Scalum 	rfs4_oldstate_t *oldstate;
7957c478bd9Sstevel@tonic-gate 
7967c478bd9Sstevel@tonic-gate 	sip = kmem_alloc(sizeof (rfs4_servinst_t), KM_SLEEP);
7977c478bd9Sstevel@tonic-gate 	rw_init(&sip->rwlock, NULL, RW_DEFAULT, NULL);
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate 	sip->start_time = (time_t)0;
8007c478bd9Sstevel@tonic-gate 	sip->grace_period = (time_t)0;
8017c478bd9Sstevel@tonic-gate 	sip->next = NULL;
8027c478bd9Sstevel@tonic-gate 	sip->prev = NULL;
8037c478bd9Sstevel@tonic-gate 
804cee86682Scalum 	rw_init(&sip->oldstate_lock, NULL, RW_DEFAULT, NULL);
805cee86682Scalum 	/*
806cee86682Scalum 	 * This initial dummy entry is required to setup for insque/remque.
807cee86682Scalum 	 * It must be skipped over whenever the list is traversed.
808cee86682Scalum 	 */
809cee86682Scalum 	oldstate = kmem_alloc(sizeof (rfs4_oldstate_t), KM_SLEEP);
810cee86682Scalum 	/* insque/remque require initial list entry to be self-terminated */
811cee86682Scalum 	oldstate->next = oldstate;
812