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_secinfononame,
  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_deallocate,
  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], -1);
  588                         else
  589                                 nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
  590                                     &mp, nfsrv_writerpc[nd->nd_procnum], -1);
  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, rstat, statsinprog = 0;
  706         u_int32_t *tl;
  707         struct nfsclient *clp, *nclp;
  708         int error = 0, igotlock, nextop, numops, savefhcnt;
  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         /* Check for and optionally clear the no space flags for DSs. */
  726         nfsrv_checknospc();
  727 
  728         NFSVNO_EXINIT(&vpnes);
  729         NFSVNO_EXINIT(&savevpnes);
  730         /*
  731          * Put the seq# of the current compound RPC in nfsrv_descript.
  732          * (This is used by nfsrv_checkgetattr(), to see if the write
  733          *  delegation was created by the same compound RPC as the one
  734          *  with that Getattr in it.)
  735          * Don't worry about the 64bit number wrapping around. It ain't
  736          * gonna happen before this server gets shut down/rebooted.
  737          */
  738         nd->nd_compref = compref++;
  739 
  740         /*
  741          * Check for and optionally get a lock on the root. This lock means that
  742          * no nfsd will be fiddling with the V4 file system and state stuff. It
  743          * is required when the V4 root is being changed, the stable storage
  744          * restart file is being updated, or callbacks are being done.
  745          * When any of the nfsd are processing an NFSv4 compound RPC, they must
  746          * either hold a reference count (nfs_usecnt) or the lock. When
  747          * nfsrv_unlock() is called to release the lock, it can optionally
  748          * also get a reference count, which saves the need for a call to
  749          * nfsrv_getref() after nfsrv_unlock().
  750          */
  751         /*
  752          * First, check to see if we need to wait for an update lock.
  753          */
  754         igotlock = 0;
  755         NFSLOCKV4ROOTMUTEX();
  756         if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
  757                 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
  758                     NFSV4ROOTLOCKMUTEXPTR, NULL);
  759         else
  760                 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
  761                     NFSV4ROOTLOCKMUTEXPTR, NULL);
  762         NFSUNLOCKV4ROOTMUTEX();
  763         if (igotlock) {
  764                 /*
  765                  * If I got the lock, I can update the stable storage file.
  766                  * Done when the grace period is over or a client has long
  767                  * since expired.
  768                  */
  769                 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
  770                 if ((nfsrv_stablefirst.nsf_flags &
  771                     (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
  772                         nfsrv_updatestable(p);
  773 
  774                 /*
  775                  * If at least one client has long since expired, search
  776                  * the client list for them, write a REVOKE record on the
  777                  * stable storage file and then remove them from the client
  778                  * list.
  779                  */
  780                 if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) {
  781                         nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT;
  782                         for (i = 0; i < nfsrv_clienthashsize; i++) {
  783                             LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash,
  784                                 nclp) {
  785                                 if (clp->lc_flags & LCL_EXPIREIT) {
  786                                     if (!LIST_EMPTY(&clp->lc_open) ||
  787                                         !LIST_EMPTY(&clp->lc_deleg))
  788                                         nfsrv_writestable(clp->lc_id,
  789                                             clp->lc_idlen, NFSNST_REVOKE, p);
  790                                     nfsrv_cleanclient(clp, p);
  791                                     nfsrv_freedeleglist(&clp->lc_deleg);
  792                                     nfsrv_freedeleglist(&clp->lc_olddeleg);
  793                                     LIST_REMOVE(clp, lc_hash);
  794                                     nfsrv_zapclient(clp, p);
  795                                 }
  796                             }
  797                         }
  798                 }
  799                 NFSLOCKV4ROOTMUTEX();
  800                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
  801                 NFSUNLOCKV4ROOTMUTEX();
  802         } else {
  803                 /*
  804                  * If we didn't get the lock, we need to get a refcnt,
  805                  * which also checks for and waits for the lock.
  806                  */
  807                 NFSLOCKV4ROOTMUTEX();
  808                 nfsv4_getref(&nfsv4rootfs_lock, NULL,
  809                     NFSV4ROOTLOCKMUTEXPTR, NULL);
  810                 NFSUNLOCKV4ROOTMUTEX();
  811         }
  812 
  813         /*
  814          * If flagged, search for open owners that haven't had any opens
  815          * for a long time.
  816          */
  817         if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
  818                 nfsrv_throwawayopens(p);
  819         }
  820 
  821         /* Do a CBLAYOUTRECALL callback if over the high water mark. */
  822         if (nfsrv_layoutcnt > nfsrv_layouthighwater)
  823                 nfsrv_recalloldlayout(p);
  824 
  825         savevp = vp = NULL;
  826         save_fsid.val[0] = save_fsid.val[1] = 0;
  827         cur_fsid.val[0] = cur_fsid.val[1] = 0;
  828         nextop = -1;
  829         savefhcnt = 0;
  830 
  831         /* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
  832         if (taglen < 0) {
  833                 error = EBADRPC;
  834                 goto nfsmout;
  835         }
  836 
  837         (void) nfsm_strtom(nd, tag, taglen);
  838         NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
  839         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
  840         if ((minorvers != NFSV4_MINORVERSION &&
  841             minorvers != NFSV41_MINORVERSION &&
  842             minorvers != NFSV42_MINORVERSION) ||
  843             minorvers < nfs_minminorv4 || minorvers > nfs_maxminorv4)
  844                 nd->nd_repstat = NFSERR_MINORVERMISMATCH;
  845         if (nd->nd_repstat)
  846                 numops = 0;
  847         else
  848                 numops = fxdr_unsigned(int, *tl);
  849         /*
  850          * Loop around doing the sub ops.
  851          * vp - is an unlocked vnode pointer for the CFH
  852          * savevp - is an unlocked vnode pointer for the SAVEDFH
  853          * (at some future date, it might turn out to be more appropriate
  854          *  to keep the file handles instead of vnode pointers?)
  855          * savevpnes and vpnes - are the export flags for the above.
  856          */
  857         for (i = 0; i < numops; i++) {
  858                 NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
  859                 if (savefhcnt > 0) {
  860                         op = NFSV4OP_SAVEFH;
  861                         *repp = txdr_unsigned(op);
  862                         savefhcnt--;
  863                 } else if (nextop == -1) {
  864                         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
  865                         *repp = *tl;
  866                         op = fxdr_unsigned(int, *tl);
  867                 } else {
  868                         op = nextop;
  869                         *repp = txdr_unsigned(op);
  870                         nextop = -1;
  871                 }
  872                 NFSD_DEBUG(4, "op=%d\n", op);
  873                 if (op < NFSV4OP_ACCESS || op >= NFSV42_NOPS ||
  874                     (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
  875                     (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV42) == 0)) {
  876                         nd->nd_repstat = NFSERR_OPILLEGAL;
  877                         *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
  878                         *repp = nfsd_errmap(nd);
  879                         retops++;
  880                         break;
  881                 } else {
  882                         repp++;
  883                 }
  884 
  885                 binuptime(&start_time);
  886                 nfsrvd_statstart(op, &start_time);
  887                 statsinprog = 1;
  888 
  889                 if (i == 0)
  890                         op0 = op;
  891                 if (i == numops - 1)
  892                         nd->nd_flag |= ND_LASTOP;
  893 
  894                 /*
  895                  * Check for a referral on the current FH and, if so, return
  896                  * NFSERR_MOVED for all ops that allow it, except Getattr.
  897                  */
  898                 if (vp != NULL && op != NFSV4OP_GETATTR &&
  899                     nfsv4root_getreferral(vp, NULL, 0) != NULL &&
  900                     nfsrv_errmoved(op)) {
  901                         nd->nd_repstat = NFSERR_MOVED;
  902                         *repp = nfsd_errmap(nd);
  903                         retops++;
  904                         break;
  905                 }
  906 
  907                 /*
  908                  * For NFSv4.1, check for a Sequence Operation being first
  909                  * or one of the other allowed operations by itself.
  910                  */
  911                 if ((nd->nd_flag & ND_NFSV41) != 0) {
  912                         if (i != 0 && op == NFSV4OP_SEQUENCE)
  913                                 nd->nd_repstat = NFSERR_SEQUENCEPOS;
  914                         else if (i == 0 && op != NFSV4OP_SEQUENCE &&
  915                             op != NFSV4OP_EXCHANGEID &&
  916                             op != NFSV4OP_CREATESESSION &&
  917                             op != NFSV4OP_BINDCONNTOSESS &&
  918                             op != NFSV4OP_DESTROYCLIENTID &&
  919                             op != NFSV4OP_DESTROYSESSION)
  920                                 nd->nd_repstat = NFSERR_OPNOTINSESS;
  921                         else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
  922                                 nd->nd_repstat = NFSERR_NOTONLYOP;
  923                         if (nd->nd_repstat != 0) {
  924                                 *repp = nfsd_errmap(nd);
  925                                 retops++;
  926                                 break;
  927                         }
  928                 }
  929 
  930                 nd->nd_procnum = op;
  931                 /*
  932                  * If over flood level, reply NFSERR_RESOURCE, if at the first
  933                  * Op. (Since a client recovery from NFSERR_RESOURCE can get
  934                  * really nasty for certain Op sequences, I'll play it safe
  935                  * and only return the error at the beginning.) The cache
  936                  * will still function over flood level, but uses lots of
  937                  * mbufs.)
  938                  * If nfsrv_mallocmget_limit() returns True, the system is near
  939                  * to its limit for memory that malloc()/mget() can allocate.
  940                  */
  941                 if (i == 0 && (nd->nd_rp == NULL ||
  942                     nd->nd_rp->rc_refcnt == 0) &&
  943                     (nfsrv_mallocmget_limit() ||
  944                      nfsrc_tcpsavedreplies > nfsrc_floodlevel)) {
  945                         if (nfsrc_tcpsavedreplies > nfsrc_floodlevel)
  946                                 printf("nfsd server cache flooded, try "
  947                                     "increasing vfs.nfsd.tcphighwater\n");
  948                         nd->nd_repstat = NFSERR_RESOURCE;
  949                         *repp = nfsd_errmap(nd);
  950                         if (op == NFSV4OP_SETATTR) {
  951                                 /*
  952                                  * Setattr replies require a bitmap.
  953                                  * even for errors like these.
  954                                  */
  955                                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
  956                                 *tl = 0;
  957                         }
  958                         retops++;
  959                         break;
  960                 }
  961                 if (nfsv4_opflag[op].savereply)
  962                         nd->nd_flag |= ND_SAVEREPLY;
  963                 switch (op) {
  964                 case NFSV4OP_PUTFH:
  965                         error = nfsrv_mtofh(nd, &fh);
  966                         if (error)
  967                                 goto nfsmout;
  968                         if ((nd->nd_flag & ND_LASTOP) == 0) {
  969                                 /*
  970                                  * Pre-parse the next op#.  If it is
  971                                  * SaveFH, count it and skip to the
  972                                  * next op#, if not the last op#.
  973                                  * nextop is used to determine if
  974                                  * NFSERR_WRONGSEC can be returned,
  975                                  * per RFC5661 Sec. 2.6.
  976                                  */
  977                                 do {
  978                                         NFSM_DISSECT(tl, uint32_t *,
  979                                             NFSX_UNSIGNED);
  980                                         nextop = fxdr_unsigned(int, *tl);
  981                                         if (nextop == NFSV4OP_SAVEFH &&
  982                                             i < numops - 1)
  983                                                 savefhcnt++;
  984                                 } while (nextop == NFSV4OP_SAVEFH &&
  985                                     i < numops - 1);
  986                         }
  987                         if (!nd->nd_repstat)
  988                                 nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
  989                                     NULL, 0, nextop);
  990                         /* For now, allow this for non-export FHs */
  991                         if (!nd->nd_repstat) {
  992                                 if (vp)
  993                                         vrele(vp);
  994                                 vp = nvp;
  995                                 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
  996                                 NFSVOPUNLOCK(vp);
  997                                 vpnes = nes;
  998                         }
  999                         break;
 1000                 case NFSV4OP_PUTPUBFH:
 1001                         if (nfs_pubfhset) {
 1002                                 if ((nd->nd_flag & ND_LASTOP) == 0) {
 1003                                         /*
 1004                                          * Pre-parse the next op#.  If it is
 1005                                          * SaveFH, count it and skip to the
 1006                                          * next op#, if not the last op#.
 1007                                          * nextop is used to determine if
 1008                                          * NFSERR_WRONGSEC can be returned,
 1009                                          * per RFC5661 Sec. 2.6.
 1010                                          */
 1011                                         do {
 1012                                                 NFSM_DISSECT(tl, uint32_t *,
 1013                                                     NFSX_UNSIGNED);
 1014                                                 nextop = fxdr_unsigned(int,
 1015                                                     *tl);
 1016                                                 if (nextop == NFSV4OP_SAVEFH &&
 1017                                                     i < numops - 1)
 1018                                                         savefhcnt++;
 1019                                         } while (nextop == NFSV4OP_SAVEFH &&
 1020                                             i < numops - 1);
 1021                                 }
 1022                                 nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
 1023                                     &nes, NULL, 0, nextop);
 1024                         } else
 1025                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
 1026                         if (!nd->nd_repstat) {
 1027                                 if (vp)
 1028                                         vrele(vp);
 1029                                 vp = nvp;
 1030                                 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
 1031                                 NFSVOPUNLOCK(vp);
 1032                                 vpnes = nes;
 1033                         }
 1034                         break;
 1035                 case NFSV4OP_PUTROOTFH:
 1036                         if (nfs_rootfhset) {
 1037                                 if ((nd->nd_flag & ND_LASTOP) == 0) {
 1038                                         /*
 1039                                          * Pre-parse the next op#.  If it is
 1040                                          * SaveFH, count it and skip to the
 1041                                          * next op#, if not the last op#.
 1042                                          * nextop is used to determine if
 1043                                          * NFSERR_WRONGSEC can be returned,
 1044                                          * per RFC5661 Sec. 2.6.
 1045                                          */
 1046                                         do {
 1047                                                 NFSM_DISSECT(tl, uint32_t *,
 1048                                                     NFSX_UNSIGNED);
 1049                                                 nextop = fxdr_unsigned(int,
 1050                                                     *tl);
 1051                                                 if (nextop == NFSV4OP_SAVEFH &&
 1052                                                     i < numops - 1)
 1053                                                         savefhcnt++;
 1054                                         } while (nextop == NFSV4OP_SAVEFH &&
 1055                                             i < numops - 1);
 1056                                 }
 1057                                 nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
 1058                                     &nes, NULL, 0, nextop);
 1059                                 if (!nd->nd_repstat) {
 1060                                         if (vp)
 1061                                                 vrele(vp);
 1062                                         vp = nvp;
 1063                                         cur_fsid = vp->v_mount->mnt_stat.f_fsid;
 1064                                         NFSVOPUNLOCK(vp);
 1065                                         vpnes = nes;
 1066                                 }
 1067                         } else
 1068                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
 1069                         break;
 1070                 case NFSV4OP_SAVEFH:
 1071                         if (vp && NFSVNO_EXPORTED(&vpnes)) {
 1072                                 nd->nd_repstat = 0;
 1073                                 /* If vp == savevp, a no-op */
 1074                                 if (vp != savevp) {
 1075                                         if (savevp)
 1076                                                 vrele(savevp);
 1077                                         VREF(vp);
 1078                                         savevp = vp;
 1079                                         savevpnes = vpnes;
 1080                                         save_fsid = cur_fsid;
 1081                                 }
 1082                                 if ((nd->nd_flag & ND_CURSTATEID) != 0) {
 1083                                         nd->nd_savedcurstateid =
 1084                                             nd->nd_curstateid;
 1085                                         nd->nd_flag |= ND_SAVEDCURSTATEID;
 1086                                 }
 1087                         } else {
 1088                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
 1089                         }
 1090                         break;
 1091                 case NFSV4OP_RESTOREFH:
 1092                         if (savevp) {
 1093                                 if ((nd->nd_flag & ND_LASTOP) == 0) {
 1094                                         /*
 1095                                          * Pre-parse the next op#.  If it is
 1096                                          * SaveFH, count it and skip to the
 1097                                          * next op#, if not the last op#.
 1098                                          * nextop is used to determine if
 1099                                          * NFSERR_WRONGSEC can be returned,
 1100                                          * per RFC5661 Sec. 2.6.
 1101                                          */
 1102                                         do {
 1103                                                 NFSM_DISSECT(tl, uint32_t *,
 1104                                                     NFSX_UNSIGNED);
 1105                                                 nextop = fxdr_unsigned(int,
 1106                                                     *tl);
 1107                                                 if (nextop == NFSV4OP_SAVEFH &&
 1108                                                     i < numops - 1)
 1109                                                         savefhcnt++;
 1110                                         } while (nextop == NFSV4OP_SAVEFH &&
 1111                                             i < numops - 1);
 1112                                 }
 1113                                 nd->nd_repstat = 0;
 1114                                 /* If vp == savevp, a no-op */
 1115                                 if (vp != savevp) {
 1116                                         if (nfsrv_checkwrongsec(nd, nextop,
 1117                                             savevp->v_type))
 1118                                                 nd->nd_repstat =
 1119                                                     nfsvno_testexp(nd,
 1120                                                     &savevpnes);
 1121                                         if (nd->nd_repstat == 0) {
 1122                                                 VREF(savevp);
 1123                                                 vrele(vp);
 1124                                                 vp = savevp;
 1125                                                 vpnes = savevpnes;
 1126                                                 cur_fsid = save_fsid;
 1127                                         }
 1128                                 }
 1129                                 if (nd->nd_repstat == 0 &&
 1130                                      (nd->nd_flag & ND_SAVEDCURSTATEID) != 0) {
 1131                                         nd->nd_curstateid =
 1132                                             nd->nd_savedcurstateid;
 1133                                         nd->nd_flag |= ND_CURSTATEID;
 1134                                 }
 1135                         } else {
 1136                                 nd->nd_repstat = NFSERR_RESTOREFH;
 1137                         }
 1138                         break;
 1139                 default:
 1140                     /*
 1141                      * Allow a Lookup, Getattr, GetFH, Secinfo on an
 1142                      * non-exported directory if
 1143                      * nfs_rootfhset. Do I need to allow any other Ops?
 1144                      * (You can only have a non-exported vpnes if
 1145                      *  nfs_rootfhset is true. See nfsd_fhtovp())
 1146                      * Allow AUTH_SYS to be used for file systems
 1147                      * exported GSS only for certain Ops, to allow
 1148                      * clients to do mounts more easily.
 1149                      */
 1150                     if (nfsv4_opflag[op].needscfh && vp) {
 1151                         if (!NFSVNO_EXPORTED(&vpnes) &&
 1152                             op != NFSV4OP_LOOKUP &&
 1153                             op != NFSV4OP_GETATTR &&
 1154                             op != NFSV4OP_GETFH &&
 1155                             op != NFSV4OP_ACCESS &&
 1156                             op != NFSV4OP_READLINK &&
 1157                             op != NFSV4OP_SECINFO &&
 1158                             op != NFSV4OP_SECINFONONAME)
 1159                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
 1160                         if (nd->nd_repstat) {
 1161                                 if (op == NFSV4OP_SETATTR) {
 1162                                     /*
 1163                                      * Setattr reply requires a bitmap
 1164                                      * even for errors like these.
 1165                                      */
 1166                                     NFSM_BUILD(tl, u_int32_t *,
 1167                                         NFSX_UNSIGNED);
 1168                                     *tl = 0;
 1169                                 }
 1170                                 break;
 1171                         }
 1172                     }
 1173 
 1174                     /*
 1175                      * Save the current positions in the mbuf lists so
 1176                      * that a rollback to this location can be done upon a
 1177                      * redo due to a ERELOOKUP return for a operation.
 1178                      */
 1179                     mb = nd->nd_mb;
 1180                     bpos = nd->nd_bpos;
 1181                     bextpg = nd->nd_bextpg;
 1182                     bextpgsiz = nd->nd_bextpgsiz;
 1183                     md = nd->nd_md;
 1184                     dpos = nd->nd_dpos;
 1185 tryagain:
 1186 
 1187                     if (nfsv4_opflag[op].retfh == 1) {
 1188                         if (!vp) {
 1189                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
 1190                                 break;
 1191                         }
 1192                         if (NFSVNO_EXPORTED(&vpnes) && (op == NFSV4OP_LOOKUP ||
 1193                             op == NFSV4OP_LOOKUPP || (op == NFSV4OP_OPEN &&
 1194                             vp->v_type == VDIR))) {
 1195                                 /* Check for wrong security. */
 1196                                 rstat = nfsvno_testexp(nd, &vpnes);
 1197                                 if (rstat != 0) {
 1198                                         nd->nd_repstat = rstat;
 1199                                         break;
 1200                                 }
 1201                         }
 1202                         VREF(vp);
 1203                         if (nfsv4_opflag[op].modifyfs)
 1204                                 vn_start_write(vp, &temp_mp, V_WAIT);
 1205                         error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
 1206                             &nvp, (fhandle_t *)fh.nfsrvfh_data, &vpnes);
 1207                         if (!error && !nd->nd_repstat) {
 1208                             if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
 1209                                 new_mp = nvp->v_mount;
 1210                                 if (fsidcmp(&cur_fsid, &new_mp->mnt_stat.f_fsid) != 0) {
 1211                                     /* crossed a server mount point */
 1212                                     nd->nd_repstat = nfsvno_checkexp(new_mp,
 1213                                         nd->nd_nam, &nes, &credanon);
 1214                                     if (!nd->nd_repstat)
 1215                                         nd->nd_repstat = nfsd_excred(nd,
 1216                                             &nes, credanon, true);
 1217                                     if (credanon != NULL)
 1218                                         crfree(credanon);
 1219                                     if (!nd->nd_repstat) {
 1220                                         vpnes = nes;
 1221                                         cur_fsid = new_mp->mnt_stat.f_fsid;
 1222                                     }
 1223                                 }
 1224                                 /* Lookup ops return a locked vnode */
 1225                                 NFSVOPUNLOCK(nvp);
 1226                             }
 1227                             if (!nd->nd_repstat) {
 1228                                     vrele(vp);
 1229                                     vp = nvp;
 1230                             } else
 1231                                     vrele(nvp);
 1232                         }
 1233                         if (nfsv4_opflag[op].modifyfs)
 1234                                 vn_finished_write(temp_mp);
 1235                     } else if (nfsv4_opflag[op].retfh == 2) {
 1236                         if (vp == NULL || savevp == NULL) {
 1237                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
 1238                                 break;
 1239                         } else if (fsidcmp(&cur_fsid, &save_fsid) != 0) {
 1240                                 nd->nd_repstat = NFSERR_XDEV;
 1241                                 break;
 1242                         }
 1243                         if (nfsv4_opflag[op].modifyfs)
 1244                                 vn_start_write(savevp, &temp_mp, V_WAIT);
 1245                         if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
 1246                                 VREF(vp);
 1247                                 VREF(savevp);
 1248                                 error = (*(nfsrv4_ops2[op]))(nd, isdgram,
 1249                                     savevp, vp, &savevpnes, &vpnes);
 1250                         } else
 1251                                 nd->nd_repstat = NFSERR_PERM;
 1252                         if (nfsv4_opflag[op].modifyfs)
 1253                                 vn_finished_write(temp_mp);
 1254                     } else {
 1255                         if (nfsv4_opflag[op].retfh != 0)
 1256                                 panic("nfsrvd_compound");
 1257                         if (nfsv4_opflag[op].needscfh) {
 1258                                 if (vp != NULL) {
 1259                                         lktype = nfsv4_opflag[op].lktype;
 1260                                         if (nfsv4_opflag[op].modifyfs) {
 1261                                                 vn_start_write(vp, &temp_mp,
 1262                                                     V_WAIT);
 1263                                                 if (op == NFSV4OP_WRITE &&
 1264                                                     MNT_SHARED_WRITES(temp_mp))
 1265                                                         lktype = LK_SHARED;
 1266                                         }
 1267                                         if (NFSVOPLOCK(vp, lktype) == 0)
 1268                                                 VREF(vp);
 1269                                         else
 1270                                                 nd->nd_repstat = NFSERR_PERM;
 1271                                 } else {
 1272                                         nd->nd_repstat = NFSERR_NOFILEHANDLE;
 1273                                         if (op == NFSV4OP_SETATTR) {
 1274                                                 /*
 1275                                                  * Setattr reply requires a
 1276                                                  * bitmap even for errors like
 1277                                                  * these.
 1278                                                  */
 1279                                                 NFSM_BUILD(tl, u_int32_t *,
 1280                                                     NFSX_UNSIGNED);
 1281                                                 *tl = 0;
 1282                                         }
 1283                                         break;
 1284                                 }
 1285                                 if (nd->nd_repstat == 0) {
 1286                                         error = (*(nfsrv4_ops0[op]))(nd,
 1287                                             isdgram, vp, &vpnes);
 1288                                         if ((op == NFSV4OP_SECINFO ||
 1289                                              op == NFSV4OP_SECINFONONAME) &&
 1290                                             error == 0 && nd->nd_repstat == 0) {
 1291                                                 /*
 1292                                                  * Secinfo and Secinfo_no_name
 1293                                                  * consume the current FH.
 1294                                                  */
 1295                                                 vrele(vp);
 1296                                                 vp = NULL;
 1297                                         }
 1298                                 }
 1299                                 if (nfsv4_opflag[op].modifyfs)
 1300                                         vn_finished_write(temp_mp);
 1301                         } else {
 1302                                 error = (*(nfsrv4_ops0[op]))(nd, isdgram,
 1303                                     NULL, &vpnes);
 1304                         }
 1305                     }
 1306                 }
 1307                 if (error) {
 1308                         if (error == EBADRPC || error == NFSERR_BADXDR) {
 1309                                 nd->nd_repstat = NFSERR_BADXDR;
 1310                         } else {
 1311                                 nd->nd_repstat = error;
 1312                                 printf("nfsv4 comperr0=%d\n", error);
 1313                         }
 1314                         error = 0;
 1315                 }
 1316 
 1317                 if (nd->nd_repstat == ERELOOKUP) {
 1318                         /*
 1319                          * Roll back to the beginning of the operation
 1320                          * arguments.
 1321                          */
 1322                         nd->nd_md = md;
 1323                         nd->nd_dpos = dpos;
 1324 
 1325                         /*
 1326                          * Trim off the bogus reply for this operation
 1327                          * and redo the operation.
 1328                          */
 1329                         nfsm_trimtrailing(nd, mb, bpos, bextpg, bextpgsiz);
 1330                         nd->nd_repstat = 0;
 1331                         nd->nd_flag |= ND_ERELOOKUP;
 1332                         goto tryagain;
 1333                 }
 1334                 nd->nd_flag &= ~ND_ERELOOKUP;
 1335 
 1336                 if (statsinprog != 0) {
 1337                         nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
 1338                             /*then*/ &start_time);
 1339                         statsinprog = 0;
 1340                 }
 1341 
 1342                 retops++;
 1343                 if (nd->nd_repstat) {
 1344                         *repp = nfsd_errmap(nd);
 1345                         break;
 1346                 } else {
 1347                         *repp = 0;      /* NFS4_OK */
 1348                 }
 1349         }
 1350 nfsmout:
 1351         if (statsinprog != 0) {
 1352                 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
 1353                     /*then*/ &start_time);
 1354                 statsinprog = 0;
 1355         }
 1356         if (error) {
 1357                 if (error == EBADRPC || error == NFSERR_BADXDR)
 1358                         nd->nd_repstat = NFSERR_BADXDR;
 1359                 else
 1360                         printf("nfsv4 comperr1=%d\n", error);
 1361         }
 1362         if (taglen == -1) {
 1363                 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 1364                 *tl++ = 0;
 1365                 *tl = 0;
 1366         } else {
 1367                 *retopsp = txdr_unsigned(retops);
 1368         }
 1369         if (vp)
 1370                 vrele(vp);
 1371         if (savevp)
 1372                 vrele(savevp);
 1373         NFSLOCKV4ROOTMUTEX();
 1374         nfsv4_relref(&nfsv4rootfs_lock);
 1375         NFSUNLOCKV4ROOTMUTEX();
 1376 
 1377         NFSEXITCODE2(0, nd);
 1378 }

Cache object: 4b5cf990b1730c97b425bcd6c4b079e4


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