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 , struct nfsexstuff *) = {
   61         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
   62         nfsrvd_getattr,
   63         nfsrvd_setattr,
   64         (int (*)(struct nfsrv_descript *, int, vnode_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 , struct nfsexstuff *))0,
   71         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
   72         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
   73         nfsrvd_remove,
   74         nfsrvd_remove,
   75         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
   76         (int (*)(struct nfsrv_descript *, int, vnode_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 *, struct nfsexstuff *) = {
   87         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
   88         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
   89         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
   90         nfsrvd_lookup,
   91         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
   92         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
   93         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
   94         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
   95         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
   96         nfsrvd_mkdir,
   97         nfsrvd_symlink,
   98         nfsrvd_mknod,
   99         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  100         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  101         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  102         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  103         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  104         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  105         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  106         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  107         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  108         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  109 };
  110 
  111 int (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *,
  112     int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *) = {
  113         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  114         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  115         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  116         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  117         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  118         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  119         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  120         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  121         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  122         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  123         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  124         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  125         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  126         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  127         nfsrvd_rename,
  128         nfsrvd_link,
  129         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  130         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  131         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  132         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  133         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  134         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  135 };
  136 
  137 int (*nfsrv4_ops0[NFSV42_NOPS])(struct nfsrv_descript *,
  138     int, vnode_t , struct nfsexstuff *) = {
  139         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
  140         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
  141         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
  142         nfsrvd_access,
  143         nfsrvd_close,
  144         nfsrvd_commit,
  145         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
  146         nfsrvd_delegpurge,
  147         nfsrvd_delegreturn,
  148         nfsrvd_getattr,
  149         nfsrvd_getfh,
  150         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
  151         nfsrvd_lock,
  152         nfsrvd_lockt,
  153         nfsrvd_locku,
  154         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
  155         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
  156         nfsrvd_verify,
  157         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
  158         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
  159         nfsrvd_openconfirm,
  160         nfsrvd_opendowngrade,
  161         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
  162         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
  163         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
  164         nfsrvd_read,
  165         nfsrvd_readdirplus,
  166         nfsrvd_readlink,
  167         nfsrvd_remove,
  168         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
  169         nfsrvd_renew,
  170         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
  171         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
  172         nfsrvd_secinfo,
  173         nfsrvd_setattr,
  174         nfsrvd_setclientid,
  175         nfsrvd_setclientidcfrm,
  176         nfsrvd_verify,
  177         nfsrvd_write,
  178         nfsrvd_releaselckown,
  179         nfsrvd_notsupp,
  180         nfsrvd_bindconnsess,
  181         nfsrvd_exchangeid,
  182         nfsrvd_createsession,
  183         nfsrvd_destroysession,
  184         nfsrvd_freestateid,
  185         nfsrvd_notsupp,
  186         nfsrvd_getdevinfo,
  187         nfsrvd_notsupp,
  188         nfsrvd_layoutcommit,
  189         nfsrvd_layoutget,
  190         nfsrvd_layoutreturn,
  191         nfsrvd_notsupp,
  192         nfsrvd_sequence,
  193         nfsrvd_notsupp,
  194         nfsrvd_teststateid,
  195         nfsrvd_notsupp,
  196         nfsrvd_destroyclientid,
  197         nfsrvd_reclaimcomplete,
  198         nfsrvd_allocate,
  199         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
  200         nfsrvd_notsupp,
  201         nfsrvd_notsupp,
  202         nfsrvd_ioadvise,
  203         nfsrvd_layouterror,
  204         nfsrvd_layoutstats,
  205         nfsrvd_notsupp,
  206         nfsrvd_notsupp,
  207         nfsrvd_notsupp,
  208         nfsrvd_seek,
  209         nfsrvd_notsupp,
  210         nfsrvd_notsupp,
  211         nfsrvd_getxattr,
  212         nfsrvd_setxattr,
  213         nfsrvd_listxattr,
  214         nfsrvd_rmxattr,
  215 };
  216 
  217 int (*nfsrv4_ops1[NFSV42_NOPS])(struct nfsrv_descript *,
  218     int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *) = {
  219         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  220         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  221         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  222         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  223         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  224         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  225         nfsrvd_mknod,
  226         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  227         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  228         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  229         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  230         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  231         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  232         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  233         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  234         nfsrvd_lookup,
  235         nfsrvd_lookup,
  236         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  237         nfsrvd_open,
  238         nfsrvd_openattr,
  239         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  240         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  241         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  242         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  243         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  244         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  245         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  246         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  247         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  248         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  249         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  250         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  251         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  252         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  253         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  254         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  255         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  256         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  257         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  258         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  259         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  260         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  261         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  262         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  263         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  264         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  265         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  266         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  267         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  268         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  269         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  270         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  271         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  272         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  273         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  274         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  275         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  276         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  277         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  278         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  279         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  280         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  281         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  282         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  283         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  284         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  285         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  286         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  287         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  288         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  289         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  290         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  291         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  292         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  293         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  294         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
  295 };
  296 
  297 int (*nfsrv4_ops2[NFSV42_NOPS])(struct nfsrv_descript *,
  298     int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *) = {
  299         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  300         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  301         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  302         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  303         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  304         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  305         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  306         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  307         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  308         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  309         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  310         nfsrvd_link,
  311         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  312         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  313         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  314         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  315         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  316         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  317         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  318         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  319         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  320         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  321         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  322         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  323         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  324         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  325         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  326         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  327         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  328         nfsrvd_rename,
  329         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  330         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  331         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  332         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  333         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  334         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  335         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  336         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  337         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  338         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  339         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  340         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  341         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  342         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  343         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  344         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  345         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  346         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  347         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  348         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  349         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  350         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  351         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  352         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  353         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  354         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  355         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  356         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  357         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  358         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  359         nfsrvd_copy_file_range,
  360         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  361         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  362         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  363         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  364         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  365         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  366         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  367         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  368         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  369         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  370         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  371         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  372         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  373         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  374         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
  375 };
  376 
  377 /*
  378  * Static array that defines which nfs rpc's are nonidempotent
  379  */
  380 static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
  381         FALSE,
  382         FALSE,
  383         TRUE,
  384         FALSE,
  385         FALSE,
  386         FALSE,
  387         FALSE,
  388         TRUE,
  389         TRUE,
  390         TRUE,
  391         TRUE,
  392         TRUE,
  393         TRUE,
  394         TRUE,
  395         TRUE,
  396         TRUE,
  397         FALSE,
  398         FALSE,
  399         FALSE,
  400         FALSE,
  401         FALSE,
  402         FALSE,
  403 };
  404 
  405 /*
  406  * This static array indicates whether or not the RPC modifies the
  407  * file system.
  408  */
  409 int nfsrv_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0,
  410     1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
  411     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
  412 
  413 SYSCTL_DECL(_vfs_nfsd);
  414 static int      nfs_minminorv4 = NFSV4_MINORVERSION;
  415 SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_min_minorversion4, CTLFLAG_RWTUN,
  416     &nfs_minminorv4, 0,
  417     "The lowest minor version of NFSv4 handled by the server");
  418 
  419 static int      nfs_maxminorv4 = NFSV42_MINORVERSION;
  420 SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_max_minorversion4, CTLFLAG_RWTUN,
  421     &nfs_maxminorv4, 0,
  422     "The highest minor version of NFSv4 handled by the server");
  423 
  424 /* local functions */
  425 static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
  426     u_char *tag, int taglen, u_int32_t minorvers);
  427 
  428 /*
  429  * This static array indicates which server procedures require the extra
  430  * arguments to return the current file handle for V2, 3.
  431  */
  432 static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
  433         1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
  434 
  435 extern struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS];
  436 
  437 static int nfsv3to4op[NFS_V3NPROCS] = {
  438         NFSPROC_NULL,
  439         NFSV4OP_GETATTR,
  440         NFSV4OP_SETATTR,
  441         NFSV4OP_LOOKUP,
  442         NFSV4OP_ACCESS,
  443         NFSV4OP_READLINK,
  444         NFSV4OP_READ,
  445         NFSV4OP_WRITE,
  446         NFSV4OP_V3CREATE,
  447         NFSV4OP_MKDIR,
  448         NFSV4OP_SYMLINK,
  449         NFSV4OP_MKNOD,
  450         NFSV4OP_REMOVE,
  451         NFSV4OP_RMDIR,
  452         NFSV4OP_RENAME,
  453         NFSV4OP_LINK,
  454         NFSV4OP_READDIR,
  455         NFSV4OP_READDIRPLUS,
  456         NFSV4OP_FSSTAT,
  457         NFSV4OP_FSINFO,
  458         NFSV4OP_PATHCONF,
  459         NFSV4OP_COMMIT,
  460 };
  461 
  462 static struct mtx nfsrvd_statmtx;
  463 MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
  464 
  465 static void
  466 nfsrvd_statstart(int op, struct bintime *now)
  467 {
  468         if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
  469                 printf("%s: op %d invalid\n", __func__, op);
  470                 return;
  471         }
  472 
  473         mtx_lock(&nfsrvd_statmtx);
  474         if (nfsstatsv1.srvstartcnt == nfsstatsv1.srvdonecnt) {
  475                 if (now != NULL)
  476                         nfsstatsv1.busyfrom = *now;
  477                 else
  478                         binuptime(&nfsstatsv1.busyfrom);
  479                 
  480         }
  481         nfsstatsv1.srvrpccnt[op]++;
  482         nfsstatsv1.srvstartcnt++;
  483         mtx_unlock(&nfsrvd_statmtx);
  484 
  485 }
  486 
  487 static void
  488 nfsrvd_statend(int op, uint64_t bytes, struct bintime *now,
  489     struct bintime *then)
  490 {
  491         struct bintime dt, lnow;
  492 
  493         if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
  494                 printf("%s: op %d invalid\n", __func__, op);
  495                 return;
  496         }
  497 
  498         if (now == NULL) {
  499                 now = &lnow;
  500                 binuptime(now);
  501         }
  502 
  503         mtx_lock(&nfsrvd_statmtx);
  504 
  505         nfsstatsv1.srvbytes[op] += bytes;
  506         nfsstatsv1.srvops[op]++;
  507 
  508         if (then != NULL) {
  509                 dt = *now;
  510                 bintime_sub(&dt, then);
  511                 bintime_add(&nfsstatsv1.srvduration[op], &dt);
  512         }
  513 
  514         dt = *now;
  515         bintime_sub(&dt, &nfsstatsv1.busyfrom);
  516         bintime_add(&nfsstatsv1.busytime, &dt);
  517         nfsstatsv1.busyfrom = *now;
  518 
  519         nfsstatsv1.srvdonecnt++;
  520 
  521         mtx_unlock(&nfsrvd_statmtx);
  522 }
  523 
  524 /*
  525  * Do an RPC. Basically, get the file handles translated to vnode pointers
  526  * and then call the appropriate server routine. The server routines are
  527  * split into groups, based on whether they use a file handle or file
  528  * handle plus name or ...
  529  * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
  530  */
  531 void
  532 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
  533     u_int32_t minorvers)
  534 {
  535         int error = 0, lktype;
  536         vnode_t vp;
  537         mount_t mp;
  538         struct nfsrvfh fh;
  539         struct nfsexstuff nes;
  540         struct mbuf *md;
  541         char *dpos;
  542 
  543         /*
  544          * Save the current position in the request mbuf list so
  545          * that a rollback to this location can be done upon an
  546          * ERELOOKUP error return from an RPC function.
  547          */
  548         md = nd->nd_md;
  549         dpos = nd->nd_dpos;
  550 tryagain:
  551         mp = NULL;
  552 
  553         /*
  554          * Get a locked vnode for the first file handle
  555          */
  556         if (!(nd->nd_flag & ND_NFSV4)) {
  557                 KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
  558                 /*
  559                  * For NFSv3, if the malloc/mget allocation is near limits,
  560                  * return NFSERR_DELAY.
  561                  */
  562                 if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
  563                         nd->nd_repstat = NFSERR_DELAY;
  564                         vp = NULL;
  565                 } else {
  566                         error = nfsrv_mtofh(nd, &fh);
  567                         if (error) {
  568                                 if (error != EBADRPC)
  569                                         printf("nfs dorpc err1=%d\n", error);
  570                                 nd->nd_repstat = NFSERR_GARBAGE;
  571                                 goto out;
  572                         }
  573                         if (nd->nd_procnum == NFSPROC_READ ||
  574                             nd->nd_procnum == NFSPROC_WRITE ||
  575                             nd->nd_procnum == NFSPROC_READDIR ||
  576                             nd->nd_procnum == NFSPROC_READDIRPLUS ||
  577                             nd->nd_procnum == NFSPROC_READLINK ||
  578                             nd->nd_procnum == NFSPROC_GETATTR ||
  579                             nd->nd_procnum == NFSPROC_ACCESS ||
  580                             nd->nd_procnum == NFSPROC_FSSTAT ||
  581                             nd->nd_procnum == NFSPROC_FSINFO)
  582                                 lktype = LK_SHARED;
  583                         else
  584                                 lktype = LK_EXCLUSIVE;
  585                         if (nd->nd_flag & ND_PUBLOOKUP)
  586                                 nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
  587                                     &mp, nfsrv_writerpc[nd->nd_procnum]);
  588                         else
  589                                 nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
  590                                     &mp, nfsrv_writerpc[nd->nd_procnum]);
  591                         if (nd->nd_repstat == NFSERR_PROGNOTV4)
  592                                 goto out;
  593                 }
  594         }
  595 
  596         /*
  597          * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
  598          * cache, as required.
  599          * For V4, nfsrvd_compound() does this.
  600          */
  601         if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
  602                 nd->nd_flag |= ND_SAVEREPLY;
  603 
  604         nfsrvd_rephead(nd);
  605         /*
  606          * If nd_repstat is non-zero, just fill in the reply status
  607          * to complete the RPC reply for V2. Otherwise, you must do
  608          * the RPC.
  609          */
  610         if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
  611                 *nd->nd_errp = nfsd_errmap(nd);
  612                 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], /*now*/ NULL);
  613                 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
  614                    /*now*/ NULL, /*then*/ NULL);
  615                 vn_finished_write(mp);
  616                 goto out;
  617         }
  618 
  619         /*
  620          * Now the procedure can be performed. For V4, nfsrvd_compound()
  621          * works through the sub-rpcs, otherwise just call the procedure.
  622          * The procedures are in three groups with different arguments.
  623          * The group is indicated by the value in nfs_retfh[].
  624          */
  625         if (nd->nd_flag & ND_NFSV4) {
  626                 nfsrvd_compound(nd, isdgram, tag, taglen, minorvers);
  627         } else {
  628                 struct bintime start_time;
  629 
  630                 binuptime(&start_time);
  631                 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], &start_time);
  632 
  633                 if (nfs_retfh[nd->nd_procnum] == 1) {
  634                         if (vp)
  635                                 NFSVOPUNLOCK(vp);
  636                         error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
  637                             vp, NULL, (fhandle_t *)fh.nfsrvfh_data, &nes);
  638                 } else if (nfs_retfh[nd->nd_procnum] == 2) {
  639                         error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
  640                             vp, NULL, &nes, NULL);
  641                 } else {
  642                         error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
  643                             vp, &nes);
  644                 }
  645                 vn_finished_write(mp);
  646 
  647                 if (error == 0 && nd->nd_repstat == ERELOOKUP) {
  648                         /*
  649                          * Roll back to the beginning of the RPC request
  650                          * arguments.
  651                          */
  652                         nd->nd_md = md;
  653                         nd->nd_dpos = dpos;
  654 
  655                         /* Free the junk RPC reply and redo the RPC. */
  656                         m_freem(nd->nd_mreq);
  657                         nd->nd_mreq = nd->nd_mb = NULL;
  658                         nd->nd_repstat = 0;
  659                         goto tryagain;
  660                 }
  661 
  662                 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
  663                     /*now*/ NULL, /*then*/ &start_time);
  664         }
  665         if (error) {
  666                 if (error != EBADRPC)
  667                         printf("nfs dorpc err2=%d\n", error);
  668                 nd->nd_repstat = NFSERR_GARBAGE;
  669         }
  670         *nd->nd_errp = nfsd_errmap(nd);
  671 
  672         /*
  673          * Don't cache certain reply status values.
  674          */
  675         if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
  676             (nd->nd_repstat == NFSERR_GARBAGE ||
  677              nd->nd_repstat == NFSERR_BADXDR ||
  678              nd->nd_repstat == NFSERR_MOVED ||
  679              nd->nd_repstat == NFSERR_DELAY ||
  680              nd->nd_repstat == NFSERR_BADSEQID ||
  681              nd->nd_repstat == NFSERR_RESOURCE ||
  682              nd->nd_repstat == NFSERR_SERVERFAULT ||
  683              nd->nd_repstat == NFSERR_STALECLIENTID ||
  684              nd->nd_repstat == NFSERR_STALESTATEID ||
  685              nd->nd_repstat == NFSERR_OLDSTATEID ||
  686              nd->nd_repstat == NFSERR_BADSTATEID ||
  687              nd->nd_repstat == NFSERR_GRACE ||
  688              nd->nd_repstat == NFSERR_NOGRACE))
  689                 nd->nd_flag &= ~ND_SAVEREPLY;
  690 
  691 out:
  692         NFSEXITCODE2(0, nd);
  693 }
  694 
  695 /*
  696  * Breaks down a compound RPC request and calls the server routines for
  697  * the subprocedures.
  698  * Some suboperations are performed directly here to simplify file handle<-->
  699  * vnode pointer handling.
  700  */
  701 static void
  702 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
  703     int taglen, u_int32_t minorvers)
  704 {
  705         int i, lktype, op, op0 = 0, statsinprog = 0;
  706         u_int32_t *tl;
  707         struct nfsclient *clp, *nclp;
  708         int numops, error = 0, igotlock;
  709         u_int32_t retops = 0, *retopsp = NULL, *repp;
  710         vnode_t vp, nvp, savevp;
  711         struct nfsrvfh fh;
  712         mount_t new_mp, temp_mp = NULL;
  713         struct ucred *credanon;
  714         struct nfsexstuff nes, vpnes, savevpnes;
  715         fsid_t cur_fsid, save_fsid;
  716         static u_int64_t compref = 0;
  717         struct bintime start_time;
  718         struct thread *p;
  719         struct mbuf *mb, *md;
  720         char *bpos, *dpos;
  721         int bextpg, bextpgsiz;
  722 
  723         p = curthread;
  724 
  725         NFSVNO_EXINIT(&vpnes);
  726         NFSVNO_EXINIT(&savevpnes);
  727         /*
  728          * Put the seq# of the current compound RPC in nfsrv_descript.
  729          * (This is used by nfsrv_checkgetattr(), to see if the write
  730          *  delegation was created by the same compound RPC as the one
  731          *  with that Getattr in it.)
  732          * Don't worry about the 64bit number wrapping around. It ain't
  733          * gonna happen before this server gets shut down/rebooted.
  734          */
  735         nd->nd_compref = compref++;
  736 
  737         /*
  738          * Check for and optionally get a lock on the root. This lock means that
  739          * no nfsd will be fiddling with the V4 file system and state stuff. It
  740          * is required when the V4 root is being changed, the stable storage
  741          * restart file is being updated, or callbacks are being done.
  742          * When any of the nfsd are processing an NFSv4 compound RPC, they must
  743          * either hold a reference count (nfs_usecnt) or the lock. When
  744          * nfsrv_unlock() is called to release the lock, it can optionally
  745          * also get a reference count, which saves the need for a call to
  746          * nfsrv_getref() after nfsrv_unlock().
  747          */
  748         /*
  749          * First, check to see if we need to wait for an update lock.
  750          */
  751         igotlock = 0;
  752         NFSLOCKV4ROOTMUTEX();
  753         if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
  754                 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
  755                     NFSV4ROOTLOCKMUTEXPTR, NULL);
  756         else
  757                 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
  758                     NFSV4ROOTLOCKMUTEXPTR, NULL);
  759         NFSUNLOCKV4ROOTMUTEX();
  760         if (igotlock) {
  761                 /*
  762                  * If I got the lock, I can update the stable storage file.
  763                  * Done when the grace period is over or a client has long
  764                  * since expired.
  765                  */
  766                 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
  767                 if ((nfsrv_stablefirst.nsf_flags &
  768                     (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
  769                         nfsrv_updatestable(p);
  770 
  771                 /*
  772                  * If at least one client has long since expired, search
  773                  * the client list for them, write a REVOKE record on the
  774                  * stable storage file and then remove them from the client
  775                  * list.
  776                  */
  777                 if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) {
  778                         nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT;
  779                         for (i = 0; i < nfsrv_clienthashsize; i++) {
  780                             LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash,
  781                                 nclp) {
  782                                 if (clp->lc_flags & LCL_EXPIREIT) {
  783                                     if (!LIST_EMPTY(&clp->lc_open) ||
  784                                         !LIST_EMPTY(&clp->lc_deleg))
  785                                         nfsrv_writestable(clp->lc_id,
  786                                             clp->lc_idlen, NFSNST_REVOKE, p);
  787                                     nfsrv_cleanclient(clp, p);
  788                                     nfsrv_freedeleglist(&clp->lc_deleg);
  789                                     nfsrv_freedeleglist(&clp->lc_olddeleg);
  790                                     LIST_REMOVE(clp, lc_hash);
  791                                     nfsrv_zapclient(clp, p);
  792                                 }
  793                             }
  794                         }
  795                 }
  796                 NFSLOCKV4ROOTMUTEX();
  797                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
  798                 NFSUNLOCKV4ROOTMUTEX();
  799         } else {
  800                 /*
  801                  * If we didn't get the lock, we need to get a refcnt,
  802                  * which also checks for and waits for the lock.
  803                  */
  804                 NFSLOCKV4ROOTMUTEX();
  805                 nfsv4_getref(&nfsv4rootfs_lock, NULL,
  806                     NFSV4ROOTLOCKMUTEXPTR, NULL);
  807                 NFSUNLOCKV4ROOTMUTEX();
  808         }
  809 
  810         /*
  811          * If flagged, search for open owners that haven't had any opens
  812          * for a long time.
  813          */
  814         if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
  815                 nfsrv_throwawayopens(p);
  816         }
  817 
  818         /* Do a CBLAYOUTRECALL callback if over the high water mark. */
  819         if (nfsrv_layoutcnt > nfsrv_layouthighwater)
  820                 nfsrv_recalloldlayout(p);
  821 
  822         savevp = vp = NULL;
  823         save_fsid.val[0] = save_fsid.val[1] = 0;
  824         cur_fsid.val[0] = cur_fsid.val[1] = 0;
  825 
  826         /* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
  827         if (taglen < 0) {
  828                 error = EBADRPC;
  829                 goto nfsmout;
  830         }
  831 
  832         (void) nfsm_strtom(nd, tag, taglen);
  833         NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
  834         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
  835         if ((minorvers != NFSV4_MINORVERSION &&
  836             minorvers != NFSV41_MINORVERSION &&
  837             minorvers != NFSV42_MINORVERSION) ||
  838             minorvers < nfs_minminorv4 || minorvers > nfs_maxminorv4)
  839                 nd->nd_repstat = NFSERR_MINORVERMISMATCH;
  840         if (nd->nd_repstat)
  841                 numops = 0;
  842         else
  843                 numops = fxdr_unsigned(int, *tl);
  844         /*
  845          * Loop around doing the sub ops.
  846          * vp - is an unlocked vnode pointer for the CFH
  847          * savevp - is an unlocked vnode pointer for the SAVEDFH
  848          * (at some future date, it might turn out to be more appropriate
  849          *  to keep the file handles instead of vnode pointers?)
  850          * savevpnes and vpnes - are the export flags for the above.
  851          */
  852         for (i = 0; i < numops; i++) {
  853                 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
  854                 NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
  855                 *repp = *tl;
  856                 op = fxdr_unsigned(int, *tl);
  857                 NFSD_DEBUG(4, "op=%d\n", op);
  858                 if (op < NFSV4OP_ACCESS || op >= NFSV42_NOPS ||
  859                     (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
  860                     (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV42) == 0)) {
  861                         nd->nd_repstat = NFSERR_OPILLEGAL;
  862                         *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
  863                         *repp = nfsd_errmap(nd);
  864                         retops++;
  865                         break;
  866                 } else {
  867                         repp++;
  868                 }
  869 
  870                 binuptime(&start_time);
  871                 nfsrvd_statstart(op, &start_time);
  872                 statsinprog = 1;
  873 
  874                 if (i == 0)
  875                         op0 = op;
  876                 if (i == numops - 1)
  877                         nd->nd_flag |= ND_LASTOP;
  878 
  879                 /*
  880                  * Check for a referral on the current FH and, if so, return
  881                  * NFSERR_MOVED for all ops that allow it, except Getattr.
  882                  */
  883                 if (vp != NULL && op != NFSV4OP_GETATTR &&
  884                     nfsv4root_getreferral(vp, NULL, 0) != NULL &&
  885                     nfsrv_errmoved(op)) {
  886                         nd->nd_repstat = NFSERR_MOVED;
  887                         *repp = nfsd_errmap(nd);
  888                         retops++;
  889                         break;
  890                 }
  891 
  892                 /*
  893                  * For NFSv4.1, check for a Sequence Operation being first
  894                  * or one of the other allowed operations by itself.
  895                  */
  896                 if ((nd->nd_flag & ND_NFSV41) != 0) {
  897                         if (i != 0 && op == NFSV4OP_SEQUENCE)
  898                                 nd->nd_repstat = NFSERR_SEQUENCEPOS;
  899                         else if (i == 0 && op != NFSV4OP_SEQUENCE &&
  900                             op != NFSV4OP_EXCHANGEID &&
  901                             op != NFSV4OP_CREATESESSION &&
  902                             op != NFSV4OP_BINDCONNTOSESS &&
  903                             op != NFSV4OP_DESTROYCLIENTID &&
  904                             op != NFSV4OP_DESTROYSESSION)
  905                                 nd->nd_repstat = NFSERR_OPNOTINSESS;
  906                         else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
  907                                 nd->nd_repstat = NFSERR_NOTONLYOP;
  908                         if (nd->nd_repstat != 0) {
  909                                 *repp = nfsd_errmap(nd);
  910                                 retops++;
  911                                 break;
  912                         }
  913                 }
  914 
  915                 nd->nd_procnum = op;
  916                 /*
  917                  * If over flood level, reply NFSERR_RESOURCE, if at the first
  918                  * Op. (Since a client recovery from NFSERR_RESOURCE can get
  919                  * really nasty for certain Op sequences, I'll play it safe
  920                  * and only return the error at the beginning.) The cache
  921                  * will still function over flood level, but uses lots of
  922                  * mbufs.)
  923                  * If nfsrv_mallocmget_limit() returns True, the system is near
  924                  * to its limit for memory that malloc()/mget() can allocate.
  925                  */
  926                 if (i == 0 && (nd->nd_rp == NULL ||
  927                     nd->nd_rp->rc_refcnt == 0) &&
  928                     (nfsrv_mallocmget_limit() ||
  929                      nfsrc_tcpsavedreplies > nfsrc_floodlevel)) {
  930                         if (nfsrc_tcpsavedreplies > nfsrc_floodlevel)
  931                                 printf("nfsd server cache flooded, try "
  932                                     "increasing vfs.nfsd.tcphighwater\n");
  933                         nd->nd_repstat = NFSERR_RESOURCE;
  934                         *repp = nfsd_errmap(nd);
  935                         if (op == NFSV4OP_SETATTR) {
  936                                 /*
  937                                  * Setattr replies require a bitmap.
  938                                  * even for errors like these.
  939                                  */
  940                                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
  941                                 *tl = 0;
  942                         }
  943                         retops++;
  944                         break;
  945                 }
  946                 if (nfsv4_opflag[op].savereply)
  947                         nd->nd_flag |= ND_SAVEREPLY;
  948                 switch (op) {
  949                 case NFSV4OP_PUTFH:
  950                         error = nfsrv_mtofh(nd, &fh);
  951                         if (error)
  952                                 goto nfsmout;
  953                         if (!nd->nd_repstat)
  954                                 nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
  955                                     NULL, 0);
  956                         /* For now, allow this for non-export FHs */
  957                         if (!nd->nd_repstat) {
  958                                 if (vp)
  959                                         vrele(vp);
  960                                 vp = nvp;
  961                                 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
  962                                 NFSVOPUNLOCK(vp);
  963                                 vpnes = nes;
  964                         }
  965                         break;
  966                 case NFSV4OP_PUTPUBFH:
  967                         if (nfs_pubfhset)
  968                             nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
  969                                 &nes, NULL, 0);
  970                         else
  971                             nd->nd_repstat = NFSERR_NOFILEHANDLE;
  972                         if (!nd->nd_repstat) {
  973                                 if (vp)
  974                                         vrele(vp);
  975                                 vp = nvp;
  976                                 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
  977                                 NFSVOPUNLOCK(vp);
  978                                 vpnes = nes;
  979                         }
  980                         break;
  981                 case NFSV4OP_PUTROOTFH:
  982                         if (nfs_rootfhset) {
  983                                 nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
  984                                     &nes, NULL, 0);
  985                                 if (!nd->nd_repstat) {
  986                                         if (vp)
  987                                                 vrele(vp);
  988                                         vp = nvp;
  989                                         cur_fsid = vp->v_mount->mnt_stat.f_fsid;
  990                                         NFSVOPUNLOCK(vp);
  991                                         vpnes = nes;
  992                                 }
  993                         } else
  994                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
  995                         break;
  996                 case NFSV4OP_SAVEFH:
  997                         if (vp && NFSVNO_EXPORTED(&vpnes)) {
  998                                 nd->nd_repstat = 0;
  999                                 /* If vp == savevp, a no-op */
 1000                                 if (vp != savevp) {
 1001                                         if (savevp)
 1002                                                 vrele(savevp);
 1003                                         VREF(vp);
 1004                                         savevp = vp;
 1005                                         savevpnes = vpnes;
 1006                                         save_fsid = cur_fsid;
 1007                                 }
 1008                                 if ((nd->nd_flag & ND_CURSTATEID) != 0) {
 1009                                         nd->nd_savedcurstateid =
 1010                                             nd->nd_curstateid;
 1011                                         nd->nd_flag |= ND_SAVEDCURSTATEID;
 1012                                 }
 1013                         } else {
 1014                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
 1015                         }
 1016                         break;
 1017                 case NFSV4OP_RESTOREFH:
 1018                         if (savevp) {
 1019                                 nd->nd_repstat = 0;
 1020                                 /* If vp == savevp, a no-op */
 1021                                 if (vp != savevp) {
 1022                                         VREF(savevp);
 1023                                         vrele(vp);
 1024                                         vp = savevp;
 1025                                         vpnes = savevpnes;
 1026                                         cur_fsid = save_fsid;
 1027                                 }
 1028                                 if ((nd->nd_flag & ND_SAVEDCURSTATEID) != 0) {
 1029                                         nd->nd_curstateid =
 1030                                             nd->nd_savedcurstateid;
 1031                                         nd->nd_flag |= ND_CURSTATEID;
 1032                                 }
 1033                         } else {
 1034                                 nd->nd_repstat = NFSERR_RESTOREFH;
 1035                         }
 1036                         break;
 1037                 default:
 1038                     /*
 1039                      * Allow a Lookup, Getattr, GetFH, Secinfo on an
 1040                      * non-exported directory if
 1041                      * nfs_rootfhset. Do I need to allow any other Ops?
 1042                      * (You can only have a non-exported vpnes if
 1043                      *  nfs_rootfhset is true. See nfsd_fhtovp())
 1044                      * Allow AUTH_SYS to be used for file systems
 1045                      * exported GSS only for certain Ops, to allow
 1046                      * clients to do mounts more easily.
 1047                      */
 1048                     if (nfsv4_opflag[op].needscfh && vp) {
 1049                         if (!NFSVNO_EXPORTED(&vpnes) &&
 1050                             op != NFSV4OP_LOOKUP &&
 1051                             op != NFSV4OP_GETATTR &&
 1052                             op != NFSV4OP_GETFH &&
 1053                             op != NFSV4OP_ACCESS &&
 1054                             op != NFSV4OP_READLINK &&
 1055                             op != NFSV4OP_SECINFO)
 1056                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
 1057                         else if (nfsvno_testexp(nd, &vpnes) &&
 1058                             op != NFSV4OP_LOOKUP &&
 1059                             op != NFSV4OP_GETFH &&
 1060                             op != NFSV4OP_GETATTR &&
 1061                             op != NFSV4OP_SECINFO)
 1062                                 nd->nd_repstat = NFSERR_WRONGSEC;
 1063                         if (nd->nd_repstat) {
 1064                                 if (op == NFSV4OP_SETATTR) {
 1065                                     /*
 1066                                      * Setattr reply requires a bitmap
 1067                                      * even for errors like these.
 1068                                      */
 1069                                     NFSM_BUILD(tl, u_int32_t *,
 1070                                         NFSX_UNSIGNED);
 1071                                     *tl = 0;
 1072                                 }
 1073                                 break;
 1074                         }
 1075                     }
 1076 
 1077                     /*
 1078                      * Save the current positions in the mbuf lists so
 1079                      * that a rollback to this location can be done upon a
 1080                      * redo due to a ERELOOKUP return for a operation.
 1081                      */
 1082                     mb = nd->nd_mb;
 1083                     bpos = nd->nd_bpos;
 1084                     bextpg = nd->nd_bextpg;
 1085                     bextpgsiz = nd->nd_bextpgsiz;
 1086                     md = nd->nd_md;
 1087                     dpos = nd->nd_dpos;
 1088 tryagain:
 1089 
 1090                     if (nfsv4_opflag[op].retfh == 1) {
 1091                         if (!vp) {
 1092                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
 1093                                 break;
 1094                         }
 1095                         VREF(vp);
 1096                         if (nfsv4_opflag[op].modifyfs)
 1097                                 vn_start_write(vp, &temp_mp, V_WAIT);
 1098                         error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
 1099                             &nvp, (fhandle_t *)fh.nfsrvfh_data, &vpnes);
 1100                         if (!error && !nd->nd_repstat) {
 1101                             if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
 1102                                 new_mp = nvp->v_mount;
 1103                                 if (fsidcmp(&cur_fsid, &new_mp->mnt_stat.f_fsid) != 0) {
 1104                                     /* crossed a server mount point */
 1105                                     nd->nd_repstat = nfsvno_checkexp(new_mp,
 1106                                         nd->nd_nam, &nes, &credanon);
 1107                                     if (!nd->nd_repstat)
 1108                                         nd->nd_repstat = nfsd_excred(nd,
 1109                                             &nes, credanon);
 1110                                     if (credanon != NULL)
 1111                                         crfree(credanon);
 1112                                     if (!nd->nd_repstat) {
 1113                                         vpnes = nes;
 1114                                         cur_fsid = new_mp->mnt_stat.f_fsid;
 1115                                     }
 1116                                 }
 1117                                 /* Lookup ops return a locked vnode */
 1118                                 NFSVOPUNLOCK(nvp);
 1119                             }
 1120                             if (!nd->nd_repstat) {
 1121                                     vrele(vp);
 1122                                     vp = nvp;
 1123                             } else
 1124                                     vrele(nvp);
 1125                         }
 1126                         if (nfsv4_opflag[op].modifyfs)
 1127                                 vn_finished_write(temp_mp);
 1128                     } else if (nfsv4_opflag[op].retfh == 2) {
 1129                         if (vp == NULL || savevp == NULL) {
 1130                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
 1131                                 break;
 1132                         } else if (fsidcmp(&cur_fsid, &save_fsid) != 0) {
 1133                                 nd->nd_repstat = NFSERR_XDEV;
 1134                                 break;
 1135                         }
 1136                         if (nfsv4_opflag[op].modifyfs)
 1137                                 vn_start_write(savevp, &temp_mp, V_WAIT);
 1138                         if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
 1139                                 VREF(vp);
 1140                                 VREF(savevp);
 1141                                 error = (*(nfsrv4_ops2[op]))(nd, isdgram,
 1142                                     savevp, vp, &savevpnes, &vpnes);
 1143                         } else
 1144                                 nd->nd_repstat = NFSERR_PERM;
 1145                         if (nfsv4_opflag[op].modifyfs)
 1146                                 vn_finished_write(temp_mp);
 1147                     } else {
 1148                         if (nfsv4_opflag[op].retfh != 0)
 1149                                 panic("nfsrvd_compound");
 1150                         if (nfsv4_opflag[op].needscfh) {
 1151                                 if (vp != NULL) {
 1152                                         lktype = nfsv4_opflag[op].lktype;
 1153                                         if (nfsv4_opflag[op].modifyfs) {
 1154                                                 vn_start_write(vp, &temp_mp,
 1155                                                     V_WAIT);
 1156                                                 if (op == NFSV4OP_WRITE &&
 1157                                                     MNT_SHARED_WRITES(temp_mp))
 1158                                                         lktype = LK_SHARED;
 1159                                         }
 1160                                         if (NFSVOPLOCK(vp, lktype) == 0)
 1161                                                 VREF(vp);
 1162                                         else
 1163                                                 nd->nd_repstat = NFSERR_PERM;
 1164                                 } else {
 1165                                         nd->nd_repstat = NFSERR_NOFILEHANDLE;
 1166                                         if (op == NFSV4OP_SETATTR) {
 1167                                                 /*
 1168                                                  * Setattr reply requires a
 1169                                                  * bitmap even for errors like
 1170                                                  * these.
 1171                                                  */
 1172                                                 NFSM_BUILD(tl, u_int32_t *,
 1173                                                     NFSX_UNSIGNED);
 1174                                                 *tl = 0;
 1175                                         }
 1176                                         break;
 1177                                 }
 1178                                 if (nd->nd_repstat == 0)
 1179                                         error = (*(nfsrv4_ops0[op]))(nd,
 1180                                             isdgram, vp, &vpnes);
 1181                                 if (nfsv4_opflag[op].modifyfs)
 1182                                         vn_finished_write(temp_mp);
 1183                         } else {
 1184                                 error = (*(nfsrv4_ops0[op]))(nd, isdgram,
 1185                                     NULL, &vpnes);
 1186                         }
 1187                     }
 1188                 }
 1189                 if (error) {
 1190                         if (error == EBADRPC || error == NFSERR_BADXDR) {
 1191                                 nd->nd_repstat = NFSERR_BADXDR;
 1192                         } else {
 1193                                 nd->nd_repstat = error;
 1194                                 printf("nfsv4 comperr0=%d\n", error);
 1195                         }
 1196                         error = 0;
 1197                 }
 1198 
 1199                 if (nd->nd_repstat == ERELOOKUP) {
 1200                         /*
 1201                          * Roll back to the beginning of the operation
 1202                          * arguments.
 1203                          */
 1204                         nd->nd_md = md;
 1205                         nd->nd_dpos = dpos;
 1206 
 1207                         /*
 1208                          * Trim off the bogus reply for this operation
 1209                          * and redo the operation.
 1210                          */
 1211                         nfsm_trimtrailing(nd, mb, bpos, bextpg, bextpgsiz);
 1212                         nd->nd_repstat = 0;
 1213                         nd->nd_flag |= ND_ERELOOKUP;
 1214                         goto tryagain;
 1215                 }
 1216                 nd->nd_flag &= ~ND_ERELOOKUP;
 1217 
 1218                 if (statsinprog != 0) {
 1219                         nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
 1220                             /*then*/ &start_time);
 1221                         statsinprog = 0;
 1222                 }
 1223 
 1224                 retops++;
 1225                 if (nd->nd_repstat) {
 1226                         *repp = nfsd_errmap(nd);
 1227                         break;
 1228                 } else {
 1229                         *repp = 0;      /* NFS4_OK */
 1230                 }
 1231         }
 1232 nfsmout:
 1233         if (statsinprog != 0) {
 1234                 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
 1235                     /*then*/ &start_time);
 1236                 statsinprog = 0;
 1237         }
 1238         if (error) {
 1239                 if (error == EBADRPC || error == NFSERR_BADXDR)
 1240                         nd->nd_repstat = NFSERR_BADXDR;
 1241                 else
 1242                         printf("nfsv4 comperr1=%d\n", error);
 1243         }
 1244         if (taglen == -1) {
 1245                 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 1246                 *tl++ = 0;
 1247                 *tl = 0;
 1248         } else {
 1249                 *retopsp = txdr_unsigned(retops);
 1250         }
 1251         if (vp)
 1252                 vrele(vp);
 1253         if (savevp)
 1254                 vrele(savevp);
 1255         NFSLOCKV4ROOTMUTEX();
 1256         nfsv4_relref(&nfsv4rootfs_lock);
 1257         NFSUNLOCKV4ROOTMUTEX();
 1258 
 1259         NFSEXITCODE2(0, nd);
 1260 }

Cache object: e5c76d6231cd010c9c6e35b8c5a143d3


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