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

Cache object: a204980d4a72c0a399c7a2e55635d95c


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