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/nfsserver/nfs_serv.c

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

    1 /*-
    2  * Copyright (c) 1989, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * This code is derived from software contributed to Berkeley by
    6  * Rick Macklem at The University of Guelph.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 4. Neither the name of the University nor the names of its contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  *      @(#)nfs_serv.c  8.8 (Berkeley) 7/31/95
   33  */
   34 
   35 #include <sys/cdefs.h>
   36 __FBSDID("$FreeBSD: src/sys/nfsserver/nfs_serv.c,v 1.147.2.5 2005/06/10 08:45:58 rwatson Exp $");
   37 
   38 /*
   39  * nfs version 2 and 3 server calls to vnode ops
   40  * - these routines generally have 3 phases
   41  *   1 - break down and validate rpc request in mbuf list
   42  *   2 - do the vnode ops for the request
   43  *       (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c)
   44  *   3 - build the rpc reply in an mbuf list
   45  *   nb:
   46  *      - do not mix the phases, since the nfsm_?? macros can return failures
   47  *        on a bad rpc or similar and do not do any vrele() or vput()'s
   48  *
   49  *      - the nfsm_reply() macro generates an nfs rpc reply with the nfs
   50  *      error number iff error != 0 whereas
   51  *      returning an error from the server function implies a fatal error
   52  *      such as a badly constructed rpc request that should be dropped without
   53  *      a reply.
   54  *      For nfsm_reply(), the case where error == EBADRPC is treated
   55  *      specially; after constructing a reply, it does an immediate
   56  *      `goto nfsmout' to avoid getting any V3 post-op status appended.
   57  *
   58  * Other notes:
   59  *      Warning: always pay careful attention to resource cleanup on return
   60  *      and note that nfsm_*() macros can terminate a procedure on certain
   61  *      errors.
   62  *
   63  *      lookup() and namei()
   64  *      may return garbage in various structural fields/return elements
   65  *      if an error is returned, and may garbage up nd.ni_dvp even if no
   66  *      error is returned and you did not request LOCKPARENT or WANTPARENT.
   67  *
   68  *      We use the ni_cnd.cn_flags 'HASBUF' flag to track whether the name
   69  *      buffer has been freed or not.
   70  */
   71 
   72 #include <sys/param.h>
   73 #include <sys/systm.h>
   74 #include <sys/proc.h>
   75 #include <sys/namei.h>
   76 #include <sys/unistd.h>
   77 #include <sys/vnode.h>
   78 #include <sys/mount.h>
   79 #include <sys/socket.h>
   80 #include <sys/socketvar.h>
   81 #include <sys/malloc.h>
   82 #include <sys/mbuf.h>
   83 #include <sys/dirent.h>
   84 #include <sys/stat.h>
   85 #include <sys/kernel.h>
   86 #include <sys/sysctl.h>
   87 #include <sys/bio.h>
   88 #include <sys/buf.h>
   89 
   90 #include <vm/vm.h>
   91 #include <vm/vm_extern.h>
   92 #include <vm/vm_object.h>
   93 
   94 #include <nfs/nfsproto.h>
   95 #include <nfs/rpcv2.h>
   96 #include <nfsserver/nfs.h>
   97 #include <nfs/xdr_subs.h>
   98 #include <nfsserver/nfsm_subs.h>
   99 
  100 #ifdef NFSRV_DEBUG
  101 #define nfsdbprintf(info)       printf info
  102 #else
  103 #define nfsdbprintf(info)
  104 #endif
  105 
  106 #define MAX_COMMIT_COUNT        (1024 * 1024)
  107 
  108 #define NUM_HEURISTIC           1017
  109 #define NHUSE_INIT              64
  110 #define NHUSE_INC               16
  111 #define NHUSE_MAX               2048
  112 
  113 static struct nfsheur {
  114         struct vnode *nh_vp;    /* vp to match (unreferenced pointer) */
  115         off_t nh_nextr;         /* next offset for sequential detection */
  116         int nh_use;             /* use count for selection */
  117         int nh_seqcount;        /* heuristic */
  118 } nfsheur[NUM_HEURISTIC];
  119 
  120 /* Global vars */
  121 
  122 int nfsrvw_procrastinate = NFS_GATHERDELAY * 1000;
  123 int nfsrvw_procrastinate_v3 = 0;
  124 
  125 static struct timeval   nfsver = { 0 };
  126 
  127 SYSCTL_NODE(_vfs, OID_AUTO, nfsrv, CTLFLAG_RW, 0, "NFS server");
  128 
  129 static int nfs_async;
  130 static int nfs_commit_blks;
  131 static int nfs_commit_miss;
  132 SYSCTL_INT(_vfs_nfsrv, OID_AUTO, async, CTLFLAG_RW, &nfs_async, 0, "");
  133 SYSCTL_INT(_vfs_nfsrv, OID_AUTO, commit_blks, CTLFLAG_RW, &nfs_commit_blks, 0, "");
  134 SYSCTL_INT(_vfs_nfsrv, OID_AUTO, commit_miss, CTLFLAG_RW, &nfs_commit_miss, 0, "");
  135 
  136 struct nfsrvstats nfsrvstats;
  137 SYSCTL_STRUCT(_vfs_nfsrv, NFS_NFSRVSTATS, nfsrvstats, CTLFLAG_RD,
  138         &nfsrvstats, nfsrvstats, "S,nfsrvstats");
  139 
  140 static int      nfsrv_access_withgiant(struct vnode *vp, int flags,
  141                     struct ucred *cred, int rdonly, struct thread *td,
  142                     int override);
  143 static int      nfsrv_access(struct vnode *, int, struct ucred *, int,
  144                     struct thread *, int);
  145 static void     nfsrvw_coalesce(struct nfsrv_descript *,
  146                     struct nfsrv_descript *);
  147 
  148 /*
  149  * Clear nameidata fields that are tested in nsfmout cleanup code prior
  150  * to using first nfsm macro (that might jump to the cleanup code).
  151  */
  152 
  153 static __inline void
  154 ndclear(struct nameidata *nd)
  155 {
  156 
  157         nd->ni_cnd.cn_flags = 0;
  158         nd->ni_vp = NULL;
  159         nd->ni_dvp = NULL;
  160         nd->ni_startdir = NULL;
  161 }
  162 
  163 /*
  164  * nfs v3 access service
  165  */
  166 int
  167 nfsrv3_access(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
  168     struct thread *td, struct mbuf **mrq)
  169 {
  170         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
  171         struct sockaddr *nam = nfsd->nd_nam;
  172         caddr_t dpos = nfsd->nd_dpos;
  173         struct ucred *cred = &nfsd->nd_cr;
  174         struct vnode *vp = NULL;
  175         nfsfh_t nfh;
  176         fhandle_t *fhp;
  177         u_int32_t *tl;
  178         caddr_t bpos;
  179         int error = 0, rdonly, getret;
  180         struct mbuf *mb, *mreq;
  181         struct vattr vattr, *vap = &vattr;
  182         u_long testmode, nfsmode;
  183         int v3 = (nfsd->nd_flag & ND_NFSV3);
  184 
  185         NFSD_LOCK_ASSERT();
  186 
  187         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
  188         if (!v3)
  189                 panic("nfsrv3_access: v3 proc called on a v2 connection");
  190         fhp = &nfh.fh_generic;
  191         nfsm_srvmtofh(fhp);
  192         tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
  193         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
  194         if (error) {
  195                 nfsm_reply(NFSX_UNSIGNED);
  196                 nfsm_srvpostop_attr(1, NULL);
  197                 error = 0;
  198                 goto nfsmout;
  199         }
  200         nfsmode = fxdr_unsigned(u_int32_t, *tl);
  201         NFSD_UNLOCK();
  202         mtx_lock(&Giant);       /* VFS */
  203         if ((nfsmode & NFSV3ACCESS_READ) &&
  204                 nfsrv_access_withgiant(vp, VREAD, cred, rdonly, td, 0))
  205                 nfsmode &= ~NFSV3ACCESS_READ;
  206         if (vp->v_type == VDIR)
  207                 testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
  208                         NFSV3ACCESS_DELETE);
  209         else
  210                 testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
  211         if ((nfsmode & testmode) &&
  212                 nfsrv_access_withgiant(vp, VWRITE, cred, rdonly, td, 0))
  213                 nfsmode &= ~testmode;
  214         if (vp->v_type == VDIR)
  215                 testmode = NFSV3ACCESS_LOOKUP;
  216         else
  217                 testmode = NFSV3ACCESS_EXECUTE;
  218         if ((nfsmode & testmode) &&
  219                 nfsrv_access_withgiant(vp, VEXEC, cred, rdonly, td, 0))
  220                 nfsmode &= ~testmode;
  221         getret = VOP_GETATTR(vp, vap, cred, td);
  222         vput(vp);
  223         mtx_unlock(&Giant);     /* VFS */
  224         vp = NULL;
  225         NFSD_LOCK();
  226         nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED);
  227         nfsm_srvpostop_attr(getret, vap);
  228         tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
  229         *tl = txdr_unsigned(nfsmode);
  230 nfsmout:
  231         NFSD_LOCK_ASSERT();
  232         if (vp) {
  233                 NFSD_UNLOCK();
  234                 mtx_lock(&Giant);       /* VFS */
  235                 vput(vp);
  236                 mtx_unlock(&Giant);     /* VFS */
  237                 NFSD_LOCK();
  238         }
  239         return(error);
  240 }
  241 
  242 /*
  243  * nfs getattr service
  244  */
  245 int
  246 nfsrv_getattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
  247     struct thread *td, struct mbuf **mrq)
  248 {
  249         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
  250         struct sockaddr *nam = nfsd->nd_nam;
  251         caddr_t dpos = nfsd->nd_dpos;
  252         struct ucred *cred = &nfsd->nd_cr;
  253         struct nfs_fattr *fp;
  254         struct vattr va;
  255         struct vattr *vap = &va;
  256         struct vnode *vp = NULL;
  257         nfsfh_t nfh;
  258         fhandle_t *fhp;
  259         caddr_t bpos;
  260         int error = 0, rdonly;
  261         struct mbuf *mb, *mreq;
  262 
  263         NFSD_LOCK_ASSERT();
  264 
  265         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
  266         fhp = &nfh.fh_generic;
  267         nfsm_srvmtofh(fhp);
  268         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
  269         if (error) {
  270                 nfsm_reply(0);
  271                 error = 0;
  272                 goto nfsmout;
  273         }
  274         NFSD_UNLOCK();
  275         mtx_lock(&Giant);       /* VFS */
  276         error = VOP_GETATTR(vp, vap, cred, td);
  277         vput(vp);
  278         mtx_unlock(&Giant);     /* VFS */
  279         vp = NULL;
  280         NFSD_LOCK();
  281         nfsm_reply(NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
  282         if (error) {
  283                 error = 0;
  284                 goto nfsmout;
  285         }
  286         fp = nfsm_build(struct nfs_fattr *,
  287             NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
  288         nfsm_srvfillattr(vap, fp);
  289         /* fall through */
  290 
  291 nfsmout:
  292         NFSD_LOCK_ASSERT();
  293         if (vp) {
  294                 NFSD_UNLOCK();
  295                 mtx_lock(&Giant);       /* VFS */
  296                 vput(vp);
  297                 mtx_unlock(&Giant);     /* VFS */
  298                 NFSD_LOCK();
  299         }
  300         return(error);
  301 }
  302 
  303 /*
  304  * nfs setattr service
  305  */
  306 int
  307 nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
  308     struct thread *td, struct mbuf **mrq)
  309 {
  310         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
  311         struct sockaddr *nam = nfsd->nd_nam;
  312         caddr_t dpos = nfsd->nd_dpos;
  313         struct ucred *cred = &nfsd->nd_cr;
  314         struct vattr va, preat;
  315         struct vattr *vap = &va;
  316         struct nfsv2_sattr *sp;
  317         struct nfs_fattr *fp;
  318         struct vnode *vp = NULL;
  319         nfsfh_t nfh;
  320         fhandle_t *fhp;
  321         u_int32_t *tl;
  322         caddr_t bpos;
  323         int error = 0, rdonly, preat_ret = 1, postat_ret = 1;
  324         int v3 = (nfsd->nd_flag & ND_NFSV3), gcheck = 0;
  325         struct mbuf *mb, *mreq;
  326         struct timespec guard;
  327         struct mount *mp = NULL;
  328 
  329         NFSD_LOCK_ASSERT();
  330 
  331         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
  332         fhp = &nfh.fh_generic;
  333         nfsm_srvmtofh(fhp);
  334         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
  335                 error = ESTALE;
  336                 goto out;
  337         }
  338         NFSD_UNLOCK();
  339         mtx_lock(&Giant);       /* VFS */
  340         (void) vn_start_write(NULL, &mp, V_WAIT);
  341         mtx_unlock(&Giant);     /* VFS */
  342         NFSD_LOCK();
  343         VATTR_NULL(vap);
  344         if (v3) {
  345                 nfsm_srvsattr(vap);
  346                 tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
  347                 gcheck = fxdr_unsigned(int, *tl);
  348                 if (gcheck) {
  349                         tl = nfsm_dissect(u_int32_t *, 2 * NFSX_UNSIGNED);
  350                         fxdr_nfsv3time(tl, &guard);
  351                 }
  352         } else {
  353                 sp = nfsm_dissect(struct nfsv2_sattr *, NFSX_V2SATTR);
  354                 /*
  355                  * Nah nah nah nah na nah
  356                  * There is a bug in the Sun client that puts 0xffff in the mode
  357                  * field of sattr when it should put in 0xffffffff. The u_short
  358                  * doesn't sign extend.
  359                  * --> check the low order 2 bytes for 0xffff
  360                  */
  361                 if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
  362                         vap->va_mode = nfstov_mode(sp->sa_mode);
  363                 if (sp->sa_uid != nfsrv_nfs_xdrneg1)
  364                         vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
  365                 if (sp->sa_gid != nfsrv_nfs_xdrneg1)
  366                         vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
  367                 if (sp->sa_size != nfsrv_nfs_xdrneg1)
  368                         vap->va_size = fxdr_unsigned(u_quad_t, sp->sa_size);
  369                 if (sp->sa_atime.nfsv2_sec != nfsrv_nfs_xdrneg1) {
  370 #ifdef notyet
  371                         fxdr_nfsv2time(&sp->sa_atime, &vap->va_atime);
  372 #else
  373                         vap->va_atime.tv_sec =
  374                                 fxdr_unsigned(int32_t, sp->sa_atime.nfsv2_sec);
  375                         vap->va_atime.tv_nsec = 0;
  376 #endif
  377                 }
  378                 if (sp->sa_mtime.nfsv2_sec != nfsrv_nfs_xdrneg1)
  379                         fxdr_nfsv2time(&sp->sa_mtime, &vap->va_mtime);
  380 
  381         }
  382 
  383         /*
  384          * Now that we have all the fields, lets do it.
  385          */
  386         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
  387         if (error) {
  388                 nfsm_reply(2 * NFSX_UNSIGNED);
  389                 if (v3)
  390                         nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
  391                 error = 0;
  392                 goto nfsmout;
  393         }
  394 
  395         /*
  396          * vp now an active resource, pay careful attention to cleanup
  397          */
  398         if (v3) {
  399                 NFSD_UNLOCK();
  400                 mtx_lock(&Giant);       /* VFS */
  401                 error = preat_ret = VOP_GETATTR(vp, &preat, cred, td);
  402                 if (!error && gcheck &&
  403                         (preat.va_ctime.tv_sec != guard.tv_sec ||
  404                          preat.va_ctime.tv_nsec != guard.tv_nsec))
  405                         error = NFSERR_NOT_SYNC;
  406                 if (error) {
  407                         vput(vp);
  408                         mtx_unlock(&Giant);     /* VFS */
  409                         vp = NULL;
  410                         NFSD_LOCK();
  411                         nfsm_reply(NFSX_WCCDATA(v3));
  412                         if (v3)
  413                                 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
  414                         error = 0;
  415                         goto nfsmout;
  416                 }
  417                 mtx_unlock(&Giant);     /* VFS */
  418                 NFSD_LOCK();
  419         }
  420         NFSD_LOCK_ASSERT();
  421 
  422         /*
  423          * If the size is being changed write acces is required, otherwise
  424          * just check for a read only filesystem.
  425          */
  426         if (vap->va_size == ((u_quad_t)((quad_t) -1))) {
  427                 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
  428                         error = EROFS;
  429                         goto out;
  430                 }
  431         } else {
  432                 if (vp->v_type == VDIR) {
  433                         error = EISDIR;
  434                         goto out;
  435                 } else if ((error = nfsrv_access(vp, VWRITE, cred, rdonly,
  436                         td, 0)) != 0)
  437                         goto out;
  438         }
  439         NFSD_UNLOCK();
  440         mtx_lock(&Giant);       /* VFS */
  441         error = VOP_SETATTR(vp, vap, cred, td);
  442         postat_ret = VOP_GETATTR(vp, vap, cred, td);
  443         mtx_unlock(&Giant);     /* VFS */
  444         NFSD_LOCK();
  445         if (!error)
  446                 error = postat_ret;
  447 out:
  448         NFSD_LOCK_ASSERT();
  449         if (vp != NULL) {
  450                 NFSD_UNLOCK();
  451                 mtx_lock(&Giant);       /* VFS */
  452                 vput(vp);
  453                 mtx_unlock(&Giant);     /* VFS */
  454                 NFSD_LOCK();
  455         }
  456 
  457         vp = NULL;
  458         nfsm_reply(NFSX_WCCORFATTR(v3));
  459         if (v3) {
  460                 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
  461         } else if (!error) {
  462                 /* v2 non-error case. */
  463                 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
  464                 nfsm_srvfillattr(vap, fp);
  465         }
  466         error = 0;
  467         /* fall through */
  468 
  469 nfsmout:
  470         NFSD_LOCK_ASSERT();
  471         NFSD_UNLOCK();
  472         mtx_lock(&Giant);       /* VFS */
  473         if (vp)
  474                 vput(vp);
  475         vn_finished_write(mp);
  476         mtx_unlock(&Giant);     /* VFS */
  477         NFSD_LOCK();
  478         return(error);
  479 }
  480 
  481 /*
  482  * nfs lookup rpc
  483  */
  484 int
  485 nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
  486     struct thread *td, struct mbuf **mrq)
  487 {
  488         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
  489         struct sockaddr *nam = nfsd->nd_nam;
  490         caddr_t dpos = nfsd->nd_dpos;
  491         struct ucred *cred = &nfsd->nd_cr;
  492         struct nfs_fattr *fp;
  493         struct nameidata nd, ind, *ndp = &nd;
  494         struct vnode *vp, *dirp = NULL;
  495         nfsfh_t nfh;
  496         fhandle_t *fhp;
  497         caddr_t bpos;
  498         int error = 0, len, dirattr_ret = 1;
  499         int v3 = (nfsd->nd_flag & ND_NFSV3), pubflag;
  500         struct mbuf *mb, *mreq;
  501         struct vattr va, dirattr, *vap = &va;
  502 
  503         NFSD_LOCK_ASSERT();
  504 
  505         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
  506         ndclear(&nd);
  507 
  508         fhp = &nfh.fh_generic;
  509         nfsm_srvmtofh(fhp);
  510         nfsm_srvnamesiz(len);
  511 
  512         pubflag = nfs_ispublicfh(fhp);
  513 
  514         nd.ni_cnd.cn_cred = cred;
  515         nd.ni_cnd.cn_nameiop = LOOKUP;
  516         nd.ni_cnd.cn_flags = LOCKLEAF | SAVESTART;
  517         error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
  518                 &dirp, v3, &dirattr, &dirattr_ret, td, pubflag);
  519 
  520         /*
  521          * namei failure, only dirp to cleanup.  Clear out garbarge from
  522          * structure in case macros jump to nfsmout.
  523          */
  524 
  525         NFSD_UNLOCK();
  526         mtx_lock(&Giant);       /* VFS */
  527         if (error) {
  528                 if (dirp) {
  529                         vrele(dirp);
  530                         dirp = NULL;
  531                 }
  532                 mtx_unlock(&Giant);     /* VFS */
  533                 NFSD_LOCK();
  534                 nfsm_reply(NFSX_POSTOPATTR(v3));
  535                 if (v3)
  536                         nfsm_srvpostop_attr(dirattr_ret, &dirattr);
  537                 error = 0;
  538                 goto nfsmout;
  539         }
  540 
  541         /*
  542          * Locate index file for public filehandle
  543          *
  544          * error is 0 on entry and 0 on exit from this block.
  545          */
  546 
  547         if (pubflag) {
  548                 if (nd.ni_vp->v_type == VDIR && nfs_pub.np_index != NULL) {
  549                         /*
  550                          * Setup call to lookup() to see if we can find
  551                          * the index file. Arguably, this doesn't belong
  552                          * in a kernel.. Ugh.  If an error occurs, do not
  553                          * try to install an index file and then clear the
  554                          * error.
  555                          *
  556                          * When we replace nd with ind and redirect ndp,
  557                          * maintenance of ni_startdir and ni_vp shift to
  558                          * ind and we have to clean them up in the old nd.
  559                          * However, the cnd resource continues to be maintained
  560                          * via the original nd.  Confused?  You aren't alone!
  561                          */
  562                         ind = nd;
  563                         VOP_UNLOCK(nd.ni_vp, 0, td);
  564                         ind.ni_pathlen = strlen(nfs_pub.np_index);
  565                         ind.ni_cnd.cn_nameptr = ind.ni_cnd.cn_pnbuf =
  566                             nfs_pub.np_index;
  567                         ind.ni_startdir = nd.ni_vp;
  568                         VREF(ind.ni_startdir);
  569 
  570                         error = lookup(&ind);
  571                         ind.ni_dvp = NULL;
  572 
  573                         if (error == 0) {
  574                                 /*
  575                                  * Found an index file. Get rid of
  576                                  * the old references.  transfer nd.ni_vp'
  577                                  */
  578                                 if (dirp)
  579                                         vrele(dirp);
  580                                 dirp = nd.ni_vp;
  581                                 nd.ni_vp = NULL;
  582                                 vrele(nd.ni_startdir);
  583                                 nd.ni_startdir = NULL;
  584                                 ndp = &ind;
  585                         }
  586                         error = 0;
  587                 }
  588                 /*
  589                  * If the public filehandle was used, check that this lookup
  590                  * didn't result in a filehandle outside the publicly exported
  591                  * filesystem.  We clear the poor vp here to avoid lockups due
  592                  * to NFS I/O.
  593                  */
  594 
  595                 if (ndp->ni_vp->v_mount != nfs_pub.np_mount) {
  596                         vput(nd.ni_vp);
  597                         nd.ni_vp = NULL;
  598                         error = EPERM;
  599                 }
  600         }
  601 
  602         if (dirp) {
  603                 vrele(dirp);
  604                 dirp = NULL;
  605         }
  606 
  607         /*
  608          * Resources at this point:
  609          *      ndp->ni_vp      may not be NULL
  610          *
  611          */
  612 
  613         if (error) {
  614                 mtx_unlock(&Giant);     /* VFS */
  615                 NFSD_LOCK();
  616                 nfsm_reply(NFSX_POSTOPATTR(v3));
  617                 if (v3)
  618                         nfsm_srvpostop_attr(dirattr_ret, &dirattr);
  619                 error = 0;
  620                 goto nfsmout;
  621         }
  622 
  623         /*
  624          * Clear out some resources prior to potentially blocking.  This
  625          * is not as critical as ni_dvp resources in other routines, but
  626          * it helps.
  627          */
  628         vrele(ndp->ni_startdir);
  629         ndp->ni_startdir = NULL;
  630         NDFREE(&nd, NDF_ONLY_PNBUF);
  631 
  632         /*
  633          * Get underlying attribute, then release remaining resources ( for
  634          * the same potential blocking reason ) and reply.
  635          */
  636         vp = ndp->ni_vp;
  637         bzero((caddr_t)fhp, sizeof(nfh));
  638         fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
  639         error = VFS_VPTOFH(vp, &fhp->fh_fid);
  640         if (!error)
  641                 error = VOP_GETATTR(vp, vap, cred, td);
  642 
  643         vput(vp);
  644         mtx_unlock(&Giant);     /* VFS */
  645         ndp->ni_vp = NULL;
  646         NFSD_LOCK();
  647         nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPORFATTR(v3) + NFSX_POSTOPATTR(v3));
  648         if (error) {
  649                 if (v3)
  650                         nfsm_srvpostop_attr(dirattr_ret, &dirattr);
  651                 error = 0;
  652                 goto nfsmout;
  653         }
  654         nfsm_srvfhtom(fhp, v3);
  655         if (v3) {
  656                 nfsm_srvpostop_attr(0, vap);
  657                 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
  658         } else {
  659                 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
  660                 nfsm_srvfillattr(vap, fp);
  661         }
  662 
  663 nfsmout:
  664         NFSD_LOCK_ASSERT();
  665         NFSD_UNLOCK();
  666         mtx_lock(&Giant);       /* VFS */
  667         if (dirp)
  668                 vrele(dirp);
  669         NDFREE(&nd, NDF_ONLY_PNBUF);
  670         if (ndp->ni_startdir)
  671                 vrele(ndp->ni_startdir);
  672         if (ndp->ni_vp)
  673                 vput(ndp->ni_vp);
  674         mtx_unlock(&Giant);     /* VFS */
  675         NFSD_LOCK();
  676         return (error);
  677 }
  678 
  679 /*
  680  * nfs readlink service
  681  */
  682 int
  683 nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
  684     struct thread *td, struct mbuf **mrq)
  685 {
  686         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
  687         struct sockaddr *nam = nfsd->nd_nam;
  688         caddr_t dpos = nfsd->nd_dpos;
  689         struct ucred *cred = &nfsd->nd_cr;
  690         struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
  691         struct iovec *ivp = iv;
  692         struct mbuf *mp;
  693         u_int32_t *tl;
  694         caddr_t bpos;
  695         int error = 0, rdonly, i, tlen, len, getret;
  696         int v3 = (nfsd->nd_flag & ND_NFSV3);
  697         struct mbuf *mb, *mp3, *nmp, *mreq;
  698         struct vnode *vp = NULL;
  699         struct vattr attr;
  700         nfsfh_t nfh;
  701         fhandle_t *fhp;
  702         struct uio io, *uiop = &io;
  703 
  704         NFSD_LOCK_ASSERT();
  705 
  706         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
  707 #ifndef nolint
  708         mp = NULL;
  709 #endif
  710         mp3 = NULL;
  711         fhp = &nfh.fh_generic;
  712         nfsm_srvmtofh(fhp);
  713         len = 0;
  714         i = 0;
  715         NFSD_UNLOCK();
  716         while (len < NFS_MAXPATHLEN) {
  717                 MGET(nmp, M_TRYWAIT, MT_DATA);
  718                 MCLGET(nmp, M_TRYWAIT);
  719                 nmp->m_len = NFSMSIZ(nmp);
  720                 if (len == 0)
  721                         mp3 = mp = nmp;
  722                 else {
  723                         mp->m_next = nmp;
  724                         mp = nmp;
  725                 }
  726                 if ((len + mp->m_len) > NFS_MAXPATHLEN) {
  727                         mp->m_len = NFS_MAXPATHLEN - len;
  728                         len = NFS_MAXPATHLEN;
  729                 } else
  730                         len += mp->m_len;
  731                 ivp->iov_base = mtod(mp, caddr_t);
  732                 ivp->iov_len = mp->m_len;
  733                 i++;
  734                 ivp++;
  735         }
  736         uiop->uio_iov = iv;
  737         uiop->uio_iovcnt = i;
  738         uiop->uio_offset = 0;
  739         uiop->uio_resid = len;
  740         uiop->uio_rw = UIO_READ;
  741         uiop->uio_segflg = UIO_SYSSPACE;
  742         uiop->uio_td = NULL;
  743         NFSD_LOCK();
  744         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
  745         if (error) {
  746                 nfsm_reply(2 * NFSX_UNSIGNED);
  747                 if (v3)
  748                         nfsm_srvpostop_attr(1, NULL);
  749                 error = 0;
  750                 goto nfsmout;
  751         }
  752         NFSD_UNLOCK();
  753         mtx_lock(&Giant);       /* VFS */
  754         if (vp->v_type != VLNK) {
  755                 if (v3)
  756                         error = EINVAL;
  757                 else
  758                         error = ENXIO;
  759         } else 
  760                 error = VOP_READLINK(vp, uiop, cred);
  761         getret = VOP_GETATTR(vp, &attr, cred, td);
  762         vput(vp);
  763         mtx_unlock(&Giant);     /* VFS */
  764         vp = NULL;
  765         NFSD_LOCK();
  766         nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_UNSIGNED);
  767         if (v3)
  768                 nfsm_srvpostop_attr(getret, &attr);
  769         if (error) {
  770                 error = 0;
  771                 goto nfsmout;
  772         }
  773         if (uiop->uio_resid > 0) {
  774                 len -= uiop->uio_resid;
  775                 tlen = nfsm_rndup(len);
  776                 nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len);
  777         }
  778         tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
  779         *tl = txdr_unsigned(len);
  780         mb->m_next = mp3;
  781         mp3 = NULL;
  782 nfsmout:
  783         NFSD_LOCK_ASSERT();
  784         if (mp3)
  785                 m_freem(mp3);
  786         if (vp) {
  787                 NFSD_UNLOCK();
  788                 mtx_lock(&Giant);       /* VFS */
  789                 vput(vp);
  790                 mtx_unlock(&Giant);     /* VFS */
  791                 NFSD_LOCK();
  792         }
  793         return(error);
  794 }
  795 
  796 /*
  797  * nfs read service
  798  */
  799 int
  800 nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
  801     struct thread *td, struct mbuf **mrq)
  802 {
  803         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
  804         struct sockaddr *nam = nfsd->nd_nam;
  805         caddr_t dpos = nfsd->nd_dpos;
  806         struct ucred *cred = &nfsd->nd_cr;
  807         struct iovec *iv;
  808         struct iovec *iv2;
  809         struct mbuf *m;
  810         struct nfs_fattr *fp;
  811         u_int32_t *tl;
  812         int i;
  813         caddr_t bpos;
  814         int error = 0, rdonly, cnt, len, left, siz, tlen, getret;
  815         int v3 = (nfsd->nd_flag & ND_NFSV3), reqlen;
  816         struct mbuf *mb, *mreq;
  817         struct mbuf *m2;
  818         struct vnode *vp = NULL;
  819         nfsfh_t nfh;
  820         fhandle_t *fhp;
  821         struct uio io, *uiop = &io;
  822         struct vattr va, *vap = &va;
  823         struct nfsheur *nh;
  824         off_t off;
  825         int ioflag = 0;
  826 
  827         NFSD_LOCK_ASSERT();
  828 
  829         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
  830         fhp = &nfh.fh_generic;
  831         nfsm_srvmtofh(fhp);
  832         if (v3) {
  833                 tl = nfsm_dissect(u_int32_t *, 2 * NFSX_UNSIGNED);
  834                 off = fxdr_hyper(tl);
  835         } else {
  836                 tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
  837                 off = (off_t)fxdr_unsigned(u_int32_t, *tl);
  838         }
  839         nfsm_srvstrsiz(reqlen, NFS_SRVMAXDATA(nfsd));
  840 
  841         /*
  842          * Reference vp.  If an error occurs, vp will be invalid, but we
  843          * have to NULL it just in case.  The macros might goto nfsmout
  844          * as well.
  845          */
  846 
  847         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
  848         if (error) {
  849                 vp = NULL;
  850                 nfsm_reply(2 * NFSX_UNSIGNED);
  851                 if (v3)
  852                         nfsm_srvpostop_attr(1, NULL);
  853                 error = 0;
  854                 goto nfsmout;
  855         }
  856 
  857         if (vp->v_type != VREG) {
  858                 if (v3)
  859                         error = EINVAL;
  860                 else
  861                         error = (vp->v_type == VDIR) ? EISDIR : EACCES;
  862         }
  863         NFSD_UNLOCK();
  864         mtx_lock(&Giant);       /* VFS */
  865         if (!error) {
  866                 if ((error = nfsrv_access_withgiant(vp, VREAD, cred, rdonly,
  867                     td, 1)) != 0)
  868                         error = nfsrv_access_withgiant(vp, VEXEC, cred,
  869                             rdonly, td, 1);
  870         }
  871         getret = VOP_GETATTR(vp, vap, cred, td);
  872         if (!error)
  873                 error = getret;
  874         if (error) {
  875                 vput(vp);
  876                 mtx_unlock(&Giant);     /* VFS */
  877                 vp = NULL;
  878                 NFSD_LOCK();
  879                 nfsm_reply(NFSX_POSTOPATTR(v3));
  880                 if (v3)
  881                         nfsm_srvpostop_attr(getret, vap);
  882                 error = 0;
  883                 goto nfsmout;
  884         }
  885         mtx_unlock(&Giant);     /* VFS */
  886         NFSD_LOCK();
  887 
  888         /*
  889          * Calculate byte count to read
  890          */
  891 
  892         if (off >= vap->va_size)
  893                 cnt = 0;
  894         else if ((off + reqlen) > vap->va_size)
  895                 cnt = vap->va_size - off;
  896         else
  897                 cnt = reqlen;
  898 
  899         /*
  900          * Calculate seqcount for heuristic
  901          */
  902 
  903         {
  904                 int hi;
  905                 int try = 32;
  906 
  907                 /*
  908                  * Locate best candidate
  909                  */
  910 
  911                 hi = ((int)(vm_offset_t)vp / sizeof(struct vnode)) % NUM_HEURISTIC;
  912                 nh = &nfsheur[hi];
  913 
  914                 while (try--) {
  915                         if (nfsheur[hi].nh_vp == vp) {
  916                                 nh = &nfsheur[hi];
  917                                 break;
  918                         }
  919                         if (nfsheur[hi].nh_use > 0)
  920                                 --nfsheur[hi].nh_use;
  921                         hi = (hi + 1) % NUM_HEURISTIC;
  922                         if (nfsheur[hi].nh_use < nh->nh_use)
  923                                 nh = &nfsheur[hi];
  924                 }
  925 
  926                 if (nh->nh_vp != vp) {
  927                         nh->nh_vp = vp;
  928                         nh->nh_nextr = off;
  929                         nh->nh_use = NHUSE_INIT;
  930                         if (off == 0)
  931                                 nh->nh_seqcount = 4;
  932                         else
  933                                 nh->nh_seqcount = 1;
  934                 }
  935 
  936                 /*
  937                  * Calculate heuristic
  938                  */
  939 
  940                 if ((off == 0 && nh->nh_seqcount > 0) || off == nh->nh_nextr) {
  941                         if (++nh->nh_seqcount > IO_SEQMAX)
  942                                 nh->nh_seqcount = IO_SEQMAX;
  943                 } else if (nh->nh_seqcount > 1) {
  944                         nh->nh_seqcount = 1;
  945                 } else {
  946                         nh->nh_seqcount = 0;
  947                 }
  948                 nh->nh_use += NHUSE_INC;
  949                 if (nh->nh_use > NHUSE_MAX)
  950                         nh->nh_use = NHUSE_MAX;
  951                 ioflag |= nh->nh_seqcount << IO_SEQSHIFT;
  952         }
  953 
  954         nfsm_reply(NFSX_POSTOPORFATTR(v3) + 3 * NFSX_UNSIGNED+nfsm_rndup(cnt));
  955         if (v3) {
  956                 tl = nfsm_build(u_int32_t *, NFSX_V3FATTR + 4 * NFSX_UNSIGNED);
  957                 *tl++ = nfsrv_nfs_true;
  958                 fp = (struct nfs_fattr *)tl;
  959                 tl += (NFSX_V3FATTR / sizeof (u_int32_t));
  960         } else {
  961                 tl = nfsm_build(u_int32_t *, NFSX_V2FATTR + NFSX_UNSIGNED);
  962                 fp = (struct nfs_fattr *)tl;
  963                 tl += (NFSX_V2FATTR / sizeof (u_int32_t));
  964         }
  965         len = left = nfsm_rndup(cnt);
  966         NFSD_UNLOCK();
  967         if (cnt > 0) {
  968                 /*
  969                  * Generate the mbuf list with the uio_iov ref. to it.
  970                  */
  971                 i = 0;
  972                 m = m2 = mb;
  973                 while (left > 0) {
  974                         siz = min(M_TRAILINGSPACE(m), left);
  975                         if (siz > 0) {
  976                                 left -= siz;
  977                                 i++;
  978                         }
  979                         if (left > 0) {
  980                                 MGET(m, M_TRYWAIT, MT_DATA);
  981                                 MCLGET(m, M_TRYWAIT);
  982                                 m->m_len = 0;
  983                                 m2->m_next = m;
  984                                 m2 = m;
  985                         }
  986                 }
  987                 MALLOC(iv, struct iovec *, i * sizeof (struct iovec),
  988                        M_TEMP, M_WAITOK);
  989                 uiop->uio_iov = iv2 = iv;
  990                 m = mb;
  991                 left = len;
  992                 i = 0;
  993                 while (left > 0) {
  994                         if (m == NULL)
  995                                 panic("nfsrv_read iov");
  996                         siz = min(M_TRAILINGSPACE(m), left);
  997                         if (siz > 0) {
  998                                 iv->iov_base = mtod(m, caddr_t) + m->m_len;
  999                                 iv->iov_len = siz;
 1000                                 m->m_len += siz;
 1001                                 left -= siz;
 1002                                 iv++;
 1003                                 i++;
 1004                         }
 1005                         m = m->m_next;
 1006                 }
 1007                 uiop->uio_iovcnt = i;
 1008                 uiop->uio_offset = off;
 1009                 uiop->uio_resid = len;
 1010                 uiop->uio_rw = UIO_READ;
 1011                 uiop->uio_segflg = UIO_SYSSPACE;
 1012                 mtx_lock(&Giant);       /* VFS */
 1013                 error = VOP_READ(vp, uiop, IO_NODELOCKED | ioflag, cred);
 1014                 off = uiop->uio_offset;
 1015                 nh->nh_nextr = off;
 1016                 FREE((caddr_t)iv2, M_TEMP);
 1017                 if (error || (getret = VOP_GETATTR(vp, vap, cred, td))) {
 1018                         if (!error)
 1019                                 error = getret;
 1020                         m_freem(mreq);
 1021                         vput(vp);
 1022                         mtx_unlock(&Giant);     /* VFS */
 1023                         NFSD_LOCK();
 1024                         vp = NULL;
 1025                         nfsm_reply(NFSX_POSTOPATTR(v3));
 1026                         if (v3)
 1027                                 nfsm_srvpostop_attr(getret, vap);
 1028                         error = 0;
 1029                         goto nfsmout;
 1030                 }
 1031         } else {
 1032                 uiop->uio_resid = 0;
 1033                 mtx_lock(&Giant);       /* VFS */
 1034         }
 1035         mtx_assert(&Giant, MA_OWNED);   /* VFS */
 1036         vput(vp);
 1037         mtx_unlock(&Giant);     /* VFS */
 1038         vp = NULL;
 1039         NFSD_LOCK();
 1040         nfsm_srvfillattr(vap, fp);
 1041         tlen = len - uiop->uio_resid;
 1042         cnt = cnt < tlen ? cnt : tlen;
 1043         tlen = nfsm_rndup(cnt);
 1044         if (len != tlen || tlen != cnt)
 1045                 nfsm_adj(mb, len - tlen, tlen - cnt);
 1046         if (v3) {
 1047                 *tl++ = txdr_unsigned(cnt);
 1048                 if (cnt < reqlen)
 1049                         *tl++ = nfsrv_nfs_true;
 1050                 else
 1051                         *tl++ = nfsrv_nfs_false;
 1052         }
 1053         *tl = txdr_unsigned(cnt);
 1054 nfsmout:
 1055         NFSD_LOCK_ASSERT();
 1056         if (vp) {
 1057                 NFSD_UNLOCK();
 1058                 mtx_lock(&Giant);       /* VFS */
 1059                 vput(vp);
 1060                 mtx_unlock(&Giant);     /* VFS */
 1061                 NFSD_LOCK();
 1062         }
 1063         return(error);
 1064 }
 1065 
 1066 /*
 1067  * nfs write service
 1068  */
 1069 int
 1070 nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 1071     struct thread *td, struct mbuf **mrq)
 1072 {
 1073         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 1074         struct sockaddr *nam = nfsd->nd_nam;
 1075         caddr_t dpos = nfsd->nd_dpos;
 1076         struct ucred *cred = &nfsd->nd_cr;
 1077         struct iovec *ivp;
 1078         int i, cnt;
 1079         struct mbuf *mp;
 1080         struct nfs_fattr *fp;
 1081         struct iovec *iv;
 1082         struct vattr va, forat;
 1083         struct vattr *vap = &va;
 1084         u_int32_t *tl;
 1085         caddr_t bpos;
 1086         int error = 0, rdonly, len, forat_ret = 1;
 1087         int ioflags, aftat_ret = 1, retlen = 0, zeroing, adjust;
 1088         int stable = NFSV3WRITE_FILESYNC;
 1089         int v3 = (nfsd->nd_flag & ND_NFSV3);
 1090         struct mbuf *mb, *mreq;
 1091         struct vnode *vp = NULL;
 1092         nfsfh_t nfh;
 1093         fhandle_t *fhp;
 1094         struct uio io, *uiop = &io;
 1095         off_t off;
 1096         struct mount *mntp = NULL;
 1097 
 1098         NFSD_LOCK_ASSERT();
 1099 
 1100         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 1101         if (mrep == NULL) {
 1102                 *mrq = NULL;
 1103                 error = 0;
 1104                 goto nfsmout;
 1105         }
 1106         fhp = &nfh.fh_generic;
 1107         nfsm_srvmtofh(fhp);
 1108         if ((mntp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
 1109                 error = ESTALE;
 1110                 goto ereply;
 1111         }
 1112         NFSD_UNLOCK();
 1113         mtx_lock(&Giant);       /* VFS */
 1114         (void) vn_start_write(NULL, &mntp, V_WAIT);
 1115         mtx_unlock(&Giant);     /* VFS */
 1116         NFSD_LOCK();
 1117         if (v3) {
 1118                 tl = nfsm_dissect(u_int32_t *, 5 * NFSX_UNSIGNED);
 1119                 off = fxdr_hyper(tl);
 1120                 tl += 3;
 1121                 stable = fxdr_unsigned(int, *tl++);
 1122         } else {
 1123                 tl = nfsm_dissect(u_int32_t *, 4 * NFSX_UNSIGNED);
 1124                 off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
 1125                 tl += 2;
 1126                 if (nfs_async)
 1127                         stable = NFSV3WRITE_UNSTABLE;
 1128         }
 1129         retlen = len = fxdr_unsigned(int32_t, *tl);
 1130         cnt = i = 0;
 1131 
 1132         /*
 1133          * For NFS Version 2, it is not obvious what a write of zero length
 1134          * should do, but I might as well be consistent with Version 3,
 1135          * which is to return ok so long as there are no permission problems.
 1136          */
 1137         if (len > 0) {
 1138             zeroing = 1;
 1139             mp = mrep;
 1140             while (mp) {
 1141                 if (mp == md) {
 1142                         zeroing = 0;
 1143                         adjust = dpos - mtod(mp, caddr_t);
 1144                         mp->m_len -= adjust;
 1145                         if (mp->m_len > 0 && adjust > 0)
 1146                                 mp->m_data += adjust;
 1147                 }
 1148                 if (zeroing)
 1149                         mp->m_len = 0;
 1150                 else if (mp->m_len > 0) {
 1151                         i += mp->m_len;
 1152                         if (i > len) {
 1153                                 mp->m_len -= (i - len);
 1154                                 zeroing = 1;
 1155                         }
 1156                         if (mp->m_len > 0)
 1157                                 cnt++;
 1158                 }
 1159                 mp = mp->m_next;
 1160             }
 1161         }
 1162         if (len > NFS_MAXDATA || len < 0 || i < len) {
 1163                 error = EIO;
 1164                 nfsm_reply(2 * NFSX_UNSIGNED);
 1165                 if (v3)
 1166                         nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
 1167                 error = 0;
 1168                 goto nfsmout;
 1169         }
 1170         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
 1171         if (error) {
 1172                 vp = NULL;
 1173                 nfsm_reply(2 * NFSX_UNSIGNED);
 1174                 if (v3)
 1175                         nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
 1176                 error = 0;
 1177                 goto nfsmout;
 1178         }
 1179         if (v3) {
 1180                 NFSD_UNLOCK();
 1181                 mtx_lock(&Giant);       /* VFS */
 1182                 forat_ret = VOP_GETATTR(vp, &forat, cred, td);
 1183                 mtx_unlock(&Giant);     /* VFS */
 1184                 NFSD_LOCK();
 1185         }
 1186         if (vp->v_type != VREG) {
 1187                 if (v3)
 1188                         error = EINVAL;
 1189                 else
 1190                         error = (vp->v_type == VDIR) ? EISDIR : EACCES;
 1191         }
 1192         if (!error)
 1193                 error = nfsrv_access(vp, VWRITE, cred, rdonly, td, 1);
 1194         if (error) {
 1195                 NFSD_UNLOCK();
 1196                 mtx_lock(&Giant);       /* VFS */
 1197                 vput(vp);
 1198                 mtx_unlock(&Giant);     /* VFS */
 1199                 NFSD_LOCK();
 1200                 vp = NULL;
 1201                 nfsm_reply(NFSX_WCCDATA(v3));
 1202                 if (v3)
 1203                         nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
 1204                 error = 0;
 1205                 goto nfsmout;
 1206         }
 1207 
 1208         NFSD_UNLOCK();
 1209         if (len > 0) {
 1210             MALLOC(ivp, struct iovec *, cnt * sizeof (struct iovec), M_TEMP,
 1211                 M_WAITOK);
 1212             uiop->uio_iov = iv = ivp;
 1213             uiop->uio_iovcnt = cnt;
 1214             mp = mrep;
 1215             while (mp) {
 1216                 if (mp->m_len > 0) {
 1217                         ivp->iov_base = mtod(mp, caddr_t);
 1218                         ivp->iov_len = mp->m_len;
 1219                         ivp++;
 1220                 }
 1221                 mp = mp->m_next;
 1222             }
 1223 
 1224             /*
 1225              * XXX
 1226              * The IO_METASYNC flag indicates that all metadata (and not just
 1227              * enough to ensure data integrity) mus be written to stable storage
 1228              * synchronously.
 1229              * (IO_METASYNC is not yet implemented in 4.4BSD-Lite.)
 1230              */
 1231             if (stable == NFSV3WRITE_UNSTABLE)
 1232                 ioflags = IO_NODELOCKED;
 1233             else if (stable == NFSV3WRITE_DATASYNC)
 1234                 ioflags = (IO_SYNC | IO_NODELOCKED);
 1235             else
 1236                 ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
 1237             uiop->uio_resid = len;
 1238             uiop->uio_rw = UIO_WRITE;
 1239             uiop->uio_segflg = UIO_SYSSPACE;
 1240             uiop->uio_td = NULL;
 1241             uiop->uio_offset = off;
 1242             mtx_lock(&Giant);   /* VFS */
 1243             error = VOP_WRITE(vp, uiop, ioflags, cred);
 1244             /* XXXRW: unlocked write. */
 1245             nfsrvstats.srvvop_writes++;
 1246             FREE((caddr_t)iv, M_TEMP);
 1247         } else
 1248             mtx_lock(&Giant);   /* VFS */
 1249         mtx_assert(&Giant, MA_OWNED);   /* VFS */
 1250         aftat_ret = VOP_GETATTR(vp, vap, cred, td);
 1251         vput(vp);
 1252         mtx_unlock(&Giant);     /* VFS */
 1253         NFSD_LOCK();
 1254         vp = NULL;
 1255         if (!error)
 1256                 error = aftat_ret;
 1257 ereply:
 1258         NFSD_LOCK_ASSERT();
 1259         nfsm_reply(NFSX_PREOPATTR(v3) + NFSX_POSTOPORFATTR(v3) +
 1260                 2 * NFSX_UNSIGNED + NFSX_WRITEVERF(v3));
 1261         if (v3) {
 1262                 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
 1263                 if (error) {
 1264                         error = 0;
 1265                         goto nfsmout;
 1266                 }
 1267                 tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
 1268                 *tl++ = txdr_unsigned(retlen);
 1269                 /*
 1270                  * If nfs_async is set, then pretend the write was FILESYNC.
 1271                  */
 1272                 if (stable == NFSV3WRITE_UNSTABLE && !nfs_async)
 1273                         *tl++ = txdr_unsigned(stable);
 1274                 else
 1275                         *tl++ = txdr_unsigned(NFSV3WRITE_FILESYNC);
 1276                 /*
 1277                  * Actually, there is no need to txdr these fields,
 1278                  * but it may make the values more human readable,
 1279                  * for debugging purposes.
 1280                  */
 1281                 if (nfsver.tv_sec == 0)
 1282                         nfsver = boottime;
 1283                 *tl++ = txdr_unsigned(nfsver.tv_sec);
 1284                 *tl = txdr_unsigned(nfsver.tv_usec);
 1285         } else if (!error) {
 1286                 /* v2 non-error case. */
 1287                 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
 1288                 nfsm_srvfillattr(vap, fp);
 1289         }
 1290         error = 0;
 1291 nfsmout:
 1292         NFSD_LOCK_ASSERT();
 1293         NFSD_UNLOCK();
 1294         mtx_lock(&Giant);       /* VFS */
 1295         if (vp)
 1296                 vput(vp);
 1297         vn_finished_write(mntp);
 1298         mtx_unlock(&Giant);     /* VFS */
 1299         NFSD_LOCK();
 1300         return(error);
 1301 }
 1302 
 1303 /*
 1304  * For the purposes of write gathering, we must decide if the credential
 1305  * associated with two pending requests have equivilent privileges.  Since
 1306  * NFS only uses a subset of the BSD ucred -- the effective uid and group
 1307  * IDs -- we have a compare routine that checks only the relevant fields.
 1308  */
 1309 static int
 1310 nfsrv_samecred(struct ucred *cr1, struct ucred *cr2)
 1311 {
 1312         int i;
 1313 
 1314         if (cr1->cr_uid != cr2->cr_uid)
 1315                 return (0);
 1316         if (cr1->cr_ngroups != cr2->cr_ngroups)
 1317                 return (0);
 1318         for (i = 0; i < cr1->cr_ngroups; i++) {
 1319                 if (cr1->cr_groups[i] != cr2->cr_groups[i])
 1320                         return (0);
 1321         }
 1322         return (1);
 1323 }
 1324 
 1325 /*
 1326  * NFS write service with write gathering support. Called when
 1327  * nfsrvw_procrastinate > 0.
 1328  * See: Chet Juszczak, "Improving the Write Performance of an NFS Server",
 1329  * in Proc. of the Winter 1994 Usenix Conference, pg. 247-259, San Franscisco,
 1330  * Jan. 1994.
 1331  */
 1332 int
 1333 nfsrv_writegather(struct nfsrv_descript **ndp, struct nfssvc_sock *slp,
 1334     struct thread *td, struct mbuf **mrq)
 1335 {
 1336         struct iovec *ivp;
 1337         struct mbuf *mp;
 1338         struct nfsrv_descript *wp, *nfsd, *owp, *swp;
 1339         struct nfs_fattr *fp;
 1340         int i;
 1341         struct iovec *iov;
 1342         struct nfsrvw_delayhash *wpp;
 1343         struct ucred *cred;
 1344         struct vattr va, forat;
 1345         u_int32_t *tl;
 1346         caddr_t bpos, dpos;
 1347         int error = 0, rdonly, len, forat_ret = 1;
 1348         int ioflags, aftat_ret = 1, s, adjust, v3, zeroing;
 1349         struct mbuf *mb, *mreq, *mrep, *md;
 1350         struct vnode *vp = NULL;
 1351         struct uio io, *uiop = &io;
 1352         u_quad_t cur_usec;
 1353         struct mount *mntp = NULL;
 1354 
 1355         NFSD_LOCK_ASSERT();
 1356 
 1357         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 1358 #ifndef nolint
 1359         i = 0;
 1360         len = 0;
 1361 #endif
 1362         *mrq = NULL;
 1363         if (*ndp) {
 1364             nfsd = *ndp;
 1365             *ndp = NULL;
 1366             mrep = nfsd->nd_mrep;
 1367             md = nfsd->nd_md;
 1368             dpos = nfsd->nd_dpos;
 1369             cred = &nfsd->nd_cr;
 1370             v3 = (nfsd->nd_flag & ND_NFSV3);
 1371             LIST_INIT(&nfsd->nd_coalesce);
 1372             nfsd->nd_mreq = NULL;
 1373             nfsd->nd_stable = NFSV3WRITE_FILESYNC;
 1374             cur_usec = nfs_curusec();
 1375             nfsd->nd_time = cur_usec +
 1376                 (v3 ? nfsrvw_procrastinate_v3 : nfsrvw_procrastinate);
 1377 
 1378             /*
 1379              * Now, get the write header..
 1380              */
 1381             nfsm_srvmtofh(&nfsd->nd_fh);
 1382             if (v3) {
 1383                 tl = nfsm_dissect(u_int32_t *, 5 * NFSX_UNSIGNED);
 1384                 nfsd->nd_off = fxdr_hyper(tl);
 1385                 tl += 3;
 1386                 nfsd->nd_stable = fxdr_unsigned(int, *tl++);
 1387             } else {
 1388                 tl = nfsm_dissect(u_int32_t *, 4 * NFSX_UNSIGNED);
 1389                 nfsd->nd_off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
 1390                 tl += 2;
 1391                 if (nfs_async)
 1392                         nfsd->nd_stable = NFSV3WRITE_UNSTABLE;
 1393             }
 1394             len = fxdr_unsigned(int32_t, *tl);
 1395             nfsd->nd_len = len;
 1396             nfsd->nd_eoff = nfsd->nd_off + len;
 1397 
 1398             /*
 1399              * Trim the header out of the mbuf list and trim off any trailing
 1400              * junk so that the mbuf list has only the write data.
 1401              */
 1402             zeroing = 1;
 1403             i = 0;
 1404             mp = mrep;
 1405             while (mp) {
 1406                 if (mp == md) {
 1407                     zeroing = 0;
 1408                     adjust = dpos - mtod(mp, caddr_t);
 1409                     mp->m_len -= adjust;
 1410                     if (mp->m_len > 0 && adjust > 0)
 1411                         mp->m_data += adjust;
 1412                 }
 1413                 if (zeroing)
 1414                     mp->m_len = 0;
 1415                 else {
 1416                     i += mp->m_len;
 1417                     if (i > len) {
 1418                         mp->m_len -= (i - len);
 1419                         zeroing = 1;
 1420                     }
 1421                 }
 1422                 mp = mp->m_next;
 1423             }
 1424             if (len > NFS_MAXDATA || len < 0  || i < len) {
 1425 nfsmout:
 1426                 NFSD_LOCK_ASSERT();
 1427                 m_freem(mrep);
 1428                 error = EIO;
 1429                 nfsm_writereply(2 * NFSX_UNSIGNED);
 1430                 if (v3)
 1431                     nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
 1432                 nfsd->nd_mreq = mreq;
 1433                 nfsd->nd_mrep = NULL;
 1434                 nfsd->nd_time = 0;
 1435             }
 1436 
 1437             /*
 1438              * Add this entry to the hash and time queues.
 1439              */
 1440             s = splsoftclock();
 1441             owp = NULL;
 1442             wp = LIST_FIRST(&slp->ns_tq);
 1443             while (wp && wp->nd_time < nfsd->nd_time) {
 1444                 owp = wp;
 1445                 wp = LIST_NEXT(wp, nd_tq);
 1446             }
 1447             NFS_DPF(WG, ("Q%03x", nfsd->nd_retxid & 0xfff));
 1448             if (owp) {
 1449                 LIST_INSERT_AFTER(owp, nfsd, nd_tq);
 1450             } else {
 1451                 LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
 1452             }
 1453             if (nfsd->nd_mrep) {
 1454                 wpp = NWDELAYHASH(slp, nfsd->nd_fh.fh_fid.fid_data);
 1455                 owp = NULL;
 1456                 wp = LIST_FIRST(wpp);
 1457                 while (wp &&
 1458                     bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh, NFSX_V3FH)){
 1459                     owp = wp;
 1460                     wp = LIST_NEXT(wp, nd_hash);
 1461                 }
 1462                 while (wp && wp->nd_off < nfsd->nd_off &&
 1463                     !bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh, NFSX_V3FH)) {
 1464                     owp = wp;
 1465                     wp = LIST_NEXT(wp, nd_hash);
 1466                 }
 1467                 if (owp) {
 1468                     LIST_INSERT_AFTER(owp, nfsd, nd_hash);
 1469 
 1470                     /*
 1471                      * Search the hash list for overlapping entries and
 1472                      * coalesce.
 1473                      */
 1474                     for(; nfsd && NFSW_CONTIG(owp, nfsd); nfsd = wp) {
 1475                         wp = LIST_NEXT(nfsd, nd_hash);
 1476                         if (nfsrv_samecred(&owp->nd_cr, &nfsd->nd_cr))
 1477                             nfsrvw_coalesce(owp, nfsd);
 1478                     }
 1479                 } else {
 1480                     LIST_INSERT_HEAD(wpp, nfsd, nd_hash);
 1481                 }
 1482             }
 1483             splx(s);
 1484         }
 1485 
 1486         /*
 1487          * Now, do VOP_WRITE()s for any one(s) that need to be done now
 1488          * and generate the associated reply mbuf list(s).
 1489          */
 1490 loop1:
 1491         cur_usec = nfs_curusec();
 1492         s = splsoftclock();
 1493         for (nfsd = LIST_FIRST(&slp->ns_tq); nfsd; nfsd = owp) {
 1494                 owp = LIST_NEXT(nfsd, nd_tq);
 1495                 if (nfsd->nd_time > cur_usec)
 1496                     break;
 1497                 if (nfsd->nd_mreq)
 1498                     continue;
 1499                 NFS_DPF(WG, ("P%03x", nfsd->nd_retxid & 0xfff));
 1500                 LIST_REMOVE(nfsd, nd_tq);
 1501                 LIST_REMOVE(nfsd, nd_hash);
 1502                 splx(s);
 1503                 mrep = nfsd->nd_mrep;
 1504                 nfsd->nd_mrep = NULL;
 1505                 cred = &nfsd->nd_cr;
 1506                 v3 = (nfsd->nd_flag & ND_NFSV3);
 1507                 forat_ret = aftat_ret = 1;
 1508                 error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &vp, cred, slp,
 1509                     nfsd->nd_nam, &rdonly, TRUE);
 1510                 if (!error) {
 1511                     if (v3) {
 1512                         NFSD_UNLOCK();
 1513                         mtx_lock(&Giant);       /* VFS */
 1514                         forat_ret = VOP_GETATTR(vp, &forat, cred, td);
 1515                         mtx_unlock(&Giant);     /* VFS */
 1516                         NFSD_LOCK();
 1517                     }
 1518                     if (vp->v_type != VREG) {
 1519                         if (v3)
 1520                             error = EINVAL;
 1521                         else
 1522                             error = (vp->v_type == VDIR) ? EISDIR : EACCES;
 1523                     }
 1524                 } else {
 1525                     vp = NULL;
 1526                 }
 1527                 NFSD_UNLOCK();
 1528                 mtx_lock(&Giant);       /* VFS */
 1529                 if (!error)
 1530                     error = nfsrv_access_withgiant(vp, VWRITE, cred, rdonly,
 1531                         td, 1);
 1532                 if (nfsd->nd_stable == NFSV3WRITE_UNSTABLE)
 1533                     ioflags = IO_NODELOCKED;
 1534                 else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC)
 1535                     ioflags = (IO_SYNC | IO_NODELOCKED);
 1536                 else
 1537                     ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
 1538                 uiop->uio_rw = UIO_WRITE;
 1539                 uiop->uio_segflg = UIO_SYSSPACE;
 1540                 uiop->uio_td = NULL;
 1541                 uiop->uio_offset = nfsd->nd_off;
 1542                 uiop->uio_resid = nfsd->nd_eoff - nfsd->nd_off;
 1543                 if (uiop->uio_resid > 0) {
 1544                     mp = mrep;
 1545                     i = 0;
 1546                     while (mp) {
 1547                         if (mp->m_len > 0)
 1548                             i++;
 1549                         mp = mp->m_next;
 1550                     }
 1551                     uiop->uio_iovcnt = i;
 1552                     MALLOC(iov, struct iovec *, i * sizeof (struct iovec),
 1553                         M_TEMP, M_WAITOK);
 1554                     uiop->uio_iov = ivp = iov;
 1555                     mp = mrep;
 1556                     while (mp) {
 1557                         if (mp->m_len > 0) {
 1558                             ivp->iov_base = mtod(mp, caddr_t);
 1559                             ivp->iov_len = mp->m_len;
 1560                             ivp++;
 1561                         }
 1562                         mp = mp->m_next;
 1563                     }
 1564                     if (!error) {
 1565                         if (vn_start_write(vp, &mntp, V_NOWAIT) != 0) {
 1566                             VOP_UNLOCK(vp, 0, td);
 1567                             error = vn_start_write(NULL, &mntp, V_WAIT);
 1568                             vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 1569                         }
 1570                     }
 1571                     if (!error) {
 1572                         error = VOP_WRITE(vp, uiop, ioflags, cred);
 1573                         /* XXXRW: unlocked write. */
 1574                         nfsrvstats.srvvop_writes++;
 1575                         vn_finished_write(mntp);
 1576                     }
 1577                     FREE((caddr_t)iov, M_TEMP);
 1578                 }
 1579                 m_freem(mrep);
 1580                 if (vp) {
 1581                     aftat_ret = VOP_GETATTR(vp, &va, cred, td);
 1582                     vput(vp);
 1583                     vp = NULL;
 1584                 }
 1585                 mtx_unlock(&Giant);     /* VFS */
 1586                 NFSD_LOCK();
 1587 
 1588                 /*
 1589                  * Loop around generating replies for all write rpcs that have
 1590                  * now been completed.
 1591                  */
 1592                 swp = nfsd;
 1593                 do {
 1594                     NFS_DPF(WG, ("R%03x", nfsd->nd_retxid & 0xfff));
 1595                     if (error) {
 1596                         nfsm_writereply(NFSX_WCCDATA(v3));
 1597                         if (v3) {
 1598                             nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
 1599                         }
 1600                     } else {
 1601                         nfsm_writereply(NFSX_PREOPATTR(v3) +
 1602                             NFSX_POSTOPORFATTR(v3) + 2 * NFSX_UNSIGNED +
 1603                             NFSX_WRITEVERF(v3));
 1604                         if (v3) {
 1605                             nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
 1606                             tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
 1607                             *tl++ = txdr_unsigned(nfsd->nd_len);
 1608                             *tl++ = txdr_unsigned(swp->nd_stable);
 1609                             /*
 1610                              * Actually, there is no need to txdr these fields,
 1611                              * but it may make the values more human readable,
 1612                              * for debugging purposes.
 1613                              */
 1614                             if (nfsver.tv_sec == 0)
 1615                                     nfsver = boottime;
 1616                             *tl++ = txdr_unsigned(nfsver.tv_sec);
 1617                             *tl = txdr_unsigned(nfsver.tv_usec);
 1618                         } else {
 1619                             fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
 1620                             nfsm_srvfillattr(&va, fp);
 1621                         }
 1622                     }
 1623                     nfsd->nd_mreq = mreq;
 1624                     if (nfsd->nd_mrep)
 1625                         panic("nfsrv_write: nd_mrep not free");
 1626 
 1627                     /*
 1628                      * Done. Put it at the head of the timer queue so that
 1629                      * the final phase can return the reply.
 1630                      */
 1631                     s = splsoftclock();
 1632                     if (nfsd != swp) {
 1633                         nfsd->nd_time = 0;
 1634                         LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
 1635                     }
 1636                     nfsd = LIST_FIRST(&swp->nd_coalesce);
 1637                     if (nfsd) {
 1638                         LIST_REMOVE(nfsd, nd_tq);
 1639                     }
 1640                     splx(s);
 1641                 } while (nfsd);
 1642                 s = splsoftclock();
 1643                 swp->nd_time = 0;
 1644                 LIST_INSERT_HEAD(&slp->ns_tq, swp, nd_tq);
 1645                 splx(s);
 1646                 goto loop1;
 1647         }
 1648         splx(s);
 1649 
 1650         /*
 1651          * Search for a reply to return.
 1652          */
 1653         s = splsoftclock();
 1654         LIST_FOREACH(nfsd, &slp->ns_tq, nd_tq)
 1655                 if (nfsd->nd_mreq) {
 1656                     NFS_DPF(WG, ("X%03x", nfsd->nd_retxid & 0xfff));
 1657                     LIST_REMOVE(nfsd, nd_tq);
 1658                     *mrq = nfsd->nd_mreq;
 1659                     *ndp = nfsd;
 1660                     break;
 1661                 }
 1662         splx(s);
 1663         return (0);
 1664 }
 1665 
 1666 /*
 1667  * Coalesce the write request nfsd into owp. To do this we must:
 1668  * - remove nfsd from the queues
 1669  * - merge nfsd->nd_mrep into owp->nd_mrep
 1670  * - update the nd_eoff and nd_stable for owp
 1671  * - put nfsd on owp's nd_coalesce list
 1672  * NB: Must be called at splsoftclock().
 1673  */
 1674 static void
 1675 nfsrvw_coalesce(struct nfsrv_descript *owp, struct nfsrv_descript *nfsd)
 1676 {
 1677         int overlap;
 1678         struct mbuf *mp;
 1679         struct nfsrv_descript *p;
 1680 
 1681         NFSD_LOCK_ASSERT();
 1682 
 1683         NFS_DPF(WG, ("C%03x-%03x",
 1684                      nfsd->nd_retxid & 0xfff, owp->nd_retxid & 0xfff));
 1685         LIST_REMOVE(nfsd, nd_hash);
 1686         LIST_REMOVE(nfsd, nd_tq);
 1687         if (owp->nd_eoff < nfsd->nd_eoff) {
 1688             overlap = owp->nd_eoff - nfsd->nd_off;
 1689             if (overlap < 0)
 1690                 panic("nfsrv_coalesce: bad off");
 1691             if (overlap > 0)
 1692                 m_adj(nfsd->nd_mrep, overlap);
 1693             mp = owp->nd_mrep;
 1694             while (mp->m_next)
 1695                 mp = mp->m_next;
 1696             mp->m_next = nfsd->nd_mrep;
 1697             owp->nd_eoff = nfsd->nd_eoff;
 1698         } else
 1699             m_freem(nfsd->nd_mrep);
 1700         nfsd->nd_mrep = NULL;
 1701         if (nfsd->nd_stable == NFSV3WRITE_FILESYNC)
 1702             owp->nd_stable = NFSV3WRITE_FILESYNC;
 1703         else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC &&
 1704             owp->nd_stable == NFSV3WRITE_UNSTABLE)
 1705             owp->nd_stable = NFSV3WRITE_DATASYNC;
 1706         LIST_INSERT_HEAD(&owp->nd_coalesce, nfsd, nd_tq);
 1707 
 1708         /*
 1709          * If nfsd had anything else coalesced into it, transfer them
 1710          * to owp, otherwise their replies will never get sent.
 1711          */
 1712         for (p = LIST_FIRST(&nfsd->nd_coalesce); p;
 1713              p = LIST_FIRST(&nfsd->nd_coalesce)) {
 1714             LIST_REMOVE(p, nd_tq);
 1715             LIST_INSERT_HEAD(&owp->nd_coalesce, p, nd_tq);
 1716         }
 1717 }
 1718 
 1719 /*
 1720  * nfs create service
 1721  * now does a truncate to 0 length via. setattr if it already exists
 1722  */
 1723 int
 1724 nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 1725     struct thread *td, struct mbuf **mrq)
 1726 {
 1727         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 1728         struct sockaddr *nam = nfsd->nd_nam;
 1729         caddr_t dpos = nfsd->nd_dpos;
 1730         struct ucred *cred = &nfsd->nd_cr;
 1731         struct nfs_fattr *fp;
 1732         struct vattr va, dirfor, diraft;
 1733         struct vattr *vap = &va;
 1734         struct nfsv2_sattr *sp;
 1735         u_int32_t *tl;
 1736         struct nameidata nd;
 1737         caddr_t bpos;
 1738         int error = 0, rdev, len, tsize, dirfor_ret = 1, diraft_ret = 1;
 1739         int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0;
 1740         caddr_t cp;
 1741         struct mbuf *mb, *mreq;
 1742         struct vnode *dirp = NULL;
 1743         nfsfh_t nfh;
 1744         fhandle_t *fhp;
 1745         u_quad_t tempsize;
 1746         u_char cverf[NFSX_V3CREATEVERF];
 1747         struct mount *mp = NULL;
 1748 
 1749         NFSD_LOCK_ASSERT();
 1750 
 1751         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 1752 #ifndef nolint
 1753         rdev = 0;
 1754 #endif
 1755         ndclear(&nd);
 1756 
 1757         fhp = &nfh.fh_generic;
 1758         nfsm_srvmtofh(fhp);
 1759         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
 1760                 error = ESTALE;
 1761                 goto ereply_locked;
 1762         }
 1763         NFSD_UNLOCK();
 1764         mtx_lock(&Giant);       /* VFS */
 1765         (void) vn_start_write(NULL, &mp, V_WAIT);
 1766         mtx_unlock(&Giant);     /* VFS */
 1767         NFSD_LOCK();
 1768         nfsm_srvnamesiz(len);
 1769 
 1770         nd.ni_cnd.cn_cred = cred;
 1771         nd.ni_cnd.cn_nameiop = CREATE;
 1772         nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
 1773 
 1774         /*
 1775          * Call namei and do initial cleanup to get a few things
 1776          * out of the way.  If we get an initial error we cleanup
 1777          * and return here to avoid special-casing the invalid nd
 1778          * structure through the rest of the case.  dirp may be
 1779          * set even if an error occurs, but the nd structure will not
 1780          * be valid at all if an error occurs so we have to invalidate it
 1781          * prior to calling nfsm_reply ( which might goto nfsmout ).
 1782          */
 1783         error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
 1784                 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
 1785         if (dirp && !v3) {
 1786                 NFSD_UNLOCK();
 1787                 mtx_lock(&Giant);       /* VFS */
 1788                 vrele(dirp);
 1789                 mtx_unlock(&Giant);     /* VFS */
 1790                 NFSD_LOCK();
 1791                 dirp = NULL;
 1792         }
 1793         if (error) {
 1794                 nfsm_reply(NFSX_WCCDATA(v3));
 1795                 if (v3)
 1796                         nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 1797                 error = 0;
 1798                 goto nfsmout;
 1799         }
 1800 
 1801         /*
 1802          * No error.  Continue.  State:
 1803          *
 1804          *      startdir        is valid ( we release this immediately )
 1805          *      dirp            may be valid
 1806          *      nd.ni_vp        may be valid
 1807          *      nd.ni_dvp       is valid
 1808          *
 1809          * The error state is set through the code and we may also do some
 1810          * opportunistic releasing of vnodes to avoid holding locks through
 1811          * NFS I/O.  The cleanup at the end is a catch-all
 1812          */
 1813 
 1814         VATTR_NULL(vap);
 1815         if (v3) {
 1816                 tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
 1817                 how = fxdr_unsigned(int, *tl);
 1818                 switch (how) {
 1819                 case NFSV3CREATE_GUARDED:
 1820                         if (nd.ni_vp) {
 1821                                 error = EEXIST;
 1822                                 break;
 1823                         }
 1824                         /* fall through */
 1825                 case NFSV3CREATE_UNCHECKED:
 1826                         nfsm_srvsattr(vap);
 1827                         break;
 1828                 case NFSV3CREATE_EXCLUSIVE:
 1829                         cp = nfsm_dissect(caddr_t, NFSX_V3CREATEVERF);
 1830                         bcopy(cp, cverf, NFSX_V3CREATEVERF);
 1831                         exclusive_flag = 1;
 1832                         break;
 1833                 };
 1834                 vap->va_type = VREG;
 1835         } else {
 1836                 sp = nfsm_dissect(struct nfsv2_sattr *, NFSX_V2SATTR);
 1837                 vap->va_type = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode));
 1838                 if (vap->va_type == VNON)
 1839                         vap->va_type = VREG;
 1840                 vap->va_mode = nfstov_mode(sp->sa_mode);
 1841                 switch (vap->va_type) {
 1842                 case VREG:
 1843                         tsize = fxdr_unsigned(int32_t, sp->sa_size);
 1844                         if (tsize != -1)
 1845                                 vap->va_size = (u_quad_t)tsize;
 1846                         break;
 1847                 case VCHR:
 1848                 case VBLK:
 1849                 case VFIFO:
 1850                         rdev = fxdr_unsigned(long, sp->sa_size);
 1851                         break;
 1852                 default:
 1853                         break;
 1854                 };
 1855         }
 1856 
 1857         /*
 1858          * Iff doesn't exist, create it
 1859          * otherwise just truncate to 0 length
 1860          *   should I set the mode too ?
 1861          *
 1862          * The only possible error we can have at this point is EEXIST.
 1863          * nd.ni_vp will also be non-NULL in that case.
 1864          */
 1865         NFSD_UNLOCK();
 1866         mtx_lock(&Giant);       /* VFS */
 1867         if (nd.ni_vp == NULL) {
 1868                 if (vap->va_mode == (mode_t)VNOVAL)
 1869                         vap->va_mode = 0;
 1870                 if (vap->va_type == VREG || vap->va_type == VSOCK) {
 1871                         error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
 1872                         if (error)
 1873                                 NDFREE(&nd, NDF_ONLY_PNBUF);
 1874                         else {
 1875                                 nfsrv_object_create(nd.ni_vp);
 1876                                 if (exclusive_flag) {
 1877                                         exclusive_flag = 0;
 1878                                         VATTR_NULL(vap);
 1879                                         bcopy(cverf, (caddr_t)&vap->va_atime,
 1880                                                 NFSX_V3CREATEVERF);
 1881                                         error = VOP_SETATTR(nd.ni_vp, vap, cred,
 1882                                                 td);
 1883                                 }
 1884                         }
 1885                 } else if (vap->va_type == VCHR || vap->va_type == VBLK ||
 1886                     vap->va_type == VFIFO) {
 1887                         /*
 1888                          * NFSv2-specific code for creating device nodes
 1889                          * and fifos.
 1890                          *
 1891                          * Handle SysV FIFO node special cases.  All other
 1892                          * devices require super user to access.
 1893                          */
 1894                         if (vap->va_type == VCHR && rdev == 0xffffffff)
 1895                                 vap->va_type = VFIFO;
 1896                         if (vap->va_type != VFIFO &&
 1897                             (error = suser_cred(cred, 0))) {
 1898                                 goto ereply;
 1899                         }
 1900                         vap->va_rdev = rdev;
 1901                         error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
 1902                         if (error) {
 1903                                 NDFREE(&nd, NDF_ONLY_PNBUF);
 1904                                 goto ereply;
 1905                         }
 1906                         vput(nd.ni_vp);
 1907                         nd.ni_vp = NULL;
 1908 
 1909                         /*
 1910                          * release dvp prior to lookup
 1911                          */
 1912                         vput(nd.ni_dvp);
 1913                         nd.ni_dvp = NULL;
 1914 
 1915                         /*
 1916                          * Setup for lookup.
 1917                          *
 1918                          * Even though LOCKPARENT was cleared, ni_dvp may
 1919                          * be garbage.
 1920                          */
 1921                         nd.ni_cnd.cn_nameiop = LOOKUP;
 1922                         nd.ni_cnd.cn_flags &= ~(LOCKPARENT);
 1923                         nd.ni_cnd.cn_thread = td;
 1924                         nd.ni_cnd.cn_cred = cred;
 1925 
 1926                         error = lookup(&nd);
 1927                         nd.ni_dvp = NULL;
 1928                         if (error)
 1929                                 goto ereply;
 1930 
 1931                         nfsrv_object_create(nd.ni_vp);
 1932                         if (nd.ni_cnd.cn_flags & ISSYMLINK) {
 1933                                 error = EINVAL;
 1934                                 goto ereply;
 1935                         }
 1936                 } else {
 1937                         error = ENXIO;
 1938                 }
 1939         } else {
 1940                 if (vap->va_size != -1) {
 1941                         error = nfsrv_access_withgiant(nd.ni_vp, VWRITE,
 1942                             cred, (nd.ni_cnd.cn_flags & RDONLY), td, 0);
 1943                         if (!error) {
 1944                                 tempsize = vap->va_size;
 1945                                 VATTR_NULL(vap);
 1946                                 vap->va_size = tempsize;
 1947                                 error = VOP_SETATTR(nd.ni_vp, vap, cred,
 1948                                          td);
 1949                         }
 1950                 }
 1951         }
 1952 
 1953         if (!error) {
 1954                 bzero((caddr_t)fhp, sizeof(nfh));
 1955                 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
 1956                 error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
 1957                 if (!error)
 1958                         error = VOP_GETATTR(nd.ni_vp, vap, cred, td);
 1959         }
 1960         if (v3) {
 1961                 if (exclusive_flag && !error &&
 1962                         bcmp(cverf, (caddr_t)&vap->va_atime, NFSX_V3CREATEVERF))
 1963                         error = EEXIST;
 1964                 if (dirp == nd.ni_dvp)
 1965                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
 1966                 else {
 1967                         /* Drop the other locks to avoid deadlock. */
 1968                         if (nd.ni_dvp) {
 1969                                 if (nd.ni_dvp == nd.ni_vp)
 1970                                         vrele(nd.ni_dvp);
 1971                                 else
 1972                                         vput(nd.ni_dvp);
 1973                         }
 1974                         if (nd.ni_vp)
 1975                                 vput(nd.ni_vp);
 1976                         nd.ni_dvp = NULL;
 1977                         nd.ni_vp = NULL;
 1978 
 1979                         vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
 1980                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
 1981                         VOP_UNLOCK(dirp, 0, td);
 1982                 }
 1983         }
 1984 ereply:
 1985         NFSD_UNLOCK_ASSERT();
 1986         mtx_unlock(&Giant);     /* VFS */
 1987         NFSD_LOCK();
 1988 ereply_locked:
 1989         NFSD_LOCK_ASSERT();
 1990         nfsm_reply(NFSX_SRVFH(v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3));
 1991         if (v3) {
 1992                 if (!error) {
 1993                         nfsm_srvpostop_fh(fhp);
 1994                         nfsm_srvpostop_attr(0, vap);
 1995                 }
 1996                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 1997         } else if (!error) {
 1998                 /* v2 non-error case. */
 1999                 nfsm_srvfhtom(fhp, v3);
 2000                 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
 2001                 nfsm_srvfillattr(vap, fp);
 2002         }
 2003         error = 0;
 2004 
 2005 nfsmout:
 2006         NFSD_LOCK_ASSERT();
 2007         NFSD_UNLOCK();
 2008         mtx_lock(&Giant);       /* VFS */
 2009         if (nd.ni_startdir) {
 2010                 vrele(nd.ni_startdir);
 2011                 nd.ni_startdir = NULL;
 2012         }
 2013         if (dirp)
 2014                 vrele(dirp);
 2015         NDFREE(&nd, NDF_ONLY_PNBUF);
 2016         if (nd.ni_dvp) {
 2017                 if (nd.ni_dvp == nd.ni_vp)
 2018                         vrele(nd.ni_dvp);
 2019                 else
 2020                         vput(nd.ni_dvp);
 2021         }
 2022         if (nd.ni_vp)
 2023                 vput(nd.ni_vp);
 2024         vn_finished_write(mp);
 2025         mtx_unlock(&Giant);     /* VFS */
 2026         NFSD_LOCK();
 2027         return (error);
 2028 }
 2029 
 2030 /*
 2031  * nfs v3 mknod service
 2032  */
 2033 int
 2034 nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 2035     struct thread *td, struct mbuf **mrq)
 2036 {
 2037         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 2038         struct sockaddr *nam = nfsd->nd_nam;
 2039         caddr_t dpos = nfsd->nd_dpos;
 2040         struct ucred *cred = &nfsd->nd_cr;
 2041         struct vattr va, dirfor, diraft;
 2042         struct vattr *vap = &va;
 2043         u_int32_t *tl;
 2044         struct nameidata nd;
 2045         caddr_t bpos;
 2046         int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
 2047         u_int32_t major, minor;
 2048         enum vtype vtyp;
 2049         struct mbuf *mb, *mreq;
 2050         struct vnode *vp, *dirp = NULL;
 2051         nfsfh_t nfh;
 2052         fhandle_t *fhp;
 2053         struct mount *mp = NULL;
 2054         int v3 = (nfsd->nd_flag & ND_NFSV3);
 2055 
 2056         NFSD_LOCK_ASSERT();
 2057 
 2058         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 2059         if (!v3)
 2060                 panic("nfsrv_mknod: v3 proc called on a v2 connection");
 2061         ndclear(&nd);
 2062 
 2063         fhp = &nfh.fh_generic;
 2064         nfsm_srvmtofh(fhp);
 2065         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
 2066                 error = ESTALE;
 2067                 goto ereply;
 2068         }
 2069         NFSD_UNLOCK();
 2070         mtx_lock(&Giant);       /* VFS */
 2071         (void) vn_start_write(NULL, &mp, V_WAIT);
 2072         mtx_unlock(&Giant);     /* VFS */
 2073         NFSD_LOCK();
 2074         nfsm_srvnamesiz(len);
 2075 
 2076         nd.ni_cnd.cn_cred = cred;
 2077         nd.ni_cnd.cn_nameiop = CREATE;
 2078         nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
 2079 
 2080         /*
 2081          * Handle nfs_namei() call.  If an error occurs, the nd structure
 2082          * is not valid.  However, nfsm_*() routines may still jump to
 2083          * nfsmout.
 2084          */
 2085 
 2086         error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
 2087                 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
 2088         if (error) {
 2089                 nfsm_reply(NFSX_WCCDATA(1));
 2090                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 2091                 error = 0;
 2092                 goto nfsmout;
 2093         }
 2094         tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
 2095         vtyp = nfsv3tov_type(*tl);
 2096         if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
 2097                 error = NFSERR_BADTYPE;
 2098                 goto out;
 2099         }
 2100         VATTR_NULL(vap);
 2101         nfsm_srvsattr(vap);
 2102         if (vtyp == VCHR || vtyp == VBLK) {
 2103                 tl = nfsm_dissect(u_int32_t *, 2 * NFSX_UNSIGNED);
 2104                 major = fxdr_unsigned(u_int32_t, *tl++);
 2105                 minor = fxdr_unsigned(u_int32_t, *tl);
 2106                 vap->va_rdev = makedev(major, minor);
 2107         }
 2108 
 2109         /*
 2110          * Iff doesn't exist, create it.
 2111          */
 2112         if (nd.ni_vp) {
 2113                 error = EEXIST;
 2114                 goto out;
 2115         }
 2116         vap->va_type = vtyp;
 2117         if (vap->va_mode == (mode_t)VNOVAL)
 2118                 vap->va_mode = 0;
 2119         NFSD_UNLOCK();
 2120         mtx_lock(&Giant);       /* VFS */
 2121         if (vtyp == VSOCK) {
 2122                 vrele(nd.ni_startdir);
 2123                 nd.ni_startdir = NULL;
 2124                 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
 2125                 if (error)
 2126                         NDFREE(&nd, NDF_ONLY_PNBUF);
 2127         } else {
 2128                 if (vtyp != VFIFO && (error = suser_cred(cred, 0)))
 2129                         goto out;
 2130                 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
 2131                 if (error) {
 2132                         NDFREE(&nd, NDF_ONLY_PNBUF);
 2133                         goto out;
 2134                 }
 2135                 vput(nd.ni_vp);
 2136                 nd.ni_vp = NULL;
 2137 
 2138                 /*
 2139                  * Release dvp prior to lookup
 2140                  */
 2141                 vput(nd.ni_dvp);
 2142                 nd.ni_dvp = NULL;
 2143 
 2144                 nd.ni_cnd.cn_nameiop = LOOKUP;
 2145                 nd.ni_cnd.cn_flags &= ~(LOCKPARENT);
 2146                 nd.ni_cnd.cn_thread = td;
 2147                 nd.ni_cnd.cn_cred = td->td_ucred;
 2148 
 2149                 error = lookup(&nd);
 2150                 nd.ni_dvp = NULL;
 2151 
 2152                 if (error)
 2153                         goto out;
 2154                 if (nd.ni_cnd.cn_flags & ISSYMLINK)
 2155                         error = EINVAL;
 2156         }
 2157 
 2158         /*
 2159          * send response, cleanup, return.
 2160          */
 2161 out:
 2162         NFSD_UNLOCK_ASSERT();
 2163         if (nd.ni_startdir) {
 2164                 vrele(nd.ni_startdir);
 2165                 nd.ni_startdir = NULL;
 2166         }
 2167         NDFREE(&nd, NDF_ONLY_PNBUF);
 2168         if (nd.ni_dvp) {
 2169                 if (nd.ni_dvp == nd.ni_vp)
 2170                         vrele(nd.ni_dvp);
 2171                 else
 2172                         vput(nd.ni_dvp);
 2173                 nd.ni_dvp = NULL;
 2174         }
 2175         vp = nd.ni_vp;
 2176         if (!error) {
 2177                 bzero((caddr_t)fhp, sizeof(nfh));
 2178                 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
 2179                 error = VFS_VPTOFH(vp, &fhp->fh_fid);
 2180                 if (!error)
 2181                         error = VOP_GETATTR(vp, vap, cred, td);
 2182         }
 2183         if (vp) {
 2184                 vput(vp);
 2185                 vp = NULL;
 2186                 nd.ni_vp = NULL;
 2187         }
 2188         if (dirp) {
 2189                 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
 2190                 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
 2191                 VOP_UNLOCK(dirp, 0, td);
 2192         }
 2193         mtx_unlock(&Giant);     /* VFS */
 2194         NFSD_LOCK();
 2195 ereply:
 2196         NFSD_LOCK_ASSERT();
 2197         nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
 2198         if (v3) {
 2199                 if (!error) {
 2200                         nfsm_srvpostop_fh(fhp);
 2201                         nfsm_srvpostop_attr(0, vap);
 2202                 }
 2203                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 2204         }
 2205         NFSD_UNLOCK();
 2206         mtx_lock(&Giant);       /* VFS */
 2207         vn_finished_write(mp);
 2208         mtx_unlock(&Giant);     /* VFS */
 2209         NFSD_LOCK();
 2210         return (0);
 2211 nfsmout:
 2212         NFSD_LOCK_ASSERT();
 2213         NFSD_UNLOCK();
 2214         mtx_lock(&Giant);       /* VFS */
 2215         if (dirp)
 2216                 vrele(dirp);
 2217         if (nd.ni_startdir)
 2218                 vrele(nd.ni_startdir);
 2219         NDFREE(&nd, NDF_ONLY_PNBUF);
 2220         if (nd.ni_dvp) {
 2221                 if (nd.ni_dvp == nd.ni_vp)
 2222                         vrele(nd.ni_dvp);
 2223                 else
 2224                         vput(nd.ni_dvp);
 2225         }
 2226         if (nd.ni_vp)
 2227                 vput(nd.ni_vp);
 2228         vn_finished_write(mp);
 2229         mtx_unlock(&Giant);     /* VFS */
 2230         NFSD_LOCK();
 2231         return (error);
 2232 }
 2233 
 2234 /*
 2235  * nfs remove service
 2236  */
 2237 int
 2238 nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 2239     struct thread *td, struct mbuf **mrq)
 2240 {
 2241         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 2242         struct sockaddr *nam = nfsd->nd_nam;
 2243         caddr_t dpos = nfsd->nd_dpos;
 2244         struct ucred *cred = &nfsd->nd_cr;
 2245         struct nameidata nd;
 2246         caddr_t bpos;
 2247         int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
 2248         int v3 = (nfsd->nd_flag & ND_NFSV3);
 2249         struct mbuf *mb, *mreq;
 2250         struct vnode *dirp;
 2251         struct vattr dirfor, diraft;
 2252         nfsfh_t nfh;
 2253         fhandle_t *fhp;
 2254         struct mount *mp = NULL;
 2255 
 2256         NFSD_LOCK_ASSERT();
 2257 
 2258         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 2259         ndclear(&nd);
 2260 
 2261         fhp = &nfh.fh_generic;
 2262         nfsm_srvmtofh(fhp);
 2263         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
 2264                 error = ESTALE;
 2265                 goto ereply;
 2266         }
 2267         NFSD_UNLOCK();
 2268         mtx_lock(&Giant);       /* VFS */
 2269         (void) vn_start_write(NULL, &mp, V_WAIT);
 2270         mtx_unlock(&Giant);     /* VFS */
 2271         NFSD_LOCK();
 2272         nfsm_srvnamesiz(len);
 2273 
 2274         nd.ni_cnd.cn_cred = cred;
 2275         nd.ni_cnd.cn_nameiop = DELETE;
 2276         nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
 2277         error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
 2278                 &dirp, v3,  &dirfor, &dirfor_ret, td, FALSE);
 2279         NFSD_UNLOCK();
 2280         mtx_lock(&Giant);       /* VFS */
 2281         if (dirp && !v3) {
 2282                 vrele(dirp);
 2283                 dirp = NULL;
 2284         }
 2285         if (error == 0) {
 2286                 if (nd.ni_vp->v_type == VDIR) {
 2287                         error = EPERM;          /* POSIX */
 2288                         goto out;
 2289                 }
 2290                 /*
 2291                  * The root of a mounted filesystem cannot be deleted.
 2292                  */
 2293                 if (nd.ni_vp->v_vflag & VV_ROOT) {
 2294                         error = EBUSY;
 2295                         goto out;
 2296                 }
 2297 out:
 2298                 NFSD_UNLOCK_ASSERT();
 2299                 if (!error) {
 2300                         error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
 2301                         NDFREE(&nd, NDF_ONLY_PNBUF);
 2302                 }
 2303         }
 2304         if (dirp && v3) {
 2305                 if (dirp == nd.ni_dvp)
 2306                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
 2307                 else {
 2308                         /* Drop the other locks to avoid deadlock. */
 2309                         if (nd.ni_dvp) {
 2310                                 if (nd.ni_dvp == nd.ni_vp)
 2311                                         vrele(nd.ni_dvp);
 2312                                 else
 2313                                         vput(nd.ni_dvp);
 2314                         }
 2315                         if (nd.ni_vp)
 2316                                 vput(nd.ni_vp);
 2317                         nd.ni_dvp = NULL;
 2318                         nd.ni_vp = NULL;
 2319 
 2320                         vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
 2321                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
 2322                         VOP_UNLOCK(dirp, 0, td);
 2323                 }
 2324                 vrele(dirp);
 2325                 dirp = NULL;
 2326         }
 2327         mtx_unlock(&Giant);     /* VFS */
 2328         NFSD_LOCK();
 2329 ereply:
 2330         NFSD_LOCK_ASSERT();
 2331         nfsm_reply(NFSX_WCCDATA(v3));
 2332         if (v3) {
 2333                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 2334                 error = 0;
 2335         }
 2336 nfsmout:
 2337         NFSD_LOCK_ASSERT();
 2338         NFSD_UNLOCK();
 2339         mtx_lock(&Giant);       /* VFS */
 2340         NDFREE(&nd, NDF_ONLY_PNBUF);
 2341         if (nd.ni_dvp) {
 2342                 if (nd.ni_dvp == nd.ni_vp)
 2343                         vrele(nd.ni_dvp);
 2344                 else
 2345                         vput(nd.ni_dvp);
 2346         }
 2347         if (nd.ni_vp)
 2348                 vput(nd.ni_vp);
 2349         vn_finished_write(mp);
 2350         mtx_unlock(&Giant);     /* VFS */
 2351         NFSD_LOCK();
 2352         return(error);
 2353 }
 2354 
 2355 /*
 2356  * nfs rename service
 2357  */
 2358 int
 2359 nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 2360     struct thread *td, struct mbuf **mrq)
 2361 {
 2362         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 2363         struct sockaddr *nam = nfsd->nd_nam;
 2364         caddr_t dpos = nfsd->nd_dpos;
 2365         struct ucred *cred = &nfsd->nd_cr;
 2366         caddr_t bpos;
 2367         int error = 0, len, len2, fdirfor_ret = 1, fdiraft_ret = 1;
 2368         int tdirfor_ret = 1, tdiraft_ret = 1;
 2369         int v3 = (nfsd->nd_flag & ND_NFSV3);
 2370         struct mbuf *mb, *mreq;
 2371         struct nameidata fromnd, tond;
 2372         struct vnode *fvp, *tvp, *tdvp, *fdirp = NULL;
 2373         struct vnode *tdirp = NULL;
 2374         struct vattr fdirfor, fdiraft, tdirfor, tdiraft;
 2375         nfsfh_t fnfh, tnfh;
 2376         fhandle_t *ffhp, *tfhp;
 2377         uid_t saved_uid;
 2378         struct mount *mp = NULL;
 2379 
 2380         NFSD_LOCK_ASSERT();
 2381 
 2382         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 2383 #ifndef nolint
 2384         fvp = NULL;
 2385 #endif
 2386         ffhp = &fnfh.fh_generic;
 2387         tfhp = &tnfh.fh_generic;
 2388 
 2389         /*
 2390          * Clear fields incase goto nfsmout occurs from macro.
 2391          */
 2392 
 2393         ndclear(&fromnd);
 2394         ndclear(&tond);
 2395 
 2396         nfsm_srvmtofh(ffhp);
 2397         if ((mp = vfs_getvfs(&ffhp->fh_fsid)) == NULL) {
 2398                 error = ESTALE;
 2399                 goto out1;
 2400         }
 2401         NFSD_UNLOCK();
 2402         mtx_lock(&Giant);
 2403         (void) vn_start_write(NULL, &mp, V_WAIT);
 2404         mtx_unlock(&Giant);
 2405         NFSD_LOCK();
 2406         nfsm_srvnamesiz(len);
 2407         /*
 2408          * Remember our original uid so that we can reset cr_uid before
 2409          * the second nfs_namei() call, in case it is remapped.
 2410          */
 2411         saved_uid = cred->cr_uid;
 2412         fromnd.ni_cnd.cn_cred = cred;
 2413         fromnd.ni_cnd.cn_nameiop = DELETE;
 2414         fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART;
 2415         error = nfs_namei(&fromnd, ffhp, len, slp, nam, &md,
 2416                 &dpos, &fdirp, v3, &fdirfor, &fdirfor_ret, td, FALSE);
 2417         if (fdirp && !v3) {
 2418                 NFSD_UNLOCK();
 2419                 mtx_lock(&Giant);       /* VFS */
 2420                 vrele(fdirp);
 2421                 mtx_unlock(&Giant);     /* VFS */
 2422                 NFSD_LOCK();
 2423                 fdirp = NULL;
 2424         }
 2425         if (error) {
 2426                 nfsm_reply(2 * NFSX_WCCDATA(v3));
 2427                 if (v3) {
 2428                         nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
 2429                         nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
 2430                 }
 2431                 error = 0;
 2432                 goto nfsmout;
 2433         }
 2434         fvp = fromnd.ni_vp;
 2435         nfsm_srvmtofh(tfhp);
 2436         nfsm_srvnamesiz(len2);
 2437         cred->cr_uid = saved_uid;
 2438         tond.ni_cnd.cn_cred = cred;
 2439         tond.ni_cnd.cn_nameiop = RENAME;
 2440         tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
 2441         error = nfs_namei(&tond, tfhp, len2, slp, nam, &md,
 2442                 &dpos, &tdirp, v3, &tdirfor, &tdirfor_ret, td, FALSE);
 2443         NFSD_UNLOCK();
 2444         mtx_lock(&Giant);       /* VFS */
 2445         if (tdirp && !v3) {
 2446                 vrele(tdirp);
 2447                 tdirp = NULL;
 2448         }
 2449         if (error) {
 2450                 mtx_unlock(&Giant);     /* VFS */
 2451                 NFSD_LOCK();
 2452                 goto out1;
 2453         }
 2454 
 2455         tdvp = tond.ni_dvp;
 2456         tvp = tond.ni_vp;
 2457         if (tvp != NULL) {
 2458                 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
 2459                         if (v3)
 2460                                 error = EEXIST;
 2461                         else
 2462                                 error = EISDIR;
 2463                         goto out;
 2464                 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
 2465                         if (v3)
 2466                                 error = EEXIST;
 2467                         else
 2468                                 error = ENOTDIR;
 2469                         goto out;
 2470                 }
 2471                 if (tvp->v_type == VDIR && tvp->v_mountedhere) {
 2472                         if (v3)
 2473                                 error = EXDEV;
 2474                         else
 2475                                 error = ENOTEMPTY;
 2476                         goto out;
 2477                 }
 2478         }
 2479         if (fvp->v_type == VDIR && fvp->v_mountedhere) {
 2480                 if (v3)
 2481                         error = EXDEV;
 2482                 else
 2483                         error = ENOTEMPTY;
 2484                 goto out;
 2485         }
 2486         if (fvp->v_mount != tdvp->v_mount) {
 2487                 if (v3)
 2488                         error = EXDEV;
 2489                 else
 2490                         error = ENOTEMPTY;
 2491                 goto out;
 2492         }
 2493         if (fvp == tdvp) {
 2494                 if (v3)
 2495                         error = EINVAL;
 2496                 else
 2497                         error = ENOTEMPTY;
 2498         }
 2499         /*
 2500          * If source is the same as the destination (that is the
 2501          * same vnode with the same name in the same directory),
 2502          * then there is nothing to do.
 2503          */
 2504         if (fvp == tvp && fromnd.ni_dvp == tdvp &&
 2505             fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
 2506             !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
 2507               fromnd.ni_cnd.cn_namelen))
 2508                 error = -1;
 2509 out:
 2510         NFSD_UNLOCK_ASSERT();
 2511         if (!error) {
 2512                 /*
 2513                  * The VOP_RENAME function releases all vnode references &
 2514                  * locks prior to returning so we need to clear the pointers
 2515                  * to bypass cleanup code later on.
 2516                  */
 2517                 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
 2518                                    tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
 2519                 fromnd.ni_dvp = NULL;
 2520                 fromnd.ni_vp = NULL;
 2521                 tond.ni_dvp = NULL;
 2522                 tond.ni_vp = NULL;
 2523                 if (error) {
 2524                         fromnd.ni_cnd.cn_flags &= ~HASBUF;
 2525                         tond.ni_cnd.cn_flags &= ~HASBUF;
 2526                 }
 2527         } else {
 2528                 if (error == -1)
 2529                         error = 0;
 2530         }
 2531         /* fall through */
 2532 
 2533         mtx_unlock(&Giant);     /* VFS */
 2534         NFSD_LOCK();
 2535 out1:
 2536         NFSD_LOCK_ASSERT();
 2537         nfsm_reply(2 * NFSX_WCCDATA(v3));
 2538         if (v3) {
 2539                 /* Release existing locks to prevent deadlock. */
 2540                 NFSD_UNLOCK();
 2541                 mtx_lock(&Giant);       /* VFS */
 2542                 if (tond.ni_dvp) {
 2543                         if (tond.ni_dvp == tond.ni_vp)
 2544                                 vrele(tond.ni_dvp);
 2545                         else
 2546                                 vput(tond.ni_dvp);
 2547                 }
 2548                 if (tond.ni_vp)
 2549                         vput(tond.ni_vp);
 2550                 tond.ni_dvp = NULL;
 2551                 tond.ni_vp = NULL;
 2552 
 2553                 if (fdirp) {
 2554                         vn_lock(fdirp, LK_EXCLUSIVE | LK_RETRY, td);
 2555                         fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, cred, td);
 2556                         VOP_UNLOCK(fdirp, 0, td);
 2557                 }
 2558                 if (tdirp) {
 2559                         vn_lock(tdirp, LK_EXCLUSIVE | LK_RETRY, td);
 2560                         tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, cred, td);
 2561                         VOP_UNLOCK(tdirp, 0, td);
 2562                 }
 2563                 mtx_unlock(&Giant);     /* VFS */
 2564                 NFSD_LOCK();
 2565                 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
 2566                 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
 2567         }
 2568         error = 0;
 2569         /* fall through */
 2570 
 2571 nfsmout:
 2572         /*
 2573          * Clear out tond related fields
 2574          */
 2575         NFSD_LOCK_ASSERT();
 2576         NFSD_UNLOCK();
 2577         mtx_lock(&Giant);       /* VFS */
 2578         if (tdirp)
 2579                 vrele(tdirp);
 2580         if (tond.ni_startdir)
 2581                 vrele(tond.ni_startdir);
 2582         NDFREE(&tond, NDF_ONLY_PNBUF);
 2583         if (tond.ni_dvp) {
 2584                 if (tond.ni_dvp == tond.ni_vp)
 2585                         vrele(tond.ni_dvp);
 2586                 else
 2587                         vput(tond.ni_dvp);
 2588         }
 2589         if (tond.ni_vp)
 2590                 vput(tond.ni_vp);
 2591 
 2592         /*
 2593          * Clear out fromnd related fields
 2594          */
 2595         if (fdirp)
 2596                 vrele(fdirp);
 2597         if (fromnd.ni_startdir)
 2598                 vrele(fromnd.ni_startdir);
 2599         NDFREE(&fromnd, NDF_ONLY_PNBUF);
 2600         if (fromnd.ni_dvp)
 2601                 vrele(fromnd.ni_dvp);
 2602         if (fromnd.ni_vp)
 2603                 vrele(fromnd.ni_vp);
 2604 
 2605         vn_finished_write(mp);
 2606         mtx_unlock(&Giant);     /* VFS */
 2607         NFSD_LOCK();
 2608         return (error);
 2609 }
 2610 
 2611 /*
 2612  * nfs link service
 2613  */
 2614 int
 2615 nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 2616     struct thread *td, struct mbuf **mrq)
 2617 {
 2618         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 2619         struct sockaddr *nam = nfsd->nd_nam;
 2620         caddr_t dpos = nfsd->nd_dpos;
 2621         struct ucred *cred = &nfsd->nd_cr;
 2622         struct nameidata nd;
 2623         caddr_t bpos;
 2624         int error = 0, rdonly, len, dirfor_ret = 1, diraft_ret = 1;
 2625         int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3);
 2626         struct mbuf *mb, *mreq;
 2627         struct vnode *vp = NULL, *xp, *dirp = NULL;
 2628         struct vattr dirfor, diraft, at;
 2629         nfsfh_t nfh, dnfh;
 2630         fhandle_t *fhp, *dfhp;
 2631         struct mount *mp = NULL;
 2632 
 2633         NFSD_LOCK_ASSERT();
 2634 
 2635         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 2636         ndclear(&nd);
 2637 
 2638         fhp = &nfh.fh_generic;
 2639         dfhp = &dnfh.fh_generic;
 2640         nfsm_srvmtofh(fhp);
 2641         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
 2642                 error = ESTALE;
 2643                 goto ereply;
 2644         }
 2645         NFSD_UNLOCK();
 2646         mtx_lock(&Giant);       /* VFS */
 2647         (void) vn_start_write(NULL, &mp, V_WAIT);
 2648         mtx_unlock(&Giant);     /* VFS */
 2649         NFSD_LOCK();
 2650         nfsm_srvmtofh(dfhp);
 2651         nfsm_srvnamesiz(len);
 2652 
 2653         error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, slp, nam, &rdonly, TRUE);
 2654         if (error) {
 2655                 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
 2656                 if (v3) {
 2657                         nfsm_srvpostop_attr(getret, &at);
 2658                         nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 2659                 }
 2660                 vp = NULL;
 2661                 error = 0;
 2662                 goto nfsmout;
 2663         }
 2664         NFSD_UNLOCK();
 2665         mtx_lock(&Giant);       /* VFS */
 2666         if (v3)
 2667                 getret = VOP_GETATTR(vp, &at, cred, td);
 2668         if (vp->v_type == VDIR) {
 2669                 error = EPERM;          /* POSIX */
 2670                 goto out1;
 2671         }
 2672         VOP_UNLOCK(vp, 0, td);
 2673         nd.ni_cnd.cn_cred = cred;
 2674         nd.ni_cnd.cn_nameiop = CREATE;
 2675         nd.ni_cnd.cn_flags = LOCKPARENT;
 2676         mtx_unlock(&Giant);     /* VFS */
 2677         NFSD_LOCK();
 2678         error = nfs_namei(&nd, dfhp, len, slp, nam, &md, &dpos,
 2679                 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
 2680         NFSD_UNLOCK();
 2681         mtx_lock(&Giant);       /* VFS */
 2682         if (dirp && !v3) {
 2683                 vrele(dirp);
 2684                 dirp = NULL;
 2685         }
 2686         if (error) {
 2687                 vrele(vp);
 2688                 vp = NULL;
 2689                 goto out2;
 2690         }
 2691         xp = nd.ni_vp;
 2692         if (xp != NULL) {
 2693                 error = EEXIST;
 2694                 vrele(vp);
 2695                 vp = NULL;
 2696                 goto out2;
 2697         }
 2698         xp = nd.ni_dvp;
 2699         if (vp->v_mount != xp->v_mount) {
 2700                 error = EXDEV;
 2701                 vrele(vp);
 2702                 vp = NULL;
 2703                 goto out2;
 2704         }
 2705         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 2706         error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
 2707         NDFREE(&nd, NDF_ONLY_PNBUF);
 2708         /* fall through */
 2709 
 2710 out1:
 2711         if (v3)
 2712                 getret = VOP_GETATTR(vp, &at, cred, td);
 2713 out2:
 2714         if (dirp) {
 2715                 if (dirp == nd.ni_dvp)
 2716                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
 2717                 else {
 2718                         /* Release existing locks to prevent deadlock. */
 2719                         if (nd.ni_dvp) {
 2720                                 if (nd.ni_dvp == nd.ni_vp)
 2721                                         vrele(nd.ni_dvp);
 2722                                 else
 2723                                         vput(nd.ni_dvp);
 2724                         }
 2725                         if (nd.ni_vp)
 2726                                 vrele(nd.ni_vp);
 2727                         nd.ni_dvp = NULL;
 2728                         nd.ni_vp = NULL;
 2729 
 2730                         vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
 2731                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
 2732                         VOP_UNLOCK(dirp, 0, td);
 2733                 }
 2734         }
 2735         mtx_unlock(&Giant);     /* VFS */
 2736         NFSD_LOCK();
 2737 ereply:
 2738         NFSD_LOCK_ASSERT();
 2739         nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
 2740         if (v3) {
 2741                 nfsm_srvpostop_attr(getret, &at);
 2742                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 2743                 error = 0;
 2744         }
 2745         /* fall through */
 2746 
 2747 nfsmout:
 2748         NFSD_LOCK_ASSERT();
 2749         NFSD_UNLOCK();
 2750         mtx_lock(&Giant);       /* VFS */
 2751         NDFREE(&nd, NDF_ONLY_PNBUF);
 2752         if (dirp)
 2753                 vrele(dirp);
 2754         if (vp)
 2755                 vput(vp);
 2756         if (nd.ni_dvp) {
 2757                 if (nd.ni_dvp == nd.ni_vp)
 2758                         vrele(nd.ni_dvp);
 2759                 else
 2760                         vput(nd.ni_dvp);
 2761         }
 2762         if (nd.ni_vp)
 2763                 vrele(nd.ni_vp);
 2764         vn_finished_write(mp);
 2765         mtx_unlock(&Giant);     /* VFS */
 2766         NFSD_LOCK();
 2767         return(error);
 2768 }
 2769 
 2770 /*
 2771  * nfs symbolic link service
 2772  */
 2773 int
 2774 nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 2775     struct thread *td, struct mbuf **mrq)
 2776 {
 2777         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 2778         struct sockaddr *nam = nfsd->nd_nam;
 2779         caddr_t dpos = nfsd->nd_dpos;
 2780         struct ucred *cred = &nfsd->nd_cr;
 2781         struct vattr va, dirfor, diraft;
 2782         struct nameidata nd;
 2783         struct vattr *vap = &va;
 2784         struct nfsv2_sattr *sp;
 2785         char *bpos, *pathcp = NULL;
 2786         struct uio io;
 2787         struct iovec iv;
 2788         int error = 0, len, len2, dirfor_ret = 1, diraft_ret = 1;
 2789         int v3 = (nfsd->nd_flag & ND_NFSV3);
 2790         struct mbuf *mb, *mreq;
 2791         struct vnode *dirp = NULL;
 2792         nfsfh_t nfh;
 2793         fhandle_t *fhp;
 2794         struct mount *mp = NULL;
 2795 
 2796         NFSD_LOCK_ASSERT();
 2797 
 2798         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 2799         ndclear(&nd);
 2800 
 2801         fhp = &nfh.fh_generic;
 2802         nfsm_srvmtofh(fhp);
 2803         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
 2804                 NFSD_UNLOCK();
 2805                 mtx_lock(&Giant);       /* VFS */
 2806                 error = ESTALE;
 2807                 goto out;
 2808         }
 2809         NFSD_UNLOCK();
 2810         mtx_lock(&Giant);       /* VFS */
 2811         (void) vn_start_write(NULL, &mp, V_WAIT);
 2812         mtx_unlock(&Giant);     /* VFS */
 2813         NFSD_LOCK();
 2814         nfsm_srvnamesiz(len);
 2815         nd.ni_cnd.cn_cred = cred;
 2816         nd.ni_cnd.cn_nameiop = CREATE;
 2817         nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART;
 2818         error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
 2819                 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
 2820         NFSD_UNLOCK();
 2821         mtx_lock(&Giant);       /* VFS */
 2822         if (dirp && !v3) {
 2823                 vrele(dirp);
 2824                 dirp = NULL;
 2825         }
 2826         if (error)
 2827                 goto out;
 2828 
 2829         VATTR_NULL(vap);
 2830         if (v3)
 2831                 nfsm_srvsattr(vap);
 2832         nfsm_srvpathsiz(len2);
 2833         MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK);
 2834         iv.iov_base = pathcp;
 2835         iv.iov_len = len2;
 2836         io.uio_resid = len2;
 2837         io.uio_offset = 0;
 2838         io.uio_iov = &iv;
 2839         io.uio_iovcnt = 1;
 2840         io.uio_segflg = UIO_SYSSPACE;
 2841         io.uio_rw = UIO_READ;
 2842         io.uio_td = NULL;
 2843         nfsm_mtouio(&io, len2);
 2844         if (!v3) {
 2845                 sp = nfsm_dissect(struct nfsv2_sattr *, NFSX_V2SATTR);
 2846                 vap->va_mode = nfstov_mode(sp->sa_mode);
 2847         }
 2848         *(pathcp + len2) = '\0';
 2849         if (nd.ni_vp) {
 2850                 error = EEXIST;
 2851                 goto out;
 2852         }
 2853 
 2854         /*
 2855          * issue symlink op.  SAVESTART is set so the underlying path component
 2856          * is only freed by the VOP if an error occurs.
 2857          */
 2858         if (vap->va_mode == (mode_t)VNOVAL)
 2859                 vap->va_mode = 0;
 2860         error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap, pathcp);
 2861         if (error)
 2862                 NDFREE(&nd, NDF_ONLY_PNBUF);
 2863         else
 2864                 vput(nd.ni_vp);
 2865         nd.ni_vp = NULL;
 2866         /*
 2867          * releases directory prior to potential lookup op.
 2868          */
 2869         vput(nd.ni_dvp);
 2870         nd.ni_dvp = NULL;
 2871 
 2872         if (error == 0) {
 2873             if (v3) {
 2874                 /*
 2875                  * Issue lookup.  Leave SAVESTART set so we can easily free
 2876                  * the name buffer later on.
 2877                  *
 2878                  * since LOCKPARENT is not set, ni_dvp will be garbage on
 2879                  * return whether an error occurs or not.
 2880                  */
 2881                 nd.ni_cnd.cn_nameiop = LOOKUP;
 2882                 nd.ni_cnd.cn_flags &= ~(LOCKPARENT | FOLLOW);
 2883                 nd.ni_cnd.cn_flags |= (NOFOLLOW | LOCKLEAF);
 2884                 nd.ni_cnd.cn_thread = td;
 2885                 nd.ni_cnd.cn_cred = cred;
 2886 
 2887                 error = lookup(&nd);
 2888                 nd.ni_dvp = NULL;
 2889 
 2890                 if (error == 0) {
 2891                         bzero((caddr_t)fhp, sizeof(nfh));
 2892                         fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
 2893                         error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
 2894                         if (!error)
 2895                                 error = VOP_GETATTR(nd.ni_vp, vap, cred,
 2896                                         td);
 2897                         vput(nd.ni_vp);
 2898                         nd.ni_vp = NULL;
 2899                 }
 2900             }
 2901         }
 2902 out:
 2903         NFSD_UNLOCK_ASSERT();
 2904         /*
 2905          * These releases aren't strictly required, does even doing them
 2906          * make any sense? XXX can nfsm_reply() block?
 2907          */
 2908         if (pathcp) {
 2909                 FREE(pathcp, M_TEMP);
 2910                 pathcp = NULL;
 2911         }
 2912         if (dirp) {
 2913                 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
 2914                 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
 2915                 VOP_UNLOCK(dirp, 0, td);
 2916         }
 2917         if (nd.ni_startdir) {
 2918                 vrele(nd.ni_startdir);
 2919                 nd.ni_startdir = NULL;
 2920         }
 2921         mtx_unlock(&Giant);     /* VFS */
 2922         NFSD_LOCK();
 2923         nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
 2924         if (v3) {
 2925                 if (!error) {
 2926                         nfsm_srvpostop_fh(fhp);
 2927                         nfsm_srvpostop_attr(0, vap);
 2928                 }
 2929                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 2930         }
 2931         error = 0;
 2932         /* fall through */
 2933 
 2934 nfsmout:
 2935         NFSD_LOCK_ASSERT();
 2936         NFSD_UNLOCK();
 2937         mtx_lock(&Giant);       /* VFS */
 2938         NDFREE(&nd, NDF_ONLY_PNBUF);
 2939         if (nd.ni_dvp) {
 2940                 if (nd.ni_dvp == nd.ni_vp)
 2941                         vrele(nd.ni_dvp);
 2942                 else
 2943                         vput(nd.ni_dvp);
 2944         }
 2945         if (nd.ni_vp)
 2946                 vrele(nd.ni_vp);
 2947         if (nd.ni_startdir)
 2948                 vrele(nd.ni_startdir);
 2949         if (dirp)
 2950                 vrele(dirp);
 2951         if (pathcp)
 2952                 FREE(pathcp, M_TEMP);
 2953 
 2954         vn_finished_write(mp);
 2955         mtx_unlock(&Giant);     /* VFS */
 2956         NFSD_LOCK();
 2957         return (error);
 2958 }
 2959 
 2960 /*
 2961  * nfs mkdir service
 2962  */
 2963 int
 2964 nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 2965     struct thread *td, struct mbuf **mrq)
 2966 {
 2967         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 2968         struct sockaddr *nam = nfsd->nd_nam;
 2969         caddr_t dpos = nfsd->nd_dpos;
 2970         struct ucred *cred = &nfsd->nd_cr;
 2971         struct vattr va, dirfor, diraft;
 2972         struct vattr *vap = &va;
 2973         struct nfs_fattr *fp;
 2974         struct nameidata nd;
 2975         u_int32_t *tl;
 2976         caddr_t bpos;
 2977         int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
 2978         int v3 = (nfsd->nd_flag & ND_NFSV3);
 2979         struct mbuf *mb, *mreq;
 2980         struct vnode *dirp = NULL;
 2981         int vpexcl = 0;
 2982         nfsfh_t nfh;
 2983         fhandle_t *fhp;
 2984         struct mount *mp = NULL;
 2985 
 2986         NFSD_LOCK_ASSERT();
 2987 
 2988         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 2989         ndclear(&nd);
 2990 
 2991         fhp = &nfh.fh_generic;
 2992         nfsm_srvmtofh(fhp);
 2993         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
 2994                 NFSD_UNLOCK();
 2995                 mtx_lock(&Giant);       /* VFS */
 2996                 error = ESTALE;
 2997                 goto out;
 2998         }
 2999         NFSD_UNLOCK();
 3000         mtx_lock(&Giant);       /* VFS */
 3001         (void) vn_start_write(NULL, &mp, V_WAIT);
 3002         mtx_unlock(&Giant);     /* VFS */
 3003         NFSD_LOCK();
 3004         nfsm_srvnamesiz(len);
 3005         nd.ni_cnd.cn_cred = cred;
 3006         nd.ni_cnd.cn_nameiop = CREATE;
 3007         nd.ni_cnd.cn_flags = LOCKPARENT;
 3008 
 3009         error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
 3010                 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
 3011         if (dirp && !v3) {
 3012                 NFSD_UNLOCK();
 3013                 mtx_lock(&Giant);       /* VFS */
 3014                 vrele(dirp);
 3015                 mtx_unlock(&Giant);     /* VFS */
 3016                 NFSD_LOCK();
 3017                 dirp = NULL;
 3018         }
 3019         if (error) {
 3020                 nfsm_reply(NFSX_WCCDATA(v3));
 3021                 if (v3)
 3022                         nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 3023                 error = 0;
 3024                 goto nfsmout;
 3025         }
 3026         VATTR_NULL(vap);
 3027         if (v3) {
 3028                 nfsm_srvsattr(vap);
 3029         } else {
 3030                 tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
 3031                 vap->va_mode = nfstov_mode(*tl++);
 3032         }
 3033 
 3034         /*
 3035          * At this point nd.ni_dvp is referenced and exclusively locked and
 3036          * nd.ni_vp, if it exists, is referenced but not locked.
 3037          */
 3038 
 3039         NFSD_UNLOCK();
 3040         mtx_lock(&Giant);       /* VFS */
 3041         vap->va_type = VDIR;
 3042         if (nd.ni_vp != NULL) {
 3043                 NDFREE(&nd, NDF_ONLY_PNBUF);
 3044                 error = EEXIST;
 3045                 goto out;
 3046         }
 3047 
 3048         /*
 3049          * Issue mkdir op.  Since SAVESTART is not set, the pathname
 3050          * component is freed by the VOP call.  This will fill-in
 3051          * nd.ni_vp, reference, and exclusively lock it.
 3052          */
 3053         if (vap->va_mode == (mode_t)VNOVAL)
 3054                 vap->va_mode = 0;
 3055         error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
 3056         NDFREE(&nd, NDF_ONLY_PNBUF);
 3057         vpexcl = 1;
 3058 
 3059         vput(nd.ni_dvp);
 3060         nd.ni_dvp = NULL;
 3061 
 3062         if (!error) {
 3063                 bzero((caddr_t)fhp, sizeof(nfh));
 3064                 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
 3065                 error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
 3066                 if (!error)
 3067                         error = VOP_GETATTR(nd.ni_vp, vap, cred, td);
 3068         }
 3069 out:
 3070         NFSD_UNLOCK_ASSERT();
 3071         if (dirp) {
 3072                 if (dirp == nd.ni_dvp) {
 3073                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
 3074                 } else {
 3075                         /* Release existing locks to prevent deadlock. */
 3076                         if (nd.ni_dvp) {
 3077                                 NDFREE(&nd, NDF_ONLY_PNBUF);
 3078                                 if (nd.ni_dvp == nd.ni_vp && vpexcl)
 3079                                         vrele(nd.ni_dvp);
 3080                                 else
 3081                                         vput(nd.ni_dvp);
 3082                         }
 3083                         if (nd.ni_vp) {
 3084                                 if (vpexcl)
 3085                                         vput(nd.ni_vp);
 3086                                 else
 3087                                         vrele(nd.ni_vp);
 3088                         }
 3089                         nd.ni_dvp = NULL;
 3090                         nd.ni_vp = NULL;
 3091                         vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
 3092                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
 3093                         VOP_UNLOCK(dirp, 0, td);
 3094                 }
 3095         }
 3096         mtx_unlock(&Giant);     /* VFS */
 3097         NFSD_LOCK();
 3098         nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
 3099         if (v3) {
 3100                 if (!error) {
 3101                         nfsm_srvpostop_fh(fhp);
 3102                         nfsm_srvpostop_attr(0, vap);
 3103                 }
 3104                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 3105         } else if (!error) {
 3106                 /* v2 non-error case. */
 3107                 nfsm_srvfhtom(fhp, v3);
 3108                 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
 3109                 nfsm_srvfillattr(vap, fp);
 3110         }
 3111         error = 0;
 3112         /* fall through */
 3113 
 3114 nfsmout:
 3115         NFSD_LOCK_ASSERT();
 3116         NFSD_UNLOCK();
 3117         mtx_lock(&Giant);       /* VFS */
 3118         if (dirp)
 3119                 vrele(dirp);
 3120         if (nd.ni_dvp) {
 3121                 NDFREE(&nd, NDF_ONLY_PNBUF);
 3122                 if (nd.ni_dvp == nd.ni_vp && vpexcl)
 3123                         vrele(nd.ni_dvp);
 3124                 else
 3125                         vput(nd.ni_dvp);
 3126         }
 3127         if (nd.ni_vp) {
 3128                 if (vpexcl)
 3129                         vput(nd.ni_vp);
 3130                 else
 3131                         vrele(nd.ni_vp);
 3132         }
 3133         vn_finished_write(mp);
 3134         mtx_unlock(&Giant);     /* VFS */
 3135         NFSD_LOCK();
 3136         return (error);
 3137 }
 3138 
 3139 /*
 3140  * nfs rmdir service
 3141  */
 3142 int
 3143 nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 3144     struct thread *td, struct mbuf **mrq)
 3145 {
 3146         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 3147         struct sockaddr *nam = nfsd->nd_nam;
 3148         caddr_t dpos = nfsd->nd_dpos;
 3149         struct ucred *cred = &nfsd->nd_cr;
 3150         caddr_t bpos;
 3151         int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
 3152         int v3 = (nfsd->nd_flag & ND_NFSV3);
 3153         struct mbuf *mb, *mreq;
 3154         struct vnode *vp, *dirp = NULL;
 3155         struct vattr dirfor, diraft;
 3156         nfsfh_t nfh;
 3157         fhandle_t *fhp;
 3158         struct nameidata nd;
 3159         struct mount *mp = NULL;
 3160 
 3161         NFSD_LOCK_ASSERT();
 3162 
 3163         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 3164         ndclear(&nd);
 3165 
 3166         fhp = &nfh.fh_generic;
 3167         nfsm_srvmtofh(fhp);
 3168         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
 3169                 error = ESTALE;
 3170                 goto out;
 3171         }
 3172         NFSD_UNLOCK();
 3173         mtx_lock(&Giant);       /* VFS */
 3174         (void) vn_start_write(NULL, &mp, V_WAIT);
 3175         mtx_unlock(&Giant);     /* VFS */
 3176         NFSD_LOCK();
 3177         nfsm_srvnamesiz(len);
 3178         nd.ni_cnd.cn_cred = cred;
 3179         nd.ni_cnd.cn_nameiop = DELETE;
 3180         nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
 3181         error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
 3182                 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
 3183         if (dirp && !v3) {
 3184                 NFSD_UNLOCK();
 3185                 mtx_lock(&Giant);       /* VFS */
 3186                 vrele(dirp);
 3187                 mtx_unlock(&Giant);     /* VFS */
 3188                 NFSD_LOCK();
 3189                 dirp = NULL;
 3190         }
 3191         if (error) {
 3192                 nfsm_reply(NFSX_WCCDATA(v3));
 3193                 if (v3)
 3194                         nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 3195                 error = 0;
 3196                 goto nfsmout;
 3197         }
 3198         vp = nd.ni_vp;
 3199         if (vp->v_type != VDIR) {
 3200                 error = ENOTDIR;
 3201                 goto out;
 3202         }
 3203         /*
 3204          * No rmdir "." please.
 3205          */
 3206         if (nd.ni_dvp == vp) {
 3207                 error = EINVAL;
 3208                 goto out;
 3209         }
 3210         /*
 3211          * The root of a mounted filesystem cannot be deleted.
 3212          */
 3213         if (vp->v_vflag & VV_ROOT)
 3214                 error = EBUSY;
 3215 out:
 3216         /*
 3217          * Issue or abort op.  Since SAVESTART is not set, path name
 3218          * component is freed by the VOP after either.
 3219          */
 3220         NFSD_LOCK_ASSERT();
 3221         NFSD_UNLOCK();
 3222         mtx_lock(&Giant);       /* VFS */
 3223         if (!error)
 3224                 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
 3225         NDFREE(&nd, NDF_ONLY_PNBUF);
 3226 
 3227         if (dirp) {
 3228                 if (dirp == nd.ni_dvp)
 3229                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
 3230                 else {
 3231                         /* Release existing locks to prevent deadlock. */
 3232                         if (nd.ni_dvp) {
 3233                                 if (nd.ni_dvp == nd.ni_vp)
 3234                                         vrele(nd.ni_dvp);
 3235                                 else
 3236                                         vput(nd.ni_dvp);
 3237                         }
 3238                         if (nd.ni_vp)
 3239                                 vput(nd.ni_vp);
 3240                         nd.ni_dvp = NULL;
 3241                         nd.ni_vp = NULL;
 3242                         vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
 3243                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
 3244                         VOP_UNLOCK(dirp, 0, td);
 3245                 }
 3246         }
 3247         mtx_unlock(&Giant);     /* VFS */
 3248         NFSD_LOCK();
 3249         nfsm_reply(NFSX_WCCDATA(v3));
 3250         error = 0;
 3251         if (v3)
 3252                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 3253         /* fall through */
 3254 
 3255 nfsmout:
 3256         NFSD_LOCK_ASSERT();
 3257         NFSD_UNLOCK();
 3258         mtx_lock(&Giant);       /* VFS */
 3259         NDFREE(&nd, NDF_ONLY_PNBUF);
 3260         if (dirp)
 3261                 vrele(dirp);
 3262         if (nd.ni_dvp) {
 3263                 if (nd.ni_dvp == nd.ni_vp)
 3264                         vrele(nd.ni_dvp);
 3265                 else
 3266                         vput(nd.ni_dvp);
 3267         }
 3268         if (nd.ni_vp)
 3269                 vput(nd.ni_vp);
 3270 
 3271         vn_finished_write(mp);
 3272         mtx_unlock(&Giant);     /* VFS */
 3273         NFSD_LOCK();
 3274         return(error);
 3275 }
 3276 
 3277 /*
 3278  * nfs readdir service
 3279  * - mallocs what it thinks is enough to read
 3280  *      count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
 3281  * - calls VOP_READDIR()
 3282  * - loops around building the reply
 3283  *      if the output generated exceeds count break out of loop
 3284  *      The nfsm_clget macro is used here so that the reply will be packed
 3285  *      tightly in mbuf clusters.
 3286  * - it only knows that it has encountered eof when the VOP_READDIR()
 3287  *      reads nothing
 3288  * - as such one readdir rpc will return eof false although you are there
 3289  *      and then the next will return eof
 3290  * - it trims out records with d_fileno == 0
 3291  *      this doesn't matter for Unix clients, but they might confuse clients
 3292  *      for other os'.
 3293  * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
 3294  *      than requested, but this may not apply to all filesystems. For
 3295  *      example, client NFS does not { although it is never remote mounted
 3296  *      anyhow }
 3297  *     The alternate call nfsrv_readdirplus() does lookups as well.
 3298  * PS: The NFS protocol spec. does not clarify what the "count" byte
 3299  *      argument is a count of.. just name strings and file id's or the
 3300  *      entire reply rpc or ...
 3301  *      I tried just file name and id sizes and it confused the Sun client,
 3302  *      so I am using the full rpc size now. The "paranoia.." comment refers
 3303  *      to including the status longwords that are not a part of the dir.
 3304  *      "entry" structures, but are in the rpc.
 3305  */
 3306 struct flrep {
 3307         nfsuint64       fl_off;
 3308         u_int32_t       fl_postopok;
 3309         u_int32_t       fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)];
 3310         u_int32_t       fl_fhok;
 3311         u_int32_t       fl_fhsize;
 3312         u_int32_t       fl_nfh[NFSX_V3FH / sizeof (u_int32_t)];
 3313 };
 3314 
 3315 int
 3316 nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 3317     struct thread *td, struct mbuf **mrq)
 3318 {
 3319         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 3320         struct sockaddr *nam = nfsd->nd_nam;
 3321         caddr_t dpos = nfsd->nd_dpos;
 3322         struct ucred *cred = &nfsd->nd_cr;
 3323         char *bp, *be;
 3324         struct mbuf *mp;
 3325         struct dirent *dp;
 3326         caddr_t cp;
 3327         u_int32_t *tl;
 3328         caddr_t bpos;
 3329         struct mbuf *mb, *mreq;
 3330         char *cpos, *cend, *rbuf;
 3331         struct vnode *vp = NULL;
 3332         struct vattr at;
 3333         nfsfh_t nfh;
 3334         fhandle_t *fhp;
 3335         struct uio io;
 3336         struct iovec iv;
 3337         int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
 3338         int siz, cnt, fullsiz, eofflag, rdonly, ncookies;
 3339         int v3 = (nfsd->nd_flag & ND_NFSV3);
 3340         u_quad_t off, toff, verf;
 3341         u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
 3342 
 3343         NFSD_LOCK_ASSERT();
 3344 
 3345         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 3346         fhp = &nfh.fh_generic;
 3347         nfsm_srvmtofh(fhp);
 3348         if (v3) {
 3349                 tl = nfsm_dissect(u_int32_t *, 5 * NFSX_UNSIGNED);
 3350                 toff = fxdr_hyper(tl);
 3351                 tl += 2;
 3352                 verf = fxdr_hyper(tl);
 3353                 tl += 2;
 3354         } else {
 3355                 tl = nfsm_dissect(u_int32_t *, 2 * NFSX_UNSIGNED);
 3356                 toff = fxdr_unsigned(u_quad_t, *tl++);
 3357                 verf = 0;       /* shut up gcc */
 3358         }
 3359         off = toff;
 3360         cnt = fxdr_unsigned(int, *tl);
 3361         siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
 3362         xfer = NFS_SRVMAXDATA(nfsd);
 3363         if (cnt > xfer)
 3364                 cnt = xfer;
 3365         if (siz > xfer)
 3366                 siz = xfer;
 3367         fullsiz = siz;
 3368         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
 3369         if (!error && vp->v_type != VDIR) {
 3370                 error = ENOTDIR;
 3371                 NFSD_UNLOCK();
 3372                 mtx_lock(&Giant);       /* VFS */
 3373                 vput(vp);
 3374                 mtx_unlock(&Giant);     /* VFS */
 3375                 NFSD_LOCK();
 3376                 vp = NULL;
 3377         }
 3378         if (error) {
 3379                 nfsm_reply(NFSX_UNSIGNED);
 3380                 if (v3)
 3381                         nfsm_srvpostop_attr(getret, &at);
 3382                 error = 0;
 3383                 goto nfsmout;
 3384         }
 3385 
 3386         /*
 3387          * Obtain lock on vnode for this section of the code
 3388          */
 3389         NFSD_UNLOCK();
 3390         mtx_lock(&Giant);       /* VFS */
 3391         if (v3) {
 3392                 error = getret = VOP_GETATTR(vp, &at, cred, td);
 3393 #if 0
 3394                 /*
 3395                  * XXX This check may be too strict for Solaris 2.5 clients.
 3396                  */
 3397                 if (!error && toff && verf && verf != at.va_filerev)
 3398                         error = NFSERR_BAD_COOKIE;
 3399 #endif
 3400         }
 3401         if (!error)
 3402                 error = nfsrv_access_withgiant(vp, VEXEC, cred, rdonly, td, 0);
 3403         if (error) {
 3404                 vput(vp);
 3405                 mtx_unlock(&Giant);     /* VFS */
 3406                 NFSD_LOCK();
 3407                 vp = NULL;
 3408                 nfsm_reply(NFSX_POSTOPATTR(v3));
 3409                 if (v3)
 3410                         nfsm_srvpostop_attr(getret, &at);
 3411                 error = 0;
 3412                 goto nfsmout;
 3413         }
 3414         VOP_UNLOCK(vp, 0, td);
 3415 
 3416         /*
 3417          * end section.  Allocate rbuf and continue
 3418          */
 3419         MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
 3420 again:
 3421         NFSD_UNLOCK_ASSERT();
 3422         iv.iov_base = rbuf;
 3423         iv.iov_len = fullsiz;
 3424         io.uio_iov = &iv;
 3425         io.uio_iovcnt = 1;
 3426         io.uio_offset = (off_t)off;
 3427         io.uio_resid = fullsiz;
 3428         io.uio_segflg = UIO_SYSSPACE;
 3429         io.uio_rw = UIO_READ;
 3430         io.uio_td = NULL;
 3431         eofflag = 0;
 3432         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 3433         if (cookies) {
 3434                 free((caddr_t)cookies, M_TEMP);
 3435                 cookies = NULL;
 3436         }
 3437         error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
 3438         off = (off_t)io.uio_offset;
 3439         if (!cookies && !error)
 3440                 error = NFSERR_PERM;
 3441         if (v3) {
 3442                 getret = VOP_GETATTR(vp, &at, cred, td);
 3443                 if (!error)
 3444                         error = getret;
 3445         }
 3446         VOP_UNLOCK(vp, 0, td);
 3447         if (error) {
 3448                 vrele(vp);
 3449                 mtx_unlock(&Giant);     /* VFS */
 3450                 vp = NULL;
 3451                 free((caddr_t)rbuf, M_TEMP);
 3452                 if (cookies)
 3453                         free((caddr_t)cookies, M_TEMP);
 3454                 NFSD_LOCK();
 3455                 nfsm_reply(NFSX_POSTOPATTR(v3));
 3456                 if (v3)
 3457                         nfsm_srvpostop_attr(getret, &at);
 3458                 error = 0;
 3459                 goto nfsmout;
 3460         }
 3461         if (io.uio_resid) {
 3462                 siz -= io.uio_resid;
 3463 
 3464                 /*
 3465                  * If nothing read, return eof
 3466                  * rpc reply
 3467                  */
 3468                 if (siz == 0) {
 3469                         vrele(vp);
 3470                         mtx_unlock(&Giant);     /* VFS */
 3471                         vp = NULL;
 3472                         NFSD_LOCK();
 3473                         nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) +
 3474                                 2 * NFSX_UNSIGNED);
 3475                         if (v3) {
 3476                                 nfsm_srvpostop_attr(getret, &at);
 3477                                 tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
 3478                                 txdr_hyper(at.va_filerev, tl);
 3479                                 tl += 2;
 3480                         } else
 3481                                 tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
 3482                         *tl++ = nfsrv_nfs_false;
 3483                         *tl = nfsrv_nfs_true;
 3484                         FREE((caddr_t)rbuf, M_TEMP);
 3485                         FREE((caddr_t)cookies, M_TEMP);
 3486                         error = 0;
 3487                         goto nfsmout;
 3488                 }
 3489         }
 3490 
 3491         /*
 3492          * Check for degenerate cases of nothing useful read.
 3493          * If so go try again
 3494          */
 3495         cpos = rbuf;
 3496         cend = rbuf + siz;
 3497         dp = (struct dirent *)cpos;
 3498         cookiep = cookies;
 3499         /*
 3500          * For some reason FreeBSD's ufs_readdir() chooses to back the
 3501          * directory offset up to a block boundary, so it is necessary to
 3502          * skip over the records that precede the requested offset. This
 3503          * requires the assumption that file offset cookies monotonically
 3504          * increase.
 3505          */
 3506         while (cpos < cend && ncookies > 0 &&
 3507                 (dp->d_fileno == 0 || dp->d_type == DT_WHT ||
 3508                  ((u_quad_t)(*cookiep)) <= toff)) {
 3509                 cpos += dp->d_reclen;
 3510                 dp = (struct dirent *)cpos;
 3511                 cookiep++;
 3512                 ncookies--;
 3513         }
 3514         if (cpos >= cend || ncookies == 0) {
 3515                 toff = off;
 3516                 siz = fullsiz;
 3517                 goto again;
 3518         }
 3519 
 3520         mtx_unlock(&Giant);     /* VFS */
 3521         NFSD_LOCK();
 3522         len = 3 * NFSX_UNSIGNED;        /* paranoia, probably can be 0 */
 3523         nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz);
 3524         if (v3) {
 3525                 nfsm_srvpostop_attr(getret, &at);
 3526                 tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
 3527                 txdr_hyper(at.va_filerev, tl);
 3528         }
 3529         mp = mb;
 3530         bp = bpos;
 3531         be = bp + M_TRAILINGSPACE(mp);
 3532 
 3533         /* Loop through the records and build reply */
 3534         while (cpos < cend && ncookies > 0) {
 3535                 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
 3536                         nlen = dp->d_namlen;
 3537                         rem = nfsm_rndup(nlen) - nlen;
 3538                         len += (4 * NFSX_UNSIGNED + nlen + rem);
 3539                         if (v3)
 3540                                 len += 2 * NFSX_UNSIGNED;
 3541                         if (len > cnt) {
 3542                                 eofflag = 0;
 3543                                 break;
 3544                         }
 3545                         /*
 3546                          * Build the directory record xdr from
 3547                          * the dirent entry.
 3548                          */
 3549                         nfsm_clget;
 3550                         *tl = nfsrv_nfs_true;
 3551                         bp += NFSX_UNSIGNED;
 3552                         if (v3) {
 3553                                 nfsm_clget;
 3554                                 *tl = 0;
 3555                                 bp += NFSX_UNSIGNED;
 3556                         }
 3557                         nfsm_clget;
 3558                         *tl = txdr_unsigned(dp->d_fileno);
 3559                         bp += NFSX_UNSIGNED;
 3560                         nfsm_clget;
 3561                         *tl = txdr_unsigned(nlen);
 3562                         bp += NFSX_UNSIGNED;
 3563 
 3564                         /* And loop around copying the name */
 3565                         xfer = nlen;
 3566                         cp = dp->d_name;
 3567                         while (xfer > 0) {
 3568                                 nfsm_clget;
 3569                                 if ((bp+xfer) > be)
 3570                                         tsiz = be-bp;
 3571                                 else
 3572                                         tsiz = xfer;
 3573                                 bcopy(cp, bp, tsiz);
 3574                                 bp += tsiz;
 3575                                 xfer -= tsiz;
 3576                                 if (xfer > 0)
 3577                                         cp += tsiz;
 3578                         }
 3579                         /* And null pad to an int32_t boundary. */
 3580                         for (i = 0; i < rem; i++)
 3581                                 *bp++ = '\0';
 3582                         nfsm_clget;
 3583 
 3584                         /* Finish off the record */
 3585                         if (v3) {
 3586                                 *tl = 0;
 3587                                 bp += NFSX_UNSIGNED;
 3588                                 nfsm_clget;
 3589                         }
 3590                         *tl = txdr_unsigned(*cookiep);
 3591                         bp += NFSX_UNSIGNED;
 3592                 }
 3593                 cpos += dp->d_reclen;
 3594                 dp = (struct dirent *)cpos;
 3595                 cookiep++;
 3596                 ncookies--;
 3597         }
 3598         NFSD_UNLOCK();
 3599         mtx_lock(&Giant);       /* VFS */
 3600         vrele(vp);
 3601         mtx_unlock(&Giant);     /* VFS */
 3602         NFSD_LOCK();
 3603         vp = NULL;
 3604         nfsm_clget;
 3605         *tl = nfsrv_nfs_false;
 3606         bp += NFSX_UNSIGNED;
 3607         nfsm_clget;
 3608         if (eofflag)
 3609                 *tl = nfsrv_nfs_true;
 3610         else
 3611                 *tl = nfsrv_nfs_false;
 3612         bp += NFSX_UNSIGNED;
 3613         if (mp != mb) {
 3614                 if (bp < be)
 3615                         mp->m_len = bp - mtod(mp, caddr_t);
 3616         } else
 3617                 mp->m_len += bp - bpos;
 3618         FREE((caddr_t)rbuf, M_TEMP);
 3619         FREE((caddr_t)cookies, M_TEMP);
 3620 
 3621 nfsmout:
 3622         NFSD_LOCK_ASSERT();
 3623         if (vp) {
 3624                 NFSD_UNLOCK();
 3625                 mtx_lock(&Giant);       /* VFS */
 3626                 vrele(vp);
 3627                 mtx_unlock(&Giant);     /* VFS */
 3628                 NFSD_LOCK();
 3629         }
 3630         return(error);
 3631 }
 3632 
 3633 int
 3634 nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 3635     struct thread *td, struct mbuf **mrq)
 3636 {
 3637         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 3638         struct sockaddr *nam = nfsd->nd_nam;
 3639         caddr_t dpos = nfsd->nd_dpos;
 3640         struct ucred *cred = &nfsd->nd_cr;
 3641         char *bp, *be;
 3642         struct mbuf *mp;
 3643         struct dirent *dp;
 3644         caddr_t cp;
 3645         u_int32_t *tl;
 3646         caddr_t bpos;
 3647         struct mbuf *mb, *mreq;
 3648         char *cpos, *cend, *rbuf;
 3649         struct vnode *vp = NULL, *nvp;
 3650         struct flrep fl;
 3651         nfsfh_t nfh;
 3652         fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh;
 3653         struct uio io;
 3654         struct iovec iv;
 3655         struct vattr va, at, *vap = &va;
 3656         struct nfs_fattr *fp;
 3657         int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
 3658         int siz, cnt, fullsiz, eofflag, rdonly, dirlen, ncookies;
 3659         u_quad_t off, toff, verf;
 3660         u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
 3661         int v3 = (nfsd->nd_flag & ND_NFSV3);
 3662 
 3663         NFSD_LOCK_ASSERT();
 3664 
 3665         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 3666         if (!v3)
 3667                 panic("nfsrv_readdirplus: v3 proc called on a v2 connection");
 3668         fhp = &nfh.fh_generic;
 3669         nfsm_srvmtofh(fhp);
 3670         tl = nfsm_dissect(u_int32_t *, 6 * NFSX_UNSIGNED);
 3671         toff = fxdr_hyper(tl);
 3672         tl += 2;
 3673         verf = fxdr_hyper(tl);
 3674         tl += 2;
 3675         siz = fxdr_unsigned(int, *tl++);
 3676         cnt = fxdr_unsigned(int, *tl);
 3677         off = toff;
 3678         siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
 3679         xfer = NFS_SRVMAXDATA(nfsd);
 3680         if (cnt > xfer)
 3681                 cnt = xfer;
 3682         if (siz > xfer)
 3683                 siz = xfer;
 3684         fullsiz = siz;
 3685         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
 3686         if (!error && vp->v_type != VDIR) {
 3687                 error = ENOTDIR;
 3688                 NFSD_UNLOCK();
 3689                 mtx_lock(&Giant);       /* VFS */
 3690                 vput(vp);
 3691                 mtx_unlock(&Giant);     /* VFS */
 3692                 vp = NULL;
 3693                 NFSD_LOCK();
 3694         }
 3695         if (error) {
 3696                 nfsm_reply(NFSX_UNSIGNED);
 3697                 nfsm_srvpostop_attr(getret, &at);
 3698                 error = 0;
 3699                 goto nfsmout;
 3700         }
 3701         NFSD_UNLOCK();
 3702         mtx_lock(&Giant);       /* VFS */
 3703         error = getret = VOP_GETATTR(vp, &at, cred, td);
 3704 #if 0
 3705         /*
 3706          * XXX This check may be too strict for Solaris 2.5 clients.
 3707          */
 3708         if (!error && toff && verf && verf != at.va_filerev)
 3709                 error = NFSERR_BAD_COOKIE;
 3710 #endif
 3711         if (!error)
 3712                 error = nfsrv_access_withgiant(vp, VEXEC, cred, rdonly, td, 0);
 3713         if (error) {
 3714                 vput(vp);
 3715                 mtx_unlock(&Giant);     /* VFS */
 3716                 NFSD_LOCK();
 3717                 vp = NULL;
 3718                 nfsm_reply(NFSX_V3POSTOPATTR);
 3719                 nfsm_srvpostop_attr(getret, &at);
 3720                 error = 0;
 3721                 goto nfsmout;
 3722         }
 3723         VOP_UNLOCK(vp, 0, td);
 3724         MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
 3725 again:
 3726         NFSD_UNLOCK_ASSERT();
 3727         iv.iov_base = rbuf;
 3728         iv.iov_len = fullsiz;
 3729         io.uio_iov = &iv;
 3730         io.uio_iovcnt = 1;
 3731         io.uio_offset = (off_t)off;
 3732         io.uio_resid = fullsiz;
 3733         io.uio_segflg = UIO_SYSSPACE;
 3734         io.uio_rw = UIO_READ;
 3735         io.uio_td = NULL;
 3736         eofflag = 0;
 3737         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 3738         if (cookies) {
 3739                 free((caddr_t)cookies, M_TEMP);
 3740                 cookies = NULL;
 3741         }
 3742         error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
 3743         off = (u_quad_t)io.uio_offset;
 3744         getret = VOP_GETATTR(vp, &at, cred, td);
 3745         VOP_UNLOCK(vp, 0, td);
 3746         if (!cookies && !error)
 3747                 error = NFSERR_PERM;
 3748         if (!error)
 3749                 error = getret;
 3750         if (error) {
 3751                 vrele(vp);
 3752                 mtx_unlock(&Giant);     /* VFS */
 3753                 vp = NULL;
 3754                 if (cookies)
 3755                         free((caddr_t)cookies, M_TEMP);
 3756                 free((caddr_t)rbuf, M_TEMP);
 3757                 NFSD_LOCK();
 3758                 nfsm_reply(NFSX_V3POSTOPATTR);
 3759                 nfsm_srvpostop_attr(getret, &at);
 3760                 error = 0;
 3761                 goto nfsmout;
 3762         }
 3763         if (io.uio_resid) {
 3764                 siz -= io.uio_resid;
 3765 
 3766                 /*
 3767                  * If nothing read, return eof
 3768                  * rpc reply
 3769                  */
 3770                 if (siz == 0) {
 3771                         vrele(vp);
 3772                         mtx_unlock(&Giant);     /* VFS */
 3773                         NFSD_LOCK();
 3774                         vp = NULL;
 3775                         nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
 3776                                 2 * NFSX_UNSIGNED);
 3777                         nfsm_srvpostop_attr(getret, &at);
 3778                         tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
 3779                         txdr_hyper(at.va_filerev, tl);
 3780                         tl += 2;
 3781                         *tl++ = nfsrv_nfs_false;
 3782                         *tl = nfsrv_nfs_true;
 3783                         FREE((caddr_t)cookies, M_TEMP);
 3784                         FREE((caddr_t)rbuf, M_TEMP);
 3785                         error = 0;
 3786                         goto nfsmout;
 3787                 }
 3788         }
 3789 
 3790         /*
 3791          * Check for degenerate cases of nothing useful read.
 3792          * If so go try again
 3793          */
 3794         cpos = rbuf;
 3795         cend = rbuf + siz;
 3796         dp = (struct dirent *)cpos;
 3797         cookiep = cookies;
 3798         /*
 3799          * For some reason FreeBSD's ufs_readdir() chooses to back the
 3800          * directory offset up to a block boundary, so it is necessary to
 3801          * skip over the records that precede the requested offset. This
 3802          * requires the assumption that file offset cookies monotonically
 3803          * increase.
 3804          */
 3805         while (cpos < cend && ncookies > 0 &&
 3806                 (dp->d_fileno == 0 || dp->d_type == DT_WHT ||
 3807                  ((u_quad_t)(*cookiep)) <= toff)) {
 3808                 cpos += dp->d_reclen;
 3809                 dp = (struct dirent *)cpos;
 3810                 cookiep++;
 3811                 ncookies--;
 3812         }
 3813         if (cpos >= cend || ncookies == 0) {
 3814                 toff = off;
 3815                 siz = fullsiz;
 3816                 goto again;
 3817         }
 3818 
 3819         /*
 3820          * Probe one of the directory entries to see if the filesystem
 3821          * supports VGET.
 3822          */
 3823         if (VFS_VGET(vp->v_mount, dp->d_fileno, LK_EXCLUSIVE, &nvp) ==
 3824             EOPNOTSUPP) {
 3825                 error = NFSERR_NOTSUPP;
 3826                 vrele(vp);
 3827                 mtx_unlock(&Giant);     /* VFS */
 3828                 vp = NULL;
 3829                 free((caddr_t)cookies, M_TEMP);
 3830                 free((caddr_t)rbuf, M_TEMP);
 3831                 NFSD_LOCK();
 3832                 nfsm_reply(NFSX_V3POSTOPATTR);
 3833                 nfsm_srvpostop_attr(getret, &at);
 3834                 error = 0;
 3835                 goto nfsmout;
 3836         }
 3837         vput(nvp);
 3838         mtx_unlock(&Giant);     /* VFS */
 3839         nvp = NULL;
 3840 
 3841         dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
 3842             2 * NFSX_UNSIGNED;
 3843         NFSD_LOCK();
 3844         nfsm_reply(cnt);
 3845         nfsm_srvpostop_attr(getret, &at);
 3846         tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
 3847         txdr_hyper(at.va_filerev, tl);
 3848         mp = mb;
 3849         bp = bpos;
 3850         be = bp + M_TRAILINGSPACE(mp);
 3851 
 3852         NFSD_UNLOCK();
 3853         mtx_lock(&Giant);       /* VFS */
 3854         /* Loop through the records and build reply */
 3855         while (cpos < cend && ncookies > 0) {
 3856                 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
 3857                         nlen = dp->d_namlen;
 3858                         rem = nfsm_rndup(nlen)-nlen;
 3859 
 3860                         /*
 3861                          * For readdir_and_lookup get the vnode using
 3862                          * the file number.
 3863                          */
 3864                         if (VFS_VGET(vp->v_mount, dp->d_fileno, LK_EXCLUSIVE,
 3865                             &nvp))
 3866                                 goto invalid;
 3867                         bzero((caddr_t)nfhp, NFSX_V3FH);
 3868                         nfhp->fh_fsid =
 3869                                 nvp->v_mount->mnt_stat.f_fsid;
 3870                         if (VFS_VPTOFH(nvp, &nfhp->fh_fid)) {
 3871                                 vput(nvp);
 3872                                 nvp = NULL;
 3873                                 goto invalid;
 3874                         }
 3875                         if (VOP_GETATTR(nvp, vap, cred, td)) {
 3876                                 vput(nvp);
 3877                                 nvp = NULL;
 3878                                 goto invalid;
 3879                         }
 3880                         vput(nvp);
 3881                         nvp = NULL;
 3882 
 3883                         /*
 3884                          * If either the dircount or maxcount will be
 3885                          * exceeded, get out now. Both of these lengths
 3886                          * are calculated conservatively, including all
 3887                          * XDR overheads.
 3888                          */
 3889                         len += (8 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH +
 3890                                 NFSX_V3POSTOPATTR);
 3891                         dirlen += (6 * NFSX_UNSIGNED + nlen + rem);
 3892                         if (len > cnt || dirlen > fullsiz) {
 3893                                 eofflag = 0;
 3894                                 break;
 3895                         }
 3896 
 3897                         /*
 3898                          * Build the directory record xdr from
 3899                          * the dirent entry.
 3900                          */
 3901                         fp = (struct nfs_fattr *)&fl.fl_fattr;
 3902                         nfsm_srvfillattr(vap, fp);
 3903                         fl.fl_fhsize = txdr_unsigned(NFSX_V3FH);
 3904                         fl.fl_fhok = nfsrv_nfs_true;
 3905                         fl.fl_postopok = nfsrv_nfs_true;
 3906                         fl.fl_off.nfsuquad[0] = 0;
 3907                         fl.fl_off.nfsuquad[1] = txdr_unsigned(*cookiep);
 3908 
 3909                         nfsm_clget_nolock;
 3910                         *tl = nfsrv_nfs_true;
 3911                         bp += NFSX_UNSIGNED;
 3912                         nfsm_clget_nolock;
 3913                         *tl = 0;
 3914                         bp += NFSX_UNSIGNED;
 3915                         nfsm_clget_nolock;
 3916                         *tl = txdr_unsigned(dp->d_fileno);
 3917                         bp += NFSX_UNSIGNED;
 3918                         nfsm_clget_nolock;
 3919                         *tl = txdr_unsigned(nlen);
 3920                         bp += NFSX_UNSIGNED;
 3921 
 3922                         /* And loop around copying the name */
 3923                         xfer = nlen;
 3924                         cp = dp->d_name;
 3925                         while (xfer > 0) {
 3926                                 nfsm_clget_nolock;
 3927                                 if ((bp + xfer) > be)
 3928                                         tsiz = be - bp;
 3929                                 else
 3930                                         tsiz = xfer;
 3931                                 bcopy(cp, bp, tsiz);
 3932                                 bp += tsiz;
 3933                                 xfer -= tsiz;
 3934                                 if (xfer > 0)
 3935                                         cp += tsiz;
 3936                         }
 3937                         /* And null pad to an int32_t boundary. */
 3938                         for (i = 0; i < rem; i++)
 3939                                 *bp++ = '\0';
 3940 
 3941                         /*
 3942                          * Now copy the flrep structure out.
 3943                          */
 3944                         xfer = sizeof (struct flrep);
 3945                         cp = (caddr_t)&fl;
 3946                         while (xfer > 0) {
 3947                                 nfsm_clget_nolock;
 3948                                 if ((bp + xfer) > be)
 3949                                         tsiz = be - bp;
 3950                                 else
 3951                                         tsiz = xfer;
 3952                                 bcopy(cp, bp, tsiz);
 3953                                 bp += tsiz;
 3954                                 xfer -= tsiz;
 3955                                 if (xfer > 0)
 3956                                         cp += tsiz;
 3957                         }
 3958                 }
 3959 invalid:
 3960                 NFSD_UNLOCK_ASSERT();
 3961                 cpos += dp->d_reclen;
 3962                 dp = (struct dirent *)cpos;
 3963                 cookiep++;
 3964                 ncookies--;
 3965         }
 3966         vrele(vp);
 3967         mtx_unlock(&Giant);     /* VFS */
 3968         vp = NULL;
 3969         nfsm_clget_nolock;
 3970         *tl = nfsrv_nfs_false;
 3971         bp += NFSX_UNSIGNED;
 3972         NFSD_LOCK();
 3973         nfsm_clget;
 3974         if (eofflag)
 3975                 *tl = nfsrv_nfs_true;
 3976         else
 3977                 *tl = nfsrv_nfs_false;
 3978         bp += NFSX_UNSIGNED;
 3979         if (mp != mb) {
 3980                 if (bp < be)
 3981                         mp->m_len = bp - mtod(mp, caddr_t);
 3982         } else
 3983                 mp->m_len += bp - bpos;
 3984         FREE((caddr_t)cookies, M_TEMP);
 3985         FREE((caddr_t)rbuf, M_TEMP);
 3986 nfsmout:
 3987         NFSD_LOCK_ASSERT();
 3988         if (vp) {
 3989                 NFSD_UNLOCK();
 3990                 mtx_lock(&Giant);       /* VFS */
 3991                 vrele(vp);
 3992                 mtx_unlock(&Giant);     /* VFS */
 3993                 NFSD_LOCK();
 3994         }
 3995         return(error);
 3996 }
 3997 
 3998 /*
 3999  * nfs commit service
 4000  */
 4001 int
 4002 nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 4003     struct thread *td, struct mbuf **mrq)
 4004 {
 4005         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 4006         struct sockaddr *nam = nfsd->nd_nam;
 4007         caddr_t dpos = nfsd->nd_dpos;
 4008         struct ucred *cred = &nfsd->nd_cr;
 4009         struct vattr bfor, aft;
 4010         struct vnode *vp = NULL;
 4011         nfsfh_t nfh;
 4012         fhandle_t *fhp;
 4013         u_int32_t *tl;
 4014         caddr_t bpos;
 4015         int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt;
 4016         struct mbuf *mb, *mreq;
 4017         u_quad_t off;
 4018         struct mount *mp = NULL;
 4019         int v3 = (nfsd->nd_flag & ND_NFSV3);
 4020 
 4021         NFSD_LOCK_ASSERT();
 4022 
 4023         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 4024         if (!v3)
 4025                 panic("nfsrv_commit: v3 proc called on a v2 connection");
 4026         fhp = &nfh.fh_generic;
 4027         nfsm_srvmtofh(fhp);
 4028         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
 4029                 error = ESTALE;
 4030                 goto ereply;
 4031         }
 4032         NFSD_UNLOCK();
 4033         mtx_lock(&Giant);       /* VFS */
 4034         (void) vn_start_write(NULL, &mp, V_WAIT);
 4035         mtx_unlock(&Giant);     /* VFS */
 4036         NFSD_LOCK();
 4037         tl = nfsm_dissect(u_int32_t *, 3 * NFSX_UNSIGNED);
 4038 
 4039         /*
 4040          * XXX At this time VOP_FSYNC() does not accept offset and byte
 4041          * count parameters, so these arguments are useless (someday maybe).
 4042          */
 4043         off = fxdr_hyper(tl);
 4044         tl += 2;
 4045         cnt = fxdr_unsigned(int, *tl);
 4046         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
 4047         if (error) {
 4048                 nfsm_reply(2 * NFSX_UNSIGNED);
 4049                 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
 4050                 error = 0;
 4051                 goto nfsmout;
 4052         }
 4053         NFSD_UNLOCK();
 4054         mtx_lock(&Giant);       /* VFS */
 4055         for_ret = VOP_GETATTR(vp, &bfor, cred, td);
 4056 
 4057         if (cnt > MAX_COMMIT_COUNT) {
 4058                 /*
 4059                  * Give up and do the whole thing
 4060                  */
 4061                 if (vp->v_object &&
 4062                    (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
 4063                         VM_OBJECT_LOCK(vp->v_object);
 4064                         vm_object_page_clean(vp->v_object, 0, 0, OBJPC_SYNC);
 4065                         VM_OBJECT_UNLOCK(vp->v_object);
 4066                 }
 4067                 error = VOP_FSYNC(vp, cred, MNT_WAIT, td);
 4068         } else {
 4069                 /*
 4070                  * Locate and synchronously write any buffers that fall
 4071                  * into the requested range.  Note:  we are assuming that
 4072                  * f_iosize is a power of 2.
 4073                  */
 4074                 int iosize = vp->v_mount->mnt_stat.f_iosize;
 4075                 int iomask = iosize - 1;
 4076                 int s;
 4077                 daddr_t lblkno;
 4078 
 4079                 /*
 4080                  * Align to iosize boundry, super-align to page boundry.
 4081                  */
 4082                 if (off & iomask) {
 4083                         cnt += off & iomask;
 4084                         off &= ~(u_quad_t)iomask;
 4085                 }
 4086                 if (off & PAGE_MASK) {
 4087                         cnt += off & PAGE_MASK;
 4088                         off &= ~(u_quad_t)PAGE_MASK;
 4089                 }
 4090                 lblkno = off / iosize;
 4091 
 4092                 if (vp->v_object &&
 4093                    (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
 4094                         VM_OBJECT_LOCK(vp->v_object);
 4095                         vm_object_page_clean(vp->v_object, off / PAGE_SIZE, (cnt + PAGE_MASK) / PAGE_SIZE, OBJPC_SYNC);
 4096                         VM_OBJECT_UNLOCK(vp->v_object);
 4097                 }
 4098 
 4099                 s = splbio();
 4100                 VI_LOCK(vp);
 4101                 while (cnt > 0) {
 4102                         struct buf *bp;
 4103 
 4104                         /*
 4105                          * If we have a buffer and it is marked B_DELWRI we
 4106                          * have to lock and write it.  Otherwise the prior
 4107                          * write is assumed to have already been committed.
 4108                          *
 4109                          * gbincore() can return invalid buffers now so we
 4110                          * have to check that bit as well (though B_DELWRI
 4111                          * should not be set if B_INVAL is set there could be
 4112                          * a race here since we haven't locked the buffer).
 4113                          */
 4114                         if ((bp = gbincore(vp, lblkno)) != NULL) {
 4115                                 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL |
 4116                                     LK_INTERLOCK, VI_MTX(vp)) == ENOLCK) {
 4117                                         VI_LOCK(vp);
 4118                                         continue; /* retry */
 4119                                 }
 4120                                 if ((bp->b_flags & (B_DELWRI|B_INVAL)) ==
 4121                                     B_DELWRI) {
 4122                                         bremfree(bp);
 4123                                         bp->b_flags &= ~B_ASYNC;
 4124                                         bwrite(bp);
 4125                                         ++nfs_commit_miss;
 4126                                 } else
 4127                                         BUF_UNLOCK(bp);
 4128                                 VI_LOCK(vp);
 4129                         }
 4130                         ++nfs_commit_blks;
 4131                         if (cnt < iosize)
 4132                                 break;
 4133                         cnt -= iosize;
 4134                         ++lblkno;
 4135                 }
 4136                 VI_UNLOCK(vp);
 4137                 splx(s);
 4138         }
 4139 
 4140         aft_ret = VOP_GETATTR(vp, &aft, cred, td);
 4141         vput(vp);
 4142         mtx_unlock(&Giant);     /* VFS */
 4143         vp = NULL;
 4144         NFSD_LOCK();
 4145 ereply:
 4146         NFSD_LOCK_ASSERT();
 4147         nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF);
 4148         nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
 4149         if (!error) {
 4150                 tl = nfsm_build(u_int32_t *, NFSX_V3WRITEVERF);
 4151                 if (nfsver.tv_sec == 0)
 4152                         nfsver = boottime;
 4153                 *tl++ = txdr_unsigned(nfsver.tv_sec);
 4154                 *tl = txdr_unsigned(nfsver.tv_usec);
 4155         } else {
 4156                 error = 0;
 4157         }
 4158 nfsmout:
 4159         NFSD_LOCK_ASSERT();
 4160         NFSD_UNLOCK();
 4161         mtx_lock(&Giant);       /* VFS */
 4162         if (vp)
 4163                 vput(vp);
 4164         vn_finished_write(mp);
 4165         mtx_unlock(&Giant);     /* VFS */
 4166         NFSD_LOCK();
 4167         return(error);
 4168 }
 4169 
 4170 /*
 4171  * nfs statfs service
 4172  */
 4173 int
 4174 nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 4175     struct thread *td, struct mbuf **mrq)
 4176 {
 4177         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 4178         struct sockaddr *nam = nfsd->nd_nam;
 4179         caddr_t dpos = nfsd->nd_dpos;
 4180         struct ucred *cred = &nfsd->nd_cr;
 4181         struct statfs *sf;
 4182         struct nfs_statfs *sfp;
 4183         caddr_t bpos;
 4184         int error = 0, rdonly, getret = 1;
 4185         int v3 = (nfsd->nd_flag & ND_NFSV3);
 4186         struct mbuf *mb, *mreq;
 4187         struct vnode *vp = NULL;
 4188         struct vattr at;
 4189         nfsfh_t nfh;
 4190         fhandle_t *fhp;
 4191         struct statfs statfs;
 4192         u_quad_t tval;
 4193 
 4194         NFSD_LOCK_ASSERT();
 4195 
 4196         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 4197         fhp = &nfh.fh_generic;
 4198         nfsm_srvmtofh(fhp);
 4199         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
 4200         if (error) {
 4201                 nfsm_reply(NFSX_UNSIGNED);
 4202                 if (v3)
 4203                         nfsm_srvpostop_attr(getret, &at);
 4204                 error = 0;
 4205                 goto nfsmout;
 4206         }
 4207         sf = &statfs;
 4208         NFSD_UNLOCK();
 4209         mtx_lock(&Giant);       /* VFS */
 4210         error = VFS_STATFS(vp->v_mount, sf, td);
 4211         getret = VOP_GETATTR(vp, &at, cred, td);
 4212         vput(vp);
 4213         mtx_unlock(&Giant);     /* VFS */
 4214         vp = NULL;
 4215         NFSD_LOCK();
 4216         nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3));
 4217         if (v3)
 4218                 nfsm_srvpostop_attr(getret, &at);
 4219         if (error) {
 4220                 error = 0;
 4221                 goto nfsmout;
 4222         }
 4223         sfp = nfsm_build(struct nfs_statfs *, NFSX_STATFS(v3));
 4224         if (v3) {
 4225                 tval = (u_quad_t)sf->f_blocks;
 4226                 tval *= (u_quad_t)sf->f_bsize;
 4227                 txdr_hyper(tval, &sfp->sf_tbytes);
 4228                 tval = (u_quad_t)sf->f_bfree;
 4229                 tval *= (u_quad_t)sf->f_bsize;
 4230                 txdr_hyper(tval, &sfp->sf_fbytes);
 4231                 /*
 4232                  * Don't send negative values for available space,
 4233                  * since this field is unsigned in the NFS protocol.
 4234                  * Otherwise, the client would see absurdly high
 4235                  * numbers for free space.
 4236                  */
 4237                 if (sf->f_bavail < 0)
 4238                         tval = 0;
 4239                 else
 4240                         tval = (u_quad_t)sf->f_bavail;
 4241                 tval *= (u_quad_t)sf->f_bsize;
 4242                 txdr_hyper(tval, &sfp->sf_abytes);
 4243                 sfp->sf_tfiles.nfsuquad[0] = 0;
 4244                 sfp->sf_tfiles.nfsuquad[1] = txdr_unsigned(sf->f_files);
 4245                 sfp->sf_ffiles.nfsuquad[0] = 0;
 4246                 sfp->sf_ffiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
 4247                 sfp->sf_afiles.nfsuquad[0] = 0;
 4248                 sfp->sf_afiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
 4249                 sfp->sf_invarsec = 0;
 4250         } else {
 4251                 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
 4252                 sfp->sf_bsize = txdr_unsigned(sf->f_bsize);
 4253                 sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
 4254                 sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
 4255                 if (sf->f_bavail < 0)
 4256                         sfp->sf_bavail = 0;
 4257                 else
 4258                         sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
 4259         }
 4260 nfsmout:
 4261         NFSD_LOCK_ASSERT();
 4262         if (vp) {
 4263                 NFSD_UNLOCK();
 4264                 mtx_lock(&Giant);       /* VFS */
 4265                 vput(vp);
 4266                 mtx_unlock(&Giant);     /* VFS */
 4267                 NFSD_LOCK();
 4268         }
 4269         return(error);
 4270 }
 4271 
 4272 /*
 4273  * nfs fsinfo service
 4274  */
 4275 int
 4276 nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 4277     struct thread *td, struct mbuf **mrq)
 4278 {
 4279         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 4280         struct sockaddr *nam = nfsd->nd_nam;
 4281         caddr_t dpos = nfsd->nd_dpos;
 4282         struct ucred *cred = &nfsd->nd_cr;
 4283         struct nfsv3_fsinfo *sip;
 4284         caddr_t bpos;
 4285         int error = 0, rdonly, getret = 1, pref;
 4286         struct mbuf *mb, *mreq;
 4287         struct vnode *vp = NULL;
 4288         struct vattr at;
 4289         nfsfh_t nfh;
 4290         fhandle_t *fhp;
 4291         u_quad_t maxfsize;
 4292         struct statfs sb;
 4293         int v3 = (nfsd->nd_flag & ND_NFSV3);
 4294 
 4295         NFSD_LOCK_ASSERT();
 4296 
 4297         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 4298         if (!v3)
 4299                 panic("nfsrv_fsinfo: v3 proc called on a v2 connection");
 4300         fhp = &nfh.fh_generic;
 4301         nfsm_srvmtofh(fhp);
 4302         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
 4303         if (error) {
 4304                 nfsm_reply(NFSX_UNSIGNED);
 4305                 nfsm_srvpostop_attr(getret, &at);
 4306                 error = 0;
 4307                 goto nfsmout;
 4308         }
 4309 
 4310         NFSD_UNLOCK();
 4311         mtx_lock(&Giant);       /* VFS */
 4312         /* XXX Try to make a guess on the max file size. */
 4313         VFS_STATFS(vp->v_mount, &sb, td);
 4314         maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1;
 4315 
 4316         getret = VOP_GETATTR(vp, &at, cred, td);
 4317         vput(vp);
 4318         mtx_unlock(&Giant);     /* VFS */
 4319         vp = NULL;
 4320         NFSD_LOCK();
 4321         nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO);
 4322         nfsm_srvpostop_attr(getret, &at);
 4323         sip = nfsm_build(struct nfsv3_fsinfo *, NFSX_V3FSINFO);
 4324 
 4325         /*
 4326          * XXX
 4327          * There should be filesystem VFS OP(s) to get this information.
 4328          * For now, assume ufs.
 4329          */
 4330         if (slp->ns_so->so_type == SOCK_DGRAM)
 4331                 pref = NFS_MAXDGRAMDATA;
 4332         else
 4333                 pref = NFS_MAXDATA;
 4334         sip->fs_rtmax = txdr_unsigned(pref);
 4335         sip->fs_rtpref = txdr_unsigned(pref);
 4336         sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE);
 4337         sip->fs_wtmax = txdr_unsigned(pref);
 4338         sip->fs_wtpref = txdr_unsigned(pref);
 4339         sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE);
 4340         sip->fs_dtpref = txdr_unsigned(pref);
 4341         txdr_hyper(maxfsize, &sip->fs_maxfilesize);
 4342         sip->fs_timedelta.nfsv3_sec = 0;
 4343         sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1);
 4344         sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK |
 4345                 NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS |
 4346                 NFSV3FSINFO_CANSETTIME);
 4347 nfsmout:
 4348         NFSD_LOCK_ASSERT();
 4349         if (vp) {
 4350                 NFSD_UNLOCK();
 4351                 mtx_lock(&Giant);       /* VFS */
 4352                 vput(vp);
 4353                 mtx_unlock(&Giant);     /* VFS */
 4354                 NFSD_LOCK();
 4355         }
 4356         return(error);
 4357 }
 4358 
 4359 /*
 4360  * nfs pathconf service
 4361  */
 4362 int
 4363 nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 4364     struct thread *td, struct mbuf **mrq)
 4365 {
 4366         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 4367         struct sockaddr *nam = nfsd->nd_nam;
 4368         caddr_t dpos = nfsd->nd_dpos;
 4369         struct ucred *cred = &nfsd->nd_cr;
 4370         struct nfsv3_pathconf *pc;
 4371         caddr_t bpos;
 4372         int error = 0, rdonly, getret = 1;
 4373         register_t linkmax, namemax, chownres, notrunc;
 4374         struct mbuf *mb, *mreq;
 4375         struct vnode *vp = NULL;
 4376         struct vattr at;
 4377         nfsfh_t nfh;
 4378         fhandle_t *fhp;
 4379         int v3 = (nfsd->nd_flag & ND_NFSV3);
 4380 
 4381         NFSD_LOCK_ASSERT();
 4382 
 4383         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 4384         if (!v3)
 4385                 panic("nfsrv_pathconf: v3 proc called on a v2 connection");
 4386         fhp = &nfh.fh_generic;
 4387         nfsm_srvmtofh(fhp);
 4388         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
 4389         if (error) {
 4390                 nfsm_reply(NFSX_UNSIGNED);
 4391                 nfsm_srvpostop_attr(getret, &at);
 4392                 error = 0;
 4393                 goto nfsmout;
 4394         }
 4395         NFSD_UNLOCK();
 4396         mtx_lock(&Giant);       /* VFS */
 4397         error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax);
 4398         if (!error)
 4399                 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax);
 4400         if (!error)
 4401                 error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres);
 4402         if (!error)
 4403                 error = VOP_PATHCONF(vp, _PC_NO_TRUNC, &notrunc);
 4404         getret = VOP_GETATTR(vp, &at, cred, td);
 4405         vput(vp);
 4406         mtx_unlock(&Giant);     /* VFS */
 4407         vp = NULL;
 4408         NFSD_LOCK();
 4409         nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF);
 4410         nfsm_srvpostop_attr(getret, &at);
 4411         if (error) {
 4412                 error = 0;
 4413                 goto nfsmout;
 4414         }
 4415         pc = nfsm_build(struct nfsv3_pathconf *, NFSX_V3PATHCONF);
 4416 
 4417         pc->pc_linkmax = txdr_unsigned(linkmax);
 4418         pc->pc_namemax = txdr_unsigned(namemax);
 4419         pc->pc_notrunc = txdr_unsigned(notrunc);
 4420         pc->pc_chownrestricted = txdr_unsigned(chownres);
 4421 
 4422         /*
 4423          * These should probably be supported by VOP_PATHCONF(), but
 4424          * until msdosfs is exportable (why would you want to?), the
 4425          * Unix defaults should be ok.
 4426          */
 4427         pc->pc_caseinsensitive = nfsrv_nfs_false;
 4428         pc->pc_casepreserving = nfsrv_nfs_true;
 4429 nfsmout:
 4430         NFSD_LOCK_ASSERT();
 4431         if (vp) {
 4432                 NFSD_UNLOCK();
 4433                 mtx_lock(&Giant);       /* VFS */
 4434                 vput(vp);
 4435                 mtx_unlock(&Giant);     /* VFS */
 4436                 NFSD_LOCK();
 4437         }
 4438         return(error);
 4439 }
 4440 
 4441 /*
 4442  * Null operation, used by clients to ping server
 4443  */
 4444 /* ARGSUSED */
 4445 int
 4446 nfsrv_null(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 4447     struct thread *td, struct mbuf **mrq)
 4448 {
 4449         struct mbuf *mrep = nfsd->nd_mrep;
 4450         caddr_t bpos;
 4451         int error = NFSERR_RETVOID;
 4452         struct mbuf *mb, *mreq;
 4453 
 4454         NFSD_LOCK_ASSERT();
 4455 
 4456         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 4457         nfsm_reply(0);
 4458 nfsmout:
 4459         NFSD_LOCK_ASSERT();
 4460         return (error);
 4461 }
 4462 
 4463 /*
 4464  * No operation, used for obsolete procedures
 4465  */
 4466 /* ARGSUSED */
 4467 int
 4468 nfsrv_noop(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 4469     struct thread *td, struct mbuf **mrq)
 4470 {
 4471         struct mbuf *mrep = nfsd->nd_mrep;
 4472         caddr_t bpos;
 4473         int error;
 4474         struct mbuf *mb, *mreq;
 4475 
 4476         NFSD_LOCK_ASSERT();
 4477 
 4478         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 4479         if (nfsd->nd_repstat)
 4480                 error = nfsd->nd_repstat;
 4481         else
 4482                 error = EPROCUNAVAIL;
 4483         nfsm_reply(0);
 4484         error = 0;
 4485 nfsmout:
 4486         NFSD_LOCK_ASSERT();
 4487         return (error);
 4488 }
 4489 
 4490 /*
 4491  * Perform access checking for vnodes obtained from file handles that would
 4492  * refer to files already opened by a Unix client. You cannot just use
 4493  * vn_writechk() and VOP_ACCESS() for two reasons.
 4494  * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write
 4495  *     case.
 4496  * 2 - The owner is to be given access irrespective of mode bits for some
 4497  *     operations, so that processes that chmod after opening a file don't
 4498  *     break. I don't like this because it opens a security hole, but since
 4499  *     the nfs server opens a security hole the size of a barn door anyhow,
 4500  *     what the heck.
 4501  *
 4502  * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS()
 4503  * will return EPERM instead of EACCESS. EPERM is always an error.
 4504  *
 4505  * There are two versions: one to be called while holding Giant (which is
 4506  * needed due to use of VFS), and the other called with the NFS server lock
 4507  * (which will be dropped and reacquired).  This is necessary because
 4508  * nfsrv_access checks are required from both classes of contexts.
 4509  */
 4510 static int
 4511 nfsrv_access_withgiant(struct vnode *vp, int flags, struct ucred *cred,
 4512     int rdonly, struct thread *td, int override)
 4513 {
 4514         struct vattr vattr;
 4515         int error;
 4516 
 4517         GIANT_REQUIRED;
 4518 
 4519         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 4520 
 4521         if (flags & VWRITE) {
 4522                 /* Just vn_writechk() changed to check rdonly */
 4523                 /*
 4524                  * Disallow write attempts on read-only filesystems;
 4525                  * unless the file is a socket or a block or character
 4526                  * device resident on the filesystem.
 4527                  */
 4528                 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
 4529                         switch (vp->v_type) {
 4530                         case VREG:
 4531                         case VDIR:
 4532                         case VLNK:
 4533                                 return (EROFS);
 4534                         default:
 4535                                 break;
 4536                         }
 4537                 }
 4538                 /*
 4539                  * If there's shared text associated with
 4540                  * the inode, we can't allow writing.
 4541                  */
 4542                 if (vp->v_vflag & VV_TEXT)
 4543                         return (ETXTBSY);
 4544         }
 4545 
 4546         error = VOP_GETATTR(vp, &vattr, cred, td);
 4547         if (error)
 4548                 return (error);
 4549         error = VOP_ACCESS(vp, flags, cred, td);
 4550         /*
 4551          * Allow certain operations for the owner (reads and writes
 4552          * on files that are already open).
 4553          */
 4554         if (override && error == EACCES && cred->cr_uid == vattr.va_uid)
 4555                 error = 0;
 4556         return (error);
 4557 }
 4558 
 4559 static int
 4560 nfsrv_access(struct vnode *vp, int flags, struct ucred *cred, int rdonly,
 4561     struct thread *td, int override)
 4562 {
 4563         int error;
 4564 
 4565         NFSD_LOCK_ASSERT();
 4566 
 4567         NFSD_UNLOCK();
 4568         mtx_lock(&Giant);       /* VFS */
 4569         error = nfsrv_access_withgiant(vp, flags, cred, rdonly, td, override);
 4570         mtx_unlock(&Giant);     /* VFS */
 4571         NFSD_LOCK();
 4572         return (error);
 4573 }

Cache object: 19a47bc83cad292e034ca89cd248e882


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