Home | History | Annotate | Line # | Download | only in server
nfs_nfsdsocket.c revision 1.1
      1  1.1  dholland /*	$NetBSD: nfs_nfsdsocket.c,v 1.1 2013/09/30 07:19:47 dholland Exp $	*/
      2  1.1  dholland /*-
      3  1.1  dholland  * Copyright (c) 1989, 1993
      4  1.1  dholland  *	The Regents of the University of California.  All rights reserved.
      5  1.1  dholland  *
      6  1.1  dholland  * This code is derived from software contributed to Berkeley by
      7  1.1  dholland  * Rick Macklem at The University of Guelph.
      8  1.1  dholland  *
      9  1.1  dholland  * Redistribution and use in source and binary forms, with or without
     10  1.1  dholland  * modification, are permitted provided that the following conditions
     11  1.1  dholland  * are met:
     12  1.1  dholland  * 1. Redistributions of source code must retain the above copyright
     13  1.1  dholland  *    notice, this list of conditions and the following disclaimer.
     14  1.1  dholland  * 2. Redistributions in binary form must reproduce the above copyright
     15  1.1  dholland  *    notice, this list of conditions and the following disclaimer in the
     16  1.1  dholland  *    documentation and/or other materials provided with the distribution.
     17  1.1  dholland  * 4. Neither the name of the University nor the names of its contributors
     18  1.1  dholland  *    may be used to endorse or promote products derived from this software
     19  1.1  dholland  *    without specific prior written permission.
     20  1.1  dholland  *
     21  1.1  dholland  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     22  1.1  dholland  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23  1.1  dholland  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24  1.1  dholland  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     25  1.1  dholland  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26  1.1  dholland  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27  1.1  dholland  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28  1.1  dholland  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29  1.1  dholland  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30  1.1  dholland  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31  1.1  dholland  * SUCH DAMAGE.
     32  1.1  dholland  *
     33  1.1  dholland  */
     34  1.1  dholland 
     35  1.1  dholland #include <sys/cdefs.h>
     36  1.1  dholland /* __FBSDID("FreeBSD: head/sys/fs/nfsserver/nfs_nfsdsocket.c 249592 2013-04-17 21:00:22Z ken "); */
     37  1.1  dholland __RCSID("$NetBSD: nfs_nfsdsocket.c,v 1.1 2013/09/30 07:19:47 dholland Exp $");
     38  1.1  dholland 
     39  1.1  dholland /*
     40  1.1  dholland  * Socket operations for use by the nfs server.
     41  1.1  dholland  */
     42  1.1  dholland 
     43  1.1  dholland #ifndef APPLEKEXT
     44  1.1  dholland #include <fs/nfs/nfsport.h>
     45  1.1  dholland 
     46  1.1  dholland extern struct nfsstats newnfsstats;
     47  1.1  dholland extern struct nfsrvfh nfs_pubfh, nfs_rootfh;
     48  1.1  dholland extern int nfs_pubfhset, nfs_rootfhset;
     49  1.1  dholland extern struct nfsv4lock nfsv4rootfs_lock;
     50  1.1  dholland extern struct nfsrv_stablefirst nfsrv_stablefirst;
     51  1.1  dholland extern struct nfsclienthashhead nfsclienthash[NFSCLIENTHASHSIZE];
     52  1.1  dholland extern int nfsrc_floodlevel, nfsrc_tcpsavedreplies;
     53  1.1  dholland NFSV4ROOTLOCKMUTEX;
     54  1.1  dholland NFSSTATESPINLOCK;
     55  1.1  dholland 
     56  1.1  dholland int (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *,
     57  1.1  dholland     int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = {
     58  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
     59  1.1  dholland 	nfsrvd_getattr,
     60  1.1  dholland 	nfsrvd_setattr,
     61  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
     62  1.1  dholland 	nfsrvd_access,
     63  1.1  dholland 	nfsrvd_readlink,
     64  1.1  dholland 	nfsrvd_read,
     65  1.1  dholland 	nfsrvd_write,
     66  1.1  dholland 	nfsrvd_create,
     67  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
     68  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
     69  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
     70  1.1  dholland 	nfsrvd_remove,
     71  1.1  dholland 	nfsrvd_remove,
     72  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
     73  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
     74  1.1  dholland 	nfsrvd_readdir,
     75  1.1  dholland 	nfsrvd_readdirplus,
     76  1.1  dholland 	nfsrvd_statfs,
     77  1.1  dholland 	nfsrvd_fsinfo,
     78  1.1  dholland 	nfsrvd_pathconf,
     79  1.1  dholland 	nfsrvd_commit,
     80  1.1  dholland };
     81  1.1  dholland 
     82  1.1  dholland int (*nfsrv3_procs1[NFS_V3NPROCS])(struct nfsrv_descript *,
     83  1.1  dholland     int, vnode_t , vnode_t *, fhandle_t *,
     84  1.1  dholland     NFSPROC_T *, struct nfsexstuff *) = {
     85  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
     86  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
     87  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
     88  1.1  dholland 	nfsrvd_lookup,
     89  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
     90  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
     91  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
     92  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
     93  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
     94  1.1  dholland 	nfsrvd_mkdir,
     95  1.1  dholland 	nfsrvd_symlink,
     96  1.1  dholland 	nfsrvd_mknod,
     97  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
     98  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
     99  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    100  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    101  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    102  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    103  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    104  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    105  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    106  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    107  1.1  dholland };
    108  1.1  dholland 
    109  1.1  dholland int (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *,
    110  1.1  dholland     int, vnode_t , vnode_t , NFSPROC_T *,
    111  1.1  dholland     struct nfsexstuff *, struct nfsexstuff *) = {
    112  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    113  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    114  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    115  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    116  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    117  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    118  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    119  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    120  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    121  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    122  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    123  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    124  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    125  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    126  1.1  dholland 	nfsrvd_rename,
    127  1.1  dholland 	nfsrvd_link,
    128  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    129  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    130  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    131  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    132  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    133  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    134  1.1  dholland };
    135  1.1  dholland 
    136  1.1  dholland int (*nfsrv4_ops0[NFSV4OP_NOPS])(struct nfsrv_descript *,
    137  1.1  dholland     int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = {
    138  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    139  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    140  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    141  1.1  dholland 	nfsrvd_access,
    142  1.1  dholland 	nfsrvd_close,
    143  1.1  dholland 	nfsrvd_commit,
    144  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    145  1.1  dholland 	nfsrvd_delegpurge,
    146  1.1  dholland 	nfsrvd_delegreturn,
    147  1.1  dholland 	nfsrvd_getattr,
    148  1.1  dholland 	nfsrvd_getfh,
    149  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    150  1.1  dholland 	nfsrvd_lock,
    151  1.1  dholland 	nfsrvd_lockt,
    152  1.1  dholland 	nfsrvd_locku,
    153  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    154  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    155  1.1  dholland 	nfsrvd_verify,
    156  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    157  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    158  1.1  dholland 	nfsrvd_openconfirm,
    159  1.1  dholland 	nfsrvd_opendowngrade,
    160  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    161  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    162  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    163  1.1  dholland 	nfsrvd_read,
    164  1.1  dholland 	nfsrvd_readdirplus,
    165  1.1  dholland 	nfsrvd_readlink,
    166  1.1  dholland 	nfsrvd_remove,
    167  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    168  1.1  dholland 	nfsrvd_renew,
    169  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    170  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
    171  1.1  dholland 	nfsrvd_secinfo,
    172  1.1  dholland 	nfsrvd_setattr,
    173  1.1  dholland 	nfsrvd_setclientid,
    174  1.1  dholland 	nfsrvd_setclientidcfrm,
    175  1.1  dholland 	nfsrvd_verify,
    176  1.1  dholland 	nfsrvd_write,
    177  1.1  dholland 	nfsrvd_releaselckown,
    178  1.1  dholland };
    179  1.1  dholland 
    180  1.1  dholland int (*nfsrv4_ops1[NFSV4OP_NOPS])(struct nfsrv_descript *,
    181  1.1  dholland     int, vnode_t , vnode_t *, fhandle_t *,
    182  1.1  dholland     NFSPROC_T *, struct nfsexstuff *) = {
    183  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    184  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    185  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    186  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    187  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    188  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    189  1.1  dholland 	nfsrvd_mknod,
    190  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    191  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    192  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    193  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    194  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    195  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    196  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    197  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    198  1.1  dholland 	nfsrvd_lookup,
    199  1.1  dholland 	nfsrvd_lookup,
    200  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    201  1.1  dholland 	nfsrvd_open,
    202  1.1  dholland 	nfsrvd_openattr,
    203  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    204  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    205  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    206  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    207  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    208  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    209  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    210  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    211  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    212  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    213  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    214  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    215  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    216  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    217  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    218  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    219  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    220  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    221  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    222  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
    223  1.1  dholland };
    224  1.1  dholland 
    225  1.1  dholland int (*nfsrv4_ops2[NFSV4OP_NOPS])(struct nfsrv_descript *,
    226  1.1  dholland     int, vnode_t , vnode_t , NFSPROC_T *,
    227  1.1  dholland     struct nfsexstuff *, struct nfsexstuff *) = {
    228  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    229  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    230  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    231  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    232  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    233  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    234  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    235  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    236  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    237  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    238  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    239  1.1  dholland 	nfsrvd_link,
    240  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    241  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    242  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    243  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    244  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    245  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    246  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    247  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    248  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    249  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    250  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    251  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    252  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    253  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    254  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    255  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    256  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    257  1.1  dholland 	nfsrvd_rename,
    258  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    259  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    260  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    261  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    262  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    263  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    264  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    265  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    266  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    267  1.1  dholland 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
    268  1.1  dholland };
    269  1.1  dholland #endif	/* !APPLEKEXT */
    270  1.1  dholland 
    271  1.1  dholland /*
    272  1.1  dholland  * Static array that defines which nfs rpc's are nonidempotent
    273  1.1  dholland  */
    274  1.1  dholland static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
    275  1.1  dholland 	FALSE,
    276  1.1  dholland 	FALSE,
    277  1.1  dholland 	TRUE,
    278  1.1  dholland 	FALSE,
    279  1.1  dholland 	FALSE,
    280  1.1  dholland 	FALSE,
    281  1.1  dholland 	FALSE,
    282  1.1  dholland 	TRUE,
    283  1.1  dholland 	TRUE,
    284  1.1  dholland 	TRUE,
    285  1.1  dholland 	TRUE,
    286  1.1  dholland 	TRUE,
    287  1.1  dholland 	TRUE,
    288  1.1  dholland 	TRUE,
    289  1.1  dholland 	TRUE,
    290  1.1  dholland 	TRUE,
    291  1.1  dholland 	FALSE,
    292  1.1  dholland 	FALSE,
    293  1.1  dholland 	FALSE,
    294  1.1  dholland 	FALSE,
    295  1.1  dholland 	FALSE,
    296  1.1  dholland 	FALSE,
    297  1.1  dholland };
    298  1.1  dholland 
    299  1.1  dholland /*
    300  1.1  dholland  * This static array indicates whether or not the RPC modifies the
    301  1.1  dholland  * file system.
    302  1.1  dholland  */
    303  1.1  dholland static int nfs_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0,
    304  1.1  dholland     1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
    305  1.1  dholland     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
    306  1.1  dholland 
    307  1.1  dholland /* local functions */
    308  1.1  dholland static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
    309  1.1  dholland     NFSPROC_T *p);
    310  1.1  dholland 
    311  1.1  dholland 
    312  1.1  dholland /*
    313  1.1  dholland  * This static array indicates which server procedures require the extra
    314  1.1  dholland  * arguments to return the current file handle for V2, 3.
    315  1.1  dholland  */
    316  1.1  dholland static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
    317  1.1  dholland 	1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
    318  1.1  dholland 
    319  1.1  dholland extern struct nfsv4_opflag nfsv4_opflag[NFSV4OP_NOPS];
    320  1.1  dholland 
    321  1.1  dholland static int nfsv3to4op[NFS_V3NPROCS] = {
    322  1.1  dholland 	NFSPROC_NULL,
    323  1.1  dholland 	NFSV4OP_GETATTR,
    324  1.1  dholland 	NFSV4OP_SETATTR,
    325  1.1  dholland 	NFSV4OP_LOOKUP,
    326  1.1  dholland 	NFSV4OP_ACCESS,
    327  1.1  dholland 	NFSV4OP_READLINK,
    328  1.1  dholland 	NFSV4OP_READ,
    329  1.1  dholland 	NFSV4OP_WRITE,
    330  1.1  dholland 	NFSV4OP_V3CREATE,
    331  1.1  dholland 	NFSV4OP_MKDIR,
    332  1.1  dholland 	NFSV4OP_SYMLINK,
    333  1.1  dholland 	NFSV4OP_MKNOD,
    334  1.1  dholland 	NFSV4OP_REMOVE,
    335  1.1  dholland 	NFSV4OP_RMDIR,
    336  1.1  dholland 	NFSV4OP_RENAME,
    337  1.1  dholland 	NFSV4OP_LINK,
    338  1.1  dholland 	NFSV4OP_READDIR,
    339  1.1  dholland 	NFSV4OP_READDIRPLUS,
    340  1.1  dholland 	NFSV4OP_FSSTAT,
    341  1.1  dholland 	NFSV4OP_FSINFO,
    342  1.1  dholland 	NFSV4OP_PATHCONF,
    343  1.1  dholland 	NFSV4OP_COMMIT,
    344  1.1  dholland };
    345  1.1  dholland 
    346  1.1  dholland /*
    347  1.1  dholland  * Do an RPC. Basically, get the file handles translated to vnode pointers
    348  1.1  dholland  * and then call the appropriate server routine. The server routines are
    349  1.1  dholland  * split into groups, based on whether they use a file handle or file
    350  1.1  dholland  * handle plus name or ...
    351  1.1  dholland  * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
    352  1.1  dholland  */
    353  1.1  dholland APPLESTATIC void
    354  1.1  dholland nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram,
    355  1.1  dholland     NFSPROC_T *p)
    356  1.1  dholland {
    357  1.1  dholland 	int error = 0, lktype;
    358  1.1  dholland 	vnode_t vp;
    359  1.1  dholland 	mount_t mp = NULL;
    360  1.1  dholland 	struct nfsrvfh fh;
    361  1.1  dholland 	struct nfsexstuff nes;
    362  1.1  dholland 
    363  1.1  dholland 	/*
    364  1.1  dholland 	 * Get a locked vnode for the first file handle
    365  1.1  dholland 	 */
    366  1.1  dholland 	if (!(nd->nd_flag & ND_NFSV4)) {
    367  1.1  dholland 		KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
    368  1.1  dholland 		/*
    369  1.1  dholland 		 * For NFSv3, if the malloc/mget allocation is near limits,
    370  1.1  dholland 		 * return NFSERR_DELAY.
    371  1.1  dholland 		 */
    372  1.1  dholland 		if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
    373  1.1  dholland 			nd->nd_repstat = NFSERR_DELAY;
    374  1.1  dholland 			vp = NULL;
    375  1.1  dholland 		} else {
    376  1.1  dholland 			error = nfsrv_mtofh(nd, &fh);
    377  1.1  dholland 			if (error) {
    378  1.1  dholland 				if (error != EBADRPC)
    379  1.1  dholland 					printf("nfs dorpc err1=%d\n", error);
    380  1.1  dholland 				nd->nd_repstat = NFSERR_GARBAGE;
    381  1.1  dholland 				goto out;
    382  1.1  dholland 			}
    383  1.1  dholland 			if (nd->nd_procnum == NFSPROC_READ ||
    384  1.1  dholland 			    nd->nd_procnum == NFSPROC_WRITE ||
    385  1.1  dholland 			    nd->nd_procnum == NFSPROC_READDIR ||
    386  1.1  dholland 			    nd->nd_procnum == NFSPROC_READLINK ||
    387  1.1  dholland 			    nd->nd_procnum == NFSPROC_GETATTR ||
    388  1.1  dholland 			    nd->nd_procnum == NFSPROC_ACCESS)
    389  1.1  dholland 				lktype = LK_SHARED;
    390  1.1  dholland 			else
    391  1.1  dholland 				lktype = LK_EXCLUSIVE;
    392  1.1  dholland 			if (nd->nd_flag & ND_PUBLOOKUP)
    393  1.1  dholland 				nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
    394  1.1  dholland 				    &mp, nfs_writerpc[nd->nd_procnum], p);
    395  1.1  dholland 			else
    396  1.1  dholland 				nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
    397  1.1  dholland 				    &mp, nfs_writerpc[nd->nd_procnum], p);
    398  1.1  dholland 			if (nd->nd_repstat == NFSERR_PROGNOTV4)
    399  1.1  dholland 				goto out;
    400  1.1  dholland 		}
    401  1.1  dholland 	}
    402  1.1  dholland 
    403  1.1  dholland 	/*
    404  1.1  dholland 	 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
    405  1.1  dholland 	 * cache, as required.
    406  1.1  dholland 	 * For V4, nfsrvd_compound() does this.
    407  1.1  dholland 	 */
    408  1.1  dholland 	if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
    409  1.1  dholland 		nd->nd_flag |= ND_SAVEREPLY;
    410  1.1  dholland 
    411  1.1  dholland 	nfsrvd_rephead(nd);
    412  1.1  dholland 	/*
    413  1.1  dholland 	 * If nd_repstat is non-zero, just fill in the reply status
    414  1.1  dholland 	 * to complete the RPC reply for V2. Otherwise, you must do
    415  1.1  dholland 	 * the RPC.
    416  1.1  dholland 	 */
    417  1.1  dholland 	if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
    418  1.1  dholland 		*nd->nd_errp = nfsd_errmap(nd);
    419  1.1  dholland 		NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]);
    420  1.1  dholland 		if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
    421  1.1  dholland 			vn_finished_write(mp);
    422  1.1  dholland 		goto out;
    423  1.1  dholland 	}
    424  1.1  dholland 
    425  1.1  dholland 	/*
    426  1.1  dholland 	 * Now the procedure can be performed. For V4, nfsrvd_compound()
    427  1.1  dholland 	 * works through the sub-rpcs, otherwise just call the procedure.
    428  1.1  dholland 	 * The procedures are in three groups with different arguments.
    429  1.1  dholland 	 * The group is indicated by the value in nfs_retfh[].
    430  1.1  dholland 	 */
    431  1.1  dholland 	if (nd->nd_flag & ND_NFSV4) {
    432  1.1  dholland 		nfsrvd_compound(nd, isdgram, p);
    433  1.1  dholland 	} else {
    434  1.1  dholland 		if (nfs_retfh[nd->nd_procnum] == 1) {
    435  1.1  dholland 			if (vp)
    436  1.1  dholland 				NFSVOPUNLOCK(vp, 0);
    437  1.1  dholland 			error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
    438  1.1  dholland 			    vp, NULL, (fhandle_t *)fh.nfsrvfh_data, p, &nes);
    439  1.1  dholland 		} else if (nfs_retfh[nd->nd_procnum] == 2) {
    440  1.1  dholland 			error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
    441  1.1  dholland 			    vp, NULL, p, &nes, NULL);
    442  1.1  dholland 		} else {
    443  1.1  dholland 			error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
    444  1.1  dholland 			    vp, p, &nes);
    445  1.1  dholland 		}
    446  1.1  dholland 		if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
    447  1.1  dholland 			vn_finished_write(mp);
    448  1.1  dholland 		NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]);
    449  1.1  dholland 	}
    450  1.1  dholland 	if (error) {
    451  1.1  dholland 		if (error != EBADRPC)
    452  1.1  dholland 			printf("nfs dorpc err2=%d\n", error);
    453  1.1  dholland 		nd->nd_repstat = NFSERR_GARBAGE;
    454  1.1  dholland 	}
    455  1.1  dholland 	*nd->nd_errp = nfsd_errmap(nd);
    456  1.1  dholland 
    457  1.1  dholland 	/*
    458  1.1  dholland 	 * Don't cache certain reply status values.
    459  1.1  dholland 	 */
    460  1.1  dholland 	if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
    461  1.1  dholland 	    (nd->nd_repstat == NFSERR_GARBAGE ||
    462  1.1  dholland 	     nd->nd_repstat == NFSERR_BADXDR ||
    463  1.1  dholland 	     nd->nd_repstat == NFSERR_MOVED ||
    464  1.1  dholland 	     nd->nd_repstat == NFSERR_DELAY ||
    465  1.1  dholland 	     nd->nd_repstat == NFSERR_BADSEQID ||
    466  1.1  dholland 	     nd->nd_repstat == NFSERR_RESOURCE ||
    467  1.1  dholland 	     nd->nd_repstat == NFSERR_SERVERFAULT ||
    468  1.1  dholland 	     nd->nd_repstat == NFSERR_STALECLIENTID ||
    469  1.1  dholland 	     nd->nd_repstat == NFSERR_STALESTATEID ||
    470  1.1  dholland 	     nd->nd_repstat == NFSERR_OLDSTATEID ||
    471  1.1  dholland 	     nd->nd_repstat == NFSERR_BADSTATEID ||
    472  1.1  dholland 	     nd->nd_repstat == NFSERR_GRACE ||
    473  1.1  dholland 	     nd->nd_repstat == NFSERR_NOGRACE))
    474  1.1  dholland 		nd->nd_flag &= ~ND_SAVEREPLY;
    475  1.1  dholland 
    476  1.1  dholland out:
    477  1.1  dholland 	NFSEXITCODE2(0, nd);
    478  1.1  dholland }
    479  1.1  dholland 
    480  1.1  dholland /*
    481  1.1  dholland  * Breaks down a compound RPC request and calls the server routines for
    482  1.1  dholland  * the subprocedures.
    483  1.1  dholland  * Some suboperations are performed directly here to simplify file handle<-->
    484  1.1  dholland  * vnode pointer handling.
    485  1.1  dholland  */
    486  1.1  dholland static void
    487  1.1  dholland nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
    488  1.1  dholland     NFSPROC_T *p)
    489  1.1  dholland {
    490  1.1  dholland 	int i, op;
    491  1.1  dholland 	u_int32_t *tl;
    492  1.1  dholland 	struct nfsclient *clp, *nclp;
    493  1.1  dholland 	int numops, taglen = -1, error = 0, igotlock;
    494  1.1  dholland 	u_int32_t minorvers, retops = 0, *retopsp = NULL, *repp;
    495  1.1  dholland 	u_char tag[NFSV4_SMALLSTR + 1], *tagstr;
    496  1.1  dholland 	vnode_t vp, nvp, savevp;
    497  1.1  dholland 	struct nfsrvfh fh;
    498  1.1  dholland 	mount_t new_mp, temp_mp = NULL;
    499  1.1  dholland 	struct ucred *credanon;
    500  1.1  dholland 	struct nfsexstuff nes, vpnes, savevpnes;
    501  1.1  dholland 	fsid_t cur_fsid, save_fsid;
    502  1.1  dholland 	static u_int64_t compref = 0;
    503  1.1  dholland 
    504  1.1  dholland 	NFSVNO_EXINIT(&vpnes);
    505  1.1  dholland 	NFSVNO_EXINIT(&savevpnes);
    506  1.1  dholland 	/*
    507  1.1  dholland 	 * Put the seq# of the current compound RPC in nfsrv_descript.
    508  1.1  dholland 	 * (This is used by nfsrv_checkgetattr(), to see if the write
    509  1.1  dholland 	 *  delegation was created by the same compound RPC as the one
    510  1.1  dholland 	 *  with that Getattr in it.)
    511  1.1  dholland 	 * Don't worry about the 64bit number wrapping around. It ain't
    512  1.1  dholland 	 * gonna happen before this server gets shut down/rebooted.
    513  1.1  dholland 	 */
    514  1.1  dholland 	nd->nd_compref = compref++;
    515  1.1  dholland 
    516  1.1  dholland 	/*
    517  1.1  dholland 	 * Check for and optionally get a lock on the root. This lock means that
    518  1.1  dholland 	 * no nfsd will be fiddling with the V4 file system and state stuff. It
    519  1.1  dholland 	 * is required when the V4 root is being changed, the stable storage
    520  1.1  dholland 	 * restart file is being updated, or callbacks are being done.
    521  1.1  dholland 	 * When any of the nfsd are processing an NFSv4 compound RPC, they must
    522  1.1  dholland 	 * either hold a reference count (nfs_usecnt) or the lock. When
    523  1.1  dholland 	 * nfsrv_unlock() is called to release the lock, it can optionally
    524  1.1  dholland 	 * also get a reference count, which saves the need for a call to
    525  1.1  dholland 	 * nfsrv_getref() after nfsrv_unlock().
    526  1.1  dholland 	 */
    527  1.1  dholland 	/*
    528  1.1  dholland 	 * First, check to see if we need to wait for an update lock.
    529  1.1  dholland 	 */
    530  1.1  dholland 	igotlock = 0;
    531  1.1  dholland 	NFSLOCKV4ROOTMUTEX();
    532  1.1  dholland 	if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
    533  1.1  dholland 		igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
    534  1.1  dholland 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
    535  1.1  dholland 	else
    536  1.1  dholland 		igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
    537  1.1  dholland 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
    538  1.1  dholland 	NFSUNLOCKV4ROOTMUTEX();
    539  1.1  dholland 	if (igotlock) {
    540  1.1  dholland 		/*
    541  1.1  dholland 		 * If I got the lock, I can update the stable storage file.
    542  1.1  dholland 		 * Done when the grace period is over or a client has long
    543  1.1  dholland 		 * since expired.
    544  1.1  dholland 		 */
    545  1.1  dholland 		nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
    546  1.1  dholland 		if ((nfsrv_stablefirst.nsf_flags &
    547  1.1  dholland 		    (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
    548  1.1  dholland 			nfsrv_updatestable(p);
    549  1.1  dholland 
    550  1.1  dholland 		/*
    551  1.1  dholland 		 * If at least one client has long since expired, search
    552  1.1  dholland 		 * the client list for them, write a REVOKE record on the
    553  1.1  dholland 		 * stable storage file and then remove them from the client
    554  1.1  dholland 		 * list.
    555  1.1  dholland 		 */
    556  1.1  dholland 		if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) {
    557  1.1  dholland 			nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT;
    558  1.1  dholland 			for (i = 0; i < NFSCLIENTHASHSIZE; i++) {
    559  1.1  dholland 			    LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash,
    560  1.1  dholland 				nclp) {
    561  1.1  dholland 				if (clp->lc_flags & LCL_EXPIREIT) {
    562  1.1  dholland 				    if (!LIST_EMPTY(&clp->lc_open) ||
    563  1.1  dholland 					!LIST_EMPTY(&clp->lc_deleg))
    564  1.1  dholland 					nfsrv_writestable(clp->lc_id,
    565  1.1  dholland 					    clp->lc_idlen, NFSNST_REVOKE, p);
    566  1.1  dholland 				    nfsrv_cleanclient(clp, p);
    567  1.1  dholland 				    nfsrv_freedeleglist(&clp->lc_deleg);
    568  1.1  dholland 				    nfsrv_freedeleglist(&clp->lc_olddeleg);
    569  1.1  dholland 				    LIST_REMOVE(clp, lc_hash);
    570  1.1  dholland 				    nfsrv_zapclient(clp, p);
    571  1.1  dholland 				}
    572  1.1  dholland 			    }
    573  1.1  dholland 			}
    574  1.1  dholland 		}
    575  1.1  dholland 		NFSLOCKV4ROOTMUTEX();
    576  1.1  dholland 		nfsv4_unlock(&nfsv4rootfs_lock, 1);
    577  1.1  dholland 		NFSUNLOCKV4ROOTMUTEX();
    578  1.1  dholland 	} else {
    579  1.1  dholland 		/*
    580  1.1  dholland 		 * If we didn't get the lock, we need to get a refcnt,
    581  1.1  dholland 		 * which also checks for and waits for the lock.
    582  1.1  dholland 		 */
    583  1.1  dholland 		NFSLOCKV4ROOTMUTEX();
    584  1.1  dholland 		nfsv4_getref(&nfsv4rootfs_lock, NULL,
    585  1.1  dholland 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
    586  1.1  dholland 		NFSUNLOCKV4ROOTMUTEX();
    587  1.1  dholland 	}
    588  1.1  dholland 
    589  1.1  dholland 	/*
    590  1.1  dholland 	 * If flagged, search for open owners that haven't had any opens
    591  1.1  dholland 	 * for a long time.
    592  1.1  dholland 	 */
    593  1.1  dholland 	if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
    594  1.1  dholland 		nfsrv_throwawayopens(p);
    595  1.1  dholland 	}
    596  1.1  dholland 
    597  1.1  dholland 	savevp = vp = NULL;
    598  1.1  dholland 	save_fsid.val[0] = save_fsid.val[1] = 0;
    599  1.1  dholland 	cur_fsid.val[0] = cur_fsid.val[1] = 0;
    600  1.1  dholland 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
    601  1.1  dholland 	taglen = fxdr_unsigned(int, *tl);
    602  1.1  dholland 	if (taglen < 0) {
    603  1.1  dholland 		error = EBADRPC;
    604  1.1  dholland 		goto nfsmout;
    605  1.1  dholland 	}
    606  1.1  dholland 	if (taglen <= NFSV4_SMALLSTR)
    607  1.1  dholland 		tagstr = tag;
    608  1.1  dholland 	else
    609  1.1  dholland 		tagstr = malloc(taglen + 1, M_TEMP, M_WAITOK);
    610  1.1  dholland 	error = nfsrv_mtostr(nd, tagstr, taglen);
    611  1.1  dholland 	if (error) {
    612  1.1  dholland 		if (taglen > NFSV4_SMALLSTR)
    613  1.1  dholland 			free(tagstr, M_TEMP);
    614  1.1  dholland 		taglen = -1;
    615  1.1  dholland 		goto nfsmout;
    616  1.1  dholland 	}
    617  1.1  dholland 	(void) nfsm_strtom(nd, tag, taglen);
    618  1.1  dholland 	if (taglen > NFSV4_SMALLSTR) {
    619  1.1  dholland 		free(tagstr, M_TEMP);
    620  1.1  dholland 	}
    621  1.1  dholland 	NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
    622  1.1  dholland 	NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
    623  1.1  dholland 	minorvers = fxdr_unsigned(u_int32_t, *tl++);
    624  1.1  dholland 	if (minorvers != NFSV4_MINORVERSION)
    625  1.1  dholland 		nd->nd_repstat = NFSERR_MINORVERMISMATCH;
    626  1.1  dholland 	if (nd->nd_repstat)
    627  1.1  dholland 		numops = 0;
    628  1.1  dholland 	else
    629  1.1  dholland 		numops = fxdr_unsigned(int, *tl);
    630  1.1  dholland 	/*
    631  1.1  dholland 	 * Loop around doing the sub ops.
    632  1.1  dholland 	 * vp - is an unlocked vnode pointer for the CFH
    633  1.1  dholland 	 * savevp - is an unlocked vnode pointer for the SAVEDFH
    634  1.1  dholland 	 * (at some future date, it might turn out to be more appropriate
    635  1.1  dholland 	 *  to keep the file handles instead of vnode pointers?)
    636  1.1  dholland 	 * savevpnes and vpnes - are the export flags for the above.
    637  1.1  dholland 	 */
    638  1.1  dholland 	for (i = 0; i < numops; i++) {
    639  1.1  dholland 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
    640  1.1  dholland 		NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
    641  1.1  dholland 		*repp = *tl;
    642  1.1  dholland 		op = fxdr_unsigned(int, *tl);
    643  1.1  dholland 		if (op < NFSV4OP_ACCESS || op >= NFSV4OP_NOPS) {
    644  1.1  dholland 			nd->nd_repstat = NFSERR_OPILLEGAL;
    645  1.1  dholland 			*repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
    646  1.1  dholland 			*repp = nfsd_errmap(nd);
    647  1.1  dholland 			retops++;
    648  1.1  dholland 			break;
    649  1.1  dholland 		} else {
    650  1.1  dholland 			repp++;
    651  1.1  dholland 		}
    652  1.1  dholland 
    653  1.1  dholland 		/*
    654  1.1  dholland 		 * Check for a referral on the current FH and, if so, return
    655  1.1  dholland 		 * NFSERR_MOVED for all ops that allow it, except Getattr.
    656  1.1  dholland 		 */
    657  1.1  dholland 		if (vp != NULL && op != NFSV4OP_GETATTR &&
    658  1.1  dholland 		    nfsv4root_getreferral(vp, NULL, 0) != NULL &&
    659  1.1  dholland 		    nfsrv_errmoved(op)) {
    660  1.1  dholland 			nd->nd_repstat = NFSERR_MOVED;
    661  1.1  dholland 			*repp = nfsd_errmap(nd);
    662  1.1  dholland 			retops++;
    663  1.1  dholland 			break;
    664  1.1  dholland 		}
    665  1.1  dholland 
    666  1.1  dholland 		nd->nd_procnum = op;
    667  1.1  dholland 		/*
    668  1.1  dholland 		 * If over flood level, reply NFSERR_RESOURCE, if at the first
    669  1.1  dholland 		 * Op. (Since a client recovery from NFSERR_RESOURCE can get
    670  1.1  dholland 		 * really nasty for certain Op sequences, I'll play it safe
    671  1.1  dholland 		 * and only return the error at the beginning.) The cache
    672  1.1  dholland 		 * will still function over flood level, but uses lots of
    673  1.1  dholland 		 * mbufs.)
    674  1.1  dholland 		 * If nfsrv_mallocmget_limit() returns True, the system is near
    675  1.1  dholland 		 * to its limit for memory that malloc()/mget() can allocate.
    676  1.1  dholland 		 */
    677  1.1  dholland 		if (i == 0 && nd->nd_rp->rc_refcnt == 0 &&
    678  1.1  dholland 		    (nfsrv_mallocmget_limit() ||
    679  1.1  dholland 		     nfsrc_tcpsavedreplies > nfsrc_floodlevel)) {
    680  1.1  dholland 			if (nfsrc_tcpsavedreplies > nfsrc_floodlevel) {
    681  1.1  dholland 				printf("nfsd server cache flooded, try to");
    682  1.1  dholland 				printf(" increase nfsrc_floodlevel\n");
    683  1.1  dholland 			}
    684  1.1  dholland 			nd->nd_repstat = NFSERR_RESOURCE;
    685  1.1  dholland 			*repp = nfsd_errmap(nd);
    686  1.1  dholland 			if (op == NFSV4OP_SETATTR) {
    687  1.1  dholland 				/*
    688  1.1  dholland 				 * Setattr replies require a bitmap.
    689  1.1  dholland 				 * even for errors like these.
    690  1.1  dholland 				 */
    691  1.1  dholland 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
    692  1.1  dholland 				*tl = 0;
    693  1.1  dholland 			}
    694  1.1  dholland 			retops++;
    695  1.1  dholland 			break;
    696  1.1  dholland 		}
    697  1.1  dholland 		if (nfsv4_opflag[op].savereply)
    698  1.1  dholland 			nd->nd_flag |= ND_SAVEREPLY;
    699  1.1  dholland 		NFSINCRGLOBAL(newnfsstats.srvrpccnt[nd->nd_procnum]);
    700  1.1  dholland 		switch (op) {
    701  1.1  dholland 		case NFSV4OP_PUTFH:
    702  1.1  dholland 			error = nfsrv_mtofh(nd, &fh);
    703  1.1  dholland 			if (error)
    704  1.1  dholland 				goto nfsmout;
    705  1.1  dholland 			if (!nd->nd_repstat)
    706  1.1  dholland 				nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
    707  1.1  dholland 				    NULL, 0, p);
    708  1.1  dholland 			/* For now, allow this for non-export FHs */
    709  1.1  dholland 			if (!nd->nd_repstat) {
    710  1.1  dholland 				if (vp)
    711  1.1  dholland 					vrele(vp);
    712  1.1  dholland 				vp = nvp;
    713  1.1  dholland 				cur_fsid = vp->v_mount->mnt_stat.f_fsid;
    714  1.1  dholland 				NFSVOPUNLOCK(vp, 0);
    715  1.1  dholland 				vpnes = nes;
    716  1.1  dholland 			}
    717  1.1  dholland 			break;
    718  1.1  dholland 		case NFSV4OP_PUTPUBFH:
    719  1.1  dholland 			if (nfs_pubfhset)
    720  1.1  dholland 			    nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
    721  1.1  dholland 				&nes, NULL, 0, p);
    722  1.1  dholland 			else
    723  1.1  dholland 			    nd->nd_repstat = NFSERR_NOFILEHANDLE;
    724  1.1  dholland 			if (!nd->nd_repstat) {
    725  1.1  dholland 				if (vp)
    726  1.1  dholland 					vrele(vp);
    727  1.1  dholland 				vp = nvp;
    728  1.1  dholland 				cur_fsid = vp->v_mount->mnt_stat.f_fsid;
    729  1.1  dholland 				NFSVOPUNLOCK(vp, 0);
    730  1.1  dholland 				vpnes = nes;
    731  1.1  dholland 			}
    732  1.1  dholland 			break;
    733  1.1  dholland 		case NFSV4OP_PUTROOTFH:
    734  1.1  dholland 			if (nfs_rootfhset) {
    735  1.1  dholland 				nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
    736  1.1  dholland 				    &nes, NULL, 0, p);
    737  1.1  dholland 				if (!nd->nd_repstat) {
    738  1.1  dholland 					if (vp)
    739  1.1  dholland 						vrele(vp);
    740  1.1  dholland 					vp = nvp;
    741  1.1  dholland 					cur_fsid = vp->v_mount->mnt_stat.f_fsid;
    742  1.1  dholland 					NFSVOPUNLOCK(vp, 0);
    743  1.1  dholland 					vpnes = nes;
    744  1.1  dholland 				}
    745  1.1  dholland 			} else
    746  1.1  dholland 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
    747  1.1  dholland 			break;
    748  1.1  dholland 		case NFSV4OP_SAVEFH:
    749  1.1  dholland 			if (vp && NFSVNO_EXPORTED(&vpnes)) {
    750  1.1  dholland 				nd->nd_repstat = 0;
    751  1.1  dholland 				/* If vp == savevp, a no-op */
    752  1.1  dholland 				if (vp != savevp) {
    753  1.1  dholland 					if (savevp)
    754  1.1  dholland 						vrele(savevp);
    755  1.1  dholland 					VREF(vp);
    756  1.1  dholland 					savevp = vp;
    757  1.1  dholland 					savevpnes = vpnes;
    758  1.1  dholland 					save_fsid = cur_fsid;
    759  1.1  dholland 				}
    760  1.1  dholland 			} else {
    761  1.1  dholland 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
    762  1.1  dholland 			}
    763  1.1  dholland 			break;
    764  1.1  dholland 		case NFSV4OP_RESTOREFH:
    765  1.1  dholland 			if (savevp) {
    766  1.1  dholland 				nd->nd_repstat = 0;
    767  1.1  dholland 				/* If vp == savevp, a no-op */
    768  1.1  dholland 				if (vp != savevp) {
    769  1.1  dholland 					VREF(savevp);
    770  1.1  dholland 					vrele(vp);
    771  1.1  dholland 					vp = savevp;
    772  1.1  dholland 					vpnes = savevpnes;
    773  1.1  dholland 					cur_fsid = save_fsid;
    774  1.1  dholland 				}
    775  1.1  dholland 			} else {
    776  1.1  dholland 				nd->nd_repstat = NFSERR_RESTOREFH;
    777  1.1  dholland 			}
    778  1.1  dholland 			break;
    779  1.1  dholland 		default:
    780  1.1  dholland 		    /*
    781  1.1  dholland 		     * Allow a Lookup, Getattr, GetFH, Secinfo on an
    782  1.1  dholland 		     * non-exported directory if
    783  1.1  dholland 		     * nfs_rootfhset. Do I need to allow any other Ops?
    784  1.1  dholland 		     * (You can only have a non-exported vpnes if
    785  1.1  dholland 		     *  nfs_rootfhset is true. See nfsd_fhtovp())
    786  1.1  dholland 		     * Allow AUTH_SYS to be used for file systems
    787  1.1  dholland 		     * exported GSS only for certain Ops, to allow
    788  1.1  dholland 		     * clients to do mounts more easily.
    789  1.1  dholland 		     */
    790  1.1  dholland 		    if (nfsv4_opflag[op].needscfh && vp) {
    791  1.1  dholland 			if (!NFSVNO_EXPORTED(&vpnes) &&
    792  1.1  dholland 			    op != NFSV4OP_LOOKUP &&
    793  1.1  dholland 			    op != NFSV4OP_GETATTR &&
    794  1.1  dholland 			    op != NFSV4OP_GETFH &&
    795  1.1  dholland 			    op != NFSV4OP_ACCESS &&
    796  1.1  dholland 			    op != NFSV4OP_READLINK &&
    797  1.1  dholland 			    op != NFSV4OP_SECINFO)
    798  1.1  dholland 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
    799  1.1  dholland 			else if (nfsvno_testexp(nd, &vpnes) &&
    800  1.1  dholland 			    op != NFSV4OP_LOOKUP &&
    801  1.1  dholland 			    op != NFSV4OP_GETFH &&
    802  1.1  dholland 			    op != NFSV4OP_GETATTR &&
    803  1.1  dholland 			    op != NFSV4OP_SECINFO)
    804  1.1  dholland 				nd->nd_repstat = NFSERR_WRONGSEC;
    805  1.1  dholland 			if (nd->nd_repstat) {
    806  1.1  dholland 				if (op == NFSV4OP_SETATTR) {
    807  1.1  dholland 				    /*
    808  1.1  dholland 				     * Setattr reply requires a bitmap
    809  1.1  dholland 				     * even for errors like these.
    810  1.1  dholland 				     */
    811  1.1  dholland 				    NFSM_BUILD(tl, u_int32_t *,
    812  1.1  dholland 					NFSX_UNSIGNED);
    813  1.1  dholland 				    *tl = 0;
    814  1.1  dholland 				}
    815  1.1  dholland 				break;
    816  1.1  dholland 			}
    817  1.1  dholland 		    }
    818  1.1  dholland 		    if (nfsv4_opflag[op].retfh == 1) {
    819  1.1  dholland 			if (!vp) {
    820  1.1  dholland 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
    821  1.1  dholland 				break;
    822  1.1  dholland 			}
    823  1.1  dholland 			VREF(vp);
    824  1.1  dholland 			if (nfsv4_opflag[op].modifyfs)
    825  1.1  dholland 				vn_start_write(vp, &temp_mp, V_WAIT);
    826  1.1  dholland 			error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
    827  1.1  dholland 			    &nvp, (fhandle_t *)fh.nfsrvfh_data, p, &vpnes);
    828  1.1  dholland 			if (!error && !nd->nd_repstat) {
    829  1.1  dholland 			    if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
    830  1.1  dholland 				new_mp = nvp->v_mount;
    831  1.1  dholland 				if (cur_fsid.val[0] !=
    832  1.1  dholland 				    new_mp->mnt_stat.f_fsid.val[0] ||
    833  1.1  dholland 				    cur_fsid.val[1] !=
    834  1.1  dholland 				    new_mp->mnt_stat.f_fsid.val[1]) {
    835  1.1  dholland 				    /* crossed a server mount point */
    836  1.1  dholland 				    nd->nd_repstat = nfsvno_checkexp(new_mp,
    837  1.1  dholland 					nd->nd_nam, &nes, &credanon);
    838  1.1  dholland 				    if (!nd->nd_repstat)
    839  1.1  dholland 					nd->nd_repstat = nfsd_excred(nd,
    840  1.1  dholland 					    &nes, credanon);
    841  1.1  dholland 				    if (credanon != NULL)
    842  1.1  dholland 					crfree(credanon);
    843  1.1  dholland 				    if (!nd->nd_repstat) {
    844  1.1  dholland 					vpnes = nes;
    845  1.1  dholland 					cur_fsid = new_mp->mnt_stat.f_fsid;
    846  1.1  dholland 				    }
    847  1.1  dholland 				}
    848  1.1  dholland 				/* Lookup ops return a locked vnode */
    849  1.1  dholland 				NFSVOPUNLOCK(nvp, 0);
    850  1.1  dholland 			    }
    851  1.1  dholland 			    if (!nd->nd_repstat) {
    852  1.1  dholland 				    vrele(vp);
    853  1.1  dholland 				    vp = nvp;
    854  1.1  dholland 			    } else
    855  1.1  dholland 				    vrele(nvp);
    856  1.1  dholland 			}
    857  1.1  dholland 			if (nfsv4_opflag[op].modifyfs)
    858  1.1  dholland 				vn_finished_write(temp_mp);
    859  1.1  dholland 		    } else if (nfsv4_opflag[op].retfh == 2) {
    860  1.1  dholland 			if (vp == NULL || savevp == NULL) {
    861  1.1  dholland 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
    862  1.1  dholland 				break;
    863  1.1  dholland 			} else if (cur_fsid.val[0] != save_fsid.val[0] ||
    864  1.1  dholland 			    cur_fsid.val[1] != save_fsid.val[1]) {
    865  1.1  dholland 				nd->nd_repstat = NFSERR_XDEV;
    866  1.1  dholland 				break;
    867  1.1  dholland 			}
    868  1.1  dholland 			if (nfsv4_opflag[op].modifyfs)
    869  1.1  dholland 				vn_start_write(savevp, &temp_mp, V_WAIT);
    870  1.1  dholland 			if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
    871  1.1  dholland 				VREF(vp);
    872  1.1  dholland 				VREF(savevp);
    873  1.1  dholland 				error = (*(nfsrv4_ops2[op]))(nd, isdgram,
    874  1.1  dholland 				    savevp, vp, p, &savevpnes, &vpnes);
    875  1.1  dholland 			} else
    876  1.1  dholland 				nd->nd_repstat = NFSERR_PERM;
    877  1.1  dholland 			if (nfsv4_opflag[op].modifyfs)
    878  1.1  dholland 				vn_finished_write(temp_mp);
    879  1.1  dholland 		    } else {
    880  1.1  dholland 			if (nfsv4_opflag[op].retfh != 0)
    881  1.1  dholland 				panic("nfsrvd_compound");
    882  1.1  dholland 			if (nfsv4_opflag[op].needscfh) {
    883  1.1  dholland 				if (vp != NULL) {
    884  1.1  dholland 					if (nfsv4_opflag[op].modifyfs)
    885  1.1  dholland 						vn_start_write(vp, &temp_mp,
    886  1.1  dholland 						    V_WAIT);
    887  1.1  dholland 					if (NFSVOPLOCK(vp, nfsv4_opflag[op].lktype)
    888  1.1  dholland 					    == 0)
    889  1.1  dholland 						VREF(vp);
    890  1.1  dholland 					else
    891  1.1  dholland 						nd->nd_repstat = NFSERR_PERM;
    892  1.1  dholland 				} else {
    893  1.1  dholland 					nd->nd_repstat = NFSERR_NOFILEHANDLE;
    894  1.1  dholland 					if (op == NFSV4OP_SETATTR) {
    895  1.1  dholland 						/*
    896  1.1  dholland 						 * Setattr reply requires a
    897  1.1  dholland 						 * bitmap even for errors like
    898  1.1  dholland 						 * these.
    899  1.1  dholland 						 */
    900  1.1  dholland 						NFSM_BUILD(tl, u_int32_t *,
    901  1.1  dholland 						    NFSX_UNSIGNED);
    902  1.1  dholland 						*tl = 0;
    903  1.1  dholland 					}
    904  1.1  dholland 					break;
    905  1.1  dholland 				}
    906  1.1  dholland 				if (nd->nd_repstat == 0)
    907  1.1  dholland 					error = (*(nfsrv4_ops0[op]))(nd,
    908  1.1  dholland 					    isdgram, vp, p, &vpnes);
    909  1.1  dholland 				if (nfsv4_opflag[op].modifyfs)
    910  1.1  dholland 					vn_finished_write(temp_mp);
    911  1.1  dholland 			} else {
    912  1.1  dholland 				error = (*(nfsrv4_ops0[op]))(nd, isdgram,
    913  1.1  dholland 				    NULL, p, &vpnes);
    914  1.1  dholland 			}
    915  1.1  dholland 		    }
    916  1.1  dholland 		};
    917  1.1  dholland 		if (error) {
    918  1.1  dholland 			if (error == EBADRPC || error == NFSERR_BADXDR) {
    919  1.1  dholland 				nd->nd_repstat = NFSERR_BADXDR;
    920  1.1  dholland 			} else {
    921  1.1  dholland 				nd->nd_repstat = error;
    922  1.1  dholland 				printf("nfsv4 comperr0=%d\n", error);
    923  1.1  dholland 			}
    924  1.1  dholland 			error = 0;
    925  1.1  dholland 		}
    926  1.1  dholland 		retops++;
    927  1.1  dholland 		if (nd->nd_repstat) {
    928  1.1  dholland 			*repp = nfsd_errmap(nd);
    929  1.1  dholland 			break;
    930  1.1  dholland 		} else {
    931  1.1  dholland 			*repp = 0;	/* NFS4_OK */
    932  1.1  dholland 		}
    933  1.1  dholland 	}
    934  1.1  dholland nfsmout:
    935  1.1  dholland 	if (error) {
    936  1.1  dholland 		if (error == EBADRPC || error == NFSERR_BADXDR)
    937  1.1  dholland 			nd->nd_repstat = NFSERR_BADXDR;
    938  1.1  dholland 		else
    939  1.1  dholland 			printf("nfsv4 comperr1=%d\n", error);
    940  1.1  dholland 	}
    941  1.1  dholland 	if (taglen == -1) {
    942  1.1  dholland 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
    943  1.1  dholland 		*tl++ = 0;
    944  1.1  dholland 		*tl = 0;
    945  1.1  dholland 	} else {
    946  1.1  dholland 		*retopsp = txdr_unsigned(retops);
    947  1.1  dholland 	}
    948  1.1  dholland 	if (vp)
    949  1.1  dholland 		vrele(vp);
    950  1.1  dholland 	if (savevp)
    951  1.1  dholland 		vrele(savevp);
    952  1.1  dholland 	NFSLOCKV4ROOTMUTEX();
    953  1.1  dholland 	nfsv4_relref(&nfsv4rootfs_lock);
    954  1.1  dholland 	NFSUNLOCKV4ROOTMUTEX();
    955  1.1  dholland 
    956  1.1  dholland 	NFSEXITCODE2(0, nd);
    957  1.1  dholland }
    958