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

Cache object: 1dec708c9402ab21db649386ab74fd3a


[ 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.