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/nfs/nfs_subs.c

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

    1 /*
    2  * Copyright (c) 1989, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * This code is derived from software contributed to Berkeley by
    6  * Rick Macklem at The University of Guelph.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *      This product includes software developed by the University of
   19  *      California, Berkeley and its contributors.
   20  * 4. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  *      @(#)nfs_subs.c  8.3 (Berkeley) 1/4/94
   37  * $FreeBSD: src/sys/nfs/nfs_subs.c,v 1.33.2.5 1999/12/12 07:28:50 dillon Exp $
   38  */
   39 
   40 /*
   41  * These functions support the macros and help fiddle mbuf chains for
   42  * the nfs op functions. They do things like create the rpc header and
   43  * copy data between mbuf chains and uio lists.
   44  */
   45 #include <sys/param.h>
   46 #include <sys/proc.h>
   47 #include <sys/systm.h>
   48 #include <sys/kernel.h>
   49 #include <sys/mount.h>
   50 #include <sys/vnode.h>
   51 #include <sys/namei.h>
   52 #include <sys/mbuf.h>
   53 #include <sys/socket.h>
   54 #include <sys/stat.h>
   55 #include <sys/malloc.h>
   56 #ifdef VFS_LKM
   57 #include <sys/sysent.h>
   58 #include <sys/syscall.h>
   59 #endif
   60 
   61 #include <vm/vm.h>
   62 #include <vm/vm_param.h>
   63 #include <vm/vm_object.h>
   64 #include <vm/vm_extern.h>
   65 #include <vm/vnode_pager.h>
   66 
   67 #include <nfs/rpcv2.h>
   68 #include <nfs/nfsproto.h>
   69 #include <nfs/nfsnode.h>
   70 #include <nfs/nfs.h>
   71 #include <nfs/xdr_subs.h>
   72 #include <nfs/nfsm_subs.h>
   73 #include <nfs/nfsmount.h>
   74 #include <nfs/nqnfs.h>
   75 #include <nfs/nfsrtt.h>
   76 
   77 #include <miscfs/specfs/specdev.h>
   78 
   79 #include <netinet/in.h>
   80 #ifdef ISO
   81 #include <netiso/iso.h>
   82 #endif
   83 
   84 /*
   85  * Data items converted to xdr at startup, since they are constant
   86  * This is kinda hokey, but may save a little time doing byte swaps
   87  */
   88 u_long nfs_xdrneg1;
   89 u_long rpc_call, rpc_vers, rpc_reply, rpc_msgdenied, rpc_autherr,
   90         rpc_mismatch, rpc_auth_unix, rpc_msgaccepted,
   91         rpc_auth_kerb;
   92 u_long nfs_prog, nqnfs_prog, nfs_true, nfs_false;
   93 
   94 /* And other global data */
   95 static u_long nfs_xid = 0;
   96 static enum vtype nv2tov_type[8]= {
   97         VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON,  VNON 
   98 };
   99 enum vtype nv3tov_type[8]= {
  100         VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO
  101 };
  102 
  103 int nfs_ticks;
  104 
  105 struct nfs_reqq nfs_reqq;
  106 struct nfssvc_sockhead nfssvc_sockhead;
  107 int nfssvc_sockhead_flag;
  108 struct nfsd_head nfsd_head;
  109 int nfsd_head_flag;
  110 struct nfs_bufq nfs_bufq;
  111 struct nqtimerhead nqtimerhead;
  112 struct nqfhhashhead *nqfhhashtbl;
  113 u_long nqfhhash;
  114 
  115 #ifndef NFS_NOSERVER
  116 /*
  117  * Mapping of old NFS Version 2 RPC numbers to generic numbers.
  118  */
  119 int nfsv3_procid[NFS_NPROCS] = {
  120         NFSPROC_NULL,
  121         NFSPROC_GETATTR,
  122         NFSPROC_SETATTR,
  123         NFSPROC_NOOP,
  124         NFSPROC_LOOKUP,
  125         NFSPROC_READLINK,
  126         NFSPROC_READ,
  127         NFSPROC_NOOP,
  128         NFSPROC_WRITE,
  129         NFSPROC_CREATE,
  130         NFSPROC_REMOVE,
  131         NFSPROC_RENAME,
  132         NFSPROC_LINK,
  133         NFSPROC_SYMLINK,
  134         NFSPROC_MKDIR,
  135         NFSPROC_RMDIR,
  136         NFSPROC_READDIR,
  137         NFSPROC_FSSTAT,
  138         NFSPROC_NOOP,
  139         NFSPROC_NOOP,
  140         NFSPROC_NOOP,
  141         NFSPROC_NOOP,
  142         NFSPROC_NOOP,
  143         NFSPROC_NOOP,
  144         NFSPROC_NOOP,
  145         NFSPROC_NOOP
  146 };
  147 
  148 #endif /* NFS_NOSERVER */
  149 /*
  150  * and the reverse mapping from generic to Version 2 procedure numbers
  151  */
  152 int nfsv2_procid[NFS_NPROCS] = {
  153         NFSV2PROC_NULL,
  154         NFSV2PROC_GETATTR,
  155         NFSV2PROC_SETATTR,
  156         NFSV2PROC_LOOKUP,
  157         NFSV2PROC_NOOP,
  158         NFSV2PROC_READLINK,
  159         NFSV2PROC_READ,
  160         NFSV2PROC_WRITE,
  161         NFSV2PROC_CREATE,
  162         NFSV2PROC_MKDIR,
  163         NFSV2PROC_SYMLINK,
  164         NFSV2PROC_CREATE,
  165         NFSV2PROC_REMOVE,
  166         NFSV2PROC_RMDIR,
  167         NFSV2PROC_RENAME,
  168         NFSV2PROC_LINK,
  169         NFSV2PROC_READDIR,
  170         NFSV2PROC_NOOP,
  171         NFSV2PROC_STATFS,
  172         NFSV2PROC_NOOP,
  173         NFSV2PROC_NOOP,
  174         NFSV2PROC_NOOP,
  175         NFSV2PROC_NOOP,
  176         NFSV2PROC_NOOP,
  177         NFSV2PROC_NOOP,
  178         NFSV2PROC_NOOP,
  179 };
  180 
  181 #ifndef NFS_NOSERVER
  182 /*
  183  * Maps errno values to nfs error numbers.
  184  * Use NFSERR_IO as the catch all for ones not specifically defined in
  185  * RFC 1094.
  186  */
  187 static u_char nfsrv_v2errmap[ELAST] = {
  188   NFSERR_PERM,  NFSERR_NOENT,   NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
  189   NFSERR_NXIO,  NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
  190   NFSERR_IO,    NFSERR_IO,      NFSERR_ACCES,   NFSERR_IO,      NFSERR_IO,
  191   NFSERR_IO,    NFSERR_EXIST,   NFSERR_IO,      NFSERR_NODEV,   NFSERR_NOTDIR,
  192   NFSERR_ISDIR, NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
  193   NFSERR_IO,    NFSERR_FBIG,    NFSERR_NOSPC,   NFSERR_IO,      NFSERR_ROFS,
  194   NFSERR_IO,    NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
  195   NFSERR_IO,    NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
  196   NFSERR_IO,    NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
  197   NFSERR_IO,    NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
  198   NFSERR_IO,    NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
  199   NFSERR_IO,    NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
  200   NFSERR_IO,    NFSERR_IO,      NFSERR_NAMETOL, NFSERR_IO,      NFSERR_IO,
  201   NFSERR_NOTEMPTY, NFSERR_IO,   NFSERR_IO,      NFSERR_DQUOT,   NFSERR_STALE,
  202   NFSERR_IO,    NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
  203   NFSERR_IO,    NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
  204   NFSERR_IO,
  205 };
  206 
  207 /*
  208  * Maps errno values to nfs error numbers.
  209  * Although it is not obvious whether or not NFS clients really care if
  210  * a returned error value is in the specified list for the procedure, the
  211  * safest thing to do is filter them appropriately. For Version 2, the
  212  * X/Open XNFS document is the only specification that defines error values
  213  * for each RPC (The RFC simply lists all possible error values for all RPCs),
  214  * so I have decided to not do this for Version 2.
  215  * The first entry is the default error return and the rest are the valid
  216  * errors for that RPC in increasing numeric order.
  217  */
  218 static short nfsv3err_null[] = {
  219         0,
  220         0,
  221 };
  222 
  223 static short nfsv3err_getattr[] = {
  224         NFSERR_IO,
  225         NFSERR_IO,
  226         NFSERR_STALE,
  227         NFSERR_BADHANDLE,
  228         NFSERR_SERVERFAULT,
  229         0,
  230 };
  231 
  232 static short nfsv3err_setattr[] = {
  233         NFSERR_IO,
  234         NFSERR_PERM,
  235         NFSERR_IO,
  236         NFSERR_ACCES,
  237         NFSERR_INVAL,
  238         NFSERR_NOSPC,
  239         NFSERR_ROFS,
  240         NFSERR_DQUOT,
  241         NFSERR_STALE,
  242         NFSERR_BADHANDLE,
  243         NFSERR_NOT_SYNC,
  244         NFSERR_SERVERFAULT,
  245         0,
  246 };
  247 
  248 static short nfsv3err_lookup[] = {
  249         NFSERR_IO,
  250         NFSERR_NOENT,
  251         NFSERR_IO,
  252         NFSERR_ACCES,
  253         NFSERR_NOTDIR,
  254         NFSERR_NAMETOL,
  255         NFSERR_STALE,
  256         NFSERR_BADHANDLE,
  257         NFSERR_SERVERFAULT,
  258         0,
  259 };
  260 
  261 static short nfsv3err_access[] = {
  262         NFSERR_IO,
  263         NFSERR_IO,
  264         NFSERR_STALE,
  265         NFSERR_BADHANDLE,
  266         NFSERR_SERVERFAULT,
  267         0,
  268 };
  269 
  270 static short nfsv3err_readlink[] = {
  271         NFSERR_IO,
  272         NFSERR_IO,
  273         NFSERR_ACCES,
  274         NFSERR_INVAL,
  275         NFSERR_STALE,
  276         NFSERR_BADHANDLE,
  277         NFSERR_NOTSUPP,
  278         NFSERR_SERVERFAULT,
  279         0,
  280 };
  281 
  282 static short nfsv3err_read[] = {
  283         NFSERR_IO,
  284         NFSERR_IO,
  285         NFSERR_NXIO,
  286         NFSERR_ACCES,
  287         NFSERR_INVAL,
  288         NFSERR_STALE,
  289         NFSERR_BADHANDLE,
  290         NFSERR_SERVERFAULT,
  291         0,
  292 };
  293 
  294 static short nfsv3err_write[] = {
  295         NFSERR_IO,
  296         NFSERR_IO,
  297         NFSERR_ACCES,
  298         NFSERR_INVAL,
  299         NFSERR_FBIG,
  300         NFSERR_NOSPC,
  301         NFSERR_ROFS,
  302         NFSERR_DQUOT,
  303         NFSERR_STALE,
  304         NFSERR_BADHANDLE,
  305         NFSERR_SERVERFAULT,
  306         0,
  307 };
  308 
  309 static short nfsv3err_create[] = {
  310         NFSERR_IO,
  311         NFSERR_IO,
  312         NFSERR_ACCES,
  313         NFSERR_EXIST,
  314         NFSERR_NOTDIR,
  315         NFSERR_NOSPC,
  316         NFSERR_ROFS,
  317         NFSERR_NAMETOL,
  318         NFSERR_DQUOT,
  319         NFSERR_STALE,
  320         NFSERR_BADHANDLE,
  321         NFSERR_NOTSUPP,
  322         NFSERR_SERVERFAULT,
  323         0,
  324 };
  325 
  326 static short nfsv3err_mkdir[] = {
  327         NFSERR_IO,
  328         NFSERR_IO,
  329         NFSERR_ACCES,
  330         NFSERR_EXIST,
  331         NFSERR_NOTDIR,
  332         NFSERR_NOSPC,
  333         NFSERR_ROFS,
  334         NFSERR_NAMETOL,
  335         NFSERR_DQUOT,
  336         NFSERR_STALE,
  337         NFSERR_BADHANDLE,
  338         NFSERR_NOTSUPP,
  339         NFSERR_SERVERFAULT,
  340         0,
  341 };
  342 
  343 static short nfsv3err_symlink[] = {
  344         NFSERR_IO,
  345         NFSERR_IO,
  346         NFSERR_ACCES,
  347         NFSERR_EXIST,
  348         NFSERR_NOTDIR,
  349         NFSERR_NOSPC,
  350         NFSERR_ROFS,
  351         NFSERR_NAMETOL,
  352         NFSERR_DQUOT,
  353         NFSERR_STALE,
  354         NFSERR_BADHANDLE,
  355         NFSERR_NOTSUPP,
  356         NFSERR_SERVERFAULT,
  357         0,
  358 };
  359 
  360 static short nfsv3err_mknod[] = {
  361         NFSERR_IO,
  362         NFSERR_IO,
  363         NFSERR_ACCES,
  364         NFSERR_EXIST,
  365         NFSERR_NOTDIR,
  366         NFSERR_NOSPC,
  367         NFSERR_ROFS,
  368         NFSERR_NAMETOL,
  369         NFSERR_DQUOT,
  370         NFSERR_STALE,
  371         NFSERR_BADHANDLE,
  372         NFSERR_NOTSUPP,
  373         NFSERR_SERVERFAULT,
  374         NFSERR_BADTYPE,
  375         0,
  376 };
  377 
  378 static short nfsv3err_remove[] = {
  379         NFSERR_IO,
  380         NFSERR_NOENT,
  381         NFSERR_IO,
  382         NFSERR_ACCES,
  383         NFSERR_NOTDIR,
  384         NFSERR_ROFS,
  385         NFSERR_NAMETOL,
  386         NFSERR_STALE,
  387         NFSERR_BADHANDLE,
  388         NFSERR_SERVERFAULT,
  389         0,
  390 };
  391 
  392 static short nfsv3err_rmdir[] = {
  393         NFSERR_IO,
  394         NFSERR_NOENT,
  395         NFSERR_IO,
  396         NFSERR_ACCES,
  397         NFSERR_EXIST,
  398         NFSERR_NOTDIR,
  399         NFSERR_INVAL,
  400         NFSERR_ROFS,
  401         NFSERR_NAMETOL,
  402         NFSERR_NOTEMPTY,
  403         NFSERR_STALE,
  404         NFSERR_BADHANDLE,
  405         NFSERR_NOTSUPP,
  406         NFSERR_SERVERFAULT,
  407         0,
  408 };
  409 
  410 static short nfsv3err_rename[] = {
  411         NFSERR_IO,
  412         NFSERR_NOENT,
  413         NFSERR_IO,
  414         NFSERR_ACCES,
  415         NFSERR_EXIST,
  416         NFSERR_XDEV,
  417         NFSERR_NOTDIR,
  418         NFSERR_ISDIR,
  419         NFSERR_INVAL,
  420         NFSERR_NOSPC,
  421         NFSERR_ROFS,
  422         NFSERR_MLINK,
  423         NFSERR_NAMETOL,
  424         NFSERR_NOTEMPTY,
  425         NFSERR_DQUOT,
  426         NFSERR_STALE,
  427         NFSERR_BADHANDLE,
  428         NFSERR_NOTSUPP,
  429         NFSERR_SERVERFAULT,
  430         0,
  431 };
  432 
  433 static short nfsv3err_link[] = {
  434         NFSERR_IO,
  435         NFSERR_IO,
  436         NFSERR_ACCES,
  437         NFSERR_EXIST,
  438         NFSERR_XDEV,
  439         NFSERR_NOTDIR,
  440         NFSERR_INVAL,
  441         NFSERR_NOSPC,
  442         NFSERR_ROFS,
  443         NFSERR_MLINK,
  444         NFSERR_NAMETOL,
  445         NFSERR_DQUOT,
  446         NFSERR_STALE,
  447         NFSERR_BADHANDLE,
  448         NFSERR_NOTSUPP,
  449         NFSERR_SERVERFAULT,
  450         0,
  451 };
  452 
  453 static short nfsv3err_readdir[] = {
  454         NFSERR_IO,
  455         NFSERR_IO,
  456         NFSERR_ACCES,
  457         NFSERR_NOTDIR,
  458         NFSERR_STALE,
  459         NFSERR_BADHANDLE,
  460         NFSERR_BAD_COOKIE,
  461         NFSERR_TOOSMALL,
  462         NFSERR_SERVERFAULT,
  463         0,
  464 };
  465 
  466 static short nfsv3err_readdirplus[] = {
  467         NFSERR_IO,
  468         NFSERR_IO,
  469         NFSERR_ACCES,
  470         NFSERR_NOTDIR,
  471         NFSERR_STALE,
  472         NFSERR_BADHANDLE,
  473         NFSERR_BAD_COOKIE,
  474         NFSERR_NOTSUPP,
  475         NFSERR_TOOSMALL,
  476         NFSERR_SERVERFAULT,
  477         0,
  478 };
  479 
  480 static short nfsv3err_fsstat[] = {
  481         NFSERR_IO,
  482         NFSERR_IO,
  483         NFSERR_STALE,
  484         NFSERR_BADHANDLE,
  485         NFSERR_SERVERFAULT,
  486         0,
  487 };
  488 
  489 static short nfsv3err_fsinfo[] = {
  490         NFSERR_STALE,
  491         NFSERR_STALE,
  492         NFSERR_BADHANDLE,
  493         NFSERR_SERVERFAULT,
  494         0,
  495 };
  496 
  497 static short nfsv3err_pathconf[] = {
  498         NFSERR_STALE,
  499         NFSERR_STALE,
  500         NFSERR_BADHANDLE,
  501         NFSERR_SERVERFAULT,
  502         0,
  503 };
  504 
  505 static short nfsv3err_commit[] = {
  506         NFSERR_IO,
  507         NFSERR_IO,
  508         NFSERR_STALE,
  509         NFSERR_BADHANDLE,
  510         NFSERR_SERVERFAULT,
  511         0,
  512 };
  513 
  514 static short *nfsrv_v3errmap[] = {
  515         nfsv3err_null,
  516         nfsv3err_getattr,
  517         nfsv3err_setattr,
  518         nfsv3err_lookup,
  519         nfsv3err_access,
  520         nfsv3err_readlink,
  521         nfsv3err_read,
  522         nfsv3err_write,
  523         nfsv3err_create,
  524         nfsv3err_mkdir,
  525         nfsv3err_symlink,
  526         nfsv3err_mknod,
  527         nfsv3err_remove,
  528         nfsv3err_rmdir,
  529         nfsv3err_rename,
  530         nfsv3err_link,
  531         nfsv3err_readdir,
  532         nfsv3err_readdirplus,
  533         nfsv3err_fsstat,
  534         nfsv3err_fsinfo,
  535         nfsv3err_pathconf,
  536         nfsv3err_commit,
  537 };
  538 
  539 #endif /* NFS_NOSERVER */
  540 
  541 extern struct nfsrtt nfsrtt;
  542 extern time_t nqnfsstarttime;
  543 extern int nqsrv_clockskew;
  544 extern int nqsrv_writeslack;
  545 extern int nqsrv_maxlease;
  546 extern struct nfsstats nfsstats;
  547 extern int nqnfs_piggy[NFS_NPROCS];
  548 extern nfstype nfsv2_type[9];
  549 extern nfstype nfsv3_type[9];
  550 extern struct nfsnodehashhead *nfsnodehashtbl;
  551 extern u_long nfsnodehash;
  552 
  553 #ifdef VFS_LKM
  554 struct getfh_args;
  555 extern int getfh(struct proc *, struct getfh_args *, int *);
  556 struct nfssvc_args;
  557 extern int nfssvc(struct proc *, struct nfssvc_args *, int *);
  558 #endif
  559 
  560 LIST_HEAD(nfsnodehashhead, nfsnode);
  561 
  562 /*
  563  * Create the header for an rpc request packet
  564  * The hsiz is the size of the rest of the nfs request header.
  565  * (just used to decide if a cluster is a good idea)
  566  */
  567 struct mbuf *
  568 nfsm_reqh(vp, procid, hsiz, bposp)
  569         struct vnode *vp;
  570         u_long procid;
  571         int hsiz;
  572         caddr_t *bposp;
  573 {
  574         register struct mbuf *mb;
  575         register u_long *tl;
  576         register caddr_t bpos;
  577         struct mbuf *mb2;
  578         struct nfsmount *nmp;
  579         int nqflag;
  580 
  581         MGET(mb, M_WAIT, MT_DATA);
  582         if (hsiz >= MINCLSIZE)
  583                 MCLGET(mb, M_WAIT);
  584         mb->m_len = 0;
  585         bpos = mtod(mb, caddr_t);
  586 
  587         /*
  588          * For NQNFS, add lease request.
  589          */
  590         if (vp) {
  591                 nmp = VFSTONFS(vp->v_mount);
  592                 if (nmp->nm_flag & NFSMNT_NQNFS) {
  593                         nqflag = NQNFS_NEEDLEASE(vp, procid);
  594                         if (nqflag) {
  595                                 nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
  596                                 *tl++ = txdr_unsigned(nqflag);
  597                                 *tl = txdr_unsigned(nmp->nm_leaseterm);
  598                         } else {
  599                                 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
  600                                 *tl = 0;
  601                         }
  602                 }
  603         }
  604         /* Finally, return values */
  605         *bposp = bpos;
  606         return (mb);
  607 }
  608 
  609 /*
  610  * Build the RPC header and fill in the authorization info.
  611  * The authorization string argument is only used when the credentials
  612  * come from outside of the kernel.
  613  * Returns the head of the mbuf list.
  614  */
  615 struct mbuf *
  616 nfsm_rpchead(cr, nmflag, procid, auth_type, auth_len, auth_str, verf_len,
  617         verf_str, mrest, mrest_len, mbp, xidp)
  618         register struct ucred *cr;
  619         int nmflag;
  620         int procid;
  621         int auth_type;
  622         int auth_len;
  623         char *auth_str;
  624         int verf_len;
  625         char *verf_str;
  626         struct mbuf *mrest;
  627         int mrest_len;
  628         struct mbuf **mbp;
  629         u_long *xidp;
  630 {
  631         register struct mbuf *mb;
  632         register u_long *tl;
  633         register caddr_t bpos;
  634         register int i;
  635         struct mbuf *mreq, *mb2;
  636         int siz, grpsiz, authsiz;
  637         struct timeval tv;
  638         static u_long base;
  639 
  640         authsiz = nfsm_rndup(auth_len);
  641         MGETHDR(mb, M_WAIT, MT_DATA);
  642         if ((authsiz + 10 * NFSX_UNSIGNED) >= MINCLSIZE) {
  643                 MCLGET(mb, M_WAIT);
  644         } else if ((authsiz + 10 * NFSX_UNSIGNED) < MHLEN) {
  645                 MH_ALIGN(mb, authsiz + 10 * NFSX_UNSIGNED);
  646         } else {
  647                 MH_ALIGN(mb, 8 * NFSX_UNSIGNED);
  648         }
  649         mb->m_len = 0;
  650         mreq = mb;
  651         bpos = mtod(mb, caddr_t);
  652 
  653         /*
  654          * First the RPC header.
  655          */
  656         nfsm_build(tl, u_long *, 8 * NFSX_UNSIGNED);
  657 
  658         /*
  659          * derive initial xid from system time
  660          * XXX time is invalid if root not yet mounted
  661          */
  662         if (!base && (rootvp)) {
  663                 microtime(&tv);
  664                 base = tv.tv_sec << 12;
  665                 nfs_xid = base;
  666         }
  667         /*
  668          * Skip zero xid if it should ever happen.
  669          */
  670         if (++nfs_xid == 0)
  671                 nfs_xid++;
  672 
  673         *tl++ = *xidp = txdr_unsigned(nfs_xid);
  674         *tl++ = rpc_call;
  675         *tl++ = rpc_vers;
  676         if (nmflag & NFSMNT_NQNFS) {
  677                 *tl++ = txdr_unsigned(NQNFS_PROG);
  678                 *tl++ = txdr_unsigned(NQNFS_VER3);
  679         } else {
  680                 *tl++ = txdr_unsigned(NFS_PROG);
  681                 if (nmflag & NFSMNT_NFSV3)
  682                         *tl++ = txdr_unsigned(NFS_VER3);
  683                 else
  684                         *tl++ = txdr_unsigned(NFS_VER2);
  685         }
  686         if (nmflag & NFSMNT_NFSV3)
  687                 *tl++ = txdr_unsigned(procid);
  688         else
  689                 *tl++ = txdr_unsigned(nfsv2_procid[procid]);
  690 
  691         /*
  692          * And then the authorization cred.
  693          */
  694         *tl++ = txdr_unsigned(auth_type);
  695         *tl = txdr_unsigned(authsiz);
  696         switch (auth_type) {
  697         case RPCAUTH_UNIX:
  698                 nfsm_build(tl, u_long *, auth_len);
  699                 *tl++ = 0;              /* stamp ?? */
  700                 *tl++ = 0;              /* NULL hostname */
  701                 *tl++ = txdr_unsigned(cr->cr_uid);
  702                 *tl++ = txdr_unsigned(cr->cr_groups[0]);
  703                 grpsiz = (auth_len >> 2) - 5;
  704                 *tl++ = txdr_unsigned(grpsiz);
  705                 for (i = 1; i <= grpsiz; i++)
  706                         *tl++ = txdr_unsigned(cr->cr_groups[i]);
  707                 break;
  708         case RPCAUTH_KERB4:
  709                 siz = auth_len;
  710                 while (siz > 0) {
  711                         if (M_TRAILINGSPACE(mb) == 0) {
  712                                 MGET(mb2, M_WAIT, MT_DATA);
  713                                 if (siz >= MINCLSIZE)
  714                                         MCLGET(mb2, M_WAIT);
  715                                 mb->m_next = mb2;
  716                                 mb = mb2;
  717                                 mb->m_len = 0;
  718                                 bpos = mtod(mb, caddr_t);
  719                         }
  720                         i = min(siz, M_TRAILINGSPACE(mb));
  721                         bcopy(auth_str, bpos, i);
  722                         mb->m_len += i;
  723                         auth_str += i;
  724                         bpos += i;
  725                         siz -= i;
  726                 }
  727                 if ((siz = (nfsm_rndup(auth_len) - auth_len)) > 0) {
  728                         for (i = 0; i < siz; i++)
  729                                 *bpos++ = '\0';
  730                         mb->m_len += siz;
  731                 }
  732                 break;
  733         };
  734 
  735         /*
  736          * And the verifier...
  737          */
  738         nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
  739         if (verf_str) {
  740                 *tl++ = txdr_unsigned(RPCAUTH_KERB4);
  741                 *tl = txdr_unsigned(verf_len);
  742                 siz = verf_len;
  743                 while (siz > 0) {
  744                         if (M_TRAILINGSPACE(mb) == 0) {
  745                                 MGET(mb2, M_WAIT, MT_DATA);
  746                                 if (siz >= MINCLSIZE)
  747                                         MCLGET(mb2, M_WAIT);
  748                                 mb->m_next = mb2;
  749                                 mb = mb2;
  750                                 mb->m_len = 0;
  751                                 bpos = mtod(mb, caddr_t);
  752                         }
  753                         i = min(siz, M_TRAILINGSPACE(mb));
  754                         bcopy(verf_str, bpos, i);
  755                         mb->m_len += i;
  756                         verf_str += i;
  757                         bpos += i;
  758                         siz -= i;
  759                 }
  760                 if ((siz = (nfsm_rndup(verf_len) - verf_len)) > 0) {
  761                         for (i = 0; i < siz; i++)
  762                                 *bpos++ = '\0';
  763                         mb->m_len += siz;
  764                 }
  765         } else {
  766                 *tl++ = txdr_unsigned(RPCAUTH_NULL);
  767                 *tl = 0;
  768         }
  769         mb->m_next = mrest;
  770         mreq->m_pkthdr.len = authsiz + 10 * NFSX_UNSIGNED + mrest_len;
  771         mreq->m_pkthdr.rcvif = (struct ifnet *)0;
  772         *mbp = mb;
  773         return (mreq);
  774 }
  775 
  776 /*
  777  * copies mbuf chain to the uio scatter/gather list
  778  */
  779 int
  780 nfsm_mbuftouio(mrep, uiop, siz, dpos)
  781         struct mbuf **mrep;
  782         register struct uio *uiop;
  783         int siz;
  784         caddr_t *dpos;
  785 {
  786         register char *mbufcp, *uiocp;
  787         register int xfer, left, len;
  788         register struct mbuf *mp;
  789         long uiosiz, rem;
  790         int error = 0;
  791 
  792         mp = *mrep;
  793         mbufcp = *dpos;
  794         len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
  795         rem = nfsm_rndup(siz)-siz;
  796         while (siz > 0) {
  797                 if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
  798                         return (EFBIG);
  799                 left = uiop->uio_iov->iov_len;
  800                 uiocp = uiop->uio_iov->iov_base;
  801                 if (left > siz)
  802                         left = siz;
  803                 uiosiz = left;
  804                 while (left > 0) {
  805                         while (len == 0) {
  806                                 mp = mp->m_next;
  807                                 if (mp == NULL)
  808                                         return (EBADRPC);
  809                                 mbufcp = mtod(mp, caddr_t);
  810                                 len = mp->m_len;
  811                         }
  812                         xfer = (left > len) ? len : left;
  813 #ifdef notdef
  814                         /* Not Yet.. */
  815                         if (uiop->uio_iov->iov_op != NULL)
  816                                 (*(uiop->uio_iov->iov_op))
  817                                 (mbufcp, uiocp, xfer);
  818                         else
  819 #endif
  820                         if (uiop->uio_segflg == UIO_SYSSPACE)
  821                                 bcopy(mbufcp, uiocp, xfer);
  822                         else
  823                                 copyout(mbufcp, uiocp, xfer);
  824                         left -= xfer;
  825                         len -= xfer;
  826                         mbufcp += xfer;
  827                         uiocp += xfer;
  828                         uiop->uio_offset += xfer;
  829                         uiop->uio_resid -= xfer;
  830                 }
  831                 if (uiop->uio_iov->iov_len <= siz) {
  832                         uiop->uio_iovcnt--;
  833                         uiop->uio_iov++;
  834                 } else {
  835                         uiop->uio_iov->iov_base += uiosiz;
  836                         uiop->uio_iov->iov_len -= uiosiz;
  837                 }
  838                 siz -= uiosiz;
  839         }
  840         *dpos = mbufcp;
  841         *mrep = mp;
  842         if (rem > 0) {
  843                 if (len < rem)
  844                         error = nfs_adv(mrep, dpos, rem, len);
  845                 else
  846                         *dpos += rem;
  847         }
  848         return (error);
  849 }
  850 
  851 /*
  852  * copies a uio scatter/gather list to an mbuf chain.
  853  * NOTE: can ony handle iovcnt == 1
  854  */
  855 int
  856 nfsm_uiotombuf(uiop, mq, siz, bpos)
  857         register struct uio *uiop;
  858         struct mbuf **mq;
  859         int siz;
  860         caddr_t *bpos;
  861 {
  862         register char *uiocp;
  863         register struct mbuf *mp, *mp2;
  864         register int xfer, left, mlen;
  865         int uiosiz, clflg, rem;
  866         char *cp;
  867 
  868         if (uiop->uio_iovcnt != 1)
  869                 panic("nfsm_uiotombuf: iovcnt != 1");
  870 
  871         if (siz > MLEN)         /* or should it >= MCLBYTES ?? */
  872                 clflg = 1;
  873         else
  874                 clflg = 0;
  875         rem = nfsm_rndup(siz)-siz;
  876         mp = mp2 = *mq;
  877         while (siz > 0) {
  878                 left = uiop->uio_iov->iov_len;
  879                 uiocp = uiop->uio_iov->iov_base;
  880                 if (left > siz)
  881                         left = siz;
  882                 uiosiz = left;
  883                 while (left > 0) {
  884                         mlen = M_TRAILINGSPACE(mp);
  885                         if (mlen == 0) {
  886                                 MGET(mp, M_WAIT, MT_DATA);
  887                                 if (clflg)
  888                                         MCLGET(mp, M_WAIT);
  889                                 mp->m_len = 0;
  890                                 mp2->m_next = mp;
  891                                 mp2 = mp;
  892                                 mlen = M_TRAILINGSPACE(mp);
  893                         }
  894                         xfer = (left > mlen) ? mlen : left;
  895 #ifdef notdef
  896                         /* Not Yet.. */
  897                         if (uiop->uio_iov->iov_op != NULL)
  898                                 (*(uiop->uio_iov->iov_op))
  899                                 (uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
  900                         else
  901 #endif
  902                         if (uiop->uio_segflg == UIO_SYSSPACE)
  903                                 bcopy(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
  904                         else
  905                                 copyin(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
  906                         mp->m_len += xfer;
  907                         left -= xfer;
  908                         uiocp += xfer;
  909                         uiop->uio_offset += xfer;
  910                         uiop->uio_resid -= xfer;
  911                 }
  912                 uiop->uio_iov->iov_base += uiosiz;
  913                 uiop->uio_iov->iov_len -= uiosiz;
  914                 siz -= uiosiz;
  915         }
  916         if (rem > 0) {
  917                 if (rem > M_TRAILINGSPACE(mp)) {
  918                         MGET(mp, M_WAIT, MT_DATA);
  919                         mp->m_len = 0;
  920                         mp2->m_next = mp;
  921                 }
  922                 cp = mtod(mp, caddr_t)+mp->m_len;
  923                 for (left = 0; left < rem; left++)
  924                         *cp++ = '\0';
  925                 mp->m_len += rem;
  926                 *bpos = cp;
  927         } else
  928                 *bpos = mtod(mp, caddr_t)+mp->m_len;
  929         *mq = mp;
  930         return (0);
  931 }
  932 
  933 /*
  934  * Help break down an mbuf chain by setting the first siz bytes contiguous
  935  * pointed to by returned val.
  936  * This is used by the macros nfsm_dissect and nfsm_dissecton for tough
  937  * cases. (The macros use the vars. dpos and dpos2)
  938  */
  939 int
  940 nfsm_disct(mdp, dposp, siz, left, cp2)
  941         struct mbuf **mdp;
  942         caddr_t *dposp;
  943         int siz;
  944         int left;
  945         caddr_t *cp2;
  946 {
  947         register struct mbuf *mp, *mp2;
  948         register int siz2, xfer;
  949         register caddr_t p;
  950 
  951         mp = *mdp;
  952         while (left == 0) {
  953                 *mdp = mp = mp->m_next;
  954                 if (mp == NULL)
  955                         return (EBADRPC);
  956                 left = mp->m_len;
  957                 *dposp = mtod(mp, caddr_t);
  958         }
  959         if (left >= siz) {
  960                 *cp2 = *dposp;
  961                 *dposp += siz;
  962         } else if (mp->m_next == NULL) {
  963                 return (EBADRPC);
  964         } else if (siz > MHLEN) {
  965                 panic("nfs S too big");
  966         } else {
  967                 MGET(mp2, M_WAIT, MT_DATA);
  968                 mp2->m_next = mp->m_next;
  969                 mp->m_next = mp2;
  970                 mp->m_len -= left;
  971                 mp = mp2;
  972                 *cp2 = p = mtod(mp, caddr_t);
  973                 bcopy(*dposp, p, left);         /* Copy what was left */
  974                 siz2 = siz-left;
  975                 p += left;
  976                 mp2 = mp->m_next;
  977                 /* Loop around copying up the siz2 bytes */
  978                 while (siz2 > 0) {
  979                         if (mp2 == NULL)
  980                                 return (EBADRPC);
  981                         xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2;
  982                         if (xfer > 0) {
  983                                 bcopy(mtod(mp2, caddr_t), p, xfer);
  984                                 NFSMADV(mp2, xfer);
  985                                 mp2->m_len -= xfer;
  986                                 p += xfer;
  987                                 siz2 -= xfer;
  988                         }
  989                         if (siz2 > 0)
  990                                 mp2 = mp2->m_next;
  991                 }
  992                 mp->m_len = siz;
  993                 *mdp = mp2;
  994                 *dposp = mtod(mp2, caddr_t);
  995         }
  996         return (0);
  997 }
  998 
  999 /*
 1000  * Advance the position in the mbuf chain.
 1001  */
 1002 int
 1003 nfs_adv(mdp, dposp, offs, left)
 1004         struct mbuf **mdp;
 1005         caddr_t *dposp;
 1006         int offs;
 1007         int left;
 1008 {
 1009         register struct mbuf *m;
 1010         register int s;
 1011 
 1012         m = *mdp;
 1013         s = left;
 1014         while (s < offs) {
 1015                 offs -= s;
 1016                 m = m->m_next;
 1017                 if (m == NULL)
 1018                         return (EBADRPC);
 1019                 s = m->m_len;
 1020         }
 1021         *mdp = m;
 1022         *dposp = mtod(m, caddr_t)+offs;
 1023         return (0);
 1024 }
 1025 
 1026 /*
 1027  * Copy a string into mbufs for the hard cases...
 1028  */
 1029 int
 1030 nfsm_strtmbuf(mb, bpos, cp, siz)
 1031         struct mbuf **mb;
 1032         char **bpos;
 1033         char *cp;
 1034         long siz;
 1035 {
 1036         register struct mbuf *m1 = 0, *m2;
 1037         long left, xfer, len, tlen;
 1038         u_long *tl;
 1039         int putsize;
 1040 
 1041         putsize = 1;
 1042         m2 = *mb;
 1043         left = M_TRAILINGSPACE(m2);
 1044         if (left > 0) {
 1045                 tl = ((u_long *)(*bpos));
 1046                 *tl++ = txdr_unsigned(siz);
 1047                 putsize = 0;
 1048                 left -= NFSX_UNSIGNED;
 1049                 m2->m_len += NFSX_UNSIGNED;
 1050                 if (left > 0) {
 1051                         bcopy(cp, (caddr_t) tl, left);
 1052                         siz -= left;
 1053                         cp += left;
 1054                         m2->m_len += left;
 1055                         left = 0;
 1056                 }
 1057         }
 1058         /* Loop around adding mbufs */
 1059         while (siz > 0) {
 1060                 MGET(m1, M_WAIT, MT_DATA);
 1061                 if (siz > MLEN)
 1062                         MCLGET(m1, M_WAIT);
 1063                 m1->m_len = NFSMSIZ(m1);
 1064                 m2->m_next = m1;
 1065                 m2 = m1;
 1066                 tl = mtod(m1, u_long *);
 1067                 tlen = 0;
 1068                 if (putsize) {
 1069                         *tl++ = txdr_unsigned(siz);
 1070                         m1->m_len -= NFSX_UNSIGNED;
 1071                         tlen = NFSX_UNSIGNED;
 1072                         putsize = 0;
 1073                 }
 1074                 if (siz < m1->m_len) {
 1075                         len = nfsm_rndup(siz);
 1076                         xfer = siz;
 1077                         if (xfer < len)
 1078                                 *(tl+(xfer>>2)) = 0;
 1079                 } else {
 1080                         xfer = len = m1->m_len;
 1081                 }
 1082                 bcopy(cp, (caddr_t) tl, xfer);
 1083                 m1->m_len = len+tlen;
 1084                 siz -= xfer;
 1085                 cp += xfer;
 1086         }
 1087         *mb = m1;
 1088         *bpos = mtod(m1, caddr_t)+m1->m_len;
 1089         return (0);
 1090 }
 1091 
 1092 /*
 1093  * Called once to initialize data structures...
 1094  */
 1095 int
 1096 nfs_init()
 1097 {
 1098         register int i;
 1099 
 1100         /*
 1101          * Check to see if major data structures haven't bloated.
 1102          */
 1103         if (sizeof (struct nfsnode) > NFS_NODEALLOC) {
 1104                 printf("struct nfsnode bloated (> %dbytes)\n", NFS_NODEALLOC);
 1105                 printf("Try reducing NFS_SMALLFH\n");
 1106         }
 1107         if (sizeof (struct nfsmount) > NFS_MNTALLOC) {
 1108                 printf("struct nfsmount bloated (> %dbytes)\n", NFS_MNTALLOC);
 1109                 printf("Try reducing NFS_MUIDHASHSIZ\n");
 1110         }
 1111         if (sizeof (struct nfssvc_sock) > NFS_SVCALLOC) {
 1112                 printf("struct nfssvc_sock bloated (> %dbytes)\n",NFS_SVCALLOC);
 1113                 printf("Try reducing NFS_UIDHASHSIZ\n");
 1114         }
 1115         if (sizeof (struct nfsuid) > NFS_UIDALLOC) {
 1116                 printf("struct nfsuid bloated (> %dbytes)\n",NFS_UIDALLOC);
 1117                 printf("Try unionizing the nu_nickname and nu_flag fields\n");
 1118         }
 1119         nfsrtt.pos = 0;
 1120         rpc_vers = txdr_unsigned(RPC_VER2);
 1121         rpc_call = txdr_unsigned(RPC_CALL);
 1122         rpc_reply = txdr_unsigned(RPC_REPLY);
 1123         rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED);
 1124         rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED);
 1125         rpc_mismatch = txdr_unsigned(RPC_MISMATCH);
 1126         rpc_autherr = txdr_unsigned(RPC_AUTHERR);
 1127         rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX);
 1128         rpc_auth_kerb = txdr_unsigned(RPCAUTH_KERB4);
 1129         nfs_prog = txdr_unsigned(NFS_PROG);
 1130         nqnfs_prog = txdr_unsigned(NQNFS_PROG);
 1131         nfs_true = txdr_unsigned(TRUE);
 1132         nfs_false = txdr_unsigned(FALSE);
 1133         nfs_xdrneg1 = txdr_unsigned(-1);
 1134         nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
 1135         if (nfs_ticks < 1)
 1136                 nfs_ticks = 1;
 1137         /* Ensure async daemons disabled */
 1138         for (i = 0; i < NFS_MAXASYNCDAEMON; i++) {
 1139                 nfs_iodwant[i] = (struct proc *)0;
 1140                 nfs_iodmount[i] = (struct nfsmount *)0;
 1141         }
 1142         nfs_nhinit();                   /* Init the nfsnode table */
 1143 #ifndef NFS_NOSERVER
 1144         nfsrv_init(0);                  /* Init server data structures */
 1145         nfsrv_initcache();              /* Init the server request cache */
 1146 #endif
 1147 
 1148         /*
 1149          * Initialize the nqnfs server stuff.
 1150          */
 1151         if (nqnfsstarttime == 0) {
 1152                 nqnfsstarttime = boottime.tv_sec + nqsrv_maxlease
 1153                         + nqsrv_clockskew + nqsrv_writeslack;
 1154                 NQLOADNOVRAM(nqnfsstarttime);
 1155                 CIRCLEQ_INIT(&nqtimerhead);
 1156                 nqfhhashtbl = hashinit(NQLCHSZ, M_NQLEASE, &nqfhhash);
 1157         }
 1158 
 1159         /*
 1160          * Initialize reply list and start timer
 1161          */
 1162         TAILQ_INIT(&nfs_reqq);
 1163 
 1164         nfs_timer(0);
 1165 
 1166 
 1167 #ifdef __FreeBSD__
 1168         /*
 1169          * Set up lease_check and lease_updatetime so that other parts
 1170          * of the system can call us, if we are loadable.
 1171          */
 1172 #ifndef NFS_NOSERVER
 1173         lease_check = nfs_lease_check;
 1174 #endif
 1175         lease_updatetime = nfs_lease_updatetime;
 1176         vfsconf[MOUNT_NFS]->vfc_refcount++; /* make us non-unloadable */
 1177 #ifdef VFS_LKM
 1178         sysent[SYS_nfssvc].sy_narg = 2;
 1179         sysent[SYS_nfssvc].sy_call = nfssvc;
 1180 #ifndef NFS_NOSERVER
 1181         sysent[SYS_getfh].sy_narg = 2;
 1182         sysent[SYS_getfh].sy_call = getfh;
 1183 #endif
 1184 #endif
 1185 #endif
 1186 
 1187         return (0);
 1188 }
 1189 
 1190 /*
 1191  * Attribute cache routines.
 1192  * nfs_loadattrcache() - loads or updates the cache contents from attributes
 1193  *      that are on the mbuf list
 1194  * nfs_getattrcache() - returns valid attributes if found in cache, returns
 1195  *      error otherwise
 1196  */
 1197 
 1198 /*
 1199  * Load the attribute cache (that lives in the nfsnode entry) with
 1200  * the values on the mbuf list and
 1201  * Iff vap not NULL
 1202  *    copy the attributes to *vaper
 1203  */
 1204 int
 1205 nfs_loadattrcache(vpp, mdp, dposp, vaper)
 1206         struct vnode **vpp;
 1207         struct mbuf **mdp;
 1208         caddr_t *dposp;
 1209         struct vattr *vaper;
 1210 {
 1211         register struct vnode *vp = *vpp;
 1212         register struct vattr *vap;
 1213         register struct nfs_fattr *fp;
 1214         register struct nfsnode *np;
 1215         register struct nfsnodehashhead *nhpp;
 1216         register long t1;
 1217         caddr_t cp2;
 1218         int error = 0, rdev;
 1219         struct mbuf *md;
 1220         enum vtype vtyp;
 1221         u_short vmode;
 1222         struct timespec mtime;
 1223         struct vnode *nvp;
 1224         int v3 = NFS_ISV3(vp);
 1225 
 1226         md = *mdp;
 1227         t1 = (mtod(md, caddr_t) + md->m_len) - *dposp;
 1228         if (error = nfsm_disct(mdp, dposp, NFSX_FATTR(v3), t1, &cp2))
 1229                 return (error);
 1230         fp = (struct nfs_fattr *)cp2;
 1231         if (v3) {
 1232                 vtyp = nfsv3tov_type(fp->fa_type);
 1233                 vmode = fxdr_unsigned(u_short, fp->fa_mode);
 1234                 rdev = makedev(fxdr_unsigned(int, fp->fa3_rdev.specdata1),
 1235                         fxdr_unsigned(int, fp->fa3_rdev.specdata2));
 1236                 fxdr_nfsv3time(&fp->fa3_mtime, &mtime);
 1237         } else {
 1238                 vtyp = nfsv2tov_type(fp->fa_type);
 1239                 vmode = fxdr_unsigned(u_short, fp->fa_mode);
 1240                 /*
 1241                  * XXX
 1242                  *
 1243                  * The duplicate information returned in fa_type and fa_mode
 1244                  * is an ambiguity in the NFS version 2 protocol.
 1245                  *
 1246                  * VREG should be taken literally as a regular file.  If a
 1247                  * server intents to return some type information differently
 1248                  * in the upper bits of the mode field (e.g. for sockets, or
 1249                  * FIFOs), NFSv2 mandates fa_type to be VNON.  Anyway, we
 1250                  * leave the examination of the mode bits even in the VREG
 1251                  * case to avoid breakage for bogus servers, but we make sure
 1252                  * that there are actually type bits set in the upper part of
 1253                  * fa_mode (and failing that, trust the va_type field).
 1254                  *
 1255                  * NFSv3 cleared the issue, and requires fa_mode to not
 1256                  * contain any type information (while also introduing sockets
 1257                  * and FIFOs for fa_type).
 1258                  */
 1259                 if (vtyp == VNON || (vtyp == VREG && (vmode & S_IFMT) != 0))
 1260                         vtyp = IFTOVT(vmode);
 1261                 rdev = fxdr_unsigned(long, fp->fa2_rdev);
 1262                 fxdr_nfsv2time(&fp->fa2_mtime, &mtime);
 1263 
 1264                 /*
 1265                  * Really ugly NFSv2 kludge.
 1266                  */
 1267                 if (vtyp == VCHR && rdev == 0xffffffff)
 1268                         vtyp = VFIFO;
 1269         }
 1270 
 1271         /*
 1272          * If v_type == VNON it is a new node, so fill in the v_type,
 1273          * n_mtime fields. Check to see if it represents a special
 1274          * device, and if so, check for a possible alias. Once the
 1275          * correct vnode has been obtained, fill in the rest of the
 1276          * information.
 1277          */
 1278         np = VTONFS(vp);
 1279         if (vp->v_type != vtyp) {
 1280                 /*
 1281                  * If we had a lock and it turns out that the vnode
 1282                  * is an object which we don't want to lock (e.g. VDIR)
 1283                  * to avoid nasty hanging problems on a server crash,
 1284                  * then release it here.
 1285                  */
 1286                 if (vtyp != VREG && VOP_ISLOCKED(vp))
 1287                         VOP_UNLOCK(vp);
 1288                 vp->v_type = vtyp;
 1289                 if (vp->v_type == VFIFO) {
 1290                         vp->v_op = fifo_nfsv2nodeop_p;
 1291                 }
 1292                 if (vp->v_type == VCHR || vp->v_type == VBLK) {
 1293                         vp->v_op = spec_nfsv2nodeop_p;
 1294                         nvp = checkalias(vp, (dev_t)rdev, vp->v_mount);
 1295                         if (nvp) {
 1296                                 /*
 1297                                  * Discard unneeded vnode, but save its nfsnode.
 1298                                  */
 1299                                 LIST_REMOVE(np, n_hash);
 1300                                 nvp->v_data = vp->v_data;
 1301                                 vp->v_data = NULL;
 1302                                 vp->v_op = spec_vnodeop_p;
 1303                                 vrele(vp);
 1304                                 vgone(vp);
 1305                                 /*
 1306                                  * Reinitialize aliased node.
 1307                                  */
 1308                                 np->n_vnode = nvp;
 1309                                 nhpp = NFSNOHASH(nfs_hash(np->n_fhp, np->n_fhsize));
 1310                                 LIST_INSERT_HEAD(nhpp, np, n_hash);
 1311                                 *vpp = vp = nvp;
 1312                         }
 1313                 }
 1314                 np->n_mtime = mtime.tv_sec;
 1315         }
 1316         vap = &np->n_vattr;
 1317         vap->va_type = vtyp;
 1318         vap->va_mode = (vmode & 07777);
 1319         vap->va_rdev = (dev_t)rdev;
 1320         vap->va_mtime = mtime;
 1321         vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
 1322         if (v3) {
 1323                 vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
 1324                 vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
 1325                 vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
 1326                 fxdr_hyper(&fp->fa3_size, &vap->va_size);
 1327                 vap->va_blocksize = NFS_FABLKSIZE;
 1328                 fxdr_hyper(&fp->fa3_used, &vap->va_bytes);
 1329                 vap->va_fileid = fxdr_unsigned(int, fp->fa3_fileid.nfsuquad[1]);
 1330                 fxdr_nfsv3time(&fp->fa3_atime, &vap->va_atime);
 1331                 fxdr_nfsv3time(&fp->fa3_ctime, &vap->va_ctime);
 1332                 vap->va_flags = 0;
 1333                 vap->va_filerev = 0;
 1334         } else {
 1335                 vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
 1336                 vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
 1337                 vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
 1338                 vap->va_size = fxdr_unsigned(u_long, fp->fa2_size);
 1339                 vap->va_blocksize = fxdr_unsigned(long, fp->fa2_blocksize);
 1340                 vap->va_bytes = (u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks)
 1341                     * NFS_FABLKSIZE;
 1342                 vap->va_fileid = fxdr_unsigned(long, fp->fa2_fileid);
 1343                 fxdr_nfsv2time(&fp->fa2_atime, &vap->va_atime);
 1344                 vap->va_flags = 0;
 1345                 vap->va_ctime.tv_sec = fxdr_unsigned(long, fp->fa2_ctime.nfsv2_sec);
 1346                 vap->va_ctime.tv_nsec = 0;
 1347                 vap->va_gen = fxdr_unsigned(u_long, fp->fa2_ctime.nfsv2_usec);
 1348                 vap->va_filerev = 0;
 1349         }
 1350         if (vap->va_size != np->n_size) {
 1351                 if (vap->va_type == VREG) {
 1352                         if (np->n_flag & NMODIFIED) {
 1353                                 if (vap->va_size < np->n_size)
 1354                                         vap->va_size = np->n_size;
 1355                                 else
 1356                                         np->n_size = vap->va_size;
 1357                         } else
 1358                                 np->n_size = vap->va_size;
 1359                         vnode_pager_setsize(vp, (u_long)np->n_size);
 1360                 } else
 1361                         np->n_size = vap->va_size;
 1362         }
 1363         np->n_attrstamp = time.tv_sec;
 1364         if (vaper != NULL) {
 1365                 bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap));
 1366                 if (np->n_flag & NCHG) {
 1367                         if (np->n_flag & NACC)
 1368                                 vaper->va_atime = np->n_atim;
 1369                         if (np->n_flag & NUPD)
 1370                                 vaper->va_mtime = np->n_mtim;
 1371                 }
 1372         }
 1373         return (0);
 1374 }
 1375 
 1376 /*
 1377  * Check the time stamp
 1378  * If the cache is valid, copy contents to *vap and return 0
 1379  * otherwise return an error
 1380  */
 1381 int
 1382 nfs_getattrcache(vp, vaper)
 1383         register struct vnode *vp;
 1384         struct vattr *vaper;
 1385 {
 1386         register struct nfsnode *np = VTONFS(vp);
 1387         register struct vattr *vap;
 1388 
 1389         if ((time.tv_sec - np->n_attrstamp) >= NFS_ATTRTIMEO(np)) {
 1390                 nfsstats.attrcache_misses++;
 1391                 return (ENOENT);
 1392         }
 1393         nfsstats.attrcache_hits++;
 1394         vap = &np->n_vattr;
 1395         if (vap->va_size != np->n_size) {
 1396                 if (vap->va_type == VREG) {
 1397                         if (np->n_flag & NMODIFIED) {
 1398                                 if (vap->va_size < np->n_size)
 1399                                         vap->va_size = np->n_size;
 1400                                 else
 1401                                         np->n_size = vap->va_size;
 1402                         } else
 1403                                 np->n_size = vap->va_size;
 1404                         vnode_pager_setsize(vp, (u_long)np->n_size);
 1405                 } else
 1406                         np->n_size = vap->va_size;
 1407         }
 1408         bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(struct vattr));
 1409         if (np->n_flag & NCHG) {
 1410                 if (np->n_flag & NACC)
 1411                         vaper->va_atime = np->n_atim;
 1412                 if (np->n_flag & NUPD)
 1413                         vaper->va_mtime = np->n_mtim;
 1414         }
 1415         return (0);
 1416 }
 1417 
 1418 #ifndef NFS_NOSERVER
 1419 /*
 1420  * Set up nameidata for a lookup() call and do it
 1421  */
 1422 int
 1423 nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag)
 1424         register struct nameidata *ndp;
 1425         fhandle_t *fhp;
 1426         int len;
 1427         struct nfssvc_sock *slp;
 1428         struct mbuf *nam;
 1429         struct mbuf **mdp;
 1430         caddr_t *dposp;
 1431         struct vnode **retdirp;
 1432         struct proc *p;
 1433         int kerbflag;
 1434 {
 1435         register int i, rem;
 1436         register struct mbuf *md;
 1437         register char *fromcp, *tocp;
 1438         struct vnode *dp;
 1439         int error, rdonly;
 1440         struct componentname *cnp = &ndp->ni_cnd;
 1441 
 1442         *retdirp = (struct vnode *)0;
 1443         MALLOC(cnp->cn_pnbuf, char *, len + 1, M_NAMEI, M_WAITOK);
 1444         /*
 1445          * Copy the name from the mbuf list to ndp->ni_pnbuf
 1446          * and set the various ndp fields appropriately.
 1447          */
 1448         fromcp = *dposp;
 1449         tocp = cnp->cn_pnbuf;
 1450         md = *mdp;
 1451         rem = mtod(md, caddr_t) + md->m_len - fromcp;
 1452         cnp->cn_hash = 0;
 1453         for (i = 0; i < len; i++) {
 1454                 while (rem == 0) {
 1455                         md = md->m_next;
 1456                         if (md == NULL) {
 1457                                 error = EBADRPC;
 1458                                 goto out;
 1459                         }
 1460                         fromcp = mtod(md, caddr_t);
 1461                         rem = md->m_len;
 1462                 }
 1463                 if (*fromcp == '\0' || *fromcp == '/') {
 1464                         error = EACCES;
 1465                         goto out;
 1466                 }
 1467                 cnp->cn_hash += (unsigned char)*fromcp;
 1468                 *tocp++ = *fromcp++;
 1469                 rem--;
 1470         }
 1471         *tocp = '\0';
 1472         *mdp = md;
 1473         *dposp = fromcp;
 1474         len = nfsm_rndup(len)-len;
 1475         if (len > 0) {
 1476                 if (rem >= len)
 1477                         *dposp += len;
 1478                 else if (error = nfs_adv(mdp, dposp, len, rem))
 1479                         goto out;
 1480         }
 1481         ndp->ni_pathlen = tocp - cnp->cn_pnbuf;
 1482         cnp->cn_nameptr = cnp->cn_pnbuf;
 1483         /*
 1484          * Extract and set starting directory.
 1485          */
 1486         if (error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
 1487             nam, &rdonly, kerbflag))
 1488                 goto out;
 1489         if (dp->v_type != VDIR) {
 1490                 vrele(dp);
 1491                 error = ENOTDIR;
 1492                 goto out;
 1493         }
 1494         VREF(dp);
 1495         *retdirp = dp;
 1496         ndp->ni_startdir = dp;
 1497         if (rdonly)
 1498                 cnp->cn_flags |= (NOCROSSMOUNT | RDONLY);
 1499         else
 1500                 cnp->cn_flags |= NOCROSSMOUNT;
 1501         /*
 1502          * And call lookup() to do the real work
 1503          */
 1504         cnp->cn_proc = p;
 1505         if (error = lookup(ndp))
 1506                 goto out;
 1507         /*
 1508          * Check for encountering a symbolic link
 1509          */
 1510         if (cnp->cn_flags & ISSYMLINK) {
 1511                 if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
 1512                         vput(ndp->ni_dvp);
 1513                 else
 1514                         vrele(ndp->ni_dvp);
 1515                 vput(ndp->ni_vp);
 1516                 ndp->ni_vp = NULL;
 1517                 error = EINVAL;
 1518                 goto out;
 1519         }
 1520 
 1521         nfsrv_object_create(ndp->ni_vp);
 1522 
 1523         /*
 1524          * Check for saved name request
 1525          */
 1526         if (cnp->cn_flags & (SAVENAME | SAVESTART)) {
 1527                 cnp->cn_flags |= HASBUF;
 1528                 return (0);
 1529         }
 1530 out:
 1531         FREE(cnp->cn_pnbuf, M_NAMEI);
 1532         return (error);
 1533 }
 1534 
 1535 /*
 1536  * A fiddled version of m_adj() that ensures null fill to a long
 1537  * boundary and only trims off the back end
 1538  */
 1539 void
 1540 nfsm_adj(mp, len, nul)
 1541         struct mbuf *mp;
 1542         register int len;
 1543         int nul;
 1544 {
 1545         register struct mbuf *m;
 1546         register int count, i;
 1547         register char *cp;
 1548 
 1549         /*
 1550          * Trim from tail.  Scan the mbuf chain,
 1551          * calculating its length and finding the last mbuf.
 1552          * If the adjustment only affects this mbuf, then just
 1553          * adjust and return.  Otherwise, rescan and truncate
 1554          * after the remaining size.
 1555          */
 1556         count = 0;
 1557         m = mp;
 1558         for (;;) {
 1559                 count += m->m_len;
 1560                 if (m->m_next == (struct mbuf *)0)
 1561                         break;
 1562                 m = m->m_next;
 1563         }
 1564         if (m->m_len > len) {
 1565                 m->m_len -= len;
 1566                 if (nul > 0) {
 1567                         cp = mtod(m, caddr_t)+m->m_len-nul;
 1568                         for (i = 0; i < nul; i++)
 1569                                 *cp++ = '\0';
 1570                 }
 1571                 return;
 1572         }
 1573         count -= len;
 1574         if (count < 0)
 1575                 count = 0;
 1576         /*
 1577          * Correct length for chain is "count".
 1578          * Find the mbuf with last data, adjust its length,
 1579          * and toss data from remaining mbufs on chain.
 1580          */
 1581         for (m = mp; m; m = m->m_next) {
 1582                 if (m->m_len >= count) {
 1583                         m->m_len = count;
 1584                         if (nul > 0) {
 1585                                 cp = mtod(m, caddr_t)+m->m_len-nul;
 1586                                 for (i = 0; i < nul; i++)
 1587                                         *cp++ = '\0';
 1588                         }
 1589                         break;
 1590                 }
 1591                 count -= m->m_len;
 1592         }
 1593         for (m = m->m_next;m;m = m->m_next)
 1594                 m->m_len = 0;
 1595 }
 1596 
 1597 /*
 1598  * Make these functions instead of macros, so that the kernel text size
 1599  * doesn't get too big...
 1600  */
 1601 void
 1602 nfsm_srvwcc(nfsd, before_ret, before_vap, after_ret, after_vap, mbp, bposp)
 1603         struct nfsrv_descript *nfsd;
 1604         int before_ret;
 1605         register struct vattr *before_vap;
 1606         int after_ret;
 1607         struct vattr *after_vap;
 1608         struct mbuf **mbp;
 1609         char **bposp;
 1610 {
 1611         register struct mbuf *mb = *mbp, *mb2;
 1612         register char *bpos = *bposp;
 1613         register u_long *tl;
 1614 
 1615         if (before_ret) {
 1616                 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
 1617                 *tl = nfs_false;
 1618         } else {
 1619                 nfsm_build(tl, u_long *, 7 * NFSX_UNSIGNED);
 1620                 *tl++ = nfs_true;
 1621                 txdr_hyper(&(before_vap->va_size), tl);
 1622                 tl += 2;
 1623                 txdr_nfsv3time(&(before_vap->va_mtime), tl);
 1624                 tl += 2;
 1625                 txdr_nfsv3time(&(before_vap->va_ctime), tl);
 1626         }
 1627         *bposp = bpos;
 1628         *mbp = mb;
 1629         nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp);
 1630 }
 1631 
 1632 void
 1633 nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp)
 1634         struct nfsrv_descript *nfsd;
 1635         int after_ret;
 1636         struct vattr *after_vap;
 1637         struct mbuf **mbp;
 1638         char **bposp;
 1639 {
 1640         register struct mbuf *mb = *mbp, *mb2;
 1641         register char *bpos = *bposp;
 1642         register u_long *tl;
 1643         register struct nfs_fattr *fp;
 1644 
 1645         if (after_ret) {
 1646                 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
 1647                 *tl = nfs_false;
 1648         } else {
 1649                 nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3FATTR);
 1650                 *tl++ = nfs_true;
 1651                 fp = (struct nfs_fattr *)tl;
 1652                 nfsm_srvfattr(nfsd, after_vap, fp);
 1653         }
 1654         *mbp = mb;
 1655         *bposp = bpos;
 1656 }
 1657 
 1658 void
 1659 nfsm_srvfattr(nfsd, vap, fp)
 1660         register struct nfsrv_descript *nfsd;
 1661         register struct vattr *vap;
 1662         register struct nfs_fattr *fp;
 1663 {
 1664 
 1665         fp->fa_nlink = txdr_unsigned(vap->va_nlink);
 1666         fp->fa_uid = txdr_unsigned(vap->va_uid);
 1667         fp->fa_gid = txdr_unsigned(vap->va_gid);
 1668         if (nfsd->nd_flag & ND_NFSV3) {
 1669                 fp->fa_type = vtonfsv3_type(vap->va_type);
 1670                 fp->fa_mode = vtonfsv3_mode(vap->va_mode);
 1671                 txdr_hyper(&vap->va_size, &fp->fa3_size);
 1672                 txdr_hyper(&vap->va_bytes, &fp->fa3_used);
 1673                 fp->fa3_rdev.specdata1 = txdr_unsigned(major(vap->va_rdev));
 1674                 fp->fa3_rdev.specdata2 = txdr_unsigned(minor(vap->va_rdev));
 1675                 fp->fa3_fsid.nfsuquad[0] = 0;
 1676                 fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid);
 1677                 fp->fa3_fileid.nfsuquad[0] = 0;
 1678                 fp->fa3_fileid.nfsuquad[1] = txdr_unsigned(vap->va_fileid);
 1679                 txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime);
 1680                 txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime);
 1681                 txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime);
 1682         } else {
 1683                 fp->fa_type = vtonfsv2_type(vap->va_type);
 1684                 fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
 1685                 fp->fa2_size = txdr_unsigned(vap->va_size);
 1686                 fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize);
 1687                 if (vap->va_type == VFIFO)
 1688                         fp->fa2_rdev = 0xffffffff;
 1689                 else
 1690                         fp->fa2_rdev = txdr_unsigned(vap->va_rdev);
 1691                 fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE);
 1692                 fp->fa2_fsid = txdr_unsigned(vap->va_fsid);
 1693                 fp->fa2_fileid = txdr_unsigned(vap->va_fileid);
 1694                 txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime);
 1695                 txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime);
 1696                 txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime);
 1697         }
 1698 }
 1699 
 1700 /*
 1701  * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked)
 1702  *      - look up fsid in mount list (if not found ret error)
 1703  *      - get vp and export rights by calling VFS_FHTOVP()
 1704  *      - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon
 1705  *      - if not lockflag unlock it with VOP_UNLOCK()
 1706  */
 1707 int
 1708 nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
 1709         fhandle_t *fhp;
 1710         int lockflag;
 1711         struct vnode **vpp;
 1712         struct ucred *cred;
 1713         struct nfssvc_sock *slp;
 1714         struct mbuf *nam;
 1715         int *rdonlyp;
 1716         int kerbflag;
 1717 {
 1718         register struct mount *mp;
 1719         register int i;
 1720         struct ucred *credanon;
 1721         int error, exflags;
 1722 
 1723         *vpp = (struct vnode *)0;
 1724         mp = getvfs(&fhp->fh_fsid);
 1725         if (!mp)
 1726                 return (ESTALE);
 1727         error = VFS_FHTOVP(mp, &fhp->fh_fid, nam, vpp, &exflags, &credanon);
 1728         if (error)
 1729                 return (error);
 1730         /*
 1731          * Check/setup credentials.
 1732          */
 1733         if (exflags & MNT_EXKERB) {
 1734                 if (!kerbflag) {
 1735                         vput(*vpp);
 1736                         *vpp = NULL;
 1737                         return (NFSERR_AUTHERR | AUTH_TOOWEAK);
 1738                 }
 1739         } else if (kerbflag) {
 1740                 vput(*vpp);
 1741                 *vpp = NULL;
 1742                 return (NFSERR_AUTHERR | AUTH_TOOWEAK);
 1743         } else if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) {
 1744                 cred->cr_uid = credanon->cr_uid;
 1745                 for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++)
 1746                         cred->cr_groups[i] = credanon->cr_groups[i];
 1747                 cred->cr_ngroups = i;
 1748         }
 1749         if (exflags & MNT_EXRDONLY)
 1750                 *rdonlyp = 1;
 1751         else
 1752                 *rdonlyp = 0;
 1753 
 1754         nfsrv_object_create(*vpp);
 1755 
 1756         if (!lockflag)
 1757                 VOP_UNLOCK(*vpp);
 1758         return (0);
 1759 }
 1760 
 1761 #endif /* NFS_NOSERVER */
 1762 /*
 1763  * This function compares two net addresses by family and returns TRUE
 1764  * if they are the same host.
 1765  * If there is any doubt, return FALSE.
 1766  * The AF_INET family is handled as a special case so that address mbufs
 1767  * don't need to be saved to store "struct in_addr", which is only 4 bytes.
 1768  */
 1769 int
 1770 netaddr_match(family, haddr, nam)
 1771         int family;
 1772         union nethostaddr *haddr;
 1773         struct mbuf *nam;
 1774 {
 1775         register struct sockaddr_in *inetaddr;
 1776 
 1777         switch (family) {
 1778         case AF_INET:
 1779                 inetaddr = mtod(nam, struct sockaddr_in *);
 1780                 if (inetaddr->sin_family == AF_INET &&
 1781                     inetaddr->sin_addr.s_addr == haddr->had_inetaddr)
 1782                         return (1);
 1783                 break;
 1784 #ifdef ISO
 1785         case AF_ISO:
 1786             {
 1787                 register struct sockaddr_iso *isoaddr1, *isoaddr2;
 1788 
 1789                 isoaddr1 = mtod(nam, struct sockaddr_iso *);
 1790                 isoaddr2 = mtod(haddr->had_nam, struct sockaddr_iso *);
 1791                 if (isoaddr1->siso_family == AF_ISO &&
 1792                     isoaddr1->siso_nlen > 0 &&
 1793                     isoaddr1->siso_nlen == isoaddr2->siso_nlen &&
 1794                     SAME_ISOADDR(isoaddr1, isoaddr2))
 1795                         return (1);
 1796                 break;
 1797             }
 1798 #endif  /* ISO */
 1799         default:
 1800                 break;
 1801         };
 1802         return (0);
 1803 }
 1804 
 1805 static nfsuint64 nfs_nullcookie = { 0, 0 };
 1806 /*
 1807  * This function finds the directory cookie that corresponds to the
 1808  * logical byte offset given.
 1809  */
 1810 nfsuint64 *
 1811 nfs_getcookie(np, off, add)
 1812         register struct nfsnode *np;
 1813         off_t off;
 1814         int add;
 1815 {
 1816         register struct nfsdmap *dp, *dp2;
 1817         register int pos;
 1818 
 1819         pos = off / NFS_DIRBLKSIZ;
 1820         if (pos == 0) {
 1821 #ifdef DIAGNOSTIC
 1822                 if (add)
 1823                         panic("nfs getcookie add at 0");
 1824 #endif
 1825                 return (&nfs_nullcookie);
 1826         }
 1827         pos--;
 1828         dp = np->n_cookies.lh_first;
 1829         if (!dp) {
 1830                 if (add) {
 1831                         MALLOC(dp, struct nfsdmap *, sizeof (struct nfsdmap),
 1832                                 M_NFSDIROFF, M_WAITOK);
 1833                         dp->ndm_eocookie = 0;
 1834                         LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list);
 1835                 } else
 1836                         return ((nfsuint64 *)0);
 1837         }
 1838         while (pos >= NFSNUMCOOKIES) {
 1839                 pos -= NFSNUMCOOKIES;
 1840                 if (dp->ndm_list.le_next) {
 1841                         if (!add && dp->ndm_eocookie < NFSNUMCOOKIES &&
 1842                                 pos >= dp->ndm_eocookie)
 1843                                 return ((nfsuint64 *)0);
 1844                         dp = dp->ndm_list.le_next;
 1845                 } else if (add) {
 1846                         MALLOC(dp2, struct nfsdmap *, sizeof (struct nfsdmap),
 1847                                 M_NFSDIROFF, M_WAITOK);
 1848                         dp2->ndm_eocookie = 0;
 1849                         LIST_INSERT_AFTER(dp, dp2, ndm_list);
 1850                         dp = dp2;
 1851                 } else
 1852                         return ((nfsuint64 *)0);
 1853         }
 1854         if (pos >= dp->ndm_eocookie) {
 1855                 if (add)
 1856                         dp->ndm_eocookie = pos + 1;
 1857                 else
 1858                         return ((nfsuint64 *)0);
 1859         }
 1860         return (&dp->ndm_cookies[pos]);
 1861 }
 1862 
 1863 /*
 1864  * Invalidate cached directory information, except for the actual directory
 1865  * blocks (which are invalidated separately).
 1866  * Done mainly to avoid the use of stale offset cookies.
 1867  */
 1868 void
 1869 nfs_invaldir(vp)
 1870         register struct vnode *vp;
 1871 {
 1872         register struct nfsnode *np = VTONFS(vp);
 1873 
 1874 #ifdef DIAGNOSTIC
 1875         if (vp->v_type != VDIR)
 1876                 panic("nfs: invaldir not dir");
 1877 #endif
 1878         np->n_direofoffset = 0;
 1879         np->n_cookieverf.nfsuquad[0] = 0;
 1880         np->n_cookieverf.nfsuquad[1] = 0;
 1881         if (np->n_cookies.lh_first)
 1882                 np->n_cookies.lh_first->ndm_eocookie = 0;
 1883 }
 1884 
 1885 /*
 1886  * The write verifier has changed (probably due to a server reboot), so all
 1887  * B_NEEDCOMMIT blocks will have to be written again. Since they are on the
 1888  * dirty block list as B_DELWRI, all this takes is clearing the B_NEEDCOMMIT
 1889  * flag. Once done the new write verifier can be set for the mount point.
 1890  */
 1891 void
 1892 nfs_clearcommit(mp)
 1893         struct mount *mp;
 1894 {
 1895         register struct vnode *vp, *nvp;
 1896         register struct buf *bp, *nbp;
 1897         int s;
 1898 
 1899         s = splbio();
 1900 loop:
 1901         for (vp = mp->mnt_vnodelist.lh_first; vp; vp = nvp) {
 1902                 if (vp->v_mount != mp)  /* Paranoia */
 1903                         goto loop;
 1904                 nvp = vp->v_mntvnodes.le_next;
 1905                 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
 1906                         nbp = bp->b_vnbufs.le_next;
 1907                         if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT))
 1908                                 == (B_DELWRI | B_NEEDCOMMIT))
 1909                                 bp->b_flags &= ~(B_NEEDCOMMIT | B_CLUSTEROK);
 1910                 }
 1911         }
 1912         splx(s);
 1913 }
 1914 
 1915 #ifndef NFS_NOSERVER
 1916 /*
 1917  * Map errnos to NFS error numbers. For Version 3 also filter out error
 1918  * numbers not specified for the associated procedure.
 1919  */
 1920 int
 1921 nfsrv_errmap(nd, err)
 1922         struct nfsrv_descript *nd;
 1923         register int err;
 1924 {
 1925         register short *defaulterrp, *errp;
 1926 
 1927         if (nd->nd_flag & ND_NFSV3) {
 1928             if (nd->nd_procnum <= NFSPROC_COMMIT) {
 1929                 errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum];
 1930                 while (*++errp) {
 1931                         if (*errp == err)
 1932                                 return (err);
 1933                         else if (*errp > err)
 1934                                 break;
 1935                 }
 1936                 return ((int)*defaulterrp);
 1937             } else
 1938                 return (err & 0xffff);
 1939         }
 1940         if (err <= ELAST)
 1941                 return ((int)nfsrv_v2errmap[err - 1]);
 1942         return (NFSERR_IO);
 1943 }
 1944 
 1945 int
 1946 nfsrv_object_create(struct vnode *vp) {
 1947 
 1948         if ((vp == NULL) || (vp->v_type != VREG))
 1949                 return 1;
 1950         return vfs_object_create(vp, curproc, curproc?curproc->p_ucred:NULL, 1);
 1951 }
 1952 #endif /* NFS_NOSERVER */

Cache object: 0ec1d782053d04bff745f5c92623f71b


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