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: releng/5.3/sys/nfsserver/nfs_serv.c 139697 2005-01-05 03:35:00Z kensmith $");
   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  * NFS write service with write gathering support. Called when
 1305  * nfsrvw_procrastinate > 0.
 1306  * See: Chet Juszczak, "Improving the Write Performance of an NFS Server",
 1307  * in Proc. of the Winter 1994 Usenix Conference, pg. 247-259, San Franscisco,
 1308  * Jan. 1994.
 1309  */
 1310 int
 1311 nfsrv_writegather(struct nfsrv_descript **ndp, struct nfssvc_sock *slp,
 1312     struct thread *td, struct mbuf **mrq)
 1313 {
 1314         struct iovec *ivp;
 1315         struct mbuf *mp;
 1316         struct nfsrv_descript *wp, *nfsd, *owp, *swp;
 1317         struct nfs_fattr *fp;
 1318         int i;
 1319         struct iovec *iov;
 1320         struct nfsrvw_delayhash *wpp;
 1321         struct ucred *cred;
 1322         struct vattr va, forat;
 1323         u_int32_t *tl;
 1324         caddr_t bpos, dpos;
 1325         int error = 0, rdonly, len, forat_ret = 1;
 1326         int ioflags, aftat_ret = 1, s, adjust, v3, zeroing;
 1327         struct mbuf *mb, *mreq, *mrep, *md;
 1328         struct vnode *vp = NULL;
 1329         struct uio io, *uiop = &io;
 1330         u_quad_t cur_usec;
 1331         struct mount *mntp = NULL;
 1332 
 1333         NFSD_LOCK_ASSERT();
 1334 
 1335         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 1336 #ifndef nolint
 1337         i = 0;
 1338         len = 0;
 1339 #endif
 1340         *mrq = NULL;
 1341         if (*ndp) {
 1342             nfsd = *ndp;
 1343             *ndp = NULL;
 1344             mrep = nfsd->nd_mrep;
 1345             md = nfsd->nd_md;
 1346             dpos = nfsd->nd_dpos;
 1347             cred = &nfsd->nd_cr;
 1348             v3 = (nfsd->nd_flag & ND_NFSV3);
 1349             LIST_INIT(&nfsd->nd_coalesce);
 1350             nfsd->nd_mreq = NULL;
 1351             nfsd->nd_stable = NFSV3WRITE_FILESYNC;
 1352             cur_usec = nfs_curusec();
 1353             nfsd->nd_time = cur_usec +
 1354                 (v3 ? nfsrvw_procrastinate_v3 : nfsrvw_procrastinate);
 1355 
 1356             /*
 1357              * Now, get the write header..
 1358              */
 1359             nfsm_srvmtofh(&nfsd->nd_fh);
 1360             if (v3) {
 1361                 tl = nfsm_dissect(u_int32_t *, 5 * NFSX_UNSIGNED);
 1362                 nfsd->nd_off = fxdr_hyper(tl);
 1363                 tl += 3;
 1364                 nfsd->nd_stable = fxdr_unsigned(int, *tl++);
 1365             } else {
 1366                 tl = nfsm_dissect(u_int32_t *, 4 * NFSX_UNSIGNED);
 1367                 nfsd->nd_off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
 1368                 tl += 2;
 1369                 if (nfs_async)
 1370                         nfsd->nd_stable = NFSV3WRITE_UNSTABLE;
 1371             }
 1372             len = fxdr_unsigned(int32_t, *tl);
 1373             nfsd->nd_len = len;
 1374             nfsd->nd_eoff = nfsd->nd_off + len;
 1375 
 1376             /*
 1377              * Trim the header out of the mbuf list and trim off any trailing
 1378              * junk so that the mbuf list has only the write data.
 1379              */
 1380             zeroing = 1;
 1381             i = 0;
 1382             mp = mrep;
 1383             while (mp) {
 1384                 if (mp == md) {
 1385                     zeroing = 0;
 1386                     adjust = dpos - mtod(mp, caddr_t);
 1387                     mp->m_len -= adjust;
 1388                     if (mp->m_len > 0 && adjust > 0)
 1389                         mp->m_data += adjust;
 1390                 }
 1391                 if (zeroing)
 1392                     mp->m_len = 0;
 1393                 else {
 1394                     i += mp->m_len;
 1395                     if (i > len) {
 1396                         mp->m_len -= (i - len);
 1397                         zeroing = 1;
 1398                     }
 1399                 }
 1400                 mp = mp->m_next;
 1401             }
 1402             if (len > NFS_MAXDATA || len < 0  || i < len) {
 1403 nfsmout:
 1404                 NFSD_LOCK_ASSERT();
 1405                 m_freem(mrep);
 1406                 error = EIO;
 1407                 nfsm_writereply(2 * NFSX_UNSIGNED);
 1408                 if (v3)
 1409                     nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
 1410                 nfsd->nd_mreq = mreq;
 1411                 nfsd->nd_mrep = NULL;
 1412                 nfsd->nd_time = 0;
 1413             }
 1414 
 1415             /*
 1416              * Add this entry to the hash and time queues.
 1417              */
 1418             s = splsoftclock();
 1419             owp = NULL;
 1420             wp = LIST_FIRST(&slp->ns_tq);
 1421             while (wp && wp->nd_time < nfsd->nd_time) {
 1422                 owp = wp;
 1423                 wp = LIST_NEXT(wp, nd_tq);
 1424             }
 1425             NFS_DPF(WG, ("Q%03x", nfsd->nd_retxid & 0xfff));
 1426             if (owp) {
 1427                 LIST_INSERT_AFTER(owp, nfsd, nd_tq);
 1428             } else {
 1429                 LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
 1430             }
 1431             if (nfsd->nd_mrep) {
 1432                 wpp = NWDELAYHASH(slp, nfsd->nd_fh.fh_fid.fid_data);
 1433                 owp = NULL;
 1434                 wp = LIST_FIRST(wpp);
 1435                 while (wp &&
 1436                     bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh, NFSX_V3FH)){
 1437                     owp = wp;
 1438                     wp = LIST_NEXT(wp, nd_hash);
 1439                 }
 1440                 while (wp && wp->nd_off < nfsd->nd_off &&
 1441                     !bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh, NFSX_V3FH)) {
 1442                     owp = wp;
 1443                     wp = LIST_NEXT(wp, nd_hash);
 1444                 }
 1445                 if (owp) {
 1446                     LIST_INSERT_AFTER(owp, nfsd, nd_hash);
 1447 
 1448                     /*
 1449                      * Search the hash list for overlapping entries and
 1450                      * coalesce.
 1451                      */
 1452                     for(; nfsd && NFSW_CONTIG(owp, nfsd); nfsd = wp) {
 1453                         wp = LIST_NEXT(nfsd, nd_hash);
 1454                         if (NFSW_SAMECRED(owp, nfsd))
 1455                             nfsrvw_coalesce(owp, nfsd);
 1456                     }
 1457                 } else {
 1458                     LIST_INSERT_HEAD(wpp, nfsd, nd_hash);
 1459                 }
 1460             }
 1461             splx(s);
 1462         }
 1463 
 1464         /*
 1465          * Now, do VOP_WRITE()s for any one(s) that need to be done now
 1466          * and generate the associated reply mbuf list(s).
 1467          */
 1468 loop1:
 1469         cur_usec = nfs_curusec();
 1470         s = splsoftclock();
 1471         for (nfsd = LIST_FIRST(&slp->ns_tq); nfsd; nfsd = owp) {
 1472                 owp = LIST_NEXT(nfsd, nd_tq);
 1473                 if (nfsd->nd_time > cur_usec)
 1474                     break;
 1475                 if (nfsd->nd_mreq)
 1476                     continue;
 1477                 NFS_DPF(WG, ("P%03x", nfsd->nd_retxid & 0xfff));
 1478                 LIST_REMOVE(nfsd, nd_tq);
 1479                 LIST_REMOVE(nfsd, nd_hash);
 1480                 splx(s);
 1481                 mrep = nfsd->nd_mrep;
 1482                 nfsd->nd_mrep = NULL;
 1483                 cred = &nfsd->nd_cr;
 1484                 v3 = (nfsd->nd_flag & ND_NFSV3);
 1485                 forat_ret = aftat_ret = 1;
 1486                 error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &vp, cred, slp,
 1487                     nfsd->nd_nam, &rdonly, TRUE);
 1488                 if (!error) {
 1489                     if (v3) {
 1490                         NFSD_UNLOCK();
 1491                         mtx_lock(&Giant);       /* VFS */
 1492                         forat_ret = VOP_GETATTR(vp, &forat, cred, td);
 1493                         mtx_unlock(&Giant);     /* VFS */
 1494                         NFSD_LOCK();
 1495                     }
 1496                     if (vp->v_type != VREG) {
 1497                         if (v3)
 1498                             error = EINVAL;
 1499                         else
 1500                             error = (vp->v_type == VDIR) ? EISDIR : EACCES;
 1501                     }
 1502                 } else {
 1503                     vp = NULL;
 1504                 }
 1505                 NFSD_UNLOCK();
 1506                 mtx_lock(&Giant);       /* VFS */
 1507                 if (!error)
 1508                     error = nfsrv_access_withgiant(vp, VWRITE, cred, rdonly,
 1509                         td, 1);
 1510                 if (nfsd->nd_stable == NFSV3WRITE_UNSTABLE)
 1511                     ioflags = IO_NODELOCKED;
 1512                 else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC)
 1513                     ioflags = (IO_SYNC | IO_NODELOCKED);
 1514                 else
 1515                     ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
 1516                 uiop->uio_rw = UIO_WRITE;
 1517                 uiop->uio_segflg = UIO_SYSSPACE;
 1518                 uiop->uio_td = NULL;
 1519                 uiop->uio_offset = nfsd->nd_off;
 1520                 uiop->uio_resid = nfsd->nd_eoff - nfsd->nd_off;
 1521                 if (uiop->uio_resid > 0) {
 1522                     mp = mrep;
 1523                     i = 0;
 1524                     while (mp) {
 1525                         if (mp->m_len > 0)
 1526                             i++;
 1527                         mp = mp->m_next;
 1528                     }
 1529                     uiop->uio_iovcnt = i;
 1530                     MALLOC(iov, struct iovec *, i * sizeof (struct iovec),
 1531                         M_TEMP, M_WAITOK);
 1532                     uiop->uio_iov = ivp = iov;
 1533                     mp = mrep;
 1534                     while (mp) {
 1535                         if (mp->m_len > 0) {
 1536                             ivp->iov_base = mtod(mp, caddr_t);
 1537                             ivp->iov_len = mp->m_len;
 1538                             ivp++;
 1539                         }
 1540                         mp = mp->m_next;
 1541                     }
 1542                     if (!error) {
 1543                         if (vn_start_write(vp, &mntp, V_NOWAIT) != 0) {
 1544                             VOP_UNLOCK(vp, 0, td);
 1545                             error = vn_start_write(NULL, &mntp, V_WAIT);
 1546                             vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 1547                         }
 1548                     }
 1549                     if (!error) {
 1550                         error = VOP_WRITE(vp, uiop, ioflags, cred);
 1551                         /* XXXRW: unlocked write. */
 1552                         nfsrvstats.srvvop_writes++;
 1553                         vn_finished_write(mntp);
 1554                     }
 1555                     FREE((caddr_t)iov, M_TEMP);
 1556                 }
 1557                 m_freem(mrep);
 1558                 if (vp) {
 1559                     aftat_ret = VOP_GETATTR(vp, &va, cred, td);
 1560                     vput(vp);
 1561                     vp = NULL;
 1562                 }
 1563                 mtx_unlock(&Giant);     /* VFS */
 1564                 NFSD_LOCK();
 1565 
 1566                 /*
 1567                  * Loop around generating replies for all write rpcs that have
 1568                  * now been completed.
 1569                  */
 1570                 swp = nfsd;
 1571                 do {
 1572                     NFS_DPF(WG, ("R%03x", nfsd->nd_retxid & 0xfff));
 1573                     if (error) {
 1574                         nfsm_writereply(NFSX_WCCDATA(v3));
 1575                         if (v3) {
 1576                             nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
 1577                         }
 1578                     } else {
 1579                         nfsm_writereply(NFSX_PREOPATTR(v3) +
 1580                             NFSX_POSTOPORFATTR(v3) + 2 * NFSX_UNSIGNED +
 1581                             NFSX_WRITEVERF(v3));
 1582                         if (v3) {
 1583                             nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
 1584                             tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
 1585                             *tl++ = txdr_unsigned(nfsd->nd_len);
 1586                             *tl++ = txdr_unsigned(swp->nd_stable);
 1587                             /*
 1588                              * Actually, there is no need to txdr these fields,
 1589                              * but it may make the values more human readable,
 1590                              * for debugging purposes.
 1591                              */
 1592                             if (nfsver.tv_sec == 0)
 1593                                     nfsver = boottime;
 1594                             *tl++ = txdr_unsigned(nfsver.tv_sec);
 1595                             *tl = txdr_unsigned(nfsver.tv_usec);
 1596                         } else {
 1597                             fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
 1598                             nfsm_srvfillattr(&va, fp);
 1599                         }
 1600                     }
 1601                     nfsd->nd_mreq = mreq;
 1602                     if (nfsd->nd_mrep)
 1603                         panic("nfsrv_write: nd_mrep not free");
 1604 
 1605                     /*
 1606                      * Done. Put it at the head of the timer queue so that
 1607                      * the final phase can return the reply.
 1608                      */
 1609                     s = splsoftclock();
 1610                     if (nfsd != swp) {
 1611                         nfsd->nd_time = 0;
 1612                         LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
 1613                     }
 1614                     nfsd = LIST_FIRST(&swp->nd_coalesce);
 1615                     if (nfsd) {
 1616                         LIST_REMOVE(nfsd, nd_tq);
 1617                     }
 1618                     splx(s);
 1619                 } while (nfsd);
 1620                 s = splsoftclock();
 1621                 swp->nd_time = 0;
 1622                 LIST_INSERT_HEAD(&slp->ns_tq, swp, nd_tq);
 1623                 splx(s);
 1624                 goto loop1;
 1625         }
 1626         splx(s);
 1627 
 1628         /*
 1629          * Search for a reply to return.
 1630          */
 1631         s = splsoftclock();
 1632         LIST_FOREACH(nfsd, &slp->ns_tq, nd_tq)
 1633                 if (nfsd->nd_mreq) {
 1634                     NFS_DPF(WG, ("X%03x", nfsd->nd_retxid & 0xfff));
 1635                     LIST_REMOVE(nfsd, nd_tq);
 1636                     *mrq = nfsd->nd_mreq;
 1637                     *ndp = nfsd;
 1638                     break;
 1639                 }
 1640         splx(s);
 1641         return (0);
 1642 }
 1643 
 1644 /*
 1645  * Coalesce the write request nfsd into owp. To do this we must:
 1646  * - remove nfsd from the queues
 1647  * - merge nfsd->nd_mrep into owp->nd_mrep
 1648  * - update the nd_eoff and nd_stable for owp
 1649  * - put nfsd on owp's nd_coalesce list
 1650  * NB: Must be called at splsoftclock().
 1651  */
 1652 static void
 1653 nfsrvw_coalesce(struct nfsrv_descript *owp, struct nfsrv_descript *nfsd)
 1654 {
 1655         int overlap;
 1656         struct mbuf *mp;
 1657         struct nfsrv_descript *p;
 1658 
 1659         NFSD_LOCK_ASSERT();
 1660 
 1661         NFS_DPF(WG, ("C%03x-%03x",
 1662                      nfsd->nd_retxid & 0xfff, owp->nd_retxid & 0xfff));
 1663         LIST_REMOVE(nfsd, nd_hash);
 1664         LIST_REMOVE(nfsd, nd_tq);
 1665         if (owp->nd_eoff < nfsd->nd_eoff) {
 1666             overlap = owp->nd_eoff - nfsd->nd_off;
 1667             if (overlap < 0)
 1668                 panic("nfsrv_coalesce: bad off");
 1669             if (overlap > 0)
 1670                 m_adj(nfsd->nd_mrep, overlap);
 1671             mp = owp->nd_mrep;
 1672             while (mp->m_next)
 1673                 mp = mp->m_next;
 1674             mp->m_next = nfsd->nd_mrep;
 1675             owp->nd_eoff = nfsd->nd_eoff;
 1676         } else
 1677             m_freem(nfsd->nd_mrep);
 1678         nfsd->nd_mrep = NULL;
 1679         if (nfsd->nd_stable == NFSV3WRITE_FILESYNC)
 1680             owp->nd_stable = NFSV3WRITE_FILESYNC;
 1681         else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC &&
 1682             owp->nd_stable == NFSV3WRITE_UNSTABLE)
 1683             owp->nd_stable = NFSV3WRITE_DATASYNC;
 1684         LIST_INSERT_HEAD(&owp->nd_coalesce, nfsd, nd_tq);
 1685 
 1686         /*
 1687          * If nfsd had anything else coalesced into it, transfer them
 1688          * to owp, otherwise their replies will never get sent.
 1689          */
 1690         for (p = LIST_FIRST(&nfsd->nd_coalesce); p;
 1691              p = LIST_FIRST(&nfsd->nd_coalesce)) {
 1692             LIST_REMOVE(p, nd_tq);
 1693             LIST_INSERT_HEAD(&owp->nd_coalesce, p, nd_tq);
 1694         }
 1695 }
 1696 
 1697 /*
 1698  * nfs create service
 1699  * now does a truncate to 0 length via. setattr if it already exists
 1700  */
 1701 int
 1702 nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 1703     struct thread *td, struct mbuf **mrq)
 1704 {
 1705         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 1706         struct sockaddr *nam = nfsd->nd_nam;
 1707         caddr_t dpos = nfsd->nd_dpos;
 1708         struct ucred *cred = &nfsd->nd_cr;
 1709         struct nfs_fattr *fp;
 1710         struct vattr va, dirfor, diraft;
 1711         struct vattr *vap = &va;
 1712         struct nfsv2_sattr *sp;
 1713         u_int32_t *tl;
 1714         struct nameidata nd;
 1715         caddr_t bpos;
 1716         int error = 0, rdev, len, tsize, dirfor_ret = 1, diraft_ret = 1;
 1717         int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0;
 1718         caddr_t cp;
 1719         struct mbuf *mb, *mreq;
 1720         struct vnode *dirp = NULL;
 1721         nfsfh_t nfh;
 1722         fhandle_t *fhp;
 1723         u_quad_t tempsize;
 1724         u_char cverf[NFSX_V3CREATEVERF];
 1725         struct mount *mp = NULL;
 1726 
 1727         NFSD_LOCK_ASSERT();
 1728 
 1729         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 1730 #ifndef nolint
 1731         rdev = 0;
 1732 #endif
 1733         ndclear(&nd);
 1734 
 1735         fhp = &nfh.fh_generic;
 1736         nfsm_srvmtofh(fhp);
 1737         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
 1738                 error = ESTALE;
 1739                 goto ereply_locked;
 1740         }
 1741         NFSD_UNLOCK();
 1742         mtx_lock(&Giant);       /* VFS */
 1743         (void) vn_start_write(NULL, &mp, V_WAIT);
 1744         mtx_unlock(&Giant);     /* VFS */
 1745         NFSD_LOCK();
 1746         nfsm_srvnamesiz(len);
 1747 
 1748         nd.ni_cnd.cn_cred = cred;
 1749         nd.ni_cnd.cn_nameiop = CREATE;
 1750         nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
 1751 
 1752         /*
 1753          * Call namei and do initial cleanup to get a few things
 1754          * out of the way.  If we get an initial error we cleanup
 1755          * and return here to avoid special-casing the invalid nd
 1756          * structure through the rest of the case.  dirp may be
 1757          * set even if an error occurs, but the nd structure will not
 1758          * be valid at all if an error occurs so we have to invalidate it
 1759          * prior to calling nfsm_reply ( which might goto nfsmout ).
 1760          */
 1761         error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
 1762                 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
 1763         if (dirp && !v3) {
 1764                 NFSD_UNLOCK();
 1765                 mtx_lock(&Giant);       /* VFS */
 1766                 vrele(dirp);
 1767                 mtx_unlock(&Giant);     /* VFS */
 1768                 NFSD_LOCK();
 1769                 dirp = NULL;
 1770         }
 1771         if (error) {
 1772                 nfsm_reply(NFSX_WCCDATA(v3));
 1773                 if (v3)
 1774                         nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 1775                 error = 0;
 1776                 goto nfsmout;
 1777         }
 1778 
 1779         /*
 1780          * No error.  Continue.  State:
 1781          *
 1782          *      startdir        is valid ( we release this immediately )
 1783          *      dirp            may be valid
 1784          *      nd.ni_vp        may be valid
 1785          *      nd.ni_dvp       is valid
 1786          *
 1787          * The error state is set through the code and we may also do some
 1788          * opportunistic releasing of vnodes to avoid holding locks through
 1789          * NFS I/O.  The cleanup at the end is a catch-all
 1790          */
 1791 
 1792         VATTR_NULL(vap);
 1793         if (v3) {
 1794                 tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
 1795                 how = fxdr_unsigned(int, *tl);
 1796                 switch (how) {
 1797                 case NFSV3CREATE_GUARDED:
 1798                         if (nd.ni_vp) {
 1799                                 error = EEXIST;
 1800                                 break;
 1801                         }
 1802                         /* fall through */
 1803                 case NFSV3CREATE_UNCHECKED:
 1804                         nfsm_srvsattr(vap);
 1805                         break;
 1806                 case NFSV3CREATE_EXCLUSIVE:
 1807                         cp = nfsm_dissect(caddr_t, NFSX_V3CREATEVERF);
 1808                         bcopy(cp, cverf, NFSX_V3CREATEVERF);
 1809                         exclusive_flag = 1;
 1810                         break;
 1811                 };
 1812                 vap->va_type = VREG;
 1813         } else {
 1814                 sp = nfsm_dissect(struct nfsv2_sattr *, NFSX_V2SATTR);
 1815                 vap->va_type = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode));
 1816                 if (vap->va_type == VNON)
 1817                         vap->va_type = VREG;
 1818                 vap->va_mode = nfstov_mode(sp->sa_mode);
 1819                 switch (vap->va_type) {
 1820                 case VREG:
 1821                         tsize = fxdr_unsigned(int32_t, sp->sa_size);
 1822                         if (tsize != -1)
 1823                                 vap->va_size = (u_quad_t)tsize;
 1824                         break;
 1825                 case VCHR:
 1826                 case VBLK:
 1827                 case VFIFO:
 1828                         rdev = fxdr_unsigned(long, sp->sa_size);
 1829                         break;
 1830                 default:
 1831                         break;
 1832                 };
 1833         }
 1834 
 1835         /*
 1836          * Iff doesn't exist, create it
 1837          * otherwise just truncate to 0 length
 1838          *   should I set the mode too ?
 1839          *
 1840          * The only possible error we can have at this point is EEXIST.
 1841          * nd.ni_vp will also be non-NULL in that case.
 1842          */
 1843         NFSD_UNLOCK();
 1844         mtx_lock(&Giant);       /* VFS */
 1845         if (nd.ni_vp == NULL) {
 1846                 if (vap->va_mode == (mode_t)VNOVAL)
 1847                         vap->va_mode = 0;
 1848                 if (vap->va_type == VREG || vap->va_type == VSOCK) {
 1849                         error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
 1850                         if (error)
 1851                                 NDFREE(&nd, NDF_ONLY_PNBUF);
 1852                         else {
 1853                                 nfsrv_object_create(nd.ni_vp);
 1854                                 if (exclusive_flag) {
 1855                                         exclusive_flag = 0;
 1856                                         VATTR_NULL(vap);
 1857                                         bcopy(cverf, (caddr_t)&vap->va_atime,
 1858                                                 NFSX_V3CREATEVERF);
 1859                                         error = VOP_SETATTR(nd.ni_vp, vap, cred,
 1860                                                 td);
 1861                                 }
 1862                         }
 1863                 } else if (vap->va_type == VCHR || vap->va_type == VBLK ||
 1864                     vap->va_type == VFIFO) {
 1865                         /*
 1866                          * NFSv2-specific code for creating device nodes
 1867                          * and fifos.
 1868                          *
 1869                          * Handle SysV FIFO node special cases.  All other
 1870                          * devices require super user to access.
 1871                          */
 1872                         if (vap->va_type == VCHR && rdev == 0xffffffff)
 1873                                 vap->va_type = VFIFO;
 1874                         if (vap->va_type != VFIFO &&
 1875                             (error = suser_cred(cred, 0))) {
 1876                                 goto ereply;
 1877                         }
 1878                         vap->va_rdev = rdev;
 1879                         error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
 1880                         if (error) {
 1881                                 NDFREE(&nd, NDF_ONLY_PNBUF);
 1882                                 goto ereply;
 1883                         }
 1884                         vput(nd.ni_vp);
 1885                         nd.ni_vp = NULL;
 1886 
 1887                         /*
 1888                          * release dvp prior to lookup
 1889                          */
 1890                         vput(nd.ni_dvp);
 1891                         nd.ni_dvp = NULL;
 1892 
 1893                         /*
 1894                          * Setup for lookup.
 1895                          *
 1896                          * Even though LOCKPARENT was cleared, ni_dvp may
 1897                          * be garbage.
 1898                          */
 1899                         nd.ni_cnd.cn_nameiop = LOOKUP;
 1900                         nd.ni_cnd.cn_flags &= ~(LOCKPARENT);
 1901                         nd.ni_cnd.cn_thread = td;
 1902                         nd.ni_cnd.cn_cred = cred;
 1903 
 1904                         error = lookup(&nd);
 1905                         nd.ni_dvp = NULL;
 1906                         if (error)
 1907                                 goto ereply;
 1908 
 1909                         nfsrv_object_create(nd.ni_vp);
 1910                         if (nd.ni_cnd.cn_flags & ISSYMLINK) {
 1911                                 error = EINVAL;
 1912                                 goto ereply;
 1913                         }
 1914                 } else {
 1915                         error = ENXIO;
 1916                 }
 1917         } else {
 1918                 if (vap->va_size != -1) {
 1919                         error = nfsrv_access_withgiant(nd.ni_vp, VWRITE,
 1920                             cred, (nd.ni_cnd.cn_flags & RDONLY), td, 0);
 1921                         if (!error) {
 1922                                 tempsize = vap->va_size;
 1923                                 VATTR_NULL(vap);
 1924                                 vap->va_size = tempsize;
 1925                                 error = VOP_SETATTR(nd.ni_vp, vap, cred,
 1926                                          td);
 1927                         }
 1928                 }
 1929         }
 1930 
 1931         if (!error) {
 1932                 bzero((caddr_t)fhp, sizeof(nfh));
 1933                 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
 1934                 error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
 1935                 if (!error)
 1936                         error = VOP_GETATTR(nd.ni_vp, vap, cred, td);
 1937         }
 1938         if (v3) {
 1939                 if (exclusive_flag && !error &&
 1940                         bcmp(cverf, (caddr_t)&vap->va_atime, NFSX_V3CREATEVERF))
 1941                         error = EEXIST;
 1942                 if (dirp == nd.ni_dvp)
 1943                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
 1944                 else {
 1945                         /* Drop the other locks to avoid deadlock. */
 1946                         if (nd.ni_dvp) {
 1947                                 if (nd.ni_dvp == nd.ni_vp)
 1948                                         vrele(nd.ni_dvp);
 1949                                 else
 1950                                         vput(nd.ni_dvp);
 1951                         }
 1952                         if (nd.ni_vp)
 1953                                 vput(nd.ni_vp);
 1954                         nd.ni_dvp = NULL;
 1955                         nd.ni_vp = NULL;
 1956 
 1957                         vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
 1958                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
 1959                         VOP_UNLOCK(dirp, 0, td);
 1960                 }
 1961         }
 1962 ereply:
 1963         NFSD_UNLOCK_ASSERT();
 1964         mtx_unlock(&Giant);     /* VFS */
 1965         NFSD_LOCK();
 1966 ereply_locked:
 1967         NFSD_LOCK_ASSERT();
 1968         nfsm_reply(NFSX_SRVFH(v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3));
 1969         if (v3) {
 1970                 if (!error) {
 1971                         nfsm_srvpostop_fh(fhp);
 1972                         nfsm_srvpostop_attr(0, vap);
 1973                 }
 1974                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 1975         } else if (!error) {
 1976                 /* v2 non-error case. */
 1977                 nfsm_srvfhtom(fhp, v3);
 1978                 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
 1979                 nfsm_srvfillattr(vap, fp);
 1980         }
 1981         error = 0;
 1982 
 1983 nfsmout:
 1984         NFSD_LOCK_ASSERT();
 1985         NFSD_UNLOCK();
 1986         mtx_lock(&Giant);       /* VFS */
 1987         if (nd.ni_startdir) {
 1988                 vrele(nd.ni_startdir);
 1989                 nd.ni_startdir = NULL;
 1990         }
 1991         if (dirp)
 1992                 vrele(dirp);
 1993         NDFREE(&nd, NDF_ONLY_PNBUF);
 1994         if (nd.ni_dvp) {
 1995                 if (nd.ni_dvp == nd.ni_vp)
 1996                         vrele(nd.ni_dvp);
 1997                 else
 1998                         vput(nd.ni_dvp);
 1999         }
 2000         if (nd.ni_vp)
 2001                 vput(nd.ni_vp);
 2002         vn_finished_write(mp);
 2003         mtx_unlock(&Giant);     /* VFS */
 2004         NFSD_LOCK();
 2005         return (error);
 2006 }
 2007 
 2008 /*
 2009  * nfs v3 mknod service
 2010  */
 2011 int
 2012 nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 2013     struct thread *td, struct mbuf **mrq)
 2014 {
 2015         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 2016         struct sockaddr *nam = nfsd->nd_nam;
 2017         caddr_t dpos = nfsd->nd_dpos;
 2018         struct ucred *cred = &nfsd->nd_cr;
 2019         struct vattr va, dirfor, diraft;
 2020         struct vattr *vap = &va;
 2021         u_int32_t *tl;
 2022         struct nameidata nd;
 2023         caddr_t bpos;
 2024         int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
 2025         u_int32_t major, minor;
 2026         enum vtype vtyp;
 2027         struct mbuf *mb, *mreq;
 2028         struct vnode *vp, *dirp = NULL;
 2029         nfsfh_t nfh;
 2030         fhandle_t *fhp;
 2031         struct mount *mp = NULL;
 2032         int v3 = (nfsd->nd_flag & ND_NFSV3);
 2033 
 2034         NFSD_LOCK_ASSERT();
 2035 
 2036         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 2037         if (!v3)
 2038                 panic("nfsrv_mknod: v3 proc called on a v2 connection");
 2039         ndclear(&nd);
 2040 
 2041         fhp = &nfh.fh_generic;
 2042         nfsm_srvmtofh(fhp);
 2043         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
 2044                 error = ESTALE;
 2045                 goto ereply;
 2046         }
 2047         NFSD_UNLOCK();
 2048         mtx_lock(&Giant);       /* VFS */
 2049         (void) vn_start_write(NULL, &mp, V_WAIT);
 2050         mtx_unlock(&Giant);     /* VFS */
 2051         NFSD_LOCK();
 2052         nfsm_srvnamesiz(len);
 2053 
 2054         nd.ni_cnd.cn_cred = cred;
 2055         nd.ni_cnd.cn_nameiop = CREATE;
 2056         nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
 2057 
 2058         /*
 2059          * Handle nfs_namei() call.  If an error occurs, the nd structure
 2060          * is not valid.  However, nfsm_*() routines may still jump to
 2061          * nfsmout.
 2062          */
 2063 
 2064         error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
 2065                 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
 2066         if (error) {
 2067                 nfsm_reply(NFSX_WCCDATA(1));
 2068                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 2069                 error = 0;
 2070                 goto nfsmout;
 2071         }
 2072         tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
 2073         vtyp = nfsv3tov_type(*tl);
 2074         if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
 2075                 error = NFSERR_BADTYPE;
 2076                 goto out;
 2077         }
 2078         VATTR_NULL(vap);
 2079         nfsm_srvsattr(vap);
 2080         if (vtyp == VCHR || vtyp == VBLK) {
 2081                 tl = nfsm_dissect(u_int32_t *, 2 * NFSX_UNSIGNED);
 2082                 major = fxdr_unsigned(u_int32_t, *tl++);
 2083                 minor = fxdr_unsigned(u_int32_t, *tl);
 2084                 vap->va_rdev = makedev(major, minor);
 2085         }
 2086 
 2087         /*
 2088          * Iff doesn't exist, create it.
 2089          */
 2090         if (nd.ni_vp) {
 2091                 error = EEXIST;
 2092                 goto out;
 2093         }
 2094         vap->va_type = vtyp;
 2095         if (vap->va_mode == (mode_t)VNOVAL)
 2096                 vap->va_mode = 0;
 2097         NFSD_UNLOCK();
 2098         mtx_lock(&Giant);       /* VFS */
 2099         if (vtyp == VSOCK) {
 2100                 vrele(nd.ni_startdir);
 2101                 nd.ni_startdir = NULL;
 2102                 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
 2103                 if (error)
 2104                         NDFREE(&nd, NDF_ONLY_PNBUF);
 2105         } else {
 2106                 if (vtyp != VFIFO && (error = suser_cred(cred, 0)))
 2107                         goto out;
 2108                 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
 2109                 if (error) {
 2110                         NDFREE(&nd, NDF_ONLY_PNBUF);
 2111                         goto out;
 2112                 }
 2113                 vput(nd.ni_vp);
 2114                 nd.ni_vp = NULL;
 2115 
 2116                 /*
 2117                  * Release dvp prior to lookup
 2118                  */
 2119                 vput(nd.ni_dvp);
 2120                 nd.ni_dvp = NULL;
 2121 
 2122                 nd.ni_cnd.cn_nameiop = LOOKUP;
 2123                 nd.ni_cnd.cn_flags &= ~(LOCKPARENT);
 2124                 nd.ni_cnd.cn_thread = td;
 2125                 nd.ni_cnd.cn_cred = td->td_ucred;
 2126 
 2127                 error = lookup(&nd);
 2128                 nd.ni_dvp = NULL;
 2129 
 2130                 if (error)
 2131                         goto out;
 2132                 if (nd.ni_cnd.cn_flags & ISSYMLINK)
 2133                         error = EINVAL;
 2134         }
 2135 
 2136         /*
 2137          * send response, cleanup, return.
 2138          */
 2139 out:
 2140         NFSD_UNLOCK_ASSERT();
 2141         if (nd.ni_startdir) {
 2142                 vrele(nd.ni_startdir);
 2143                 nd.ni_startdir = NULL;
 2144         }
 2145         NDFREE(&nd, NDF_ONLY_PNBUF);
 2146         if (nd.ni_dvp) {
 2147                 if (nd.ni_dvp == nd.ni_vp)
 2148                         vrele(nd.ni_dvp);
 2149                 else
 2150                         vput(nd.ni_dvp);
 2151                 nd.ni_dvp = NULL;
 2152         }
 2153         vp = nd.ni_vp;
 2154         if (!error) {
 2155                 bzero((caddr_t)fhp, sizeof(nfh));
 2156                 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
 2157                 error = VFS_VPTOFH(vp, &fhp->fh_fid);
 2158                 if (!error)
 2159                         error = VOP_GETATTR(vp, vap, cred, td);
 2160         }
 2161         if (vp) {
 2162                 vput(vp);
 2163                 vp = NULL;
 2164                 nd.ni_vp = NULL;
 2165         }
 2166         if (dirp) {
 2167                 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
 2168                 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
 2169                 VOP_UNLOCK(dirp, 0, td);
 2170         }
 2171         mtx_unlock(&Giant);     /* VFS */
 2172         NFSD_LOCK();
 2173 ereply:
 2174         NFSD_LOCK_ASSERT();
 2175         nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
 2176         if (v3) {
 2177                 if (!error) {
 2178                         nfsm_srvpostop_fh(fhp);
 2179                         nfsm_srvpostop_attr(0, vap);
 2180                 }
 2181                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 2182         }
 2183         NFSD_UNLOCK();
 2184         mtx_lock(&Giant);       /* VFS */
 2185         vn_finished_write(mp);
 2186         mtx_unlock(&Giant);     /* VFS */
 2187         NFSD_LOCK();
 2188         return (0);
 2189 nfsmout:
 2190         NFSD_LOCK_ASSERT();
 2191         NFSD_UNLOCK();
 2192         mtx_lock(&Giant);       /* VFS */
 2193         if (dirp)
 2194                 vrele(dirp);
 2195         if (nd.ni_startdir)
 2196                 vrele(nd.ni_startdir);
 2197         NDFREE(&nd, NDF_ONLY_PNBUF);
 2198         if (nd.ni_dvp) {
 2199                 if (nd.ni_dvp == nd.ni_vp)
 2200                         vrele(nd.ni_dvp);
 2201                 else
 2202                         vput(nd.ni_dvp);
 2203         }
 2204         if (nd.ni_vp)
 2205                 vput(nd.ni_vp);
 2206         vn_finished_write(mp);
 2207         mtx_unlock(&Giant);     /* VFS */
 2208         NFSD_LOCK();
 2209         return (error);
 2210 }
 2211 
 2212 /*
 2213  * nfs remove service
 2214  */
 2215 int
 2216 nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 2217     struct thread *td, struct mbuf **mrq)
 2218 {
 2219         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 2220         struct sockaddr *nam = nfsd->nd_nam;
 2221         caddr_t dpos = nfsd->nd_dpos;
 2222         struct ucred *cred = &nfsd->nd_cr;
 2223         struct nameidata nd;
 2224         caddr_t bpos;
 2225         int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
 2226         int v3 = (nfsd->nd_flag & ND_NFSV3);
 2227         struct mbuf *mb, *mreq;
 2228         struct vnode *dirp;
 2229         struct vattr dirfor, diraft;
 2230         nfsfh_t nfh;
 2231         fhandle_t *fhp;
 2232         struct mount *mp = NULL;
 2233 
 2234         NFSD_LOCK_ASSERT();
 2235 
 2236         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 2237         ndclear(&nd);
 2238 
 2239         fhp = &nfh.fh_generic;
 2240         nfsm_srvmtofh(fhp);
 2241         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
 2242                 error = ESTALE;
 2243                 goto ereply;
 2244         }
 2245         NFSD_UNLOCK();
 2246         mtx_lock(&Giant);       /* VFS */
 2247         (void) vn_start_write(NULL, &mp, V_WAIT);
 2248         mtx_unlock(&Giant);     /* VFS */
 2249         NFSD_LOCK();
 2250         nfsm_srvnamesiz(len);
 2251 
 2252         nd.ni_cnd.cn_cred = cred;
 2253         nd.ni_cnd.cn_nameiop = DELETE;
 2254         nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
 2255         error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
 2256                 &dirp, v3,  &dirfor, &dirfor_ret, td, FALSE);
 2257         NFSD_UNLOCK();
 2258         mtx_lock(&Giant);       /* VFS */
 2259         if (dirp && !v3) {
 2260                 vrele(dirp);
 2261                 dirp = NULL;
 2262         }
 2263         if (error == 0) {
 2264                 if (nd.ni_vp->v_type == VDIR) {
 2265                         error = EPERM;          /* POSIX */
 2266                         goto out;
 2267                 }
 2268                 /*
 2269                  * The root of a mounted filesystem cannot be deleted.
 2270                  */
 2271                 if (nd.ni_vp->v_vflag & VV_ROOT) {
 2272                         error = EBUSY;
 2273                         goto out;
 2274                 }
 2275 out:
 2276                 NFSD_UNLOCK_ASSERT();
 2277                 if (!error) {
 2278                         error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
 2279                         NDFREE(&nd, NDF_ONLY_PNBUF);
 2280                 }
 2281         }
 2282         if (dirp && v3) {
 2283                 if (dirp == nd.ni_dvp)
 2284                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
 2285                 else {
 2286                         /* Drop the other locks to avoid deadlock. */
 2287                         if (nd.ni_dvp) {
 2288                                 if (nd.ni_dvp == nd.ni_vp)
 2289                                         vrele(nd.ni_dvp);
 2290                                 else
 2291                                         vput(nd.ni_dvp);
 2292                         }
 2293                         if (nd.ni_vp)
 2294                                 vput(nd.ni_vp);
 2295                         nd.ni_dvp = NULL;
 2296                         nd.ni_vp = NULL;
 2297 
 2298                         vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
 2299                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
 2300                         VOP_UNLOCK(dirp, 0, td);
 2301                 }
 2302                 vrele(dirp);
 2303                 dirp = NULL;
 2304         }
 2305         mtx_unlock(&Giant);     /* VFS */
 2306         NFSD_LOCK();
 2307 ereply:
 2308         NFSD_LOCK_ASSERT();
 2309         nfsm_reply(NFSX_WCCDATA(v3));
 2310         if (v3) {
 2311                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 2312                 error = 0;
 2313         }
 2314 nfsmout:
 2315         NFSD_LOCK_ASSERT();
 2316         NFSD_UNLOCK();
 2317         mtx_lock(&Giant);       /* VFS */
 2318         NDFREE(&nd, NDF_ONLY_PNBUF);
 2319         if (nd.ni_dvp) {
 2320                 if (nd.ni_dvp == nd.ni_vp)
 2321                         vrele(nd.ni_dvp);
 2322                 else
 2323                         vput(nd.ni_dvp);
 2324         }
 2325         if (nd.ni_vp)
 2326                 vput(nd.ni_vp);
 2327         vn_finished_write(mp);
 2328         mtx_unlock(&Giant);     /* VFS */
 2329         NFSD_LOCK();
 2330         return(error);
 2331 }
 2332 
 2333 /*
 2334  * nfs rename service
 2335  */
 2336 int
 2337 nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 2338     struct thread *td, struct mbuf **mrq)
 2339 {
 2340         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 2341         struct sockaddr *nam = nfsd->nd_nam;
 2342         caddr_t dpos = nfsd->nd_dpos;
 2343         struct ucred *cred = &nfsd->nd_cr;
 2344         caddr_t bpos;
 2345         int error = 0, len, len2, fdirfor_ret = 1, fdiraft_ret = 1;
 2346         int tdirfor_ret = 1, tdiraft_ret = 1;
 2347         int v3 = (nfsd->nd_flag & ND_NFSV3);
 2348         struct mbuf *mb, *mreq;
 2349         struct nameidata fromnd, tond;
 2350         struct vnode *fvp, *tvp, *tdvp, *fdirp = NULL;
 2351         struct vnode *tdirp = NULL;
 2352         struct vattr fdirfor, fdiraft, tdirfor, tdiraft;
 2353         nfsfh_t fnfh, tnfh;
 2354         fhandle_t *ffhp, *tfhp;
 2355         uid_t saved_uid;
 2356         struct mount *mp = NULL;
 2357 
 2358         NFSD_LOCK_ASSERT();
 2359 
 2360         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 2361 #ifndef nolint
 2362         fvp = NULL;
 2363 #endif
 2364         ffhp = &fnfh.fh_generic;
 2365         tfhp = &tnfh.fh_generic;
 2366 
 2367         /*
 2368          * Clear fields incase goto nfsmout occurs from macro.
 2369          */
 2370 
 2371         ndclear(&fromnd);
 2372         ndclear(&tond);
 2373 
 2374         nfsm_srvmtofh(ffhp);
 2375         if ((mp = vfs_getvfs(&ffhp->fh_fsid)) == NULL) {
 2376                 error = ESTALE;
 2377                 goto out1;
 2378         }
 2379         NFSD_UNLOCK();
 2380         mtx_lock(&Giant);
 2381         (void) vn_start_write(NULL, &mp, V_WAIT);
 2382         mtx_unlock(&Giant);
 2383         NFSD_LOCK();
 2384         nfsm_srvnamesiz(len);
 2385         /*
 2386          * Remember our original uid so that we can reset cr_uid before
 2387          * the second nfs_namei() call, in case it is remapped.
 2388          */
 2389         saved_uid = cred->cr_uid;
 2390         fromnd.ni_cnd.cn_cred = cred;
 2391         fromnd.ni_cnd.cn_nameiop = DELETE;
 2392         fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART;
 2393         error = nfs_namei(&fromnd, ffhp, len, slp, nam, &md,
 2394                 &dpos, &fdirp, v3, &fdirfor, &fdirfor_ret, td, FALSE);
 2395         if (fdirp && !v3) {
 2396                 NFSD_UNLOCK();
 2397                 mtx_lock(&Giant);       /* VFS */
 2398                 vrele(fdirp);
 2399                 mtx_unlock(&Giant);     /* VFS */
 2400                 NFSD_LOCK();
 2401                 fdirp = NULL;
 2402         }
 2403         if (error) {
 2404                 nfsm_reply(2 * NFSX_WCCDATA(v3));
 2405                 if (v3) {
 2406                         nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
 2407                         nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
 2408                 }
 2409                 error = 0;
 2410                 goto nfsmout;
 2411         }
 2412         fvp = fromnd.ni_vp;
 2413         nfsm_srvmtofh(tfhp);
 2414         nfsm_srvnamesiz(len2);
 2415         cred->cr_uid = saved_uid;
 2416         tond.ni_cnd.cn_cred = cred;
 2417         tond.ni_cnd.cn_nameiop = RENAME;
 2418         tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
 2419         error = nfs_namei(&tond, tfhp, len2, slp, nam, &md,
 2420                 &dpos, &tdirp, v3, &tdirfor, &tdirfor_ret, td, FALSE);
 2421         NFSD_UNLOCK();
 2422         mtx_lock(&Giant);       /* VFS */
 2423         if (tdirp && !v3) {
 2424                 vrele(tdirp);
 2425                 tdirp = NULL;
 2426         }
 2427         if (error) {
 2428                 mtx_unlock(&Giant);     /* VFS */
 2429                 NFSD_LOCK();
 2430                 goto out1;
 2431         }
 2432 
 2433         tdvp = tond.ni_dvp;
 2434         tvp = tond.ni_vp;
 2435         if (tvp != NULL) {
 2436                 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
 2437                         if (v3)
 2438                                 error = EEXIST;
 2439                         else
 2440                                 error = EISDIR;
 2441                         goto out;
 2442                 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
 2443                         if (v3)
 2444                                 error = EEXIST;
 2445                         else
 2446                                 error = ENOTDIR;
 2447                         goto out;
 2448                 }
 2449                 if (tvp->v_type == VDIR && tvp->v_mountedhere) {
 2450                         if (v3)
 2451                                 error = EXDEV;
 2452                         else
 2453                                 error = ENOTEMPTY;
 2454                         goto out;
 2455                 }
 2456         }
 2457         if (fvp->v_type == VDIR && fvp->v_mountedhere) {
 2458                 if (v3)
 2459                         error = EXDEV;
 2460                 else
 2461                         error = ENOTEMPTY;
 2462                 goto out;
 2463         }
 2464         if (fvp->v_mount != tdvp->v_mount) {
 2465                 if (v3)
 2466                         error = EXDEV;
 2467                 else
 2468                         error = ENOTEMPTY;
 2469                 goto out;
 2470         }
 2471         if (fvp == tdvp) {
 2472                 if (v3)
 2473                         error = EINVAL;
 2474                 else
 2475                         error = ENOTEMPTY;
 2476         }
 2477         /*
 2478          * If source is the same as the destination (that is the
 2479          * same vnode with the same name in the same directory),
 2480          * then there is nothing to do.
 2481          */
 2482         if (fvp == tvp && fromnd.ni_dvp == tdvp &&
 2483             fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
 2484             !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
 2485               fromnd.ni_cnd.cn_namelen))
 2486                 error = -1;
 2487 out:
 2488         NFSD_UNLOCK_ASSERT();
 2489         if (!error) {
 2490                 /*
 2491                  * The VOP_RENAME function releases all vnode references &
 2492                  * locks prior to returning so we need to clear the pointers
 2493                  * to bypass cleanup code later on.
 2494                  */
 2495                 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
 2496                                    tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
 2497                 fromnd.ni_dvp = NULL;
 2498                 fromnd.ni_vp = NULL;
 2499                 tond.ni_dvp = NULL;
 2500                 tond.ni_vp = NULL;
 2501                 if (error) {
 2502                         fromnd.ni_cnd.cn_flags &= ~HASBUF;
 2503                         tond.ni_cnd.cn_flags &= ~HASBUF;
 2504                 }
 2505         } else {
 2506                 if (error == -1)
 2507                         error = 0;
 2508         }
 2509         /* fall through */
 2510 
 2511         mtx_unlock(&Giant);     /* VFS */
 2512         NFSD_LOCK();
 2513 out1:
 2514         NFSD_LOCK_ASSERT();
 2515         nfsm_reply(2 * NFSX_WCCDATA(v3));
 2516         if (v3) {
 2517                 /* Release existing locks to prevent deadlock. */
 2518                 NFSD_UNLOCK();
 2519                 mtx_lock(&Giant);       /* VFS */
 2520                 if (tond.ni_dvp) {
 2521                         if (tond.ni_dvp == tond.ni_vp)
 2522                                 vrele(tond.ni_dvp);
 2523                         else
 2524                                 vput(tond.ni_dvp);
 2525                 }
 2526                 if (tond.ni_vp)
 2527                         vput(tond.ni_vp);
 2528                 tond.ni_dvp = NULL;
 2529                 tond.ni_vp = NULL;
 2530 
 2531                 if (fdirp) {
 2532                         vn_lock(fdirp, LK_EXCLUSIVE | LK_RETRY, td);
 2533                         fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, cred, td);
 2534                         VOP_UNLOCK(fdirp, 0, td);
 2535                 }
 2536                 if (tdirp) {
 2537                         vn_lock(tdirp, LK_EXCLUSIVE | LK_RETRY, td);
 2538                         tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, cred, td);
 2539                         VOP_UNLOCK(tdirp, 0, td);
 2540                 }
 2541                 mtx_unlock(&Giant);     /* VFS */
 2542                 NFSD_LOCK();
 2543                 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
 2544                 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
 2545         }
 2546         error = 0;
 2547         /* fall through */
 2548 
 2549 nfsmout:
 2550         /*
 2551          * Clear out tond related fields
 2552          */
 2553         NFSD_LOCK_ASSERT();
 2554         NFSD_UNLOCK();
 2555         mtx_lock(&Giant);       /* VFS */
 2556         if (tdirp)
 2557                 vrele(tdirp);
 2558         if (tond.ni_startdir)
 2559                 vrele(tond.ni_startdir);
 2560         NDFREE(&tond, NDF_ONLY_PNBUF);
 2561         if (tond.ni_dvp) {
 2562                 if (tond.ni_dvp == tond.ni_vp)
 2563                         vrele(tond.ni_dvp);
 2564                 else
 2565                         vput(tond.ni_dvp);
 2566         }
 2567         if (tond.ni_vp)
 2568                 vput(tond.ni_vp);
 2569 
 2570         /*
 2571          * Clear out fromnd related fields
 2572          */
 2573         if (fdirp)
 2574                 vrele(fdirp);
 2575         if (fromnd.ni_startdir)
 2576                 vrele(fromnd.ni_startdir);
 2577         NDFREE(&fromnd, NDF_ONLY_PNBUF);
 2578         if (fromnd.ni_dvp)
 2579                 vrele(fromnd.ni_dvp);
 2580         if (fromnd.ni_vp)
 2581                 vrele(fromnd.ni_vp);
 2582 
 2583         vn_finished_write(mp);
 2584         mtx_unlock(&Giant);     /* VFS */
 2585         NFSD_LOCK();
 2586         return (error);
 2587 }
 2588 
 2589 /*
 2590  * nfs link service
 2591  */
 2592 int
 2593 nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 2594     struct thread *td, struct mbuf **mrq)
 2595 {
 2596         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 2597         struct sockaddr *nam = nfsd->nd_nam;
 2598         caddr_t dpos = nfsd->nd_dpos;
 2599         struct ucred *cred = &nfsd->nd_cr;
 2600         struct nameidata nd;
 2601         caddr_t bpos;
 2602         int error = 0, rdonly, len, dirfor_ret = 1, diraft_ret = 1;
 2603         int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3);
 2604         struct mbuf *mb, *mreq;
 2605         struct vnode *vp = NULL, *xp, *dirp = NULL;
 2606         struct vattr dirfor, diraft, at;
 2607         nfsfh_t nfh, dnfh;
 2608         fhandle_t *fhp, *dfhp;
 2609         struct mount *mp = NULL;
 2610 
 2611         NFSD_LOCK_ASSERT();
 2612 
 2613         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 2614         ndclear(&nd);
 2615 
 2616         fhp = &nfh.fh_generic;
 2617         dfhp = &dnfh.fh_generic;
 2618         nfsm_srvmtofh(fhp);
 2619         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
 2620                 error = ESTALE;
 2621                 goto ereply;
 2622         }
 2623         NFSD_UNLOCK();
 2624         mtx_lock(&Giant);       /* VFS */
 2625         (void) vn_start_write(NULL, &mp, V_WAIT);
 2626         mtx_unlock(&Giant);     /* VFS */
 2627         NFSD_LOCK();
 2628         nfsm_srvmtofh(dfhp);
 2629         nfsm_srvnamesiz(len);
 2630 
 2631         error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, slp, nam, &rdonly, TRUE);
 2632         if (error) {
 2633                 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
 2634                 if (v3) {
 2635                         nfsm_srvpostop_attr(getret, &at);
 2636                         nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 2637                 }
 2638                 vp = NULL;
 2639                 error = 0;
 2640                 goto nfsmout;
 2641         }
 2642         NFSD_UNLOCK();
 2643         mtx_lock(&Giant);       /* VFS */
 2644         if (v3)
 2645                 getret = VOP_GETATTR(vp, &at, cred, td);
 2646         if (vp->v_type == VDIR) {
 2647                 error = EPERM;          /* POSIX */
 2648                 goto out1;
 2649         }
 2650         VOP_UNLOCK(vp, 0, td);
 2651         nd.ni_cnd.cn_cred = cred;
 2652         nd.ni_cnd.cn_nameiop = CREATE;
 2653         nd.ni_cnd.cn_flags = LOCKPARENT;
 2654         mtx_unlock(&Giant);     /* VFS */
 2655         NFSD_LOCK();
 2656         error = nfs_namei(&nd, dfhp, len, slp, nam, &md, &dpos,
 2657                 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
 2658         NFSD_UNLOCK();
 2659         mtx_lock(&Giant);       /* VFS */
 2660         if (dirp && !v3) {
 2661                 vrele(dirp);
 2662                 dirp = NULL;
 2663         }
 2664         if (error) {
 2665                 vrele(vp);
 2666                 vp = NULL;
 2667                 goto out2;
 2668         }
 2669         xp = nd.ni_vp;
 2670         if (xp != NULL) {
 2671                 error = EEXIST;
 2672                 vrele(vp);
 2673                 vp = NULL;
 2674                 goto out2;
 2675         }
 2676         xp = nd.ni_dvp;
 2677         if (vp->v_mount != xp->v_mount) {
 2678                 error = EXDEV;
 2679                 vrele(vp);
 2680                 vp = NULL;
 2681                 goto out2;
 2682         }
 2683         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 2684         error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
 2685         NDFREE(&nd, NDF_ONLY_PNBUF);
 2686         /* fall through */
 2687 
 2688 out1:
 2689         if (v3)
 2690                 getret = VOP_GETATTR(vp, &at, cred, td);
 2691 out2:
 2692         if (dirp) {
 2693                 if (dirp == nd.ni_dvp)
 2694                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
 2695                 else {
 2696                         /* Release existing locks to prevent deadlock. */
 2697                         if (nd.ni_dvp) {
 2698                                 if (nd.ni_dvp == nd.ni_vp)
 2699                                         vrele(nd.ni_dvp);
 2700                                 else
 2701                                         vput(nd.ni_dvp);
 2702                         }
 2703                         if (nd.ni_vp)
 2704                                 vrele(nd.ni_vp);
 2705                         nd.ni_dvp = NULL;
 2706                         nd.ni_vp = NULL;
 2707 
 2708                         vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
 2709                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
 2710                         VOP_UNLOCK(dirp, 0, td);
 2711                 }
 2712         }
 2713         mtx_unlock(&Giant);     /* VFS */
 2714         NFSD_LOCK();
 2715 ereply:
 2716         NFSD_LOCK_ASSERT();
 2717         nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
 2718         if (v3) {
 2719                 nfsm_srvpostop_attr(getret, &at);
 2720                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 2721                 error = 0;
 2722         }
 2723         /* fall through */
 2724 
 2725 nfsmout:
 2726         NFSD_LOCK_ASSERT();
 2727         NFSD_UNLOCK();
 2728         mtx_lock(&Giant);       /* VFS */
 2729         NDFREE(&nd, NDF_ONLY_PNBUF);
 2730         if (dirp)
 2731                 vrele(dirp);
 2732         if (vp)
 2733                 vput(vp);
 2734         if (nd.ni_dvp) {
 2735                 if (nd.ni_dvp == nd.ni_vp)
 2736                         vrele(nd.ni_dvp);
 2737                 else
 2738                         vput(nd.ni_dvp);
 2739         }
 2740         if (nd.ni_vp)
 2741                 vrele(nd.ni_vp);
 2742         vn_finished_write(mp);
 2743         mtx_unlock(&Giant);     /* VFS */
 2744         NFSD_LOCK();
 2745         return(error);
 2746 }
 2747 
 2748 /*
 2749  * nfs symbolic link service
 2750  */
 2751 int
 2752 nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 2753     struct thread *td, struct mbuf **mrq)
 2754 {
 2755         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 2756         struct sockaddr *nam = nfsd->nd_nam;
 2757         caddr_t dpos = nfsd->nd_dpos;
 2758         struct ucred *cred = &nfsd->nd_cr;
 2759         struct vattr va, dirfor, diraft;
 2760         struct nameidata nd;
 2761         struct vattr *vap = &va;
 2762         struct nfsv2_sattr *sp;
 2763         char *bpos, *pathcp = NULL;
 2764         struct uio io;
 2765         struct iovec iv;
 2766         int error = 0, len, len2, dirfor_ret = 1, diraft_ret = 1;
 2767         int v3 = (nfsd->nd_flag & ND_NFSV3);
 2768         struct mbuf *mb, *mreq;
 2769         struct vnode *dirp = NULL;
 2770         nfsfh_t nfh;
 2771         fhandle_t *fhp;
 2772         struct mount *mp = NULL;
 2773 
 2774         NFSD_LOCK_ASSERT();
 2775 
 2776         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 2777         ndclear(&nd);
 2778 
 2779         fhp = &nfh.fh_generic;
 2780         nfsm_srvmtofh(fhp);
 2781         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
 2782                 NFSD_UNLOCK();
 2783                 mtx_lock(&Giant);       /* VFS */
 2784                 error = ESTALE;
 2785                 goto out;
 2786         }
 2787         NFSD_UNLOCK();
 2788         mtx_lock(&Giant);       /* VFS */
 2789         (void) vn_start_write(NULL, &mp, V_WAIT);
 2790         mtx_unlock(&Giant);     /* VFS */
 2791         NFSD_LOCK();
 2792         nfsm_srvnamesiz(len);
 2793         nd.ni_cnd.cn_cred = cred;
 2794         nd.ni_cnd.cn_nameiop = CREATE;
 2795         nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART;
 2796         error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
 2797                 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
 2798         NFSD_UNLOCK();
 2799         mtx_lock(&Giant);       /* VFS */
 2800         if (dirp && !v3) {
 2801                 vrele(dirp);
 2802                 dirp = NULL;
 2803         }
 2804         if (error)
 2805                 goto out;
 2806 
 2807         VATTR_NULL(vap);
 2808         if (v3)
 2809                 nfsm_srvsattr(vap);
 2810         nfsm_srvpathsiz(len2);
 2811         MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK);
 2812         iv.iov_base = pathcp;
 2813         iv.iov_len = len2;
 2814         io.uio_resid = len2;
 2815         io.uio_offset = 0;
 2816         io.uio_iov = &iv;
 2817         io.uio_iovcnt = 1;
 2818         io.uio_segflg = UIO_SYSSPACE;
 2819         io.uio_rw = UIO_READ;
 2820         io.uio_td = NULL;
 2821         nfsm_mtouio(&io, len2);
 2822         if (!v3) {
 2823                 sp = nfsm_dissect(struct nfsv2_sattr *, NFSX_V2SATTR);
 2824                 vap->va_mode = nfstov_mode(sp->sa_mode);
 2825         }
 2826         *(pathcp + len2) = '\0';
 2827         if (nd.ni_vp) {
 2828                 error = EEXIST;
 2829                 goto out;
 2830         }
 2831 
 2832         /*
 2833          * issue symlink op.  SAVESTART is set so the underlying path component
 2834          * is only freed by the VOP if an error occurs.
 2835          */
 2836         if (vap->va_mode == (mode_t)VNOVAL)
 2837                 vap->va_mode = 0;
 2838         error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap, pathcp);
 2839         if (error)
 2840                 NDFREE(&nd, NDF_ONLY_PNBUF);
 2841         else
 2842                 vput(nd.ni_vp);
 2843         nd.ni_vp = NULL;
 2844         /*
 2845          * releases directory prior to potential lookup op.
 2846          */
 2847         vput(nd.ni_dvp);
 2848         nd.ni_dvp = NULL;
 2849 
 2850         if (error == 0) {
 2851             if (v3) {
 2852                 /*
 2853                  * Issue lookup.  Leave SAVESTART set so we can easily free
 2854                  * the name buffer later on.
 2855                  *
 2856                  * since LOCKPARENT is not set, ni_dvp will be garbage on
 2857                  * return whether an error occurs or not.
 2858                  */
 2859                 nd.ni_cnd.cn_nameiop = LOOKUP;
 2860                 nd.ni_cnd.cn_flags &= ~(LOCKPARENT | FOLLOW);
 2861                 nd.ni_cnd.cn_flags |= (NOFOLLOW | LOCKLEAF);
 2862                 nd.ni_cnd.cn_thread = td;
 2863                 nd.ni_cnd.cn_cred = cred;
 2864 
 2865                 error = lookup(&nd);
 2866                 nd.ni_dvp = NULL;
 2867 
 2868                 if (error == 0) {
 2869                         bzero((caddr_t)fhp, sizeof(nfh));
 2870                         fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
 2871                         error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
 2872                         if (!error)
 2873                                 error = VOP_GETATTR(nd.ni_vp, vap, cred,
 2874                                         td);
 2875                         vput(nd.ni_vp);
 2876                         nd.ni_vp = NULL;
 2877                 }
 2878             }
 2879         }
 2880 out:
 2881         NFSD_UNLOCK_ASSERT();
 2882         /*
 2883          * These releases aren't strictly required, does even doing them
 2884          * make any sense? XXX can nfsm_reply() block?
 2885          */
 2886         if (pathcp) {
 2887                 FREE(pathcp, M_TEMP);
 2888                 pathcp = NULL;
 2889         }
 2890         if (dirp) {
 2891                 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
 2892                 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
 2893                 VOP_UNLOCK(dirp, 0, td);
 2894         }
 2895         if (nd.ni_startdir) {
 2896                 vrele(nd.ni_startdir);
 2897                 nd.ni_startdir = NULL;
 2898         }
 2899         mtx_unlock(&Giant);     /* VFS */
 2900         NFSD_LOCK();
 2901         nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
 2902         if (v3) {
 2903                 if (!error) {
 2904                         nfsm_srvpostop_fh(fhp);
 2905                         nfsm_srvpostop_attr(0, vap);
 2906                 }
 2907                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 2908         }
 2909         error = 0;
 2910         /* fall through */
 2911 
 2912 nfsmout:
 2913         NFSD_LOCK_ASSERT();
 2914         NFSD_UNLOCK();
 2915         mtx_lock(&Giant);       /* VFS */
 2916         NDFREE(&nd, NDF_ONLY_PNBUF);
 2917         if (nd.ni_dvp) {
 2918                 if (nd.ni_dvp == nd.ni_vp)
 2919                         vrele(nd.ni_dvp);
 2920                 else
 2921                         vput(nd.ni_dvp);
 2922         }
 2923         if (nd.ni_vp)
 2924                 vrele(nd.ni_vp);
 2925         if (nd.ni_startdir)
 2926                 vrele(nd.ni_startdir);
 2927         if (dirp)
 2928                 vrele(dirp);
 2929         if (pathcp)
 2930                 FREE(pathcp, M_TEMP);
 2931 
 2932         vn_finished_write(mp);
 2933         mtx_unlock(&Giant);     /* VFS */
 2934         NFSD_LOCK();
 2935         return (error);
 2936 }
 2937 
 2938 /*
 2939  * nfs mkdir service
 2940  */
 2941 int
 2942 nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 2943     struct thread *td, struct mbuf **mrq)
 2944 {
 2945         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 2946         struct sockaddr *nam = nfsd->nd_nam;
 2947         caddr_t dpos = nfsd->nd_dpos;
 2948         struct ucred *cred = &nfsd->nd_cr;
 2949         struct vattr va, dirfor, diraft;
 2950         struct vattr *vap = &va;
 2951         struct nfs_fattr *fp;
 2952         struct nameidata nd;
 2953         u_int32_t *tl;
 2954         caddr_t bpos;
 2955         int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
 2956         int v3 = (nfsd->nd_flag & ND_NFSV3);
 2957         struct mbuf *mb, *mreq;
 2958         struct vnode *dirp = NULL;
 2959         int vpexcl = 0;
 2960         nfsfh_t nfh;
 2961         fhandle_t *fhp;
 2962         struct mount *mp = NULL;
 2963 
 2964         NFSD_LOCK_ASSERT();
 2965 
 2966         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 2967         ndclear(&nd);
 2968 
 2969         fhp = &nfh.fh_generic;
 2970         nfsm_srvmtofh(fhp);
 2971         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
 2972                 NFSD_UNLOCK();
 2973                 mtx_lock(&Giant);       /* VFS */
 2974                 error = ESTALE;
 2975                 goto out;
 2976         }
 2977         NFSD_UNLOCK();
 2978         mtx_lock(&Giant);       /* VFS */
 2979         (void) vn_start_write(NULL, &mp, V_WAIT);
 2980         mtx_unlock(&Giant);     /* VFS */
 2981         NFSD_LOCK();
 2982         nfsm_srvnamesiz(len);
 2983         nd.ni_cnd.cn_cred = cred;
 2984         nd.ni_cnd.cn_nameiop = CREATE;
 2985         nd.ni_cnd.cn_flags = LOCKPARENT;
 2986 
 2987         error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
 2988                 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
 2989         if (dirp && !v3) {
 2990                 NFSD_UNLOCK();
 2991                 mtx_lock(&Giant);       /* VFS */
 2992                 vrele(dirp);
 2993                 mtx_unlock(&Giant);     /* VFS */
 2994                 NFSD_LOCK();
 2995                 dirp = NULL;
 2996         }
 2997         if (error) {
 2998                 nfsm_reply(NFSX_WCCDATA(v3));
 2999                 if (v3)
 3000                         nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 3001                 error = 0;
 3002                 goto nfsmout;
 3003         }
 3004         VATTR_NULL(vap);
 3005         if (v3) {
 3006                 nfsm_srvsattr(vap);
 3007         } else {
 3008                 tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
 3009                 vap->va_mode = nfstov_mode(*tl++);
 3010         }
 3011 
 3012         /*
 3013          * At this point nd.ni_dvp is referenced and exclusively locked and
 3014          * nd.ni_vp, if it exists, is referenced but not locked.
 3015          */
 3016 
 3017         NFSD_UNLOCK();
 3018         mtx_lock(&Giant);       /* VFS */
 3019         vap->va_type = VDIR;
 3020         if (nd.ni_vp != NULL) {
 3021                 NDFREE(&nd, NDF_ONLY_PNBUF);
 3022                 error = EEXIST;
 3023                 goto out;
 3024         }
 3025 
 3026         /*
 3027          * Issue mkdir op.  Since SAVESTART is not set, the pathname
 3028          * component is freed by the VOP call.  This will fill-in
 3029          * nd.ni_vp, reference, and exclusively lock it.
 3030          */
 3031         if (vap->va_mode == (mode_t)VNOVAL)
 3032                 vap->va_mode = 0;
 3033         error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
 3034         NDFREE(&nd, NDF_ONLY_PNBUF);
 3035         vpexcl = 1;
 3036 
 3037         vput(nd.ni_dvp);
 3038         nd.ni_dvp = NULL;
 3039 
 3040         if (!error) {
 3041                 bzero((caddr_t)fhp, sizeof(nfh));
 3042                 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
 3043                 error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
 3044                 if (!error)
 3045                         error = VOP_GETATTR(nd.ni_vp, vap, cred, td);
 3046         }
 3047 out:
 3048         NFSD_UNLOCK_ASSERT();
 3049         if (dirp) {
 3050                 if (dirp == nd.ni_dvp) {
 3051                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
 3052                 } else {
 3053                         /* Release existing locks to prevent deadlock. */
 3054                         if (nd.ni_dvp) {
 3055                                 NDFREE(&nd, NDF_ONLY_PNBUF);
 3056                                 if (nd.ni_dvp == nd.ni_vp && vpexcl)
 3057                                         vrele(nd.ni_dvp);
 3058                                 else
 3059                                         vput(nd.ni_dvp);
 3060                         }
 3061                         if (nd.ni_vp) {
 3062                                 if (vpexcl)
 3063                                         vput(nd.ni_vp);
 3064                                 else
 3065                                         vrele(nd.ni_vp);
 3066                         }
 3067                         nd.ni_dvp = NULL;
 3068                         nd.ni_vp = NULL;
 3069                         vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
 3070                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
 3071                         VOP_UNLOCK(dirp, 0, td);
 3072                 }
 3073         }
 3074         mtx_unlock(&Giant);     /* VFS */
 3075         NFSD_LOCK();
 3076         nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
 3077         if (v3) {
 3078                 if (!error) {
 3079                         nfsm_srvpostop_fh(fhp);
 3080                         nfsm_srvpostop_attr(0, vap);
 3081                 }
 3082                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 3083         } else if (!error) {
 3084                 /* v2 non-error case. */
 3085                 nfsm_srvfhtom(fhp, v3);
 3086                 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
 3087                 nfsm_srvfillattr(vap, fp);
 3088         }
 3089         error = 0;
 3090         /* fall through */
 3091 
 3092 nfsmout:
 3093         NFSD_LOCK_ASSERT();
 3094         NFSD_UNLOCK();
 3095         mtx_lock(&Giant);       /* VFS */
 3096         if (dirp)
 3097                 vrele(dirp);
 3098         if (nd.ni_dvp) {
 3099                 NDFREE(&nd, NDF_ONLY_PNBUF);
 3100                 if (nd.ni_dvp == nd.ni_vp && vpexcl)
 3101                         vrele(nd.ni_dvp);
 3102                 else
 3103                         vput(nd.ni_dvp);
 3104         }
 3105         if (nd.ni_vp) {
 3106                 if (vpexcl)
 3107                         vput(nd.ni_vp);
 3108                 else
 3109                         vrele(nd.ni_vp);
 3110         }
 3111         vn_finished_write(mp);
 3112         mtx_unlock(&Giant);     /* VFS */
 3113         NFSD_LOCK();
 3114         return (error);
 3115 }
 3116 
 3117 /*
 3118  * nfs rmdir service
 3119  */
 3120 int
 3121 nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 3122     struct thread *td, struct mbuf **mrq)
 3123 {
 3124         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 3125         struct sockaddr *nam = nfsd->nd_nam;
 3126         caddr_t dpos = nfsd->nd_dpos;
 3127         struct ucred *cred = &nfsd->nd_cr;
 3128         caddr_t bpos;
 3129         int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
 3130         int v3 = (nfsd->nd_flag & ND_NFSV3);
 3131         struct mbuf *mb, *mreq;
 3132         struct vnode *vp, *dirp = NULL;
 3133         struct vattr dirfor, diraft;
 3134         nfsfh_t nfh;
 3135         fhandle_t *fhp;
 3136         struct nameidata nd;
 3137         struct mount *mp = NULL;
 3138 
 3139         NFSD_LOCK_ASSERT();
 3140 
 3141         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 3142         ndclear(&nd);
 3143 
 3144         fhp = &nfh.fh_generic;
 3145         nfsm_srvmtofh(fhp);
 3146         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
 3147                 error = ESTALE;
 3148                 goto out;
 3149         }
 3150         NFSD_UNLOCK();
 3151         mtx_lock(&Giant);       /* VFS */
 3152         (void) vn_start_write(NULL, &mp, V_WAIT);
 3153         mtx_unlock(&Giant);     /* VFS */
 3154         NFSD_LOCK();
 3155         nfsm_srvnamesiz(len);
 3156         nd.ni_cnd.cn_cred = cred;
 3157         nd.ni_cnd.cn_nameiop = DELETE;
 3158         nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
 3159         error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
 3160                 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
 3161         if (dirp && !v3) {
 3162                 NFSD_UNLOCK();
 3163                 mtx_lock(&Giant);       /* VFS */
 3164                 vrele(dirp);
 3165                 mtx_unlock(&Giant);     /* VFS */
 3166                 NFSD_LOCK();
 3167                 dirp = NULL;
 3168         }
 3169         if (error) {
 3170                 nfsm_reply(NFSX_WCCDATA(v3));
 3171                 if (v3)
 3172                         nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 3173                 error = 0;
 3174                 goto nfsmout;
 3175         }
 3176         vp = nd.ni_vp;
 3177         if (vp->v_type != VDIR) {
 3178                 error = ENOTDIR;
 3179                 goto out;
 3180         }
 3181         /*
 3182          * No rmdir "." please.
 3183          */
 3184         if (nd.ni_dvp == vp) {
 3185                 error = EINVAL;
 3186                 goto out;
 3187         }
 3188         /*
 3189          * The root of a mounted filesystem cannot be deleted.
 3190          */
 3191         if (vp->v_vflag & VV_ROOT)
 3192                 error = EBUSY;
 3193 out:
 3194         /*
 3195          * Issue or abort op.  Since SAVESTART is not set, path name
 3196          * component is freed by the VOP after either.
 3197          */
 3198         NFSD_LOCK_ASSERT();
 3199         NFSD_UNLOCK();
 3200         mtx_lock(&Giant);       /* VFS */
 3201         if (!error)
 3202                 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
 3203         NDFREE(&nd, NDF_ONLY_PNBUF);
 3204 
 3205         if (dirp) {
 3206                 if (dirp == nd.ni_dvp)
 3207                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
 3208                 else {
 3209                         /* Release existing locks to prevent deadlock. */
 3210                         if (nd.ni_dvp) {
 3211                                 if (nd.ni_dvp == nd.ni_vp)
 3212                                         vrele(nd.ni_dvp);
 3213                                 else
 3214                                         vput(nd.ni_dvp);
 3215                         }
 3216                         if (nd.ni_vp)
 3217                                 vput(nd.ni_vp);
 3218                         nd.ni_dvp = NULL;
 3219                         nd.ni_vp = NULL;
 3220                         vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
 3221                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
 3222                         VOP_UNLOCK(dirp, 0, td);
 3223                 }
 3224         }
 3225         mtx_unlock(&Giant);     /* VFS */
 3226         NFSD_LOCK();
 3227         nfsm_reply(NFSX_WCCDATA(v3));
 3228         error = 0;
 3229         if (v3)
 3230                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 3231         /* fall through */
 3232 
 3233 nfsmout:
 3234         NFSD_LOCK_ASSERT();
 3235         NFSD_UNLOCK();
 3236         mtx_lock(&Giant);       /* VFS */
 3237         NDFREE(&nd, NDF_ONLY_PNBUF);
 3238         if (dirp)
 3239                 vrele(dirp);
 3240         if (nd.ni_dvp) {
 3241                 if (nd.ni_dvp == nd.ni_vp)
 3242                         vrele(nd.ni_dvp);
 3243                 else
 3244                         vput(nd.ni_dvp);
 3245         }
 3246         if (nd.ni_vp)
 3247                 vput(nd.ni_vp);
 3248 
 3249         vn_finished_write(mp);
 3250         mtx_unlock(&Giant);     /* VFS */
 3251         NFSD_LOCK();
 3252         return(error);
 3253 }
 3254 
 3255 /*
 3256  * nfs readdir service
 3257  * - mallocs what it thinks is enough to read
 3258  *      count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
 3259  * - calls VOP_READDIR()
 3260  * - loops around building the reply
 3261  *      if the output generated exceeds count break out of loop
 3262  *      The nfsm_clget macro is used here so that the reply will be packed
 3263  *      tightly in mbuf clusters.
 3264  * - it only knows that it has encountered eof when the VOP_READDIR()
 3265  *      reads nothing
 3266  * - as such one readdir rpc will return eof false although you are there
 3267  *      and then the next will return eof
 3268  * - it trims out records with d_fileno == 0
 3269  *      this doesn't matter for Unix clients, but they might confuse clients
 3270  *      for other os'.
 3271  * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
 3272  *      than requested, but this may not apply to all filesystems. For
 3273  *      example, client NFS does not { although it is never remote mounted
 3274  *      anyhow }
 3275  *     The alternate call nfsrv_readdirplus() does lookups as well.
 3276  * PS: The NFS protocol spec. does not clarify what the "count" byte
 3277  *      argument is a count of.. just name strings and file id's or the
 3278  *      entire reply rpc or ...
 3279  *      I tried just file name and id sizes and it confused the Sun client,
 3280  *      so I am using the full rpc size now. The "paranoia.." comment refers
 3281  *      to including the status longwords that are not a part of the dir.
 3282  *      "entry" structures, but are in the rpc.
 3283  */
 3284 struct flrep {
 3285         nfsuint64       fl_off;
 3286         u_int32_t       fl_postopok;
 3287         u_int32_t       fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)];
 3288         u_int32_t       fl_fhok;
 3289         u_int32_t       fl_fhsize;
 3290         u_int32_t       fl_nfh[NFSX_V3FH / sizeof (u_int32_t)];
 3291 };
 3292 
 3293 int
 3294 nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 3295     struct thread *td, struct mbuf **mrq)
 3296 {
 3297         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 3298         struct sockaddr *nam = nfsd->nd_nam;
 3299         caddr_t dpos = nfsd->nd_dpos;
 3300         struct ucred *cred = &nfsd->nd_cr;
 3301         char *bp, *be;
 3302         struct mbuf *mp;
 3303         struct dirent *dp;
 3304         caddr_t cp;
 3305         u_int32_t *tl;
 3306         caddr_t bpos;
 3307         struct mbuf *mb, *mreq;
 3308         char *cpos, *cend, *rbuf;
 3309         struct vnode *vp = NULL;
 3310         struct vattr at;
 3311         nfsfh_t nfh;
 3312         fhandle_t *fhp;
 3313         struct uio io;
 3314         struct iovec iv;
 3315         int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
 3316         int siz, cnt, fullsiz, eofflag, rdonly, ncookies;
 3317         int v3 = (nfsd->nd_flag & ND_NFSV3);
 3318         u_quad_t off, toff, verf;
 3319         u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
 3320 
 3321         NFSD_LOCK_ASSERT();
 3322 
 3323         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 3324         fhp = &nfh.fh_generic;
 3325         nfsm_srvmtofh(fhp);
 3326         if (v3) {
 3327                 tl = nfsm_dissect(u_int32_t *, 5 * NFSX_UNSIGNED);
 3328                 toff = fxdr_hyper(tl);
 3329                 tl += 2;
 3330                 verf = fxdr_hyper(tl);
 3331                 tl += 2;
 3332         } else {
 3333                 tl = nfsm_dissect(u_int32_t *, 2 * NFSX_UNSIGNED);
 3334                 toff = fxdr_unsigned(u_quad_t, *tl++);
 3335                 verf = 0;       /* shut up gcc */
 3336         }
 3337         off = toff;
 3338         cnt = fxdr_unsigned(int, *tl);
 3339         siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
 3340         xfer = NFS_SRVMAXDATA(nfsd);
 3341         if (cnt > xfer)
 3342                 cnt = xfer;
 3343         if (siz > xfer)
 3344                 siz = xfer;
 3345         fullsiz = siz;
 3346         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
 3347         if (!error && vp->v_type != VDIR) {
 3348                 error = ENOTDIR;
 3349                 NFSD_UNLOCK();
 3350                 mtx_lock(&Giant);       /* VFS */
 3351                 vput(vp);
 3352                 mtx_unlock(&Giant);     /* VFS */
 3353                 NFSD_LOCK();
 3354                 vp = NULL;
 3355         }
 3356         if (error) {
 3357                 nfsm_reply(NFSX_UNSIGNED);
 3358                 if (v3)
 3359                         nfsm_srvpostop_attr(getret, &at);
 3360                 error = 0;
 3361                 goto nfsmout;
 3362         }
 3363 
 3364         /*
 3365          * Obtain lock on vnode for this section of the code
 3366          */
 3367         NFSD_UNLOCK();
 3368         mtx_lock(&Giant);       /* VFS */
 3369         if (v3) {
 3370                 error = getret = VOP_GETATTR(vp, &at, cred, td);
 3371 #if 0
 3372                 /*
 3373                  * XXX This check may be too strict for Solaris 2.5 clients.
 3374                  */
 3375                 if (!error && toff && verf && verf != at.va_filerev)
 3376                         error = NFSERR_BAD_COOKIE;
 3377 #endif
 3378         }
 3379         if (!error)
 3380                 error = nfsrv_access_withgiant(vp, VEXEC, cred, rdonly, td, 0);
 3381         if (error) {
 3382                 vput(vp);
 3383                 mtx_unlock(&Giant);     /* VFS */
 3384                 NFSD_LOCK();
 3385                 vp = NULL;
 3386                 nfsm_reply(NFSX_POSTOPATTR(v3));
 3387                 if (v3)
 3388                         nfsm_srvpostop_attr(getret, &at);
 3389                 error = 0;
 3390                 goto nfsmout;
 3391         }
 3392         VOP_UNLOCK(vp, 0, td);
 3393 
 3394         /*
 3395          * end section.  Allocate rbuf and continue
 3396          */
 3397         MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
 3398 again:
 3399         NFSD_UNLOCK_ASSERT();
 3400         iv.iov_base = rbuf;
 3401         iv.iov_len = fullsiz;
 3402         io.uio_iov = &iv;
 3403         io.uio_iovcnt = 1;
 3404         io.uio_offset = (off_t)off;
 3405         io.uio_resid = fullsiz;
 3406         io.uio_segflg = UIO_SYSSPACE;
 3407         io.uio_rw = UIO_READ;
 3408         io.uio_td = NULL;
 3409         eofflag = 0;
 3410         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 3411         if (cookies) {
 3412                 free((caddr_t)cookies, M_TEMP);
 3413                 cookies = NULL;
 3414         }
 3415         error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
 3416         off = (off_t)io.uio_offset;
 3417         if (!cookies && !error)
 3418                 error = NFSERR_PERM;
 3419         if (v3) {
 3420                 getret = VOP_GETATTR(vp, &at, cred, td);
 3421                 if (!error)
 3422                         error = getret;
 3423         }
 3424         VOP_UNLOCK(vp, 0, td);
 3425         if (error) {
 3426                 vrele(vp);
 3427                 mtx_unlock(&Giant);     /* VFS */
 3428                 vp = NULL;
 3429                 free((caddr_t)rbuf, M_TEMP);
 3430                 if (cookies)
 3431                         free((caddr_t)cookies, M_TEMP);
 3432                 NFSD_LOCK();
 3433                 nfsm_reply(NFSX_POSTOPATTR(v3));
 3434                 if (v3)
 3435                         nfsm_srvpostop_attr(getret, &at);
 3436                 error = 0;
 3437                 goto nfsmout;
 3438         }
 3439         if (io.uio_resid) {
 3440                 siz -= io.uio_resid;
 3441 
 3442                 /*
 3443                  * If nothing read, return eof
 3444                  * rpc reply
 3445                  */
 3446                 if (siz == 0) {
 3447                         vrele(vp);
 3448                         mtx_unlock(&Giant);     /* VFS */
 3449                         vp = NULL;
 3450                         NFSD_LOCK();
 3451                         nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) +
 3452                                 2 * NFSX_UNSIGNED);
 3453                         if (v3) {
 3454                                 nfsm_srvpostop_attr(getret, &at);
 3455                                 tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
 3456                                 txdr_hyper(at.va_filerev, tl);
 3457                                 tl += 2;
 3458                         } else
 3459                                 tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
 3460                         *tl++ = nfsrv_nfs_false;
 3461                         *tl = nfsrv_nfs_true;
 3462                         FREE((caddr_t)rbuf, M_TEMP);
 3463                         FREE((caddr_t)cookies, M_TEMP);
 3464                         error = 0;
 3465                         goto nfsmout;
 3466                 }
 3467         }
 3468 
 3469         /*
 3470          * Check for degenerate cases of nothing useful read.
 3471          * If so go try again
 3472          */
 3473         cpos = rbuf;
 3474         cend = rbuf + siz;
 3475         dp = (struct dirent *)cpos;
 3476         cookiep = cookies;
 3477         /*
 3478          * For some reason FreeBSD's ufs_readdir() chooses to back the
 3479          * directory offset up to a block boundary, so it is necessary to
 3480          * skip over the records that precede the requested offset. This
 3481          * requires the assumption that file offset cookies monotonically
 3482          * increase.
 3483          */
 3484         while (cpos < cend && ncookies > 0 &&
 3485                 (dp->d_fileno == 0 || dp->d_type == DT_WHT ||
 3486                  ((u_quad_t)(*cookiep)) <= toff)) {
 3487                 cpos += dp->d_reclen;
 3488                 dp = (struct dirent *)cpos;
 3489                 cookiep++;
 3490                 ncookies--;
 3491         }
 3492         if (cpos >= cend || ncookies == 0) {
 3493                 toff = off;
 3494                 siz = fullsiz;
 3495                 goto again;
 3496         }
 3497 
 3498         mtx_unlock(&Giant);     /* VFS */
 3499         NFSD_LOCK();
 3500         len = 3 * NFSX_UNSIGNED;        /* paranoia, probably can be 0 */
 3501         nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz);
 3502         if (v3) {
 3503                 nfsm_srvpostop_attr(getret, &at);
 3504                 tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
 3505                 txdr_hyper(at.va_filerev, tl);
 3506         }
 3507         mp = mb;
 3508         bp = bpos;
 3509         be = bp + M_TRAILINGSPACE(mp);
 3510 
 3511         /* Loop through the records and build reply */
 3512         while (cpos < cend && ncookies > 0) {
 3513                 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
 3514                         nlen = dp->d_namlen;
 3515                         rem = nfsm_rndup(nlen) - nlen;
 3516                         len += (4 * NFSX_UNSIGNED + nlen + rem);
 3517                         if (v3)
 3518                                 len += 2 * NFSX_UNSIGNED;
 3519                         if (len > cnt) {
 3520                                 eofflag = 0;
 3521                                 break;
 3522                         }
 3523                         /*
 3524                          * Build the directory record xdr from
 3525                          * the dirent entry.
 3526                          */
 3527                         nfsm_clget;
 3528                         *tl = nfsrv_nfs_true;
 3529                         bp += NFSX_UNSIGNED;
 3530                         if (v3) {
 3531                                 nfsm_clget;
 3532                                 *tl = 0;
 3533                                 bp += NFSX_UNSIGNED;
 3534                         }
 3535                         nfsm_clget;
 3536                         *tl = txdr_unsigned(dp->d_fileno);
 3537                         bp += NFSX_UNSIGNED;
 3538                         nfsm_clget;
 3539                         *tl = txdr_unsigned(nlen);
 3540                         bp += NFSX_UNSIGNED;
 3541 
 3542                         /* And loop around copying the name */
 3543                         xfer = nlen;
 3544                         cp = dp->d_name;
 3545                         while (xfer > 0) {
 3546                                 nfsm_clget;
 3547                                 if ((bp+xfer) > be)
 3548                                         tsiz = be-bp;
 3549                                 else
 3550                                         tsiz = xfer;
 3551                                 bcopy(cp, bp, tsiz);
 3552                                 bp += tsiz;
 3553                                 xfer -= tsiz;
 3554                                 if (xfer > 0)
 3555                                         cp += tsiz;
 3556                         }
 3557                         /* And null pad to an int32_t boundary. */
 3558                         for (i = 0; i < rem; i++)
 3559                                 *bp++ = '\0';
 3560                         nfsm_clget;
 3561 
 3562                         /* Finish off the record */
 3563                         if (v3) {
 3564                                 *tl = 0;
 3565                                 bp += NFSX_UNSIGNED;
 3566                                 nfsm_clget;
 3567                         }
 3568                         *tl = txdr_unsigned(*cookiep);
 3569                         bp += NFSX_UNSIGNED;
 3570                 }
 3571                 cpos += dp->d_reclen;
 3572                 dp = (struct dirent *)cpos;
 3573                 cookiep++;
 3574                 ncookies--;
 3575         }
 3576         NFSD_UNLOCK();
 3577         mtx_lock(&Giant);       /* VFS */
 3578         vrele(vp);
 3579         mtx_unlock(&Giant);     /* VFS */
 3580         NFSD_LOCK();
 3581         vp = NULL;
 3582         nfsm_clget;
 3583         *tl = nfsrv_nfs_false;
 3584         bp += NFSX_UNSIGNED;
 3585         nfsm_clget;
 3586         if (eofflag)
 3587                 *tl = nfsrv_nfs_true;
 3588         else
 3589                 *tl = nfsrv_nfs_false;
 3590         bp += NFSX_UNSIGNED;
 3591         if (mp != mb) {
 3592                 if (bp < be)
 3593                         mp->m_len = bp - mtod(mp, caddr_t);
 3594         } else
 3595                 mp->m_len += bp - bpos;
 3596         FREE((caddr_t)rbuf, M_TEMP);
 3597         FREE((caddr_t)cookies, M_TEMP);
 3598 
 3599 nfsmout:
 3600         NFSD_LOCK_ASSERT();
 3601         if (vp) {
 3602                 NFSD_UNLOCK();
 3603                 mtx_lock(&Giant);       /* VFS */
 3604                 vrele(vp);
 3605                 mtx_unlock(&Giant);     /* VFS */
 3606                 NFSD_LOCK();
 3607         }
 3608         return(error);
 3609 }
 3610 
 3611 int
 3612 nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 3613     struct thread *td, struct mbuf **mrq)
 3614 {
 3615         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 3616         struct sockaddr *nam = nfsd->nd_nam;
 3617         caddr_t dpos = nfsd->nd_dpos;
 3618         struct ucred *cred = &nfsd->nd_cr;
 3619         char *bp, *be;
 3620         struct mbuf *mp;
 3621         struct dirent *dp;
 3622         caddr_t cp;
 3623         u_int32_t *tl;
 3624         caddr_t bpos;
 3625         struct mbuf *mb, *mreq;
 3626         char *cpos, *cend, *rbuf;
 3627         struct vnode *vp = NULL, *nvp;
 3628         struct flrep fl;
 3629         nfsfh_t nfh;
 3630         fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh;
 3631         struct uio io;
 3632         struct iovec iv;
 3633         struct vattr va, at, *vap = &va;
 3634         struct nfs_fattr *fp;
 3635         int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
 3636         int siz, cnt, fullsiz, eofflag, rdonly, dirlen, ncookies;
 3637         u_quad_t off, toff, verf;
 3638         u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
 3639         int v3 = (nfsd->nd_flag & ND_NFSV3);
 3640 
 3641         NFSD_LOCK_ASSERT();
 3642 
 3643         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 3644         if (!v3)
 3645                 panic("nfsrv_readdirplus: v3 proc called on a v2 connection");
 3646         fhp = &nfh.fh_generic;
 3647         nfsm_srvmtofh(fhp);
 3648         tl = nfsm_dissect(u_int32_t *, 6 * NFSX_UNSIGNED);
 3649         toff = fxdr_hyper(tl);
 3650         tl += 2;
 3651         verf = fxdr_hyper(tl);
 3652         tl += 2;
 3653         siz = fxdr_unsigned(int, *tl++);
 3654         cnt = fxdr_unsigned(int, *tl);
 3655         off = toff;
 3656         siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
 3657         xfer = NFS_SRVMAXDATA(nfsd);
 3658         if (cnt > xfer)
 3659                 cnt = xfer;
 3660         if (siz > xfer)
 3661                 siz = xfer;
 3662         fullsiz = siz;
 3663         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
 3664         if (!error && vp->v_type != VDIR) {
 3665                 error = ENOTDIR;
 3666                 NFSD_UNLOCK();
 3667                 mtx_lock(&Giant);       /* VFS */
 3668                 vput(vp);
 3669                 mtx_unlock(&Giant);     /* VFS */
 3670                 vp = NULL;
 3671                 NFSD_LOCK();
 3672         }
 3673         if (error) {
 3674                 nfsm_reply(NFSX_UNSIGNED);
 3675                 nfsm_srvpostop_attr(getret, &at);
 3676                 error = 0;
 3677                 goto nfsmout;
 3678         }
 3679         NFSD_UNLOCK();
 3680         mtx_lock(&Giant);       /* VFS */
 3681         error = getret = VOP_GETATTR(vp, &at, cred, td);
 3682 #if 0
 3683         /*
 3684          * XXX This check may be too strict for Solaris 2.5 clients.
 3685          */
 3686         if (!error && toff && verf && verf != at.va_filerev)
 3687                 error = NFSERR_BAD_COOKIE;
 3688 #endif
 3689         if (!error)
 3690                 error = nfsrv_access_withgiant(vp, VEXEC, cred, rdonly, td, 0);
 3691         if (error) {
 3692                 vput(vp);
 3693                 mtx_unlock(&Giant);     /* VFS */
 3694                 NFSD_LOCK();
 3695                 vp = NULL;
 3696                 nfsm_reply(NFSX_V3POSTOPATTR);
 3697                 nfsm_srvpostop_attr(getret, &at);
 3698                 error = 0;
 3699                 goto nfsmout;
 3700         }
 3701         VOP_UNLOCK(vp, 0, td);
 3702         MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
 3703 again:
 3704         NFSD_UNLOCK_ASSERT();
 3705         iv.iov_base = rbuf;
 3706         iv.iov_len = fullsiz;
 3707         io.uio_iov = &iv;
 3708         io.uio_iovcnt = 1;
 3709         io.uio_offset = (off_t)off;
 3710         io.uio_resid = fullsiz;
 3711         io.uio_segflg = UIO_SYSSPACE;
 3712         io.uio_rw = UIO_READ;
 3713         io.uio_td = NULL;
 3714         eofflag = 0;
 3715         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
 3716         if (cookies) {
 3717                 free((caddr_t)cookies, M_TEMP);
 3718                 cookies = NULL;
 3719         }
 3720         error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
 3721         off = (u_quad_t)io.uio_offset;
 3722         getret = VOP_GETATTR(vp, &at, cred, td);
 3723         VOP_UNLOCK(vp, 0, td);
 3724         if (!cookies && !error)
 3725                 error = NFSERR_PERM;
 3726         if (!error)
 3727                 error = getret;
 3728         if (error) {
 3729                 vrele(vp);
 3730                 mtx_unlock(&Giant);     /* VFS */
 3731                 vp = NULL;
 3732                 if (cookies)
 3733                         free((caddr_t)cookies, M_TEMP);
 3734                 free((caddr_t)rbuf, M_TEMP);
 3735                 NFSD_LOCK();
 3736                 nfsm_reply(NFSX_V3POSTOPATTR);
 3737                 nfsm_srvpostop_attr(getret, &at);
 3738                 error = 0;
 3739                 goto nfsmout;
 3740         }
 3741         if (io.uio_resid) {
 3742                 siz -= io.uio_resid;
 3743 
 3744                 /*
 3745                  * If nothing read, return eof
 3746                  * rpc reply
 3747                  */
 3748                 if (siz == 0) {
 3749                         vrele(vp);
 3750                         mtx_unlock(&Giant);     /* VFS */
 3751                         NFSD_LOCK();
 3752                         vp = NULL;
 3753                         nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
 3754                                 2 * NFSX_UNSIGNED);
 3755                         nfsm_srvpostop_attr(getret, &at);
 3756                         tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
 3757                         txdr_hyper(at.va_filerev, tl);
 3758                         tl += 2;
 3759                         *tl++ = nfsrv_nfs_false;
 3760                         *tl = nfsrv_nfs_true;
 3761                         FREE((caddr_t)cookies, M_TEMP);
 3762                         FREE((caddr_t)rbuf, M_TEMP);
 3763                         error = 0;
 3764                         goto nfsmout;
 3765                 }
 3766         }
 3767 
 3768         /*
 3769          * Check for degenerate cases of nothing useful read.
 3770          * If so go try again
 3771          */
 3772         cpos = rbuf;
 3773         cend = rbuf + siz;
 3774         dp = (struct dirent *)cpos;
 3775         cookiep = cookies;
 3776         /*
 3777          * For some reason FreeBSD's ufs_readdir() chooses to back the
 3778          * directory offset up to a block boundary, so it is necessary to
 3779          * skip over the records that precede the requested offset. This
 3780          * requires the assumption that file offset cookies monotonically
 3781          * increase.
 3782          */
 3783         while (cpos < cend && ncookies > 0 &&
 3784                 (dp->d_fileno == 0 || dp->d_type == DT_WHT ||
 3785                  ((u_quad_t)(*cookiep)) <= toff)) {
 3786                 cpos += dp->d_reclen;
 3787                 dp = (struct dirent *)cpos;
 3788                 cookiep++;
 3789                 ncookies--;
 3790         }
 3791         if (cpos >= cend || ncookies == 0) {
 3792                 toff = off;
 3793                 siz = fullsiz;
 3794                 goto again;
 3795         }
 3796 
 3797         /*
 3798          * Probe one of the directory entries to see if the filesystem
 3799          * supports VGET.
 3800          */
 3801         if (VFS_VGET(vp->v_mount, dp->d_fileno, LK_EXCLUSIVE, &nvp) ==
 3802             EOPNOTSUPP) {
 3803                 error = NFSERR_NOTSUPP;
 3804                 vrele(vp);
 3805                 mtx_unlock(&Giant);     /* VFS */
 3806                 vp = NULL;
 3807                 free((caddr_t)cookies, M_TEMP);
 3808                 free((caddr_t)rbuf, M_TEMP);
 3809                 NFSD_LOCK();
 3810                 nfsm_reply(NFSX_V3POSTOPATTR);
 3811                 nfsm_srvpostop_attr(getret, &at);
 3812                 error = 0;
 3813                 goto nfsmout;
 3814         }
 3815         vput(nvp);
 3816         mtx_unlock(&Giant);     /* VFS */
 3817         nvp = NULL;
 3818 
 3819         dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
 3820             2 * NFSX_UNSIGNED;
 3821         NFSD_LOCK();
 3822         nfsm_reply(cnt);
 3823         nfsm_srvpostop_attr(getret, &at);
 3824         tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
 3825         txdr_hyper(at.va_filerev, tl);
 3826         mp = mb;
 3827         bp = bpos;
 3828         be = bp + M_TRAILINGSPACE(mp);
 3829 
 3830         NFSD_UNLOCK();
 3831         mtx_lock(&Giant);       /* VFS */
 3832         /* Loop through the records and build reply */
 3833         while (cpos < cend && ncookies > 0) {
 3834                 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
 3835                         nlen = dp->d_namlen;
 3836                         rem = nfsm_rndup(nlen)-nlen;
 3837 
 3838                         /*
 3839                          * For readdir_and_lookup get the vnode using
 3840                          * the file number.
 3841                          */
 3842                         if (VFS_VGET(vp->v_mount, dp->d_fileno, LK_EXCLUSIVE,
 3843                             &nvp))
 3844                                 goto invalid;
 3845                         bzero((caddr_t)nfhp, NFSX_V3FH);
 3846                         nfhp->fh_fsid =
 3847                                 nvp->v_mount->mnt_stat.f_fsid;
 3848                         if (VFS_VPTOFH(nvp, &nfhp->fh_fid)) {
 3849                                 vput(nvp);
 3850                                 nvp = NULL;
 3851                                 goto invalid;
 3852                         }
 3853                         if (VOP_GETATTR(nvp, vap, cred, td)) {
 3854                                 vput(nvp);
 3855                                 nvp = NULL;
 3856                                 goto invalid;
 3857                         }
 3858                         vput(nvp);
 3859                         nvp = NULL;
 3860 
 3861                         /*
 3862                          * If either the dircount or maxcount will be
 3863                          * exceeded, get out now. Both of these lengths
 3864                          * are calculated conservatively, including all
 3865                          * XDR overheads.
 3866                          */
 3867                         len += (8 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH +
 3868                                 NFSX_V3POSTOPATTR);
 3869                         dirlen += (6 * NFSX_UNSIGNED + nlen + rem);
 3870                         if (len > cnt || dirlen > fullsiz) {
 3871                                 eofflag = 0;
 3872                                 break;
 3873                         }
 3874 
 3875                         /*
 3876                          * Build the directory record xdr from
 3877                          * the dirent entry.
 3878                          */
 3879                         fp = (struct nfs_fattr *)&fl.fl_fattr;
 3880                         nfsm_srvfillattr(vap, fp);
 3881                         fl.fl_fhsize = txdr_unsigned(NFSX_V3FH);
 3882                         fl.fl_fhok = nfsrv_nfs_true;
 3883                         fl.fl_postopok = nfsrv_nfs_true;
 3884                         fl.fl_off.nfsuquad[0] = 0;
 3885                         fl.fl_off.nfsuquad[1] = txdr_unsigned(*cookiep);
 3886 
 3887                         nfsm_clget_nolock;
 3888                         *tl = nfsrv_nfs_true;
 3889                         bp += NFSX_UNSIGNED;
 3890                         nfsm_clget_nolock;
 3891                         *tl = 0;
 3892                         bp += NFSX_UNSIGNED;
 3893                         nfsm_clget_nolock;
 3894                         *tl = txdr_unsigned(dp->d_fileno);
 3895                         bp += NFSX_UNSIGNED;
 3896                         nfsm_clget_nolock;
 3897                         *tl = txdr_unsigned(nlen);
 3898                         bp += NFSX_UNSIGNED;
 3899 
 3900                         /* And loop around copying the name */
 3901                         xfer = nlen;
 3902                         cp = dp->d_name;
 3903                         while (xfer > 0) {
 3904                                 nfsm_clget_nolock;
 3905                                 if ((bp + xfer) > be)
 3906                                         tsiz = be - bp;
 3907                                 else
 3908                                         tsiz = xfer;
 3909                                 bcopy(cp, bp, tsiz);
 3910                                 bp += tsiz;
 3911                                 xfer -= tsiz;
 3912                                 if (xfer > 0)
 3913                                         cp += tsiz;
 3914                         }
 3915                         /* And null pad to an int32_t boundary. */
 3916                         for (i = 0; i < rem; i++)
 3917                                 *bp++ = '\0';
 3918 
 3919                         /*
 3920                          * Now copy the flrep structure out.
 3921                          */
 3922                         xfer = sizeof (struct flrep);
 3923                         cp = (caddr_t)&fl;
 3924                         while (xfer > 0) {
 3925                                 nfsm_clget_nolock;
 3926                                 if ((bp + xfer) > be)
 3927                                         tsiz = be - bp;
 3928                                 else
 3929                                         tsiz = xfer;
 3930                                 bcopy(cp, bp, tsiz);
 3931                                 bp += tsiz;
 3932                                 xfer -= tsiz;
 3933                                 if (xfer > 0)
 3934                                         cp += tsiz;
 3935                         }
 3936                 }
 3937 invalid:
 3938                 NFSD_UNLOCK_ASSERT();
 3939                 cpos += dp->d_reclen;
 3940                 dp = (struct dirent *)cpos;
 3941                 cookiep++;
 3942                 ncookies--;
 3943         }
 3944         vrele(vp);
 3945         mtx_unlock(&Giant);     /* VFS */
 3946         vp = NULL;
 3947         nfsm_clget_nolock;
 3948         *tl = nfsrv_nfs_false;
 3949         bp += NFSX_UNSIGNED;
 3950         NFSD_LOCK();
 3951         nfsm_clget;
 3952         if (eofflag)
 3953                 *tl = nfsrv_nfs_true;
 3954         else
 3955                 *tl = nfsrv_nfs_false;
 3956         bp += NFSX_UNSIGNED;
 3957         if (mp != mb) {
 3958                 if (bp < be)
 3959                         mp->m_len = bp - mtod(mp, caddr_t);
 3960         } else
 3961                 mp->m_len += bp - bpos;
 3962         FREE((caddr_t)cookies, M_TEMP);
 3963         FREE((caddr_t)rbuf, M_TEMP);
 3964 nfsmout:
 3965         NFSD_LOCK_ASSERT();
 3966         if (vp) {
 3967                 NFSD_UNLOCK();
 3968                 mtx_lock(&Giant);       /* VFS */
 3969                 vrele(vp);
 3970                 mtx_unlock(&Giant);     /* VFS */
 3971                 NFSD_LOCK();
 3972         }
 3973         return(error);
 3974 }
 3975 
 3976 /*
 3977  * nfs commit service
 3978  */
 3979 int
 3980 nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 3981     struct thread *td, struct mbuf **mrq)
 3982 {
 3983         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 3984         struct sockaddr *nam = nfsd->nd_nam;
 3985         caddr_t dpos = nfsd->nd_dpos;
 3986         struct ucred *cred = &nfsd->nd_cr;
 3987         struct vattr bfor, aft;
 3988         struct vnode *vp = NULL;
 3989         nfsfh_t nfh;
 3990         fhandle_t *fhp;
 3991         u_int32_t *tl;
 3992         caddr_t bpos;
 3993         int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt;
 3994         struct mbuf *mb, *mreq;
 3995         u_quad_t off;
 3996         struct mount *mp = NULL;
 3997         int v3 = (nfsd->nd_flag & ND_NFSV3);
 3998 
 3999         NFSD_LOCK_ASSERT();
 4000 
 4001         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 4002         if (!v3)
 4003                 panic("nfsrv_commit: v3 proc called on a v2 connection");
 4004         fhp = &nfh.fh_generic;
 4005         nfsm_srvmtofh(fhp);
 4006         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
 4007                 error = ESTALE;
 4008                 goto ereply;
 4009         }
 4010         NFSD_UNLOCK();
 4011         mtx_lock(&Giant);       /* VFS */
 4012         (void) vn_start_write(NULL, &mp, V_WAIT);
 4013         mtx_unlock(&Giant);     /* VFS */
 4014         NFSD_LOCK();
 4015         tl = nfsm_dissect(u_int32_t *, 3 * NFSX_UNSIGNED);
 4016 
 4017         /*
 4018          * XXX At this time VOP_FSYNC() does not accept offset and byte
 4019          * count parameters, so these arguments are useless (someday maybe).
 4020          */
 4021         off = fxdr_hyper(tl);
 4022         tl += 2;
 4023         cnt = fxdr_unsigned(int, *tl);
 4024         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
 4025         if (error) {
 4026                 nfsm_reply(2 * NFSX_UNSIGNED);
 4027                 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
 4028                 error = 0;
 4029                 goto nfsmout;
 4030         }
 4031         NFSD_UNLOCK();
 4032         mtx_lock(&Giant);       /* VFS */
 4033         for_ret = VOP_GETATTR(vp, &bfor, cred, td);
 4034 
 4035         if (cnt > MAX_COMMIT_COUNT) {
 4036                 /*
 4037                  * Give up and do the whole thing
 4038                  */
 4039                 if (vp->v_object &&
 4040                    (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
 4041                         VM_OBJECT_LOCK(vp->v_object);
 4042                         vm_object_page_clean(vp->v_object, 0, 0, OBJPC_SYNC);
 4043                         VM_OBJECT_UNLOCK(vp->v_object);
 4044                 }
 4045                 error = VOP_FSYNC(vp, cred, MNT_WAIT, td);
 4046         } else {
 4047                 /*
 4048                  * Locate and synchronously write any buffers that fall
 4049                  * into the requested range.  Note:  we are assuming that
 4050                  * f_iosize is a power of 2.
 4051                  */
 4052                 int iosize = vp->v_mount->mnt_stat.f_iosize;
 4053                 int iomask = iosize - 1;
 4054                 int s;
 4055                 daddr_t lblkno;
 4056 
 4057                 /*
 4058                  * Align to iosize boundry, super-align to page boundry.
 4059                  */
 4060                 if (off & iomask) {
 4061                         cnt += off & iomask;
 4062                         off &= ~(u_quad_t)iomask;
 4063                 }
 4064                 if (off & PAGE_MASK) {
 4065                         cnt += off & PAGE_MASK;
 4066                         off &= ~(u_quad_t)PAGE_MASK;
 4067                 }
 4068                 lblkno = off / iosize;
 4069 
 4070                 if (vp->v_object &&
 4071                    (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
 4072                         VM_OBJECT_LOCK(vp->v_object);
 4073                         vm_object_page_clean(vp->v_object, off / PAGE_SIZE, (cnt + PAGE_MASK) / PAGE_SIZE, OBJPC_SYNC);
 4074                         VM_OBJECT_UNLOCK(vp->v_object);
 4075                 }
 4076 
 4077                 s = splbio();
 4078                 VI_LOCK(vp);
 4079                 while (cnt > 0) {
 4080                         struct buf *bp;
 4081 
 4082                         /*
 4083                          * If we have a buffer and it is marked B_DELWRI we
 4084                          * have to lock and write it.  Otherwise the prior
 4085                          * write is assumed to have already been committed.
 4086                          *
 4087                          * gbincore() can return invalid buffers now so we
 4088                          * have to check that bit as well (though B_DELWRI
 4089                          * should not be set if B_INVAL is set there could be
 4090                          * a race here since we haven't locked the buffer).
 4091                          */
 4092                         if ((bp = gbincore(vp, lblkno)) != NULL) {
 4093                                 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL |
 4094                                     LK_INTERLOCK, VI_MTX(vp)) == ENOLCK) {
 4095                                         VI_LOCK(vp);
 4096                                         continue; /* retry */
 4097                                 }
 4098                                 if ((bp->b_flags & (B_DELWRI|B_INVAL)) ==
 4099                                     B_DELWRI) {
 4100                                         bremfree(bp);
 4101                                         bp->b_flags &= ~B_ASYNC;
 4102                                         bwrite(bp);
 4103                                         ++nfs_commit_miss;
 4104                                 } else
 4105                                         BUF_UNLOCK(bp);
 4106                                 VI_LOCK(vp);
 4107                         }
 4108                         ++nfs_commit_blks;
 4109                         if (cnt < iosize)
 4110                                 break;
 4111                         cnt -= iosize;
 4112                         ++lblkno;
 4113                 }
 4114                 VI_UNLOCK(vp);
 4115                 splx(s);
 4116         }
 4117 
 4118         aft_ret = VOP_GETATTR(vp, &aft, cred, td);
 4119         vput(vp);
 4120         mtx_unlock(&Giant);     /* VFS */
 4121         vp = NULL;
 4122         NFSD_LOCK();
 4123 ereply:
 4124         NFSD_LOCK_ASSERT();
 4125         nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF);
 4126         nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
 4127         if (!error) {
 4128                 tl = nfsm_build(u_int32_t *, NFSX_V3WRITEVERF);
 4129                 if (nfsver.tv_sec == 0)
 4130                         nfsver = boottime;
 4131                 *tl++ = txdr_unsigned(nfsver.tv_sec);
 4132                 *tl = txdr_unsigned(nfsver.tv_usec);
 4133         } else {
 4134                 error = 0;
 4135         }
 4136 nfsmout:
 4137         NFSD_LOCK_ASSERT();
 4138         NFSD_UNLOCK();
 4139         mtx_lock(&Giant);       /* VFS */
 4140         if (vp)
 4141                 vput(vp);
 4142         vn_finished_write(mp);
 4143         mtx_unlock(&Giant);     /* VFS */
 4144         NFSD_LOCK();
 4145         return(error);
 4146 }
 4147 
 4148 /*
 4149  * nfs statfs service
 4150  */
 4151 int
 4152 nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 4153     struct thread *td, struct mbuf **mrq)
 4154 {
 4155         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 4156         struct sockaddr *nam = nfsd->nd_nam;
 4157         caddr_t dpos = nfsd->nd_dpos;
 4158         struct ucred *cred = &nfsd->nd_cr;
 4159         struct statfs *sf;
 4160         struct nfs_statfs *sfp;
 4161         caddr_t bpos;
 4162         int error = 0, rdonly, getret = 1;
 4163         int v3 = (nfsd->nd_flag & ND_NFSV3);
 4164         struct mbuf *mb, *mreq;
 4165         struct vnode *vp = NULL;
 4166         struct vattr at;
 4167         nfsfh_t nfh;
 4168         fhandle_t *fhp;
 4169         struct statfs statfs;
 4170         u_quad_t tval;
 4171 
 4172         NFSD_LOCK_ASSERT();
 4173 
 4174         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 4175         fhp = &nfh.fh_generic;
 4176         nfsm_srvmtofh(fhp);
 4177         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
 4178         if (error) {
 4179                 nfsm_reply(NFSX_UNSIGNED);
 4180                 if (v3)
 4181                         nfsm_srvpostop_attr(getret, &at);
 4182                 error = 0;
 4183                 goto nfsmout;
 4184         }
 4185         sf = &statfs;
 4186         NFSD_UNLOCK();
 4187         mtx_lock(&Giant);       /* VFS */
 4188         error = VFS_STATFS(vp->v_mount, sf, td);
 4189         getret = VOP_GETATTR(vp, &at, cred, td);
 4190         vput(vp);
 4191         mtx_unlock(&Giant);     /* VFS */
 4192         vp = NULL;
 4193         NFSD_LOCK();
 4194         nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3));
 4195         if (v3)
 4196                 nfsm_srvpostop_attr(getret, &at);
 4197         if (error) {
 4198                 error = 0;
 4199                 goto nfsmout;
 4200         }
 4201         sfp = nfsm_build(struct nfs_statfs *, NFSX_STATFS(v3));
 4202         if (v3) {
 4203                 tval = (u_quad_t)sf->f_blocks;
 4204                 tval *= (u_quad_t)sf->f_bsize;
 4205                 txdr_hyper(tval, &sfp->sf_tbytes);
 4206                 tval = (u_quad_t)sf->f_bfree;
 4207                 tval *= (u_quad_t)sf->f_bsize;
 4208                 txdr_hyper(tval, &sfp->sf_fbytes);
 4209                 /*
 4210                  * Don't send negative values for available space,
 4211                  * since this field is unsigned in the NFS protocol.
 4212                  * Otherwise, the client would see absurdly high
 4213                  * numbers for free space.
 4214                  */
 4215                 if (sf->f_bavail < 0)
 4216                         tval = 0;
 4217                 else
 4218                         tval = (u_quad_t)sf->f_bavail;
 4219                 tval *= (u_quad_t)sf->f_bsize;
 4220                 txdr_hyper(tval, &sfp->sf_abytes);
 4221                 sfp->sf_tfiles.nfsuquad[0] = 0;
 4222                 sfp->sf_tfiles.nfsuquad[1] = txdr_unsigned(sf->f_files);
 4223                 sfp->sf_ffiles.nfsuquad[0] = 0;
 4224                 sfp->sf_ffiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
 4225                 sfp->sf_afiles.nfsuquad[0] = 0;
 4226                 sfp->sf_afiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
 4227                 sfp->sf_invarsec = 0;
 4228         } else {
 4229                 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
 4230                 sfp->sf_bsize = txdr_unsigned(sf->f_bsize);
 4231                 sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
 4232                 sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
 4233                 if (sf->f_bavail < 0)
 4234                         sfp->sf_bavail = 0;
 4235                 else
 4236                         sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
 4237         }
 4238 nfsmout:
 4239         NFSD_LOCK_ASSERT();
 4240         if (vp) {
 4241                 NFSD_UNLOCK();
 4242                 mtx_lock(&Giant);       /* VFS */
 4243                 vput(vp);
 4244                 mtx_unlock(&Giant);     /* VFS */
 4245                 NFSD_LOCK();
 4246         }
 4247         return(error);
 4248 }
 4249 
 4250 /*
 4251  * nfs fsinfo service
 4252  */
 4253 int
 4254 nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 4255     struct thread *td, struct mbuf **mrq)
 4256 {
 4257         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 4258         struct sockaddr *nam = nfsd->nd_nam;
 4259         caddr_t dpos = nfsd->nd_dpos;
 4260         struct ucred *cred = &nfsd->nd_cr;
 4261         struct nfsv3_fsinfo *sip;
 4262         caddr_t bpos;
 4263         int error = 0, rdonly, getret = 1, pref;
 4264         struct mbuf *mb, *mreq;
 4265         struct vnode *vp = NULL;
 4266         struct vattr at;
 4267         nfsfh_t nfh;
 4268         fhandle_t *fhp;
 4269         u_quad_t maxfsize;
 4270         struct statfs sb;
 4271         int v3 = (nfsd->nd_flag & ND_NFSV3);
 4272 
 4273         NFSD_LOCK_ASSERT();
 4274 
 4275         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 4276         if (!v3)
 4277                 panic("nfsrv_fsinfo: v3 proc called on a v2 connection");
 4278         fhp = &nfh.fh_generic;
 4279         nfsm_srvmtofh(fhp);
 4280         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
 4281         if (error) {
 4282                 nfsm_reply(NFSX_UNSIGNED);
 4283                 nfsm_srvpostop_attr(getret, &at);
 4284                 error = 0;
 4285                 goto nfsmout;
 4286         }
 4287 
 4288         NFSD_UNLOCK();
 4289         mtx_lock(&Giant);       /* VFS */
 4290         /* XXX Try to make a guess on the max file size. */
 4291         VFS_STATFS(vp->v_mount, &sb, td);
 4292         maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1;
 4293 
 4294         getret = VOP_GETATTR(vp, &at, cred, td);
 4295         vput(vp);
 4296         mtx_unlock(&Giant);     /* VFS */
 4297         vp = NULL;
 4298         NFSD_LOCK();
 4299         nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO);
 4300         nfsm_srvpostop_attr(getret, &at);
 4301         sip = nfsm_build(struct nfsv3_fsinfo *, NFSX_V3FSINFO);
 4302 
 4303         /*
 4304          * XXX
 4305          * There should be filesystem VFS OP(s) to get this information.
 4306          * For now, assume ufs.
 4307          */
 4308         if (slp->ns_so->so_type == SOCK_DGRAM)
 4309                 pref = NFS_MAXDGRAMDATA;
 4310         else
 4311                 pref = NFS_MAXDATA;
 4312         sip->fs_rtmax = txdr_unsigned(pref);
 4313         sip->fs_rtpref = txdr_unsigned(pref);
 4314         sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE);
 4315         sip->fs_wtmax = txdr_unsigned(pref);
 4316         sip->fs_wtpref = txdr_unsigned(pref);
 4317         sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE);
 4318         sip->fs_dtpref = txdr_unsigned(pref);
 4319         txdr_hyper(maxfsize, &sip->fs_maxfilesize);
 4320         sip->fs_timedelta.nfsv3_sec = 0;
 4321         sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1);
 4322         sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK |
 4323                 NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS |
 4324                 NFSV3FSINFO_CANSETTIME);
 4325 nfsmout:
 4326         NFSD_LOCK_ASSERT();
 4327         if (vp) {
 4328                 NFSD_UNLOCK();
 4329                 mtx_lock(&Giant);       /* VFS */
 4330                 vput(vp);
 4331                 mtx_unlock(&Giant);     /* VFS */
 4332                 NFSD_LOCK();
 4333         }
 4334         return(error);
 4335 }
 4336 
 4337 /*
 4338  * nfs pathconf service
 4339  */
 4340 int
 4341 nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 4342     struct thread *td, struct mbuf **mrq)
 4343 {
 4344         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 4345         struct sockaddr *nam = nfsd->nd_nam;
 4346         caddr_t dpos = nfsd->nd_dpos;
 4347         struct ucred *cred = &nfsd->nd_cr;
 4348         struct nfsv3_pathconf *pc;
 4349         caddr_t bpos;
 4350         int error = 0, rdonly, getret = 1;
 4351         register_t linkmax, namemax, chownres, notrunc;
 4352         struct mbuf *mb, *mreq;
 4353         struct vnode *vp = NULL;
 4354         struct vattr at;
 4355         nfsfh_t nfh;
 4356         fhandle_t *fhp;
 4357         int v3 = (nfsd->nd_flag & ND_NFSV3);
 4358 
 4359         NFSD_LOCK_ASSERT();
 4360 
 4361         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 4362         if (!v3)
 4363                 panic("nfsrv_pathconf: v3 proc called on a v2 connection");
 4364         fhp = &nfh.fh_generic;
 4365         nfsm_srvmtofh(fhp);
 4366         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
 4367         if (error) {
 4368                 nfsm_reply(NFSX_UNSIGNED);
 4369                 nfsm_srvpostop_attr(getret, &at);
 4370                 error = 0;
 4371                 goto nfsmout;
 4372         }
 4373         NFSD_UNLOCK();
 4374         mtx_lock(&Giant);       /* VFS */
 4375         error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax);
 4376         if (!error)
 4377                 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax);
 4378         if (!error)
 4379                 error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres);
 4380         if (!error)
 4381                 error = VOP_PATHCONF(vp, _PC_NO_TRUNC, &notrunc);
 4382         getret = VOP_GETATTR(vp, &at, cred, td);
 4383         vput(vp);
 4384         mtx_unlock(&Giant);     /* VFS */
 4385         vp = NULL;
 4386         NFSD_LOCK();
 4387         nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF);
 4388         nfsm_srvpostop_attr(getret, &at);
 4389         if (error) {
 4390                 error = 0;
 4391                 goto nfsmout;
 4392         }
 4393         pc = nfsm_build(struct nfsv3_pathconf *, NFSX_V3PATHCONF);
 4394 
 4395         pc->pc_linkmax = txdr_unsigned(linkmax);
 4396         pc->pc_namemax = txdr_unsigned(namemax);
 4397         pc->pc_notrunc = txdr_unsigned(notrunc);
 4398         pc->pc_chownrestricted = txdr_unsigned(chownres);
 4399 
 4400         /*
 4401          * These should probably be supported by VOP_PATHCONF(), but
 4402          * until msdosfs is exportable (why would you want to?), the
 4403          * Unix defaults should be ok.
 4404          */
 4405         pc->pc_caseinsensitive = nfsrv_nfs_false;
 4406         pc->pc_casepreserving = nfsrv_nfs_true;
 4407 nfsmout:
 4408         NFSD_LOCK_ASSERT();
 4409         if (vp) {
 4410                 NFSD_UNLOCK();
 4411                 mtx_lock(&Giant);       /* VFS */
 4412                 vput(vp);
 4413                 mtx_unlock(&Giant);     /* VFS */
 4414                 NFSD_LOCK();
 4415         }
 4416         return(error);
 4417 }
 4418 
 4419 /*
 4420  * Null operation, used by clients to ping server
 4421  */
 4422 /* ARGSUSED */
 4423 int
 4424 nfsrv_null(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 4425     struct thread *td, struct mbuf **mrq)
 4426 {
 4427         struct mbuf *mrep = nfsd->nd_mrep;
 4428         caddr_t bpos;
 4429         int error = NFSERR_RETVOID;
 4430         struct mbuf *mb, *mreq;
 4431 
 4432         NFSD_LOCK_ASSERT();
 4433 
 4434         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 4435         nfsm_reply(0);
 4436 nfsmout:
 4437         NFSD_LOCK_ASSERT();
 4438         return (error);
 4439 }
 4440 
 4441 /*
 4442  * No operation, used for obsolete procedures
 4443  */
 4444 /* ARGSUSED */
 4445 int
 4446 nfsrv_noop(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;
 4452         struct mbuf *mb, *mreq;
 4453 
 4454         NFSD_LOCK_ASSERT();
 4455 
 4456         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 4457         if (nfsd->nd_repstat)
 4458                 error = nfsd->nd_repstat;
 4459         else
 4460                 error = EPROCUNAVAIL;
 4461         nfsm_reply(0);
 4462         error = 0;
 4463 nfsmout:
 4464         NFSD_LOCK_ASSERT();
 4465         return (error);
 4466 }
 4467 
 4468 /*
 4469  * Perform access checking for vnodes obtained from file handles that would
 4470  * refer to files already opened by a Unix client. You cannot just use
 4471  * vn_writechk() and VOP_ACCESS() for two reasons.
 4472  * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write
 4473  *     case.
 4474  * 2 - The owner is to be given access irrespective of mode bits for some
 4475  *     operations, so that processes that chmod after opening a file don't
 4476  *     break. I don't like this because it opens a security hole, but since
 4477  *     the nfs server opens a security hole the size of a barn door anyhow,
 4478  *     what the heck.
 4479  *
 4480  * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS()
 4481  * will return EPERM instead of EACCESS. EPERM is always an error.
 4482  *
 4483  * There are two versions: one to be called while holding Giant (which is
 4484  * needed due to use of VFS), and the other called with the NFS server lock
 4485  * (which will be dropped and reacquired).  This is necessary because
 4486  * nfsrv_access checks are required from both classes of contexts.
 4487  */
 4488 static int
 4489 nfsrv_access_withgiant(struct vnode *vp, int flags, struct ucred *cred,
 4490     int rdonly, struct thread *td, int override)
 4491 {
 4492         struct vattr vattr;
 4493         int error;
 4494 
 4495         GIANT_REQUIRED;
 4496 
 4497         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 4498 
 4499         if (flags & VWRITE) {
 4500                 /* Just vn_writechk() changed to check rdonly */
 4501                 /*
 4502                  * Disallow write attempts on read-only filesystems;
 4503                  * unless the file is a socket or a block or character
 4504                  * device resident on the filesystem.
 4505                  */
 4506                 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
 4507                         switch (vp->v_type) {
 4508                         case VREG:
 4509                         case VDIR:
 4510                         case VLNK:
 4511                                 return (EROFS);
 4512                         default:
 4513                                 break;
 4514                         }
 4515                 }
 4516                 /*
 4517                  * If there's shared text associated with
 4518                  * the inode, we can't allow writing.
 4519                  */
 4520                 if (vp->v_vflag & VV_TEXT)
 4521                         return (ETXTBSY);
 4522         }
 4523 
 4524         error = VOP_GETATTR(vp, &vattr, cred, td);
 4525         if (error)
 4526                 return (error);
 4527         error = VOP_ACCESS(vp, flags, cred, td);
 4528         /*
 4529          * Allow certain operations for the owner (reads and writes
 4530          * on files that are already open).
 4531          */
 4532         if (override && error == EACCES && cred->cr_uid == vattr.va_uid)
 4533                 error = 0;
 4534         return (error);
 4535 }
 4536 
 4537 static int
 4538 nfsrv_access(struct vnode *vp, int flags, struct ucred *cred, int rdonly,
 4539     struct thread *td, int override)
 4540 {
 4541         int error;
 4542 
 4543         NFSD_LOCK_ASSERT();
 4544 
 4545         NFSD_UNLOCK();
 4546         mtx_lock(&Giant);       /* VFS */
 4547         error = nfsrv_access_withgiant(vp, flags, cred, rdonly, td, override);
 4548         mtx_unlock(&Giant);     /* VFS */
 4549         NFSD_LOCK();
 4550         return (error);
 4551 }

Cache object: 1f4f86db164a3d0ac75332600479697d


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