The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/nfsserver/nfs_nfsdsocket.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: e6577649a03ac1e55f8b20172795fe2b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.