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

Cache object: 33d2f1cdf86e1ae8e98c7ee20d666f76


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