xref: /freebsd/sys/fs/nfsserver/nfs_nfsdsocket.c (revision 1b819cf2)
19ec7b004SRick Macklem /*-
29ec7b004SRick Macklem  * Copyright (c) 1989, 1993
39ec7b004SRick Macklem  *	The Regents of the University of California.  All rights reserved.
49ec7b004SRick Macklem  *
59ec7b004SRick Macklem  * This code is derived from software contributed to Berkeley by
69ec7b004SRick Macklem  * Rick Macklem at The University of Guelph.
79ec7b004SRick Macklem  *
89ec7b004SRick Macklem  * Redistribution and use in source and binary forms, with or without
99ec7b004SRick Macklem  * modification, are permitted provided that the following conditions
109ec7b004SRick Macklem  * are met:
119ec7b004SRick Macklem  * 1. Redistributions of source code must retain the above copyright
129ec7b004SRick Macklem  *    notice, this list of conditions and the following disclaimer.
139ec7b004SRick Macklem  * 2. Redistributions in binary form must reproduce the above copyright
149ec7b004SRick Macklem  *    notice, this list of conditions and the following disclaimer in the
159ec7b004SRick Macklem  *    documentation and/or other materials provided with the distribution.
169ec7b004SRick Macklem  * 4. Neither the name of the University nor the names of its contributors
179ec7b004SRick Macklem  *    may be used to endorse or promote products derived from this software
189ec7b004SRick Macklem  *    without specific prior written permission.
199ec7b004SRick Macklem  *
209ec7b004SRick Macklem  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
219ec7b004SRick Macklem  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
229ec7b004SRick Macklem  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
239ec7b004SRick Macklem  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
249ec7b004SRick Macklem  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
259ec7b004SRick Macklem  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
269ec7b004SRick Macklem  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
279ec7b004SRick Macklem  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
289ec7b004SRick Macklem  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
299ec7b004SRick Macklem  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
309ec7b004SRick Macklem  * SUCH DAMAGE.
319ec7b004SRick Macklem  *
329ec7b004SRick Macklem  */
339ec7b004SRick Macklem 
349ec7b004SRick Macklem #include <sys/cdefs.h>
359ec7b004SRick Macklem __FBSDID("$FreeBSD$");
369ec7b004SRick Macklem 
379ec7b004SRick Macklem /*
389ec7b004SRick Macklem  * Socket operations for use by the nfs server.
399ec7b004SRick Macklem  */
409ec7b004SRick Macklem 
419ec7b004SRick Macklem #ifndef APPLEKEXT
429ec7b004SRick Macklem #include <fs/nfs/nfsport.h>
439ec7b004SRick Macklem 
441b819cf2SRick Macklem extern struct nfsstatsv1 nfsstatsv1;
459ec7b004SRick Macklem extern struct nfsrvfh nfs_pubfh, nfs_rootfh;
469ec7b004SRick Macklem extern int nfs_pubfhset, nfs_rootfhset;
479ec7b004SRick Macklem extern struct nfsv4lock nfsv4rootfs_lock;
489ec7b004SRick Macklem extern struct nfsrv_stablefirst nfsrv_stablefirst;
491f54e596SRick Macklem extern struct nfsclienthashhead *nfsclienthash;
501f54e596SRick Macklem extern int nfsrv_clienthashsize;
519ec7b004SRick Macklem extern int nfsrc_floodlevel, nfsrc_tcpsavedreplies;
52c59e4cc3SRick Macklem extern int nfsd_debuglevel;
539ec7b004SRick Macklem NFSV4ROOTLOCKMUTEX;
549ec7b004SRick Macklem NFSSTATESPINLOCK;
559ec7b004SRick Macklem 
569ec7b004SRick Macklem int (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *,
579ec7b004SRick Macklem     int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = {
589ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
599ec7b004SRick Macklem 	nfsrvd_getattr,
609ec7b004SRick Macklem 	nfsrvd_setattr,
619ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
629ec7b004SRick Macklem 	nfsrvd_access,
639ec7b004SRick Macklem 	nfsrvd_readlink,
649ec7b004SRick Macklem 	nfsrvd_read,
659ec7b004SRick Macklem 	nfsrvd_write,
669ec7b004SRick Macklem 	nfsrvd_create,
679ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
689ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
699ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
709ec7b004SRick Macklem 	nfsrvd_remove,
719ec7b004SRick Macklem 	nfsrvd_remove,
729ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
739ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
749ec7b004SRick Macklem 	nfsrvd_readdir,
759ec7b004SRick Macklem 	nfsrvd_readdirplus,
769ec7b004SRick Macklem 	nfsrvd_statfs,
779ec7b004SRick Macklem 	nfsrvd_fsinfo,
789ec7b004SRick Macklem 	nfsrvd_pathconf,
799ec7b004SRick Macklem 	nfsrvd_commit,
809ec7b004SRick Macklem };
819ec7b004SRick Macklem 
829ec7b004SRick Macklem int (*nfsrv3_procs1[NFS_V3NPROCS])(struct nfsrv_descript *,
839ec7b004SRick Macklem     int, vnode_t , vnode_t *, fhandle_t *,
849ec7b004SRick Macklem     NFSPROC_T *, struct nfsexstuff *) = {
859ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
869ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
879ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
889ec7b004SRick Macklem 	nfsrvd_lookup,
899ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
909ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
919ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
929ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
939ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
949ec7b004SRick Macklem 	nfsrvd_mkdir,
959ec7b004SRick Macklem 	nfsrvd_symlink,
969ec7b004SRick Macklem 	nfsrvd_mknod,
979ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
989ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
999ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
1009ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
1019ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
1029ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
1039ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
1049ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
1059ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
1069ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
1079ec7b004SRick Macklem };
1089ec7b004SRick Macklem 
1099ec7b004SRick Macklem int (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *,
1109ec7b004SRick Macklem     int, vnode_t , vnode_t , NFSPROC_T *,
1119ec7b004SRick Macklem     struct nfsexstuff *, struct nfsexstuff *) = {
1129ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1139ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1149ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1159ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1169ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1179ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1189ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1199ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1209ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1219ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1229ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1239ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1249ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1259ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1269ec7b004SRick Macklem 	nfsrvd_rename,
1279ec7b004SRick Macklem 	nfsrvd_link,
1289ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1299ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1309ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1319ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1329ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1339ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1349ec7b004SRick Macklem };
1359ec7b004SRick Macklem 
136c59e4cc3SRick Macklem int (*nfsrv4_ops0[NFSV41_NOPS])(struct nfsrv_descript *,
1379ec7b004SRick Macklem     int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = {
1389ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1399ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1409ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1419ec7b004SRick Macklem 	nfsrvd_access,
1429ec7b004SRick Macklem 	nfsrvd_close,
1439ec7b004SRick Macklem 	nfsrvd_commit,
1449ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1459ec7b004SRick Macklem 	nfsrvd_delegpurge,
1469ec7b004SRick Macklem 	nfsrvd_delegreturn,
1479ec7b004SRick Macklem 	nfsrvd_getattr,
1489ec7b004SRick Macklem 	nfsrvd_getfh,
1499ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1509ec7b004SRick Macklem 	nfsrvd_lock,
1519ec7b004SRick Macklem 	nfsrvd_lockt,
1529ec7b004SRick Macklem 	nfsrvd_locku,
1539ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1549ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1559ec7b004SRick Macklem 	nfsrvd_verify,
1569ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1579ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1589ec7b004SRick Macklem 	nfsrvd_openconfirm,
1599ec7b004SRick Macklem 	nfsrvd_opendowngrade,
1609ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1619ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1629ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1639ec7b004SRick Macklem 	nfsrvd_read,
1649ec7b004SRick Macklem 	nfsrvd_readdirplus,
1659ec7b004SRick Macklem 	nfsrvd_readlink,
1669ec7b004SRick Macklem 	nfsrvd_remove,
1679ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1689ec7b004SRick Macklem 	nfsrvd_renew,
1699ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1709ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1719ec7b004SRick Macklem 	nfsrvd_secinfo,
1729ec7b004SRick Macklem 	nfsrvd_setattr,
1739ec7b004SRick Macklem 	nfsrvd_setclientid,
1749ec7b004SRick Macklem 	nfsrvd_setclientidcfrm,
1759ec7b004SRick Macklem 	nfsrvd_verify,
1769ec7b004SRick Macklem 	nfsrvd_write,
1779ec7b004SRick Macklem 	nfsrvd_releaselckown,
178c59e4cc3SRick Macklem 	nfsrvd_notsupp,
179c59e4cc3SRick Macklem 	nfsrvd_notsupp,
180c59e4cc3SRick Macklem 	nfsrvd_exchangeid,
181c59e4cc3SRick Macklem 	nfsrvd_createsession,
182c59e4cc3SRick Macklem 	nfsrvd_destroysession,
183c59e4cc3SRick Macklem 	nfsrvd_freestateid,
184c59e4cc3SRick Macklem 	nfsrvd_notsupp,
185c59e4cc3SRick Macklem 	nfsrvd_notsupp,
186c59e4cc3SRick Macklem 	nfsrvd_notsupp,
187c59e4cc3SRick Macklem 	nfsrvd_notsupp,
188c59e4cc3SRick Macklem 	nfsrvd_notsupp,
189c59e4cc3SRick Macklem 	nfsrvd_notsupp,
190c59e4cc3SRick Macklem 	nfsrvd_notsupp,
191c59e4cc3SRick Macklem 	nfsrvd_sequence,
192c59e4cc3SRick Macklem 	nfsrvd_notsupp,
193c59e4cc3SRick Macklem 	nfsrvd_notsupp,
194c59e4cc3SRick Macklem 	nfsrvd_notsupp,
195c59e4cc3SRick Macklem 	nfsrvd_destroyclientid,
196c59e4cc3SRick Macklem 	nfsrvd_reclaimcomplete,
1979ec7b004SRick Macklem };
1989ec7b004SRick Macklem 
199c59e4cc3SRick Macklem int (*nfsrv4_ops1[NFSV41_NOPS])(struct nfsrv_descript *,
2009ec7b004SRick Macklem     int, vnode_t , vnode_t *, fhandle_t *,
2019ec7b004SRick Macklem     NFSPROC_T *, struct nfsexstuff *) = {
2029ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2039ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2049ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2059ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2069ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2079ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2089ec7b004SRick Macklem 	nfsrvd_mknod,
2099ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2109ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2119ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2129ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2139ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2149ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2159ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2169ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2179ec7b004SRick Macklem 	nfsrvd_lookup,
2189ec7b004SRick Macklem 	nfsrvd_lookup,
2199ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2209ec7b004SRick Macklem 	nfsrvd_open,
2219ec7b004SRick Macklem 	nfsrvd_openattr,
2229ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2239ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2249ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2259ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2269ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2279ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2289ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2299ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2309ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2319ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2329ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2339ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2349ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2359ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2369ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2379ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2389ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2399ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2409ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2419ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
242c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
243c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
244c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
245c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
246c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
247c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
248c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
249c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
250c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
251c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
252c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
253c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
254c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
255c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
256c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
257c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
258c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
259c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
260c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2619ec7b004SRick Macklem };
2629ec7b004SRick Macklem 
263c59e4cc3SRick Macklem int (*nfsrv4_ops2[NFSV41_NOPS])(struct nfsrv_descript *,
2649ec7b004SRick Macklem     int, vnode_t , vnode_t , NFSPROC_T *,
2659ec7b004SRick Macklem     struct nfsexstuff *, struct nfsexstuff *) = {
2669ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2679ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2689ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2699ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2709ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2719ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2729ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2739ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2749ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2759ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2769ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2779ec7b004SRick Macklem 	nfsrvd_link,
2789ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2799ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2809ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2819ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2829ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2839ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2849ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2859ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2869ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2879ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2889ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2899ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2909ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2919ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2929ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2939ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2949ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2959ec7b004SRick Macklem 	nfsrvd_rename,
2969ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2979ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2989ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2999ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
3009ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
3019ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
3029ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
3039ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
3049ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
3059ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
306c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
307c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
308c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
309c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
310c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
311c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
312c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
313c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
314c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
315c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
316c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
317c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
318c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
319c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
320c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
321c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
322c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
323c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
324c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
3259ec7b004SRick Macklem };
3269ec7b004SRick Macklem #endif	/* !APPLEKEXT */
3279ec7b004SRick Macklem 
3289ec7b004SRick Macklem /*
3299ec7b004SRick Macklem  * Static array that defines which nfs rpc's are nonidempotent
3309ec7b004SRick Macklem  */
3319ec7b004SRick Macklem static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
3329ec7b004SRick Macklem 	FALSE,
3339ec7b004SRick Macklem 	FALSE,
3349ec7b004SRick Macklem 	TRUE,
3359ec7b004SRick Macklem 	FALSE,
3369ec7b004SRick Macklem 	FALSE,
3379ec7b004SRick Macklem 	FALSE,
3389ec7b004SRick Macklem 	FALSE,
3399ec7b004SRick Macklem 	TRUE,
3409ec7b004SRick Macklem 	TRUE,
3419ec7b004SRick Macklem 	TRUE,
3429ec7b004SRick Macklem 	TRUE,
3439ec7b004SRick Macklem 	TRUE,
3449ec7b004SRick Macklem 	TRUE,
3459ec7b004SRick Macklem 	TRUE,
3469ec7b004SRick Macklem 	TRUE,
3479ec7b004SRick Macklem 	TRUE,
3489ec7b004SRick Macklem 	FALSE,
3499ec7b004SRick Macklem 	FALSE,
3509ec7b004SRick Macklem 	FALSE,
3519ec7b004SRick Macklem 	FALSE,
3529ec7b004SRick Macklem 	FALSE,
3539ec7b004SRick Macklem 	FALSE,
3549ec7b004SRick Macklem };
3559ec7b004SRick Macklem 
3569ec7b004SRick Macklem /*
3579ec7b004SRick Macklem  * This static array indicates whether or not the RPC modifies the
3589ec7b004SRick Macklem  * file system.
3599ec7b004SRick Macklem  */
3609ec7b004SRick Macklem static int nfs_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0,
3619ec7b004SRick Macklem     1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
3629ec7b004SRick Macklem     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
3639ec7b004SRick Macklem 
3649ec7b004SRick Macklem /* local functions */
3659ec7b004SRick Macklem static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
366c59e4cc3SRick Macklem     u_char *tag, int taglen, u_int32_t minorvers, NFSPROC_T *p);
3679ec7b004SRick Macklem 
3689ec7b004SRick Macklem 
3699ec7b004SRick Macklem /*
3709ec7b004SRick Macklem  * This static array indicates which server procedures require the extra
3719ec7b004SRick Macklem  * arguments to return the current file handle for V2, 3.
3729ec7b004SRick Macklem  */
3739ec7b004SRick Macklem static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
3749ec7b004SRick Macklem 	1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
3759ec7b004SRick Macklem 
376c59e4cc3SRick Macklem extern struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS];
3779ec7b004SRick Macklem 
3789ec7b004SRick Macklem static int nfsv3to4op[NFS_V3NPROCS] = {
3799ec7b004SRick Macklem 	NFSPROC_NULL,
3809ec7b004SRick Macklem 	NFSV4OP_GETATTR,
3819ec7b004SRick Macklem 	NFSV4OP_SETATTR,
3829ec7b004SRick Macklem 	NFSV4OP_LOOKUP,
3839ec7b004SRick Macklem 	NFSV4OP_ACCESS,
3849ec7b004SRick Macklem 	NFSV4OP_READLINK,
3859ec7b004SRick Macklem 	NFSV4OP_READ,
3869ec7b004SRick Macklem 	NFSV4OP_WRITE,
3879ec7b004SRick Macklem 	NFSV4OP_V3CREATE,
3889ec7b004SRick Macklem 	NFSV4OP_MKDIR,
3899ec7b004SRick Macklem 	NFSV4OP_SYMLINK,
3909ec7b004SRick Macklem 	NFSV4OP_MKNOD,
3919ec7b004SRick Macklem 	NFSV4OP_REMOVE,
3929ec7b004SRick Macklem 	NFSV4OP_RMDIR,
3939ec7b004SRick Macklem 	NFSV4OP_RENAME,
3949ec7b004SRick Macklem 	NFSV4OP_LINK,
3959ec7b004SRick Macklem 	NFSV4OP_READDIR,
3969ec7b004SRick Macklem 	NFSV4OP_READDIRPLUS,
3979ec7b004SRick Macklem 	NFSV4OP_FSSTAT,
3989ec7b004SRick Macklem 	NFSV4OP_FSINFO,
3999ec7b004SRick Macklem 	NFSV4OP_PATHCONF,
4009ec7b004SRick Macklem 	NFSV4OP_COMMIT,
4019ec7b004SRick Macklem };
4029ec7b004SRick Macklem 
4031b819cf2SRick Macklem static struct mtx nfsrvd_statmtx;
4041b819cf2SRick Macklem MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
4051b819cf2SRick Macklem 
4061b819cf2SRick Macklem static void
4071b819cf2SRick Macklem nfsrvd_statstart(int op, struct bintime *now)
4081b819cf2SRick Macklem {
4091b819cf2SRick Macklem 	if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
4101b819cf2SRick Macklem 		printf("%s: op %d invalid\n", __func__, op);
4111b819cf2SRick Macklem 		return;
4121b819cf2SRick Macklem 	}
4131b819cf2SRick Macklem 
4141b819cf2SRick Macklem 	mtx_lock(&nfsrvd_statmtx);
4151b819cf2SRick Macklem 	if (nfsstatsv1.srvstartcnt == nfsstatsv1.srvdonecnt) {
4161b819cf2SRick Macklem 		if (now != NULL)
4171b819cf2SRick Macklem 			nfsstatsv1.busyfrom = *now;
4181b819cf2SRick Macklem 		else
4191b819cf2SRick Macklem 			binuptime(&nfsstatsv1.busyfrom);
4201b819cf2SRick Macklem 
4211b819cf2SRick Macklem 	}
4221b819cf2SRick Macklem 	nfsstatsv1.srvrpccnt[op]++;
4231b819cf2SRick Macklem 	nfsstatsv1.srvstartcnt++;
4241b819cf2SRick Macklem 	mtx_unlock(&nfsrvd_statmtx);
4251b819cf2SRick Macklem 
4261b819cf2SRick Macklem }
4271b819cf2SRick Macklem 
4281b819cf2SRick Macklem static void
4291b819cf2SRick Macklem nfsrvd_statend(int op, uint64_t bytes, struct bintime *now,
4301b819cf2SRick Macklem     struct bintime *then)
4311b819cf2SRick Macklem {
4321b819cf2SRick Macklem 	struct bintime dt, lnow;
4331b819cf2SRick Macklem 
4341b819cf2SRick Macklem 	if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
4351b819cf2SRick Macklem 		printf("%s: op %d invalid\n", __func__, op);
4361b819cf2SRick Macklem 		return;
4371b819cf2SRick Macklem 	}
4381b819cf2SRick Macklem 
4391b819cf2SRick Macklem 	if (now == NULL) {
4401b819cf2SRick Macklem 		now = &lnow;
4411b819cf2SRick Macklem 		binuptime(now);
4421b819cf2SRick Macklem 	}
4431b819cf2SRick Macklem 
4441b819cf2SRick Macklem 	mtx_lock(&nfsrvd_statmtx);
4451b819cf2SRick Macklem 
4461b819cf2SRick Macklem 	nfsstatsv1.srvbytes[op] += bytes;
4471b819cf2SRick Macklem 	nfsstatsv1.srvops[op]++;
4481b819cf2SRick Macklem 
4491b819cf2SRick Macklem 	if (then != NULL) {
4501b819cf2SRick Macklem 		dt = *now;
4511b819cf2SRick Macklem 		bintime_sub(&dt, then);
4521b819cf2SRick Macklem 		bintime_add(&nfsstatsv1.srvduration[op], &dt);
4531b819cf2SRick Macklem 	}
4541b819cf2SRick Macklem 
4551b819cf2SRick Macklem 	dt = *now;
4561b819cf2SRick Macklem 	bintime_sub(&dt, &nfsstatsv1.busyfrom);
4571b819cf2SRick Macklem 	bintime_add(&nfsstatsv1.busytime, &dt);
4581b819cf2SRick Macklem 	nfsstatsv1.busyfrom = *now;
4591b819cf2SRick Macklem 
4601b819cf2SRick Macklem 	nfsstatsv1.srvdonecnt++;
4611b819cf2SRick Macklem 
4621b819cf2SRick Macklem 	mtx_unlock(&nfsrvd_statmtx);
4631b819cf2SRick Macklem }
4641b819cf2SRick Macklem 
4659ec7b004SRick Macklem /*
4669ec7b004SRick Macklem  * Do an RPC. Basically, get the file handles translated to vnode pointers
4679ec7b004SRick Macklem  * and then call the appropriate server routine. The server routines are
4689ec7b004SRick Macklem  * split into groups, based on whether they use a file handle or file
4699ec7b004SRick Macklem  * handle plus name or ...
4709ec7b004SRick Macklem  * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
4719ec7b004SRick Macklem  */
4729ec7b004SRick Macklem APPLESTATIC void
473c59e4cc3SRick Macklem nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
474c59e4cc3SRick Macklem     u_int32_t minorvers, NFSPROC_T *p)
4759ec7b004SRick Macklem {
47617891d00SRick Macklem 	int error = 0, lktype;
4779ec7b004SRick Macklem 	vnode_t vp;
4789ec7b004SRick Macklem 	mount_t mp = NULL;
4799ec7b004SRick Macklem 	struct nfsrvfh fh;
4809ec7b004SRick Macklem 	struct nfsexstuff nes;
4819ec7b004SRick Macklem 
4829ec7b004SRick Macklem 	/*
4839ec7b004SRick Macklem 	 * Get a locked vnode for the first file handle
4849ec7b004SRick Macklem 	 */
4859ec7b004SRick Macklem 	if (!(nd->nd_flag & ND_NFSV4)) {
486b38f7723SKonstantin Belousov 		KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
4879ec7b004SRick Macklem 		/*
4889ec7b004SRick Macklem 		 * For NFSv3, if the malloc/mget allocation is near limits,
4899ec7b004SRick Macklem 		 * return NFSERR_DELAY.
4909ec7b004SRick Macklem 		 */
4919ec7b004SRick Macklem 		if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
4929ec7b004SRick Macklem 			nd->nd_repstat = NFSERR_DELAY;
4939ec7b004SRick Macklem 			vp = NULL;
4949ec7b004SRick Macklem 		} else {
4959ec7b004SRick Macklem 			error = nfsrv_mtofh(nd, &fh);
4969ec7b004SRick Macklem 			if (error) {
4979ec7b004SRick Macklem 				if (error != EBADRPC)
4989ec7b004SRick Macklem 					printf("nfs dorpc err1=%d\n", error);
4999ec7b004SRick Macklem 				nd->nd_repstat = NFSERR_GARBAGE;
500a9285ae5SZack Kirsch 				goto out;
5019ec7b004SRick Macklem 			}
50217891d00SRick Macklem 			if (nd->nd_procnum == NFSPROC_READ ||
503d96b98a3SKenneth D. Merry 			    nd->nd_procnum == NFSPROC_WRITE ||
50417891d00SRick Macklem 			    nd->nd_procnum == NFSPROC_READDIR ||
5050c419e22SRick Macklem 			    nd->nd_procnum == NFSPROC_READDIRPLUS ||
50617891d00SRick Macklem 			    nd->nd_procnum == NFSPROC_READLINK ||
50717891d00SRick Macklem 			    nd->nd_procnum == NFSPROC_GETATTR ||
5080c419e22SRick Macklem 			    nd->nd_procnum == NFSPROC_ACCESS ||
5090c419e22SRick Macklem 			    nd->nd_procnum == NFSPROC_FSSTAT ||
5100c419e22SRick Macklem 			    nd->nd_procnum == NFSPROC_FSINFO)
51117891d00SRick Macklem 				lktype = LK_SHARED;
51217891d00SRick Macklem 			else
51317891d00SRick Macklem 				lktype = LK_EXCLUSIVE;
5149ec7b004SRick Macklem 			if (nd->nd_flag & ND_PUBLOOKUP)
51517891d00SRick Macklem 				nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
5169ec7b004SRick Macklem 				    &mp, nfs_writerpc[nd->nd_procnum], p);
5179ec7b004SRick Macklem 			else
51817891d00SRick Macklem 				nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
5199ec7b004SRick Macklem 				    &mp, nfs_writerpc[nd->nd_procnum], p);
5209ec7b004SRick Macklem 			if (nd->nd_repstat == NFSERR_PROGNOTV4)
521a9285ae5SZack Kirsch 				goto out;
5229ec7b004SRick Macklem 		}
5239ec7b004SRick Macklem 	}
5249ec7b004SRick Macklem 
5259ec7b004SRick Macklem 	/*
5269ec7b004SRick Macklem 	 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
5279ec7b004SRick Macklem 	 * cache, as required.
5289ec7b004SRick Macklem 	 * For V4, nfsrvd_compound() does this.
5299ec7b004SRick Macklem 	 */
5309ec7b004SRick Macklem 	if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
5319ec7b004SRick Macklem 		nd->nd_flag |= ND_SAVEREPLY;
5329ec7b004SRick Macklem 
5339ec7b004SRick Macklem 	nfsrvd_rephead(nd);
5349ec7b004SRick Macklem 	/*
5359ec7b004SRick Macklem 	 * If nd_repstat is non-zero, just fill in the reply status
5369ec7b004SRick Macklem 	 * to complete the RPC reply for V2. Otherwise, you must do
5379ec7b004SRick Macklem 	 * the RPC.
5389ec7b004SRick Macklem 	 */
5399ec7b004SRick Macklem 	if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
5409ec7b004SRick Macklem 		*nd->nd_errp = nfsd_errmap(nd);
5411b819cf2SRick Macklem 		nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], /*now*/ NULL);
5421b819cf2SRick Macklem 		nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
5431b819cf2SRick Macklem 		   /*now*/ NULL, /*then*/ NULL);
5448974bc2fSRick Macklem 		if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
5458974bc2fSRick Macklem 			vn_finished_write(mp);
546a9285ae5SZack Kirsch 		goto out;
5479ec7b004SRick Macklem 	}
5489ec7b004SRick Macklem 
5499ec7b004SRick Macklem 	/*
5509ec7b004SRick Macklem 	 * Now the procedure can be performed. For V4, nfsrvd_compound()
5519ec7b004SRick Macklem 	 * works through the sub-rpcs, otherwise just call the procedure.
5529ec7b004SRick Macklem 	 * The procedures are in three groups with different arguments.
5539ec7b004SRick Macklem 	 * The group is indicated by the value in nfs_retfh[].
5549ec7b004SRick Macklem 	 */
5559ec7b004SRick Macklem 	if (nd->nd_flag & ND_NFSV4) {
556c59e4cc3SRick Macklem 		nfsrvd_compound(nd, isdgram, tag, taglen, minorvers, p);
5579ec7b004SRick Macklem 	} else {
5581b819cf2SRick Macklem 		struct bintime start_time;
5591b819cf2SRick Macklem 
5601b819cf2SRick Macklem 		binuptime(&start_time);
5611b819cf2SRick Macklem 		nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], &start_time);
5621b819cf2SRick Macklem 
5639ec7b004SRick Macklem 		if (nfs_retfh[nd->nd_procnum] == 1) {
5649ec7b004SRick Macklem 			if (vp)
565c383087cSZack Kirsch 				NFSVOPUNLOCK(vp, 0);
5669ec7b004SRick Macklem 			error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
5679ec7b004SRick Macklem 			    vp, NULL, (fhandle_t *)fh.nfsrvfh_data, p, &nes);
5689ec7b004SRick Macklem 		} else if (nfs_retfh[nd->nd_procnum] == 2) {
5699ec7b004SRick Macklem 			error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
5709ec7b004SRick Macklem 			    vp, NULL, p, &nes, NULL);
5719ec7b004SRick Macklem 		} else {
5729ec7b004SRick Macklem 			error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
5739ec7b004SRick Macklem 			    vp, p, &nes);
5749ec7b004SRick Macklem 		}
5758974bc2fSRick Macklem 		if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
5768974bc2fSRick Macklem 			vn_finished_write(mp);
5771b819cf2SRick Macklem 
5781b819cf2SRick Macklem 		nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
5791b819cf2SRick Macklem 		    /*now*/ NULL, /*then*/ &start_time);
5809ec7b004SRick Macklem 	}
5819ec7b004SRick Macklem 	if (error) {
5829ec7b004SRick Macklem 		if (error != EBADRPC)
5839ec7b004SRick Macklem 			printf("nfs dorpc err2=%d\n", error);
5849ec7b004SRick Macklem 		nd->nd_repstat = NFSERR_GARBAGE;
5859ec7b004SRick Macklem 	}
5869ec7b004SRick Macklem 	*nd->nd_errp = nfsd_errmap(nd);
5879ec7b004SRick Macklem 
5889ec7b004SRick Macklem 	/*
5899ec7b004SRick Macklem 	 * Don't cache certain reply status values.
5909ec7b004SRick Macklem 	 */
5919ec7b004SRick Macklem 	if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
5929ec7b004SRick Macklem 	    (nd->nd_repstat == NFSERR_GARBAGE ||
5939ec7b004SRick Macklem 	     nd->nd_repstat == NFSERR_BADXDR ||
5949ec7b004SRick Macklem 	     nd->nd_repstat == NFSERR_MOVED ||
5959ec7b004SRick Macklem 	     nd->nd_repstat == NFSERR_DELAY ||
5969ec7b004SRick Macklem 	     nd->nd_repstat == NFSERR_BADSEQID ||
5979ec7b004SRick Macklem 	     nd->nd_repstat == NFSERR_RESOURCE ||
5989ec7b004SRick Macklem 	     nd->nd_repstat == NFSERR_SERVERFAULT ||
5999ec7b004SRick Macklem 	     nd->nd_repstat == NFSERR_STALECLIENTID ||
6009ec7b004SRick Macklem 	     nd->nd_repstat == NFSERR_STALESTATEID ||
6019ec7b004SRick Macklem 	     nd->nd_repstat == NFSERR_OLDSTATEID ||
6029ec7b004SRick Macklem 	     nd->nd_repstat == NFSERR_BADSTATEID ||
6039ec7b004SRick Macklem 	     nd->nd_repstat == NFSERR_GRACE ||
6049ec7b004SRick Macklem 	     nd->nd_repstat == NFSERR_NOGRACE))
6059ec7b004SRick Macklem 		nd->nd_flag &= ~ND_SAVEREPLY;
606a9285ae5SZack Kirsch 
607a9285ae5SZack Kirsch out:
608a9285ae5SZack Kirsch 	NFSEXITCODE2(0, nd);
6099ec7b004SRick Macklem }
6109ec7b004SRick Macklem 
6119ec7b004SRick Macklem /*
6129ec7b004SRick Macklem  * Breaks down a compound RPC request and calls the server routines for
6139ec7b004SRick Macklem  * the subprocedures.
6149ec7b004SRick Macklem  * Some suboperations are performed directly here to simplify file handle<-->
6159ec7b004SRick Macklem  * vnode pointer handling.
6169ec7b004SRick Macklem  */
6179ec7b004SRick Macklem static void
618c59e4cc3SRick Macklem nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
619c59e4cc3SRick Macklem     int taglen, u_int32_t minorvers, NFSPROC_T *p)
6209ec7b004SRick Macklem {
6211b819cf2SRick Macklem 	int i, lktype, op, op0 = 0, statsinprog = 0;
6229ec7b004SRick Macklem 	u_int32_t *tl;
6239ec7b004SRick Macklem 	struct nfsclient *clp, *nclp;
624c59e4cc3SRick Macklem 	int numops, error = 0, igotlock;
625c59e4cc3SRick Macklem 	u_int32_t retops = 0, *retopsp = NULL, *repp;
6269ec7b004SRick Macklem 	vnode_t vp, nvp, savevp;
6279ec7b004SRick Macklem 	struct nfsrvfh fh;
6288974bc2fSRick Macklem 	mount_t new_mp, temp_mp = NULL;
6299ec7b004SRick Macklem 	struct ucred *credanon;
6309ec7b004SRick Macklem 	struct nfsexstuff nes, vpnes, savevpnes;
6318974bc2fSRick Macklem 	fsid_t cur_fsid, save_fsid;
6329ec7b004SRick Macklem 	static u_int64_t compref = 0;
6331b819cf2SRick Macklem 	struct bintime start_time;
6349ec7b004SRick Macklem 
6359ec7b004SRick Macklem 	NFSVNO_EXINIT(&vpnes);
6369ec7b004SRick Macklem 	NFSVNO_EXINIT(&savevpnes);
6379ec7b004SRick Macklem 	/*
6389ec7b004SRick Macklem 	 * Put the seq# of the current compound RPC in nfsrv_descript.
6399ec7b004SRick Macklem 	 * (This is used by nfsrv_checkgetattr(), to see if the write
6409ec7b004SRick Macklem 	 *  delegation was created by the same compound RPC as the one
6419ec7b004SRick Macklem 	 *  with that Getattr in it.)
6429ec7b004SRick Macklem 	 * Don't worry about the 64bit number wrapping around. It ain't
6439ec7b004SRick Macklem 	 * gonna happen before this server gets shut down/rebooted.
6449ec7b004SRick Macklem 	 */
6459ec7b004SRick Macklem 	nd->nd_compref = compref++;
6469ec7b004SRick Macklem 
6479ec7b004SRick Macklem 	/*
6489ec7b004SRick Macklem 	 * Check for and optionally get a lock on the root. This lock means that
6499ec7b004SRick Macklem 	 * no nfsd will be fiddling with the V4 file system and state stuff. It
6509ec7b004SRick Macklem 	 * is required when the V4 root is being changed, the stable storage
6519ec7b004SRick Macklem 	 * restart file is being updated, or callbacks are being done.
6529ec7b004SRick Macklem 	 * When any of the nfsd are processing an NFSv4 compound RPC, they must
6539ec7b004SRick Macklem 	 * either hold a reference count (nfs_usecnt) or the lock. When
6549ec7b004SRick Macklem 	 * nfsrv_unlock() is called to release the lock, it can optionally
6559ec7b004SRick Macklem 	 * also get a reference count, which saves the need for a call to
6569ec7b004SRick Macklem 	 * nfsrv_getref() after nfsrv_unlock().
6579ec7b004SRick Macklem 	 */
6589ec7b004SRick Macklem 	/*
6599ec7b004SRick Macklem 	 * First, check to see if we need to wait for an update lock.
6609ec7b004SRick Macklem 	 */
6619ec7b004SRick Macklem 	igotlock = 0;
6629ec7b004SRick Macklem 	NFSLOCKV4ROOTMUTEX();
6639ec7b004SRick Macklem 	if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
6649ec7b004SRick Macklem 		igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
665ff29f3b2SRick Macklem 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
6669ec7b004SRick Macklem 	else
6679ec7b004SRick Macklem 		igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
668ff29f3b2SRick Macklem 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
6699ec7b004SRick Macklem 	NFSUNLOCKV4ROOTMUTEX();
6709ec7b004SRick Macklem 	if (igotlock) {
6719ec7b004SRick Macklem 		/*
6729ec7b004SRick Macklem 		 * If I got the lock, I can update the stable storage file.
6739ec7b004SRick Macklem 		 * Done when the grace period is over or a client has long
6749ec7b004SRick Macklem 		 * since expired.
6759ec7b004SRick Macklem 		 */
6769ec7b004SRick Macklem 		nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
6779ec7b004SRick Macklem 		if ((nfsrv_stablefirst.nsf_flags &
6789ec7b004SRick Macklem 		    (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
6799ec7b004SRick Macklem 			nfsrv_updatestable(p);
6809ec7b004SRick Macklem 
6819ec7b004SRick Macklem 		/*
6829ec7b004SRick Macklem 		 * If at least one client has long since expired, search
6839ec7b004SRick Macklem 		 * the client list for them, write a REVOKE record on the
6849ec7b004SRick Macklem 		 * stable storage file and then remove them from the client
6859ec7b004SRick Macklem 		 * list.
6869ec7b004SRick Macklem 		 */
6879ec7b004SRick Macklem 		if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) {
6889ec7b004SRick Macklem 			nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT;
6891f54e596SRick Macklem 			for (i = 0; i < nfsrv_clienthashsize; i++) {
6909ec7b004SRick Macklem 			    LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash,
6919ec7b004SRick Macklem 				nclp) {
6929ec7b004SRick Macklem 				if (clp->lc_flags & LCL_EXPIREIT) {
6939ec7b004SRick Macklem 				    if (!LIST_EMPTY(&clp->lc_open) ||
6949ec7b004SRick Macklem 					!LIST_EMPTY(&clp->lc_deleg))
6959ec7b004SRick Macklem 					nfsrv_writestable(clp->lc_id,
6969ec7b004SRick Macklem 					    clp->lc_idlen, NFSNST_REVOKE, p);
6979ec7b004SRick Macklem 				    nfsrv_cleanclient(clp, p);
6989ec7b004SRick Macklem 				    nfsrv_freedeleglist(&clp->lc_deleg);
6999ec7b004SRick Macklem 				    nfsrv_freedeleglist(&clp->lc_olddeleg);
7009ec7b004SRick Macklem 				    LIST_REMOVE(clp, lc_hash);
7019ec7b004SRick Macklem 				    nfsrv_zapclient(clp, p);
7029ec7b004SRick Macklem 				}
7039ec7b004SRick Macklem 			    }
7049ec7b004SRick Macklem 			}
7059ec7b004SRick Macklem 		}
7069ec7b004SRick Macklem 		NFSLOCKV4ROOTMUTEX();
7079ec7b004SRick Macklem 		nfsv4_unlock(&nfsv4rootfs_lock, 1);
7089ec7b004SRick Macklem 		NFSUNLOCKV4ROOTMUTEX();
7099ec7b004SRick Macklem 	} else {
7109ec7b004SRick Macklem 		/*
7119ec7b004SRick Macklem 		 * If we didn't get the lock, we need to get a refcnt,
7129ec7b004SRick Macklem 		 * which also checks for and waits for the lock.
7139ec7b004SRick Macklem 		 */
7149ec7b004SRick Macklem 		NFSLOCKV4ROOTMUTEX();
7159ec7b004SRick Macklem 		nfsv4_getref(&nfsv4rootfs_lock, NULL,
716ff29f3b2SRick Macklem 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
7179ec7b004SRick Macklem 		NFSUNLOCKV4ROOTMUTEX();
7189ec7b004SRick Macklem 	}
7199ec7b004SRick Macklem 
7209ec7b004SRick Macklem 	/*
7219ec7b004SRick Macklem 	 * If flagged, search for open owners that haven't had any opens
7229ec7b004SRick Macklem 	 * for a long time.
7239ec7b004SRick Macklem 	 */
7249ec7b004SRick Macklem 	if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
7259ec7b004SRick Macklem 		nfsrv_throwawayopens(p);
7269ec7b004SRick Macklem 	}
7279ec7b004SRick Macklem 
7289ec7b004SRick Macklem 	savevp = vp = NULL;
7298974bc2fSRick Macklem 	save_fsid.val[0] = save_fsid.val[1] = 0;
7308974bc2fSRick Macklem 	cur_fsid.val[0] = cur_fsid.val[1] = 0;
731c59e4cc3SRick Macklem 
732c59e4cc3SRick Macklem 	/* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
7339ec7b004SRick Macklem 	if (taglen < 0) {
7349ec7b004SRick Macklem 		error = EBADRPC;
7359ec7b004SRick Macklem 		goto nfsmout;
7369ec7b004SRick Macklem 	}
737c59e4cc3SRick Macklem 
7389ec7b004SRick Macklem 	(void) nfsm_strtom(nd, tag, taglen);
7399ec7b004SRick Macklem 	NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
740c59e4cc3SRick Macklem 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
741c59e4cc3SRick Macklem 	if (minorvers != NFSV4_MINORVERSION && minorvers != NFSV41_MINORVERSION)
7429ec7b004SRick Macklem 		nd->nd_repstat = NFSERR_MINORVERMISMATCH;
7439ec7b004SRick Macklem 	if (nd->nd_repstat)
7449ec7b004SRick Macklem 		numops = 0;
7459ec7b004SRick Macklem 	else
7469ec7b004SRick Macklem 		numops = fxdr_unsigned(int, *tl);
7479ec7b004SRick Macklem 	/*
7489ec7b004SRick Macklem 	 * Loop around doing the sub ops.
7499ec7b004SRick Macklem 	 * vp - is an unlocked vnode pointer for the CFH
7509ec7b004SRick Macklem 	 * savevp - is an unlocked vnode pointer for the SAVEDFH
7519ec7b004SRick Macklem 	 * (at some future date, it might turn out to be more appropriate
7529ec7b004SRick Macklem 	 *  to keep the file handles instead of vnode pointers?)
7539ec7b004SRick Macklem 	 * savevpnes and vpnes - are the export flags for the above.
7549ec7b004SRick Macklem 	 */
7559ec7b004SRick Macklem 	for (i = 0; i < numops; i++) {
7569ec7b004SRick Macklem 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
7579ec7b004SRick Macklem 		NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
7589183a2a3SRick Macklem 		*repp = *tl;
7599ec7b004SRick Macklem 		op = fxdr_unsigned(int, *tl);
760c59e4cc3SRick Macklem 		NFSD_DEBUG(4, "op=%d\n", op);
7611b819cf2SRick Macklem 
7621b819cf2SRick Macklem 		binuptime(&start_time);
7631b819cf2SRick Macklem 		nfsrvd_statstart(op, &start_time);
7641b819cf2SRick Macklem 		statsinprog = 1;
7651b819cf2SRick Macklem 
766c59e4cc3SRick Macklem 		if (op < NFSV4OP_ACCESS ||
767c59e4cc3SRick Macklem 		    (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
768c59e4cc3SRick Macklem 		    (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV41) != 0)) {
7699ec7b004SRick Macklem 			nd->nd_repstat = NFSERR_OPILLEGAL;
7709183a2a3SRick Macklem 			*repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
7719ec7b004SRick Macklem 			*repp = nfsd_errmap(nd);
7729ec7b004SRick Macklem 			retops++;
7739ec7b004SRick Macklem 			break;
7749183a2a3SRick Macklem 		} else {
7759183a2a3SRick Macklem 			repp++;
7769ec7b004SRick Macklem 		}
777c59e4cc3SRick Macklem 		if (i == 0)
778c59e4cc3SRick Macklem 			op0 = op;
779c59e4cc3SRick Macklem 		if (i == numops - 1)
780c59e4cc3SRick Macklem 			nd->nd_flag |= ND_LASTOP;
7819ec7b004SRick Macklem 
7829ec7b004SRick Macklem 		/*
7839ec7b004SRick Macklem 		 * Check for a referral on the current FH and, if so, return
7849ec7b004SRick Macklem 		 * NFSERR_MOVED for all ops that allow it, except Getattr.
7859ec7b004SRick Macklem 		 */
7869ec7b004SRick Macklem 		if (vp != NULL && op != NFSV4OP_GETATTR &&
7879ec7b004SRick Macklem 		    nfsv4root_getreferral(vp, NULL, 0) != NULL &&
7889ec7b004SRick Macklem 		    nfsrv_errmoved(op)) {
7899ec7b004SRick Macklem 			nd->nd_repstat = NFSERR_MOVED;
7909ec7b004SRick Macklem 			*repp = nfsd_errmap(nd);
7919ec7b004SRick Macklem 			retops++;
7929ec7b004SRick Macklem 			break;
7939ec7b004SRick Macklem 		}
7949ec7b004SRick Macklem 
795c59e4cc3SRick Macklem 		/*
796c59e4cc3SRick Macklem 		 * For NFSv4.1, check for a Sequence Operation being first
797c59e4cc3SRick Macklem 		 * or one of the other allowed operations by itself.
798c59e4cc3SRick Macklem 		 */
799c59e4cc3SRick Macklem 		if ((nd->nd_flag & ND_NFSV41) != 0) {
800c59e4cc3SRick Macklem 			if (i != 0 && op == NFSV4OP_SEQUENCE)
801c59e4cc3SRick Macklem 				nd->nd_repstat = NFSERR_SEQUENCEPOS;
802c59e4cc3SRick Macklem 			else if (i == 0 && op != NFSV4OP_SEQUENCE &&
803c59e4cc3SRick Macklem 			    op != NFSV4OP_EXCHANGEID &&
804c59e4cc3SRick Macklem 			    op != NFSV4OP_CREATESESSION &&
805c59e4cc3SRick Macklem 			    op != NFSV4OP_BINDCONNTOSESS &&
806c59e4cc3SRick Macklem 			    op != NFSV4OP_DESTROYCLIENTID &&
807c59e4cc3SRick Macklem 			    op != NFSV4OP_DESTROYSESSION)
808c59e4cc3SRick Macklem 				nd->nd_repstat = NFSERR_OPNOTINSESS;
809c59e4cc3SRick Macklem 			else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
810c59e4cc3SRick Macklem 				nd->nd_repstat = NFSERR_NOTONLYOP;
811c59e4cc3SRick Macklem 			if (nd->nd_repstat != 0) {
812c59e4cc3SRick Macklem 				*repp = nfsd_errmap(nd);
813c59e4cc3SRick Macklem 				retops++;
814c59e4cc3SRick Macklem 				break;
815c59e4cc3SRick Macklem 			}
816c59e4cc3SRick Macklem 		}
817c59e4cc3SRick Macklem 
8189ec7b004SRick Macklem 		nd->nd_procnum = op;
8199ec7b004SRick Macklem 		/*
8209ec7b004SRick Macklem 		 * If over flood level, reply NFSERR_RESOURCE, if at the first
8219ec7b004SRick Macklem 		 * Op. (Since a client recovery from NFSERR_RESOURCE can get
8229ec7b004SRick Macklem 		 * really nasty for certain Op sequences, I'll play it safe
8239ec7b004SRick Macklem 		 * and only return the error at the beginning.) The cache
8249ec7b004SRick Macklem 		 * will still function over flood level, but uses lots of
8259ec7b004SRick Macklem 		 * mbufs.)
8269ec7b004SRick Macklem 		 * If nfsrv_mallocmget_limit() returns True, the system is near
8279ec7b004SRick Macklem 		 * to its limit for memory that malloc()/mget() can allocate.
8289ec7b004SRick Macklem 		 */
829c59e4cc3SRick Macklem 		if (i == 0 && (nd->nd_rp == NULL ||
830c59e4cc3SRick Macklem 		    nd->nd_rp->rc_refcnt == 0) &&
8319ec7b004SRick Macklem 		    (nfsrv_mallocmget_limit() ||
8329ec7b004SRick Macklem 		     nfsrc_tcpsavedreplies > nfsrc_floodlevel)) {
83303738f60SRick Macklem 			if (nfsrc_tcpsavedreplies > nfsrc_floodlevel)
83403738f60SRick Macklem 				printf("nfsd server cache flooded, try "
83503738f60SRick Macklem 				    "increasing vfs.nfsd.tcphighwater\n");
8369ec7b004SRick Macklem 			nd->nd_repstat = NFSERR_RESOURCE;
8379ec7b004SRick Macklem 			*repp = nfsd_errmap(nd);
8389ec7b004SRick Macklem 			if (op == NFSV4OP_SETATTR) {
8399ec7b004SRick Macklem 				/*
8409ec7b004SRick Macklem 				 * Setattr replies require a bitmap.
8419ec7b004SRick Macklem 				 * even for errors like these.
8429ec7b004SRick Macklem 				 */
8439ec7b004SRick Macklem 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
8449ec7b004SRick Macklem 				*tl = 0;
8459ec7b004SRick Macklem 			}
8469ec7b004SRick Macklem 			retops++;
8479ec7b004SRick Macklem 			break;
8489ec7b004SRick Macklem 		}
8499ec7b004SRick Macklem 		if (nfsv4_opflag[op].savereply)
8509ec7b004SRick Macklem 			nd->nd_flag |= ND_SAVEREPLY;
8519ec7b004SRick Macklem 		switch (op) {
8529ec7b004SRick Macklem 		case NFSV4OP_PUTFH:
8539ec7b004SRick Macklem 			error = nfsrv_mtofh(nd, &fh);
8549ec7b004SRick Macklem 			if (error)
8559ec7b004SRick Macklem 				goto nfsmout;
8568974bc2fSRick Macklem 			if (!nd->nd_repstat)
8578974bc2fSRick Macklem 				nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
8588974bc2fSRick Macklem 				    NULL, 0, p);
8599ec7b004SRick Macklem 			/* For now, allow this for non-export FHs */
8609ec7b004SRick Macklem 			if (!nd->nd_repstat) {
8619ec7b004SRick Macklem 				if (vp)
8629ec7b004SRick Macklem 					vrele(vp);
8639ec7b004SRick Macklem 				vp = nvp;
8648974bc2fSRick Macklem 				cur_fsid = vp->v_mount->mnt_stat.f_fsid;
865a9989634SZack Kirsch 				NFSVOPUNLOCK(vp, 0);
8669ec7b004SRick Macklem 				vpnes = nes;
8679ec7b004SRick Macklem 			}
8689ec7b004SRick Macklem 			break;
8699ec7b004SRick Macklem 		case NFSV4OP_PUTPUBFH:
8708974bc2fSRick Macklem 			if (nfs_pubfhset)
87117891d00SRick Macklem 			    nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
8728974bc2fSRick Macklem 				&nes, NULL, 0, p);
8738974bc2fSRick Macklem 			else
8749ec7b004SRick Macklem 			    nd->nd_repstat = NFSERR_NOFILEHANDLE;
8759ec7b004SRick Macklem 			if (!nd->nd_repstat) {
8769ec7b004SRick Macklem 				if (vp)
8779ec7b004SRick Macklem 					vrele(vp);
8789ec7b004SRick Macklem 				vp = nvp;
8798974bc2fSRick Macklem 				cur_fsid = vp->v_mount->mnt_stat.f_fsid;
880a9989634SZack Kirsch 				NFSVOPUNLOCK(vp, 0);
8819ec7b004SRick Macklem 				vpnes = nes;
8829ec7b004SRick Macklem 			}
8839ec7b004SRick Macklem 			break;
8849ec7b004SRick Macklem 		case NFSV4OP_PUTROOTFH:
8859ec7b004SRick Macklem 			if (nfs_rootfhset) {
88617891d00SRick Macklem 				nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
8878974bc2fSRick Macklem 				    &nes, NULL, 0, p);
8889ec7b004SRick Macklem 				if (!nd->nd_repstat) {
8899ec7b004SRick Macklem 					if (vp)
8909ec7b004SRick Macklem 						vrele(vp);
8919ec7b004SRick Macklem 					vp = nvp;
8928974bc2fSRick Macklem 					cur_fsid = vp->v_mount->mnt_stat.f_fsid;
893a9989634SZack Kirsch 					NFSVOPUNLOCK(vp, 0);
8949ec7b004SRick Macklem 					vpnes = nes;
8959ec7b004SRick Macklem 				}
896c9aad40fSRick Macklem 			} else
8979ec7b004SRick Macklem 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
8989ec7b004SRick Macklem 			break;
8999ec7b004SRick Macklem 		case NFSV4OP_SAVEFH:
9009ec7b004SRick Macklem 			if (vp && NFSVNO_EXPORTED(&vpnes)) {
9019ec7b004SRick Macklem 				nd->nd_repstat = 0;
9029ec7b004SRick Macklem 				/* If vp == savevp, a no-op */
9039ec7b004SRick Macklem 				if (vp != savevp) {
9049ec7b004SRick Macklem 					if (savevp)
9059ec7b004SRick Macklem 						vrele(savevp);
9069ec7b004SRick Macklem 					VREF(vp);
9079ec7b004SRick Macklem 					savevp = vp;
9089ec7b004SRick Macklem 					savevpnes = vpnes;
9098974bc2fSRick Macklem 					save_fsid = cur_fsid;
9109ec7b004SRick Macklem 				}
9119ec7b004SRick Macklem 			} else {
9129ec7b004SRick Macklem 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
9139ec7b004SRick Macklem 			}
9149ec7b004SRick Macklem 			break;
9159ec7b004SRick Macklem 		case NFSV4OP_RESTOREFH:
9169ec7b004SRick Macklem 			if (savevp) {
9179ec7b004SRick Macklem 				nd->nd_repstat = 0;
9189ec7b004SRick Macklem 				/* If vp == savevp, a no-op */
9199ec7b004SRick Macklem 				if (vp != savevp) {
9209ec7b004SRick Macklem 					VREF(savevp);
9219ec7b004SRick Macklem 					vrele(vp);
9229ec7b004SRick Macklem 					vp = savevp;
9239ec7b004SRick Macklem 					vpnes = savevpnes;
9248974bc2fSRick Macklem 					cur_fsid = save_fsid;
9259ec7b004SRick Macklem 				}
9269ec7b004SRick Macklem 			} else {
9279ec7b004SRick Macklem 				nd->nd_repstat = NFSERR_RESTOREFH;
9289ec7b004SRick Macklem 			}
9299ec7b004SRick Macklem 			break;
9309ec7b004SRick Macklem 		default:
9319ec7b004SRick Macklem 		    /*
9329ec7b004SRick Macklem 		     * Allow a Lookup, Getattr, GetFH, Secinfo on an
9339ec7b004SRick Macklem 		     * non-exported directory if
9349ec7b004SRick Macklem 		     * nfs_rootfhset. Do I need to allow any other Ops?
9359ec7b004SRick Macklem 		     * (You can only have a non-exported vpnes if
9369ec7b004SRick Macklem 		     *  nfs_rootfhset is true. See nfsd_fhtovp())
9379ec7b004SRick Macklem 		     * Allow AUTH_SYS to be used for file systems
9389ec7b004SRick Macklem 		     * exported GSS only for certain Ops, to allow
9399ec7b004SRick Macklem 		     * clients to do mounts more easily.
9409ec7b004SRick Macklem 		     */
9419ec7b004SRick Macklem 		    if (nfsv4_opflag[op].needscfh && vp) {
9429ec7b004SRick Macklem 			if (!NFSVNO_EXPORTED(&vpnes) &&
9439ec7b004SRick Macklem 			    op != NFSV4OP_LOOKUP &&
9449ec7b004SRick Macklem 			    op != NFSV4OP_GETATTR &&
9459ec7b004SRick Macklem 			    op != NFSV4OP_GETFH &&
9465a55e04fSRick Macklem 			    op != NFSV4OP_ACCESS &&
9475a55e04fSRick Macklem 			    op != NFSV4OP_READLINK &&
9489ec7b004SRick Macklem 			    op != NFSV4OP_SECINFO)
9499ec7b004SRick Macklem 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
95098ad4453SRick Macklem 			else if (nfsvno_testexp(nd, &vpnes) &&
9519ec7b004SRick Macklem 			    op != NFSV4OP_LOOKUP &&
9529ec7b004SRick Macklem 			    op != NFSV4OP_GETFH &&
9539ec7b004SRick Macklem 			    op != NFSV4OP_GETATTR &&
9549ec7b004SRick Macklem 			    op != NFSV4OP_SECINFO)
9559ec7b004SRick Macklem 				nd->nd_repstat = NFSERR_WRONGSEC;
9569ec7b004SRick Macklem 			if (nd->nd_repstat) {
9579ec7b004SRick Macklem 				if (op == NFSV4OP_SETATTR) {
9589ec7b004SRick Macklem 				    /*
9599ec7b004SRick Macklem 				     * Setattr reply requires a bitmap
9609ec7b004SRick Macklem 				     * even for errors like these.
9619ec7b004SRick Macklem 				     */
9629ec7b004SRick Macklem 				    NFSM_BUILD(tl, u_int32_t *,
9639ec7b004SRick Macklem 					NFSX_UNSIGNED);
9649ec7b004SRick Macklem 				    *tl = 0;
9659ec7b004SRick Macklem 				}
9669ec7b004SRick Macklem 				break;
9679ec7b004SRick Macklem 			}
9689ec7b004SRick Macklem 		    }
9699ec7b004SRick Macklem 		    if (nfsv4_opflag[op].retfh == 1) {
9709ec7b004SRick Macklem 			if (!vp) {
9719ec7b004SRick Macklem 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
9729ec7b004SRick Macklem 				break;
9739ec7b004SRick Macklem 			}
9749ec7b004SRick Macklem 			VREF(vp);
9759ec7b004SRick Macklem 			if (nfsv4_opflag[op].modifyfs)
976785f073bSRick Macklem 				vn_start_write(vp, &temp_mp, V_WAIT);
9779ec7b004SRick Macklem 			error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
9789ec7b004SRick Macklem 			    &nvp, (fhandle_t *)fh.nfsrvfh_data, p, &vpnes);
9799ec7b004SRick Macklem 			if (!error && !nd->nd_repstat) {
9808974bc2fSRick Macklem 			    if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
9818974bc2fSRick Macklem 				new_mp = nvp->v_mount;
9828974bc2fSRick Macklem 				if (cur_fsid.val[0] !=
9838974bc2fSRick Macklem 				    new_mp->mnt_stat.f_fsid.val[0] ||
9848974bc2fSRick Macklem 				    cur_fsid.val[1] !=
9858974bc2fSRick Macklem 				    new_mp->mnt_stat.f_fsid.val[1]) {
9868974bc2fSRick Macklem 				    /* crossed a server mount point */
9878974bc2fSRick Macklem 				    nd->nd_repstat = nfsvno_checkexp(new_mp,
9889ec7b004SRick Macklem 					nd->nd_nam, &nes, &credanon);
9899ec7b004SRick Macklem 				    if (!nd->nd_repstat)
9909ec7b004SRick Macklem 					nd->nd_repstat = nfsd_excred(nd,
9919ec7b004SRick Macklem 					    &nes, credanon);
9925679fe19SAlexander Kabaev 				    if (credanon != NULL)
9935679fe19SAlexander Kabaev 					crfree(credanon);
9949ec7b004SRick Macklem 				    if (!nd->nd_repstat) {
9959ec7b004SRick Macklem 					vpnes = nes;
9968974bc2fSRick Macklem 					cur_fsid = new_mp->mnt_stat.f_fsid;
9979ec7b004SRick Macklem 				    }
9989ec7b004SRick Macklem 				}
99981f78d99SRick Macklem 				/* Lookup ops return a locked vnode */
1000a9989634SZack Kirsch 				NFSVOPUNLOCK(nvp, 0);
10018974bc2fSRick Macklem 			    }
10029ec7b004SRick Macklem 			    if (!nd->nd_repstat) {
10039ec7b004SRick Macklem 				    vrele(vp);
10049ec7b004SRick Macklem 				    vp = nvp;
100581f78d99SRick Macklem 			    } else
100681f78d99SRick Macklem 				    vrele(nvp);
10079ec7b004SRick Macklem 			}
10089ec7b004SRick Macklem 			if (nfsv4_opflag[op].modifyfs)
1009785f073bSRick Macklem 				vn_finished_write(temp_mp);
10109ec7b004SRick Macklem 		    } else if (nfsv4_opflag[op].retfh == 2) {
10119ec7b004SRick Macklem 			if (vp == NULL || savevp == NULL) {
10129ec7b004SRick Macklem 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
10139ec7b004SRick Macklem 				break;
10148974bc2fSRick Macklem 			} else if (cur_fsid.val[0] != save_fsid.val[0] ||
10158974bc2fSRick Macklem 			    cur_fsid.val[1] != save_fsid.val[1]) {
10169ec7b004SRick Macklem 				nd->nd_repstat = NFSERR_XDEV;
10179ec7b004SRick Macklem 				break;
10189ec7b004SRick Macklem 			}
10199ec7b004SRick Macklem 			if (nfsv4_opflag[op].modifyfs)
1020785f073bSRick Macklem 				vn_start_write(savevp, &temp_mp, V_WAIT);
102198f234f3SZack Kirsch 			if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
1022629fa50eSRick Macklem 				VREF(vp);
1023629fa50eSRick Macklem 				VREF(savevp);
1024629fa50eSRick Macklem 				error = (*(nfsrv4_ops2[op]))(nd, isdgram,
1025629fa50eSRick Macklem 				    savevp, vp, p, &savevpnes, &vpnes);
1026629fa50eSRick Macklem 			} else
1027629fa50eSRick Macklem 				nd->nd_repstat = NFSERR_PERM;
10289ec7b004SRick Macklem 			if (nfsv4_opflag[op].modifyfs)
1029785f073bSRick Macklem 				vn_finished_write(temp_mp);
10309ec7b004SRick Macklem 		    } else {
10319ec7b004SRick Macklem 			if (nfsv4_opflag[op].retfh != 0)
10329ec7b004SRick Macklem 				panic("nfsrvd_compound");
10339ec7b004SRick Macklem 			if (nfsv4_opflag[op].needscfh) {
103417891d00SRick Macklem 				if (vp != NULL) {
10350c419e22SRick Macklem 					lktype = nfsv4_opflag[op].lktype;
10360c419e22SRick Macklem 					if (nfsv4_opflag[op].modifyfs) {
1037785f073bSRick Macklem 						vn_start_write(vp, &temp_mp,
1038785f073bSRick Macklem 						    V_WAIT);
10390c419e22SRick Macklem 						if (op == NFSV4OP_WRITE &&
10400c419e22SRick Macklem 						    MNT_SHARED_WRITES(temp_mp))
10410c419e22SRick Macklem 							lktype = LK_SHARED;
10420c419e22SRick Macklem 					}
10430c419e22SRick Macklem 					if (NFSVOPLOCK(vp, lktype) == 0)
1044629fa50eSRick Macklem 						VREF(vp);
1045629fa50eSRick Macklem 					else
104617891d00SRick Macklem 						nd->nd_repstat = NFSERR_PERM;
1047629fa50eSRick Macklem 				} else {
10489ec7b004SRick Macklem 					nd->nd_repstat = NFSERR_NOFILEHANDLE;
10499ec7b004SRick Macklem 					if (op == NFSV4OP_SETATTR) {
10509ec7b004SRick Macklem 						/*
105117891d00SRick Macklem 						 * Setattr reply requires a
105217891d00SRick Macklem 						 * bitmap even for errors like
105317891d00SRick Macklem 						 * these.
10549ec7b004SRick Macklem 						 */
10559ec7b004SRick Macklem 						NFSM_BUILD(tl, u_int32_t *,
10569ec7b004SRick Macklem 						    NFSX_UNSIGNED);
10579ec7b004SRick Macklem 						*tl = 0;
10589ec7b004SRick Macklem 					}
10599ec7b004SRick Macklem 					break;
10609ec7b004SRick Macklem 				}
1061629fa50eSRick Macklem 				if (nd->nd_repstat == 0)
1062629fa50eSRick Macklem 					error = (*(nfsrv4_ops0[op]))(nd,
1063629fa50eSRick Macklem 					    isdgram, vp, p, &vpnes);
10649ec7b004SRick Macklem 				if (nfsv4_opflag[op].modifyfs)
1065785f073bSRick Macklem 					vn_finished_write(temp_mp);
10669ec7b004SRick Macklem 			} else {
10679ec7b004SRick Macklem 				error = (*(nfsrv4_ops0[op]))(nd, isdgram,
10689ec7b004SRick Macklem 				    NULL, p, &vpnes);
10699ec7b004SRick Macklem 			}
10709ec7b004SRick Macklem 		    }
107174b8d63dSPedro F. Giffuni 		}
10729ec7b004SRick Macklem 		if (error) {
10739ec7b004SRick Macklem 			if (error == EBADRPC || error == NFSERR_BADXDR) {
10749ec7b004SRick Macklem 				nd->nd_repstat = NFSERR_BADXDR;
10759ec7b004SRick Macklem 			} else {
10769ec7b004SRick Macklem 				nd->nd_repstat = error;
10779ec7b004SRick Macklem 				printf("nfsv4 comperr0=%d\n", error);
10789ec7b004SRick Macklem 			}
10799ec7b004SRick Macklem 			error = 0;
10809ec7b004SRick Macklem 		}
10811b819cf2SRick Macklem 
10821b819cf2SRick Macklem 		if (statsinprog != 0) {
10831b819cf2SRick Macklem 			nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
10841b819cf2SRick Macklem 			    /*then*/ &start_time);
10851b819cf2SRick Macklem 			statsinprog = 0;
10861b819cf2SRick Macklem 		}
10871b819cf2SRick Macklem 
10889ec7b004SRick Macklem 		retops++;
10899ec7b004SRick Macklem 		if (nd->nd_repstat) {
10909ec7b004SRick Macklem 			*repp = nfsd_errmap(nd);
10919ec7b004SRick Macklem 			break;
10929ec7b004SRick Macklem 		} else {
10939ec7b004SRick Macklem 			*repp = 0;	/* NFS4_OK */
10949ec7b004SRick Macklem 		}
10959ec7b004SRick Macklem 	}
10969ec7b004SRick Macklem nfsmout:
10971b819cf2SRick Macklem 	if (statsinprog != 0) {
10981b819cf2SRick Macklem 		nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
10991b819cf2SRick Macklem 		    /*then*/ &start_time);
11001b819cf2SRick Macklem 		statsinprog = 0;
11011b819cf2SRick Macklem 	}
11029ec7b004SRick Macklem 	if (error) {
11039ec7b004SRick Macklem 		if (error == EBADRPC || error == NFSERR_BADXDR)
11049ec7b004SRick Macklem 			nd->nd_repstat = NFSERR_BADXDR;
11059ec7b004SRick Macklem 		else
11069ec7b004SRick Macklem 			printf("nfsv4 comperr1=%d\n", error);
11079ec7b004SRick Macklem 	}
11089ec7b004SRick Macklem 	if (taglen == -1) {
11099ec7b004SRick Macklem 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
11109ec7b004SRick Macklem 		*tl++ = 0;
11119ec7b004SRick Macklem 		*tl = 0;
11129ec7b004SRick Macklem 	} else {
11139ec7b004SRick Macklem 		*retopsp = txdr_unsigned(retops);
11149ec7b004SRick Macklem 	}
11159ec7b004SRick Macklem 	if (vp)
11169ec7b004SRick Macklem 		vrele(vp);
11179ec7b004SRick Macklem 	if (savevp)
11189ec7b004SRick Macklem 		vrele(savevp);
11199ec7b004SRick Macklem 	NFSLOCKV4ROOTMUTEX();
11209ec7b004SRick Macklem 	nfsv4_relref(&nfsv4rootfs_lock);
11219ec7b004SRick Macklem 	NFSUNLOCKV4ROOTMUTEX();
1122a9285ae5SZack Kirsch 
1123a9285ae5SZack Kirsch 	NFSEXITCODE2(0, nd);
11249ec7b004SRick Macklem }
1125