The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/nfs/nfs_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 /*      $NetBSD: nfs_serv.c,v 1.94 2005/02/26 22:39:50 perry Exp $      */
    2 
    3 /*
    4  * Copyright (c) 1989, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This code is derived from software contributed to Berkeley by
    8  * Rick Macklem at The University of Guelph.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. Neither the name of the University nor the names of its contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  *
   34  *      @(#)nfs_serv.c  8.8 (Berkeley) 7/31/95
   35  */
   36 
   37 /*
   38  * nfs version 2 and 3 server calls to vnode ops
   39  * - these routines generally have 3 phases
   40  *   1 - break down and validate rpc request in mbuf list
   41  *   2 - do the vnode ops for the request
   42  *       (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c)
   43  *   3 - build the rpc reply in an mbuf list
   44  *   nb:
   45  *      - do not mix the phases, since the nfsm_?? macros can return failures
   46  *        on a bad rpc or similar and do not do any vrele() or vput()'s
   47  *
   48  *      - the nfsm_reply() macro generates an nfs rpc reply with the nfs
   49  *      error number iff error != 0 whereas
   50  *      returning an error from the server function implies a fatal error
   51  *      such as a badly constructed rpc request that should be dropped without
   52  *      a reply.
   53  *      For Version 3, nfsm_reply() does not return for the error case, since
   54  *      most version 3 rpcs return more than the status for error cases.
   55  */
   56 
   57 #include <sys/cdefs.h>
   58 __KERNEL_RCSID(0, "$NetBSD: nfs_serv.c,v 1.94 2005/02/26 22:39:50 perry Exp $");
   59 
   60 #include <sys/param.h>
   61 #include <sys/systm.h>
   62 #include <sys/proc.h>
   63 #include <sys/file.h>
   64 #include <sys/namei.h>
   65 #include <sys/vnode.h>
   66 #include <sys/mount.h>
   67 #include <sys/socket.h>
   68 #include <sys/socketvar.h>
   69 #include <sys/mbuf.h>
   70 #include <sys/dirent.h>
   71 #include <sys/stat.h>
   72 #include <sys/kernel.h>
   73 #include <ufs/ufs/dir.h>
   74 
   75 #include <uvm/uvm.h>
   76 
   77 #include <nfs/nfsproto.h>
   78 #include <nfs/rpcv2.h>
   79 #include <nfs/nfs.h>
   80 #include <nfs/xdr_subs.h>
   81 #include <nfs/nfsm_subs.h>
   82 #include <nfs/nqnfs.h>
   83 #include <nfs/nfs_var.h>
   84 
   85 /* Global vars */
   86 extern u_int32_t nfs_xdrneg1;
   87 extern u_int32_t nfs_false, nfs_true;
   88 extern enum vtype nv3tov_type[8];
   89 extern struct nfsstats nfsstats;
   90 extern const nfstype nfsv2_type[9];
   91 extern const nfstype nfsv3_type[9];
   92 int nfsrvw_procrastinate = NFS_GATHERDELAY * 1000;
   93 int nfsd_use_loan = 1;  /* use page-loan for READ OP */
   94 
   95 /*
   96  * nfs v3 access service
   97  */
   98 int
   99 nfsrv3_access(nfsd, slp, procp, mrq)
  100         struct nfsrv_descript *nfsd;
  101         struct nfssvc_sock *slp;
  102         struct proc *procp;
  103         struct mbuf **mrq;
  104 {
  105         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
  106         struct mbuf *nam = nfsd->nd_nam;
  107         caddr_t dpos = nfsd->nd_dpos;
  108         struct ucred *cred = &nfsd->nd_cr;
  109         struct vnode *vp;
  110         nfsfh_t nfh;
  111         fhandle_t *fhp;
  112         u_int32_t *tl;
  113         int32_t t1;
  114         caddr_t bpos;
  115         int error = 0, rdonly, cache = 0, getret;
  116         char *cp2;
  117         struct mbuf *mb, *mreq;
  118         struct vattr va;
  119         u_long inmode, testmode, outmode;
  120         u_quad_t frev;
  121 
  122         fhp = &nfh.fh_generic;
  123         nfsm_srvmtofh(fhp);
  124         nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
  125         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
  126             (nfsd->nd_flag & ND_KERBAUTH), FALSE);
  127         if (error) {
  128                 nfsm_reply(NFSX_UNSIGNED);
  129                 nfsm_srvpostop_attr(1, (struct vattr *)0);
  130                 return (0);
  131         }
  132         inmode = fxdr_unsigned(u_int32_t, *tl);
  133         outmode = 0;
  134         if ((inmode & NFSV3ACCESS_READ) &&
  135             nfsrv_access(vp, VREAD, cred, rdonly, procp, 0) == 0)
  136                 outmode |= NFSV3ACCESS_READ;
  137         if (vp->v_type != VDIR) {
  138                 testmode = inmode & (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
  139                 if (testmode &&
  140                     nfsrv_access(vp, VWRITE, cred, rdonly, procp, 0) == 0)
  141                         outmode |= testmode;
  142                 if ((inmode & NFSV3ACCESS_EXECUTE) &&
  143                     nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0) == 0)
  144                         outmode |= NFSV3ACCESS_EXECUTE;
  145         } else {
  146                 testmode = inmode & (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
  147                     NFSV3ACCESS_DELETE);
  148                 if (testmode &&
  149                     nfsrv_access(vp, VWRITE, cred, rdonly, procp, 0) == 0)
  150                         outmode |= testmode;
  151                 if ((inmode & NFSV3ACCESS_LOOKUP) &&
  152                     nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0) == 0)
  153                         outmode |= NFSV3ACCESS_LOOKUP;
  154         }
  155         getret = VOP_GETATTR(vp, &va, cred, procp);
  156         vput(vp);
  157         nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED);
  158         nfsm_srvpostop_attr(getret, &va);
  159         nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
  160         *tl = txdr_unsigned(outmode);
  161         nfsm_srvdone;
  162 }
  163 
  164 /*
  165  * nfs getattr service
  166  */
  167 int
  168 nfsrv_getattr(nfsd, slp, procp, mrq)
  169         struct nfsrv_descript *nfsd;
  170         struct nfssvc_sock *slp;
  171         struct proc *procp;
  172         struct mbuf **mrq;
  173 {
  174         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
  175         struct mbuf *nam = nfsd->nd_nam;
  176         caddr_t dpos = nfsd->nd_dpos;
  177         struct ucred *cred = &nfsd->nd_cr;
  178         struct nfs_fattr *fp;
  179         struct vattr va;
  180         struct vnode *vp;
  181         nfsfh_t nfh;
  182         fhandle_t *fhp;
  183         u_int32_t *tl;
  184         int32_t t1;
  185         caddr_t bpos;
  186         int error = 0, rdonly, cache;
  187         char *cp2;
  188         struct mbuf *mb, *mreq;
  189         u_quad_t frev;
  190 
  191         fhp = &nfh.fh_generic;
  192         nfsm_srvmtofh(fhp);
  193         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
  194             (nfsd->nd_flag & ND_KERBAUTH), FALSE);
  195         if (error) {
  196                 nfsm_reply(0);
  197                 return (0);
  198         }
  199         nqsrv_getl(vp, ND_READ);
  200         error = VOP_GETATTR(vp, &va, cred, procp);
  201         vput(vp);
  202         nfsm_reply(NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
  203         if (error)
  204                 return (0);
  205         nfsm_build(fp, struct nfs_fattr *, NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
  206         nfsm_srvfillattr(&va, fp);
  207         nfsm_srvdone;
  208 }
  209 
  210 /*
  211  * nfs setattr service
  212  */
  213 int
  214 nfsrv_setattr(nfsd, slp, procp, mrq)
  215         struct nfsrv_descript *nfsd;
  216         struct nfssvc_sock *slp;
  217         struct proc *procp;
  218         struct mbuf **mrq;
  219 {
  220         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
  221         struct mbuf *nam = nfsd->nd_nam;
  222         caddr_t dpos = nfsd->nd_dpos;
  223         struct ucred *cred = &nfsd->nd_cr;
  224         struct vattr va, preat;
  225         struct nfsv2_sattr *sp;
  226         struct nfs_fattr *fp;
  227         struct vnode *vp;
  228         nfsfh_t nfh;
  229         fhandle_t *fhp;
  230         u_int32_t *tl;
  231         int32_t t1;
  232         caddr_t bpos;
  233         int error = 0, rdonly, cache, preat_ret = 1, postat_ret = 1;
  234         int v3 = (nfsd->nd_flag & ND_NFSV3), gcheck = 0;
  235         char *cp2;
  236         struct mbuf *mb, *mreq;
  237         u_quad_t frev;
  238         struct timespec guard;
  239         struct mount *mp = NULL;
  240 
  241         fhp = &nfh.fh_generic;
  242         nfsm_srvmtofh(fhp);
  243         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL)
  244                 return (ESTALE);
  245         vn_start_write(NULL, &mp, V_WAIT);
  246         VATTR_NULL(&va);
  247         if (v3) {
  248                 nfsm_srvsattr(&va);
  249                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
  250                 gcheck = fxdr_unsigned(int, *tl);
  251                 if (gcheck) {
  252                         nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
  253                         fxdr_nfsv3time(tl, &guard);
  254                 }
  255         } else {
  256                 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
  257                 /*
  258                  * Nah nah nah nah na nah
  259                  * There is a bug in the Sun client that puts 0xffff in the mode
  260                  * field of sattr when it should put in 0xffffffff. The u_short
  261                  * doesn't sign extend.
  262                  * --> check the low order 2 bytes for 0xffff
  263                  */
  264                 if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
  265                         va.va_mode = nfstov_mode(sp->sa_mode);
  266                 if (sp->sa_uid != nfs_xdrneg1)
  267                         va.va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
  268                 if (sp->sa_gid != nfs_xdrneg1)
  269                         va.va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
  270                 if (sp->sa_size != nfs_xdrneg1)
  271                         va.va_size = fxdr_unsigned(u_quad_t, sp->sa_size);
  272                 if (sp->sa_atime.nfsv2_sec != nfs_xdrneg1) {
  273 #ifdef notyet
  274                         fxdr_nfsv2time(&sp->sa_atime, &va.va_atime);
  275 #else
  276                         va.va_atime.tv_sec =
  277                                 fxdr_unsigned(u_int32_t,sp->sa_atime.nfsv2_sec);
  278                         va.va_atime.tv_nsec = 0;
  279 #endif
  280                 }
  281                 if (sp->sa_mtime.nfsv2_sec != nfs_xdrneg1)
  282                         fxdr_nfsv2time(&sp->sa_mtime, &va.va_mtime);
  283 
  284         }
  285 
  286         /*
  287          * Now that we have all the fields, lets do it.
  288          */
  289         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
  290             (nfsd->nd_flag & ND_KERBAUTH), FALSE);
  291         if (error) {
  292                 nfsm_reply(2 * NFSX_UNSIGNED);
  293                 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, &va);
  294                 vn_finished_write(mp, 0);
  295                 return (0);
  296         }
  297         nqsrv_getl(vp, ND_WRITE);
  298         if (v3) {
  299                 error = preat_ret = VOP_GETATTR(vp, &preat, cred, procp);
  300                 if (!error && gcheck &&
  301                         (preat.va_ctime.tv_sec != guard.tv_sec ||
  302                          preat.va_ctime.tv_nsec != guard.tv_nsec))
  303                         error = NFSERR_NOT_SYNC;
  304                 if (error) {
  305                         vput(vp);
  306                         nfsm_reply(NFSX_WCCDATA(v3));
  307                         nfsm_srvwcc_data(preat_ret, &preat, postat_ret, &va);
  308                         vn_finished_write(mp, 0);
  309                         return (0);
  310                 }
  311         }
  312 
  313         /*
  314          * If the size is being changed write acces is required, otherwise
  315          * just check for a read only file system.
  316          */
  317         if (va.va_size == ((u_quad_t)((quad_t) -1))) {
  318                 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
  319                         error = EROFS;
  320                         goto out;
  321                 }
  322         } else {
  323                 if (vp->v_type == VDIR) {
  324                         error = EISDIR;
  325                         goto out;
  326                 } else if ((error = nfsrv_access(vp, VWRITE, cred, rdonly,
  327                         procp, 0)) != 0)
  328                         goto out;
  329         }
  330         error = VOP_SETATTR(vp, &va, cred, procp);
  331         postat_ret = VOP_GETATTR(vp, &va, cred, procp);
  332         if (!error)
  333                 error = postat_ret;
  334 out:
  335         vput(vp);
  336         vn_finished_write(mp, 0);
  337         nfsm_reply(NFSX_WCCORFATTR(v3));
  338         if (v3) {
  339                 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, &va);
  340                 return (0);
  341         } else {
  342                 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
  343                 nfsm_srvfillattr(&va, fp);
  344         }
  345         nfsm_srvdone;
  346 }
  347 
  348 /*
  349  * nfs lookup rpc
  350  */
  351 int
  352 nfsrv_lookup(nfsd, slp, procp, mrq)
  353         struct nfsrv_descript *nfsd;
  354         struct nfssvc_sock *slp;
  355         struct proc *procp;
  356         struct mbuf **mrq;
  357 {
  358         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
  359         struct mbuf *nam = nfsd->nd_nam;
  360         caddr_t dpos = nfsd->nd_dpos;
  361         struct ucred *cred = &nfsd->nd_cr;
  362         struct nfs_fattr *fp;
  363         struct nameidata nd, ind, *ndp = &nd;
  364         struct vnode *vp, *dirp;
  365         nfsfh_t nfh;
  366         fhandle_t *fhp;
  367         caddr_t cp;
  368         u_int32_t *tl;
  369         int32_t t1;
  370         caddr_t bpos;
  371         int error = 0, cache, dirattr_ret = 1;
  372         uint32_t len;
  373         int v3 = (nfsd->nd_flag & ND_NFSV3), pubflag;
  374         char *cp2;
  375         struct mbuf *mb, *mreq;
  376         struct vattr va, dirattr;
  377         u_quad_t frev;
  378 
  379         fhp = &nfh.fh_generic;
  380         nfsm_srvmtofh(fhp);
  381         nfsm_srvnamesiz(len);
  382 
  383         pubflag = nfs_ispublicfh(fhp);
  384 
  385         nd.ni_cnd.cn_cred = cred;
  386         nd.ni_cnd.cn_nameiop = LOOKUP;
  387         nd.ni_cnd.cn_flags = LOCKLEAF | SAVESTART;
  388         error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
  389                 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), pubflag);
  390 
  391         if (!error && pubflag) {
  392                 if (nd.ni_vp->v_type == VDIR && nfs_pub.np_index != NULL) {
  393                         /*
  394                          * Setup call to lookup() to see if we can find
  395                          * the index file. Arguably, this doesn't belong
  396                          * in a kernel.. Ugh.
  397                          */
  398                         ind = nd;
  399                         VOP_UNLOCK(nd.ni_vp, 0);
  400                         ind.ni_pathlen = strlen(nfs_pub.np_index);
  401                         ind.ni_cnd.cn_nameptr = ind.ni_cnd.cn_pnbuf =
  402                             nfs_pub.np_index;
  403                         ind.ni_startdir = nd.ni_vp;
  404                         VREF(ind.ni_startdir);
  405                         error = lookup(&ind);
  406                         if (!error) {
  407                                 /*
  408                                  * Found an index file. Get rid of
  409                                  * the old references.
  410                                  */
  411                                 if (dirp)
  412                                         vrele(dirp);
  413                                 dirp = nd.ni_vp;
  414                                 vrele(nd.ni_startdir);
  415                                 ndp = &ind;
  416                         } else
  417                                 error = 0;
  418                 }
  419                 /*
  420                  * If the public filehandle was used, check that this lookup
  421                  * didn't result in a filehandle outside the publicly exported
  422                  * filesystem.
  423                  */
  424 
  425                 if (!error && ndp->ni_vp->v_mount != nfs_pub.np_mount) {
  426                         vput(nd.ni_vp);
  427                         error = EPERM;
  428                 }
  429         }
  430 
  431         if (dirp) {
  432                 if (v3)
  433                         dirattr_ret = VOP_GETATTR(dirp, &dirattr, cred,
  434                                 procp);
  435                 vrele(dirp);
  436         }
  437 
  438         if (error) {
  439                 nfsm_reply(NFSX_POSTOPATTR(v3));
  440                 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
  441                 return (0);
  442         }
  443 
  444         nqsrv_getl(ndp->ni_startdir, ND_READ);
  445         vrele(ndp->ni_startdir);
  446         PNBUF_PUT(nd.ni_cnd.cn_pnbuf);
  447         vp = ndp->ni_vp;
  448         memset((caddr_t)fhp, 0, sizeof(nfh));
  449         fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsidx;
  450         error = VFS_VPTOFH(vp, &fhp->fh_fid);
  451         if (!error)
  452                 error = VOP_GETATTR(vp, &va, cred, procp);
  453         vput(vp);
  454         nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPORFATTR(v3) + NFSX_POSTOPATTR(v3));
  455         if (error) {
  456                 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
  457                 return (0);
  458         }
  459         nfsm_srvfhtom(fhp, v3);
  460         if (v3) {
  461                 nfsm_srvpostop_attr(0, &va);
  462                 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
  463         } else {
  464                 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
  465                 nfsm_srvfillattr(&va, fp);
  466         }
  467         nfsm_srvdone;
  468 }
  469 
  470 /*
  471  * nfs readlink service
  472  */
  473 int
  474 nfsrv_readlink(nfsd, slp, procp, mrq)
  475         struct nfsrv_descript *nfsd;
  476         struct nfssvc_sock *slp;
  477         struct proc *procp;
  478         struct mbuf **mrq;
  479 {
  480         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
  481         struct mbuf *nam = nfsd->nd_nam;
  482         caddr_t dpos = nfsd->nd_dpos;
  483         struct ucred *cred = &nfsd->nd_cr;
  484         struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
  485         struct iovec *ivp = iv;
  486         struct mbuf *mp;
  487         u_int32_t *tl;
  488         int32_t t1;
  489         caddr_t bpos;
  490         int error = 0, rdonly, cache, i, padlen, getret;
  491         uint32_t len;
  492         int v3 = (nfsd->nd_flag & ND_NFSV3);
  493         char *cp2;
  494         struct mbuf *mb, *mp2 = NULL, *mp3 = NULL, *mreq;
  495         struct vnode *vp;
  496         struct vattr attr;
  497         nfsfh_t nfh;
  498         fhandle_t *fhp;
  499         struct uio io, *uiop = &io;
  500         u_quad_t frev;
  501 
  502         fhp = &nfh.fh_generic;
  503         nfsm_srvmtofh(fhp);
  504         len = 0;
  505         i = 0;
  506         while (len < NFS_MAXPATHLEN) {
  507                 mp = m_get(M_WAIT, MT_DATA);
  508                 MCLAIM(mp, &nfs_mowner);
  509                 m_clget(mp, M_WAIT);
  510                 mp->m_len = NFSMSIZ(mp);
  511                 if (len == 0)
  512                         mp3 = mp2 = mp;
  513                 else {
  514                         mp2->m_next = mp;
  515                         mp2 = mp;
  516                 }
  517                 if ((len+mp->m_len) > NFS_MAXPATHLEN) {
  518                         mp->m_len = NFS_MAXPATHLEN-len;
  519                         len = NFS_MAXPATHLEN;
  520                 } else
  521                         len += mp->m_len;
  522                 ivp->iov_base = mtod(mp, caddr_t);
  523                 ivp->iov_len = mp->m_len;
  524                 i++;
  525                 ivp++;
  526         }
  527         uiop->uio_iov = iv;
  528         uiop->uio_iovcnt = i;
  529         uiop->uio_offset = 0;
  530         uiop->uio_resid = len;
  531         uiop->uio_rw = UIO_READ;
  532         uiop->uio_segflg = UIO_SYSSPACE;
  533         uiop->uio_procp = NULL;
  534         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
  535                  &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
  536         if (error) {
  537                 m_freem(mp3);
  538                 nfsm_reply(2 * NFSX_UNSIGNED);
  539                 nfsm_srvpostop_attr(1, (struct vattr *)0);
  540                 return (0);
  541         }
  542         if (vp->v_type != VLNK) {
  543                 if (v3)
  544                         error = EINVAL;
  545                 else
  546                         error = ENXIO;
  547                 goto out;
  548         }
  549         nqsrv_getl(vp, ND_READ);
  550         error = VOP_READLINK(vp, uiop, cred);
  551 out:
  552         getret = VOP_GETATTR(vp, &attr, cred, procp);
  553         vput(vp);
  554         if (error)
  555                 m_freem(mp3);
  556         nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_UNSIGNED);
  557         if (v3) {
  558                 nfsm_srvpostop_attr(getret, &attr);
  559                 if (error)
  560                         return (0);
  561         }
  562         len -= uiop->uio_resid;
  563         padlen = nfsm_padlen(len);
  564         if (uiop->uio_resid || padlen)
  565                 nfs_zeropad(mp3, uiop->uio_resid, padlen);
  566         nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
  567         *tl = txdr_unsigned(len);
  568         mb->m_next = mp3;
  569         nfsm_srvdone;
  570 }
  571 
  572 /*
  573  * nfs read service
  574  */
  575 int
  576 nfsrv_read(nfsd, slp, procp, mrq)
  577         struct nfsrv_descript *nfsd;
  578         struct nfssvc_sock *slp;
  579         struct proc *procp;
  580         struct mbuf **mrq;
  581 {
  582         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
  583         struct mbuf *nam = nfsd->nd_nam;
  584         caddr_t dpos = nfsd->nd_dpos;
  585         struct ucred *cred = &nfsd->nd_cr;
  586         struct mbuf *m;
  587         struct nfs_fattr *fp;
  588         u_int32_t *tl;
  589         int32_t t1;
  590         int i;
  591         caddr_t bpos;
  592         int error = 0, rdonly, cache, getret;
  593         int v3 = (nfsd->nd_flag & ND_NFSV3);
  594         uint32_t reqlen, len, cnt, left;
  595         int padlen;
  596         char *cp2;
  597         struct mbuf *mb, *mreq;
  598         struct vnode *vp;
  599         nfsfh_t nfh;
  600         fhandle_t *fhp;
  601         struct uio io, *uiop = &io;
  602         struct vattr va;
  603         off_t off;
  604         u_quad_t frev;
  605 
  606         fhp = &nfh.fh_generic;
  607         nfsm_srvmtofh(fhp);
  608         if (v3) {
  609                 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
  610                 off = fxdr_hyper(tl);
  611         } else {
  612                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
  613                 off = (off_t)fxdr_unsigned(u_int32_t, *tl);
  614         }
  615         nfsm_dissect(tl, uint32_t *, NFSX_UNSIGNED);
  616         reqlen = fxdr_unsigned(uint32_t, *tl);
  617         reqlen = MIN(reqlen, NFS_SRVMAXDATA(nfsd));
  618         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
  619                  &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
  620         if (error) {
  621                 nfsm_reply(2 * NFSX_UNSIGNED);
  622                 nfsm_srvpostop_attr(1, (struct vattr *)0);
  623                 return (0);
  624         }
  625         if (vp->v_type != VREG) {
  626                 if (v3)
  627                         error = EINVAL;
  628                 else
  629                         error = (vp->v_type == VDIR) ? EISDIR : EACCES;
  630         }
  631         if (!error) {
  632             nqsrv_getl(vp, ND_READ);
  633             if ((error = nfsrv_access(vp, VREAD, cred, rdonly, procp, 1)) != 0)
  634                 error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 1);
  635         }
  636         getret = VOP_GETATTR(vp, &va, cred, procp);
  637         if (!error)
  638                 error = getret;
  639         if (error) {
  640                 vput(vp);
  641                 nfsm_reply(NFSX_POSTOPATTR(v3));
  642                 nfsm_srvpostop_attr(getret, &va);
  643                 return (0);
  644         }
  645         if (off >= va.va_size)
  646                 cnt = 0;
  647         else if ((off + reqlen) > va.va_size)
  648                 cnt = va.va_size - off;
  649         else
  650                 cnt = reqlen;
  651         nfsm_reply(NFSX_POSTOPORFATTR(v3) + 3 * NFSX_UNSIGNED+nfsm_rndup(cnt));
  652         if (v3) {
  653                 nfsm_build(tl, u_int32_t *, NFSX_V3FATTR + 4 * NFSX_UNSIGNED);
  654                 *tl++ = nfs_true;
  655                 fp = (struct nfs_fattr *)tl;
  656                 tl += (NFSX_V3FATTR / sizeof (u_int32_t));
  657         } else {
  658                 nfsm_build(tl, u_int32_t *, NFSX_V2FATTR + NFSX_UNSIGNED);
  659                 fp = (struct nfs_fattr *)tl;
  660                 tl += (NFSX_V2FATTR / sizeof (u_int32_t));
  661         }
  662         len = left = cnt;
  663         if (cnt > 0) {
  664                 if (nfsd_use_loan) {
  665                         struct vm_page **pgpp;
  666                         voff_t pgoff = trunc_page(off);
  667                         int npages;
  668                         vaddr_t lva;
  669 
  670                         npages = (round_page(off + cnt) - pgoff) >> PAGE_SHIFT;
  671                         KASSERT(npages <= M_EXT_MAXPAGES); /* XXX */
  672 
  673                         /* allocate kva for mbuf data */
  674                         lva = sokvaalloc(npages << PAGE_SHIFT, slp->ns_so);
  675                         if (lva == 0) {
  676                                 /* fall back to VOP_READ */
  677                                 goto loan_fail;
  678                         }
  679 
  680                         /* allocate mbuf */
  681                         m = m_get(M_WAIT, MT_DATA);
  682                         MCLAIM(m, &nfs_mowner);
  683                         pgpp = m->m_ext.ext_pgs;
  684 
  685                         /* loan pages */
  686                         error = uvm_loanuobjpages(&vp->v_uobj, pgoff, npages,
  687                             pgpp);
  688                         if (error) {
  689                                 sokvafree(lva, npages << PAGE_SHIFT);
  690                                 m_free(m);
  691                                 if (error == EBUSY)
  692                                         goto loan_fail;
  693                                 goto read_error;
  694                         }
  695 
  696                         /* associate kva to mbuf */
  697                         MEXTADD(m, (void *)(lva + ((vaddr_t)off & PAGE_MASK)),
  698                             cnt, M_MBUF, soloanfree, slp->ns_so);
  699                         m->m_flags |= M_EXT_PAGES | M_EXT_ROMAP;
  700                         m->m_len = cnt;
  701 
  702                         /* map pages */
  703                         for (i = 0; i < npages; i++) {
  704                                 pmap_kenter_pa(lva, VM_PAGE_TO_PHYS(pgpp[i]),
  705                                     VM_PROT_READ);
  706                                 lva += PAGE_SIZE;
  707                         }
  708 
  709                         pmap_update(pmap_kernel());
  710 
  711                         mb->m_next = m;
  712                         mb = m;
  713                         error = 0;
  714                         uiop->uio_resid = 0;
  715                 } else {
  716                         struct iovec *iv;
  717                         struct iovec *iv2;
  718                         struct mbuf *m2;
  719                         int siz;
  720 loan_fail:
  721                         /*
  722                          * Generate the mbuf list with the uio_iov ref. to it.
  723                          */
  724                         i = 0;
  725                         m = m2 = mb;
  726                         while (left > 0) {
  727                                 siz = min(M_TRAILINGSPACE(m), left);
  728                                 if (siz > 0) {
  729                                         left -= siz;
  730                                         i++;
  731                                 }
  732                                 if (left > 0) {
  733                                         m = m_get(M_WAIT, MT_DATA);
  734                                         MCLAIM(m, &nfs_mowner);
  735                                         m_clget(m, M_WAIT);
  736                                         m->m_len = 0;
  737                                         m2->m_next = m;
  738                                         m2 = m;
  739                                 }
  740                         }
  741                         iv = malloc(i * sizeof(struct iovec), M_TEMP, M_WAITOK);
  742                         uiop->uio_iov = iv2 = iv;
  743                         m = mb;
  744                         left = cnt;
  745                         i = 0;
  746                         while (left > 0) {
  747                                 if (m == NULL)
  748                                         panic("nfsrv_read iov");
  749                                 siz = min(M_TRAILINGSPACE(m), left);
  750                                 if (siz > 0) {
  751                                         iv->iov_base = mtod(m, caddr_t) +
  752                                             m->m_len;
  753                                         iv->iov_len = siz;
  754                                         m->m_len += siz;
  755                                         left -= siz;
  756                                         iv++;
  757                                         i++;
  758                                 }
  759                                 m = m->m_next;
  760                         }
  761                         uiop->uio_iovcnt = i;
  762                         uiop->uio_offset = off;
  763                         uiop->uio_resid = cnt;
  764                         uiop->uio_rw = UIO_READ;
  765                         uiop->uio_segflg = UIO_SYSSPACE;
  766                         error = VOP_READ(vp, uiop, IO_NODELOCKED, cred);
  767                         free((caddr_t)iv2, M_TEMP);
  768                 }
  769 read_error:
  770                 if (error || (getret = VOP_GETATTR(vp, &va, cred, procp)) != 0){
  771                         if (!error)
  772                                 error = getret;
  773                         m_freem(mreq);
  774                         vput(vp);
  775                         nfsm_reply(NFSX_POSTOPATTR(v3));
  776                         nfsm_srvpostop_attr(getret, &va);
  777                         return (0);
  778                 }
  779         } else {
  780                 uiop->uio_resid = 0;
  781         }
  782         vput(vp);
  783         nfsm_srvfillattr(&va, fp);
  784         len -= uiop->uio_resid;
  785         padlen = nfsm_padlen(len);
  786         if (uiop->uio_resid || padlen)
  787                 nfs_zeropad(mb, uiop->uio_resid, padlen);
  788         if (v3) {
  789                 /* count */
  790                 *tl++ = txdr_unsigned(len);
  791                 /* eof */
  792                 if (off + len >= va.va_size)
  793                         *tl++ = nfs_true;
  794                 else
  795                         *tl++ = nfs_false;
  796         }
  797         *tl = txdr_unsigned(len);
  798         nfsm_srvdone;
  799 }
  800 
  801 /*
  802  * nfs write service
  803  */
  804 int
  805 nfsrv_write(nfsd, slp, procp, mrq)
  806         struct nfsrv_descript *nfsd;
  807         struct nfssvc_sock *slp;
  808         struct proc *procp;
  809         struct mbuf **mrq;
  810 {
  811         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
  812         struct mbuf *nam = nfsd->nd_nam;
  813         caddr_t dpos = nfsd->nd_dpos;
  814         struct ucred *cred = &nfsd->nd_cr;
  815         struct iovec *ivp;
  816         int i, cnt;
  817         struct mbuf *mp;
  818         struct nfs_fattr *fp;
  819         struct iovec *iv;
  820         struct vattr va, forat;
  821         u_int32_t *tl;
  822         int32_t t1;
  823         caddr_t bpos;
  824         int error = 0, rdonly, cache, len, forat_ret = 1;
  825         int ioflags, aftat_ret = 1, retlen, zeroing, adjust;
  826         int stable = NFSV3WRITE_FILESYNC;
  827         int v3 = (nfsd->nd_flag & ND_NFSV3);
  828         char *cp2;
  829         struct mbuf *mb, *mreq;
  830         struct vnode *vp;
  831         nfsfh_t nfh;
  832         fhandle_t *fhp;
  833         struct uio io, *uiop = &io;
  834         off_t off;
  835         u_quad_t frev;
  836         struct mount *mntp = NULL;
  837 
  838         if (mrep == NULL) {
  839                 *mrq = NULL;
  840                 return (0);
  841         }
  842         fhp = &nfh.fh_generic;
  843         nfsm_srvmtofh(fhp);
  844         if ((mntp = vfs_getvfs(&fhp->fh_fsid)) == NULL)
  845                 return (ESTALE);
  846         vn_start_write(NULL, &mntp, V_WAIT);
  847         if (v3) {
  848                 nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
  849                 off = fxdr_hyper(tl);
  850                 tl += 3;
  851                 stable = fxdr_unsigned(int, *tl++);
  852         } else {
  853                 nfsm_dissect(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
  854                 off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
  855                 tl += 2;
  856         }
  857         retlen = len = fxdr_unsigned(int32_t, *tl);
  858         cnt = i = 0;
  859 
  860         /*
  861          * For NFS Version 2, it is not obvious what a write of zero length
  862          * should do, but I might as well be consistent with Version 3,
  863          * which is to return ok so long as there are no permission problems.
  864          */
  865         if (len > 0) {
  866                 zeroing = 1;
  867                 mp = mrep;
  868                 while (mp) {
  869                         if (mp == md) {
  870                                 zeroing = 0;
  871                                 adjust = dpos - mtod(mp, caddr_t);
  872                                 mp->m_len -= adjust;
  873                                 if (mp->m_len > 0 && adjust > 0)
  874                                         NFSMADV(mp, adjust);
  875                         }
  876                         if (zeroing)
  877                                 mp->m_len = 0;
  878                         else if (mp->m_len > 0) {
  879                                 i += mp->m_len;
  880                                 if (i > len) {
  881                                         mp->m_len -= (i - len);
  882                                         zeroing = 1;
  883                                 }
  884                                 if (mp->m_len > 0)
  885                                         cnt++;
  886                         }
  887                         mp = mp->m_next;
  888                 }
  889         }
  890         if (len > NFS_MAXDATA || len < 0 || i < len) {
  891                 error = EIO;
  892                 nfsm_reply(2 * NFSX_UNSIGNED);
  893                 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
  894                 vn_finished_write(mntp, 0);
  895                 return (0);
  896         }
  897         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
  898                  &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
  899         if (error) {
  900                 nfsm_reply(2 * NFSX_UNSIGNED);
  901                 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
  902                 vn_finished_write(mntp, 0);
  903                 return (0);
  904         }
  905         if (v3)
  906                 forat_ret = VOP_GETATTR(vp, &forat, cred, procp);
  907         if (vp->v_type != VREG) {
  908                 if (v3)
  909                         error = EINVAL;
  910                 else
  911                         error = (vp->v_type == VDIR) ? EISDIR : EACCES;
  912         }
  913         if (!error) {
  914                 nqsrv_getl(vp, ND_WRITE);
  915                 error = nfsrv_access(vp, VWRITE, cred, rdonly, procp, 1);
  916         }
  917         if (error) {
  918                 vput(vp);
  919                 nfsm_reply(NFSX_WCCDATA(v3));
  920                 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
  921                 vn_finished_write(mntp, 0);
  922                 return (0);
  923         }
  924 
  925         if (len > 0) {
  926                 ivp = malloc(cnt * sizeof (struct iovec), M_TEMP, M_WAITOK);
  927                 uiop->uio_iov = iv = ivp;
  928                 uiop->uio_iovcnt = cnt;
  929                 mp = mrep;
  930                 while (mp) {
  931                         if (mp->m_len > 0) {
  932                                 ivp->iov_base = mtod(mp, caddr_t);
  933                                 ivp->iov_len = mp->m_len;
  934                                 ivp++;
  935                         }
  936                         mp = mp->m_next;
  937                 }
  938 
  939                 /*
  940                  * XXX
  941                  * The IO_METASYNC flag indicates that all metadata (and not
  942                  * just enough to ensure data integrity) must be written to
  943                  * stable storage synchronously.
  944                  * (IO_METASYNC is not yet implemented in 4.4BSD-Lite.)
  945                  */
  946                 if (stable == NFSV3WRITE_UNSTABLE)
  947                         ioflags = IO_NODELOCKED;
  948                 else if (stable == NFSV3WRITE_DATASYNC)
  949                         ioflags = (IO_SYNC | IO_NODELOCKED);
  950                 else
  951                         ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
  952                 uiop->uio_resid = len;
  953                 uiop->uio_rw = UIO_WRITE;
  954                 uiop->uio_segflg = UIO_SYSSPACE;
  955                 uiop->uio_procp = NULL;
  956                 uiop->uio_offset = off;
  957                 error = VOP_WRITE(vp, uiop, ioflags, cred);
  958                 nfsstats.srvvop_writes++;
  959                 free(iv, M_TEMP);
  960         }
  961         aftat_ret = VOP_GETATTR(vp, &va, cred, procp);
  962         vput(vp);
  963         vn_finished_write(mntp, 0);
  964         if (!error)
  965                 error = aftat_ret;
  966         nfsm_reply(NFSX_PREOPATTR(v3) + NFSX_POSTOPORFATTR(v3) +
  967                 2 * NFSX_UNSIGNED + NFSX_WRITEVERF(v3));
  968         if (v3) {
  969                 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
  970                 if (error)
  971                         return (0);
  972                 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
  973                 *tl++ = txdr_unsigned(retlen);
  974                 if (stable == NFSV3WRITE_UNSTABLE)
  975                         *tl++ = txdr_unsigned(stable);
  976                 else
  977                         *tl++ = txdr_unsigned(NFSV3WRITE_FILESYNC);
  978                 /*
  979                  * Actually, there is no need to txdr these fields,
  980                  * but it may make the values more human readable,
  981                  * for debugging purposes.
  982                  */
  983                 *tl++ = txdr_unsigned(boottime.tv_sec);
  984                 *tl = txdr_unsigned(boottime.tv_usec);
  985         } else {
  986                 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
  987                 nfsm_srvfillattr(&va, fp);
  988         }
  989         nfsm_srvdone;
  990 }
  991 
  992 /*
  993  * NFS write service with write gathering support. Called when
  994  * nfsrvw_procrastinate > 0.
  995  * See: Chet Juszczak, "Improving the Write Performance of an NFS Server",
  996  * in Proc. of the Winter 1994 Usenix Conference, pg. 247-259, San Franscisco,
  997  * Jan. 1994.
  998  */
  999 int
 1000 nfsrv_writegather(ndp, slp, procp, mrq)
 1001         struct nfsrv_descript **ndp;
 1002         struct nfssvc_sock *slp;
 1003         struct proc *procp;
 1004         struct mbuf **mrq;
 1005 {
 1006         struct iovec *ivp;
 1007         struct mbuf *mp;
 1008         struct nfsrv_descript *wp, *nfsd, *owp, *swp;
 1009         struct nfs_fattr *fp;
 1010         int i = 0;
 1011         struct iovec *iov;
 1012         struct nfsrvw_delayhash *wpp;
 1013         struct ucred *cred;
 1014         struct vattr va, forat;
 1015         u_int32_t *tl;
 1016         int32_t t1;
 1017         caddr_t bpos, dpos;
 1018         int error = 0, rdonly, cache, len = 0, forat_ret = 1;
 1019         int ioflags, aftat_ret = 1, s, adjust, v3, zeroing;
 1020         char *cp2;
 1021         struct mbuf *mb, *mreq, *mrep, *md;
 1022         struct vnode *vp;
 1023         struct uio io, *uiop = &io;
 1024         u_quad_t frev, cur_usec;
 1025         struct mount *mntp = NULL;
 1026 
 1027         *mrq = NULL;
 1028         if (*ndp) {
 1029             nfsd = *ndp;
 1030             *ndp = NULL;
 1031             mrep = nfsd->nd_mrep;
 1032             md = nfsd->nd_md;
 1033             dpos = nfsd->nd_dpos;
 1034             cred = &nfsd->nd_cr;
 1035             v3 = (nfsd->nd_flag & ND_NFSV3);
 1036             LIST_INIT(&nfsd->nd_coalesce);
 1037             nfsd->nd_mreq = NULL;
 1038             nfsd->nd_stable = NFSV3WRITE_FILESYNC;
 1039             cur_usec = (u_quad_t)time.tv_sec * 1000000 + (u_quad_t)time.tv_usec;
 1040             nfsd->nd_time = cur_usec + nfsrvw_procrastinate;
 1041 
 1042             /*
 1043              * Now, get the write header..
 1044              */
 1045             nfsm_srvmtofh(&nfsd->nd_fh);
 1046             if (v3) {
 1047                 nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
 1048                 nfsd->nd_off = fxdr_hyper(tl);
 1049                 tl += 3;
 1050                 nfsd->nd_stable = fxdr_unsigned(int, *tl++);
 1051             } else {
 1052                 nfsm_dissect(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
 1053                 nfsd->nd_off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
 1054                 tl += 2;
 1055             }
 1056             len = fxdr_unsigned(int32_t, *tl);
 1057             nfsd->nd_len = len;
 1058             nfsd->nd_eoff = nfsd->nd_off + len;
 1059 
 1060             /*
 1061              * Trim the header out of the mbuf list and trim off any trailing
 1062              * junk so that the mbuf list has only the write data.
 1063              */
 1064             zeroing = 1;
 1065             i = 0;
 1066             mp = mrep;
 1067             while (mp) {
 1068                 if (mp == md) {
 1069                     zeroing = 0;
 1070                     adjust = dpos - mtod(mp, caddr_t);
 1071                     mp->m_len -= adjust;
 1072                     if (mp->m_len > 0 && adjust > 0)
 1073                         NFSMADV(mp, adjust);
 1074                 }
 1075                 if (zeroing)
 1076                     mp->m_len = 0;
 1077                 else {
 1078                     i += mp->m_len;
 1079                     if (i > len) {
 1080                         mp->m_len -= (i - len);
 1081                         zeroing = 1;
 1082                     }
 1083                 }
 1084                 mp = mp->m_next;
 1085             }
 1086             if (len > NFS_MAXDATA || len < 0  || i < len) {
 1087 nfsmout:
 1088                 m_freem(mrep);
 1089                 error = EIO;
 1090                 nfsm_writereply(2 * NFSX_UNSIGNED, v3);
 1091                 if (v3)
 1092                     nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
 1093                 nfsd->nd_mreq = mreq;
 1094                 nfsd->nd_mrep = NULL;
 1095                 nfsd->nd_time = 0;
 1096             }
 1097 
 1098             /*
 1099              * Add this entry to the hash and time queues.
 1100              */
 1101             s = splsoftclock();
 1102             owp = NULL;
 1103             wp = LIST_FIRST(&slp->ns_tq);
 1104             while (wp && wp->nd_time < nfsd->nd_time) {
 1105                 owp = wp;
 1106                 wp = LIST_NEXT(wp, nd_tq);
 1107             }
 1108             if (owp) {
 1109                 LIST_INSERT_AFTER(owp, nfsd, nd_tq);
 1110             } else {
 1111                 LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
 1112             }
 1113             if (nfsd->nd_mrep) {
 1114                 wpp = NWDELAYHASH(slp, nfsd->nd_fh.fh_fid.fid_data);
 1115                 owp = NULL;
 1116                 wp = LIST_FIRST(wpp);
 1117                 while (wp &&
 1118                     memcmp((caddr_t)&nfsd->nd_fh, (caddr_t)&wp->nd_fh, NFSX_V3FH)) {
 1119                     owp = wp;
 1120                     wp = LIST_NEXT(wp, nd_hash);
 1121                 }
 1122                 while (wp && wp->nd_off < nfsd->nd_off &&
 1123                     !memcmp((caddr_t)&nfsd->nd_fh, (caddr_t)&wp->nd_fh, NFSX_V3FH)) {
 1124                     owp = wp;
 1125                     wp = LIST_NEXT(wp, nd_hash);
 1126                 }
 1127                 if (owp) {
 1128                     LIST_INSERT_AFTER(owp, nfsd, nd_hash);
 1129 
 1130                     /*
 1131                      * Search the hash list for overlapping entries and
 1132                      * coalesce.
 1133                      */
 1134                     for(; nfsd && NFSW_CONTIG(owp, nfsd); nfsd = wp) {
 1135                         wp = LIST_NEXT(nfsd, nd_hash);
 1136                         if (NFSW_SAMECRED(owp, nfsd))
 1137                             nfsrvw_coalesce(owp, nfsd);
 1138                     }
 1139                 } else {
 1140                     LIST_INSERT_HEAD(wpp, nfsd, nd_hash);
 1141                 }
 1142             }
 1143             splx(s);
 1144         }
 1145 
 1146         /*
 1147          * Now, do VOP_WRITE()s for any one(s) that need to be done now
 1148          * and generate the associated reply mbuf list(s).
 1149          */
 1150 loop1:
 1151         cur_usec = (u_quad_t)time.tv_sec * 1000000 + (u_quad_t)time.tv_usec;
 1152         s = splsoftclock();
 1153         for (nfsd = LIST_FIRST(&slp->ns_tq); nfsd; nfsd = owp) {
 1154                 owp = LIST_NEXT(nfsd, nd_tq);
 1155                 if (nfsd->nd_time > cur_usec)
 1156                     break;
 1157                 if (nfsd->nd_mreq)
 1158                     continue;
 1159                 LIST_REMOVE(nfsd, nd_tq);
 1160                 LIST_REMOVE(nfsd, nd_hash);
 1161                 splx(s);
 1162                 mrep = nfsd->nd_mrep;
 1163                 nfsd->nd_mrep = NULL;
 1164                 cred = &nfsd->nd_cr;
 1165                 v3 = (nfsd->nd_flag & ND_NFSV3);
 1166                 forat_ret = aftat_ret = 1;
 1167                 error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &vp, cred, slp,
 1168                     nfsd->nd_nam, &rdonly, (nfsd->nd_flag & ND_KERBAUTH),
 1169                     FALSE);
 1170                 if (!error) {
 1171                     if (v3)
 1172                         forat_ret = VOP_GETATTR(vp, &forat, cred, procp);
 1173                     if (vp->v_type != VREG) {
 1174                         if (v3)
 1175                             error = EINVAL;
 1176                         else
 1177                             error = (vp->v_type == VDIR) ? EISDIR : EACCES;
 1178                     }
 1179                 } else
 1180                     vp = NULL;
 1181                 if (!error) {
 1182                     nqsrv_getl(vp, ND_WRITE);
 1183                     error = nfsrv_access(vp, VWRITE, cred, rdonly, procp, 1);
 1184                 }
 1185 
 1186                 if (nfsd->nd_stable == NFSV3WRITE_UNSTABLE)
 1187                     ioflags = IO_NODELOCKED;
 1188                 else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC)
 1189                     ioflags = (IO_SYNC | IO_NODELOCKED);
 1190                 else
 1191                     ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
 1192                 uiop->uio_rw = UIO_WRITE;
 1193                 uiop->uio_segflg = UIO_SYSSPACE;
 1194                 uiop->uio_procp = NULL;
 1195                 uiop->uio_offset = nfsd->nd_off;
 1196                 uiop->uio_resid = nfsd->nd_eoff - nfsd->nd_off;
 1197                 if (uiop->uio_resid > 0) {
 1198                     mp = mrep;
 1199                     i = 0;
 1200                     while (mp) {
 1201                         if (mp->m_len > 0)
 1202                             i++;
 1203                         mp = mp->m_next;
 1204                     }
 1205                     uiop->uio_iovcnt = i;
 1206                     iov = malloc(i * sizeof (struct iovec), M_TEMP, M_WAITOK);
 1207                     uiop->uio_iov = ivp = iov;
 1208                     mp = mrep;
 1209                     while (mp) {
 1210                         if (mp->m_len > 0) {
 1211                             ivp->iov_base = mtod(mp, caddr_t);
 1212                             ivp->iov_len = mp->m_len;
 1213                             ivp++;
 1214                         }
 1215                         mp = mp->m_next;
 1216                     }
 1217                     if (!error) {
 1218                         if (vn_start_write(vp, &mntp, V_NOWAIT) != 0) {
 1219                             VOP_UNLOCK(vp, 0);
 1220                             vn_start_write(NULL, &mntp, V_WAIT);
 1221                             vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 1222                         }
 1223                         if (!error) {
 1224                             error = VOP_WRITE(vp, uiop, ioflags, cred);
 1225                             nfsstats.srvvop_writes++;
 1226                             vn_finished_write(mntp, 0);
 1227                         }
 1228                     }
 1229                     free((caddr_t)iov, M_TEMP);
 1230                 }
 1231                 m_freem(mrep);
 1232                 if (vp) {
 1233                     aftat_ret = VOP_GETATTR(vp, &va, cred, procp);
 1234                     vput(vp);
 1235                 }
 1236 
 1237                 /*
 1238                  * Loop around generating replies for all write rpcs that have
 1239                  * now been completed.
 1240                  */
 1241                 swp = nfsd;
 1242                 do {
 1243                     if (error) {
 1244                         nfsm_writereply(NFSX_WCCDATA(v3), v3);
 1245                         if (v3) {
 1246                             nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
 1247                         }
 1248                     } else {
 1249                         nfsm_writereply(NFSX_PREOPATTR(v3) +
 1250                             NFSX_POSTOPORFATTR(v3) + 2 * NFSX_UNSIGNED +
 1251                             NFSX_WRITEVERF(v3), v3);
 1252                         if (v3) {
 1253                             nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
 1254                             nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
 1255                             *tl++ = txdr_unsigned(nfsd->nd_len);
 1256                             *tl++ = txdr_unsigned(swp->nd_stable);
 1257                             /*
 1258                              * Actually, there is no need to txdr these fields,
 1259                              * but it may make the values more human readable,
 1260                              * for debugging purposes.
 1261                              */
 1262                             *tl++ = txdr_unsigned(boottime.tv_sec);
 1263                             *tl = txdr_unsigned(boottime.tv_usec);
 1264                         } else {
 1265                             nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
 1266                             nfsm_srvfillattr(&va, fp);
 1267                         }
 1268                     }
 1269                     nfsd->nd_mreq = mreq;
 1270                     if (nfsd->nd_mrep)
 1271                         panic("nfsrv_write: nd_mrep not free");
 1272 
 1273                     /*
 1274                      * Done. Put it at the head of the timer queue so that
 1275                      * the final phase can return the reply.
 1276                      */
 1277                     s = splsoftclock();
 1278                     if (nfsd != swp) {
 1279                         nfsd->nd_time = 0;
 1280                         LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
 1281                     }
 1282                     nfsd = LIST_FIRST(&swp->nd_coalesce);
 1283                     if (nfsd) {
 1284                         LIST_REMOVE(nfsd, nd_tq);
 1285                     }
 1286                     splx(s);
 1287                 } while (nfsd);
 1288                 s = splsoftclock();
 1289                 swp->nd_time = 0;
 1290                 LIST_INSERT_HEAD(&slp->ns_tq, swp, nd_tq);
 1291                 splx(s);
 1292                 goto loop1;
 1293         }
 1294         splx(s);
 1295 
 1296         /*
 1297          * Search for a reply to return.
 1298          */
 1299         s = splsoftclock();
 1300         LIST_FOREACH(nfsd, &slp->ns_tq, nd_tq) {
 1301                 if (nfsd->nd_mreq) {
 1302                     LIST_REMOVE(nfsd, nd_tq);
 1303                     *mrq = nfsd->nd_mreq;
 1304                     *ndp = nfsd;
 1305                     break;
 1306                 }
 1307         }
 1308         splx(s);
 1309         return (0);
 1310 }
 1311 
 1312 /*
 1313  * Coalesce the write request nfsd into owp. To do this we must:
 1314  * - remove nfsd from the queues
 1315  * - merge nfsd->nd_mrep into owp->nd_mrep
 1316  * - update the nd_eoff and nd_stable for owp
 1317  * - put nfsd on owp's nd_coalesce list
 1318  * NB: Must be called at splsoftclock().
 1319  */
 1320 void
 1321 nfsrvw_coalesce(owp, nfsd)
 1322         struct nfsrv_descript *owp;
 1323         struct nfsrv_descript *nfsd;
 1324 {
 1325         int overlap;
 1326         struct mbuf *mp;
 1327         struct nfsrv_descript *m;
 1328 
 1329         LIST_REMOVE(nfsd, nd_hash);
 1330         LIST_REMOVE(nfsd, nd_tq);
 1331         if (owp->nd_eoff < nfsd->nd_eoff) {
 1332             overlap = owp->nd_eoff - nfsd->nd_off;
 1333             if (overlap < 0)
 1334                 panic("nfsrv_coalesce: bad off");
 1335             if (overlap > 0)
 1336                 m_adj(nfsd->nd_mrep, overlap);
 1337             mp = owp->nd_mrep;
 1338             while (mp->m_next)
 1339                 mp = mp->m_next;
 1340             mp->m_next = nfsd->nd_mrep;
 1341             owp->nd_eoff = nfsd->nd_eoff;
 1342         } else
 1343             m_freem(nfsd->nd_mrep);
 1344         nfsd->nd_mrep = NULL;
 1345         if (nfsd->nd_stable == NFSV3WRITE_FILESYNC)
 1346             owp->nd_stable = NFSV3WRITE_FILESYNC;
 1347         else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC &&
 1348             owp->nd_stable == NFSV3WRITE_UNSTABLE)
 1349             owp->nd_stable = NFSV3WRITE_DATASYNC;
 1350         LIST_INSERT_HEAD(&owp->nd_coalesce, nfsd, nd_tq);
 1351         /*
 1352          * nfsd might hold coalesce elements! Move them to owp.
 1353          * Otherwise, requests may be lost and clients will be stuck.
 1354          */
 1355         while ((m = LIST_FIRST(&nfsd->nd_coalesce)) != NULL) {
 1356                 LIST_REMOVE(m, nd_tq);
 1357                 LIST_INSERT_HEAD(&owp->nd_coalesce, m, nd_tq);
 1358         }
 1359 }
 1360 
 1361 /*
 1362  * nfs create service
 1363  * now does a truncate to 0 length via. setattr if it already exists
 1364  */
 1365 int
 1366 nfsrv_create(nfsd, slp, procp, mrq)
 1367         struct nfsrv_descript *nfsd;
 1368         struct nfssvc_sock *slp;
 1369         struct proc *procp;
 1370         struct mbuf **mrq;
 1371 {
 1372         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 1373         struct mbuf *nam = nfsd->nd_nam;
 1374         caddr_t dpos = nfsd->nd_dpos;
 1375         struct ucred *cred = &nfsd->nd_cr;
 1376         struct nfs_fattr *fp;
 1377         struct vattr va, dirfor, diraft;
 1378         struct nfsv2_sattr *sp;
 1379         u_int32_t *tl;
 1380         struct nameidata nd;
 1381         caddr_t cp;
 1382         int32_t t1;
 1383         caddr_t bpos;
 1384         int error = 0, cache, len, tsize, dirfor_ret = 1, diraft_ret = 1;
 1385         int rdev = 0;
 1386         int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0;
 1387         char *cp2;
 1388         struct mbuf *mb, *mreq;
 1389         struct vnode *vp = NULL, *dirp = NULL;
 1390         nfsfh_t nfh;
 1391         fhandle_t *fhp;
 1392         u_quad_t frev, tempsize;
 1393         u_char cverf[NFSX_V3CREATEVERF];
 1394         struct mount *mp = NULL;
 1395 
 1396         nd.ni_cnd.cn_nameiop = 0;
 1397         fhp = &nfh.fh_generic;
 1398         nfsm_srvmtofh(fhp);
 1399         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL)
 1400                 return (ESTALE);
 1401         vn_start_write(NULL, &mp, V_WAIT);
 1402         nfsm_srvnamesiz(len);
 1403         nd.ni_cnd.cn_cred = cred;
 1404         nd.ni_cnd.cn_nameiop = CREATE;
 1405         nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
 1406         error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
 1407                 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
 1408         if (dirp) {
 1409                 if (v3)
 1410                         dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
 1411                                 procp);
 1412                 else {
 1413                         vrele(dirp);
 1414                         dirp = (struct vnode *)0;
 1415                 }
 1416         }
 1417         if (error) {
 1418                 nfsm_reply(NFSX_WCCDATA(v3));
 1419                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 1420                 if (dirp)
 1421                         vrele(dirp);
 1422                 vn_finished_write(mp, 0);
 1423                 return (0);
 1424         }
 1425         VATTR_NULL(&va);
 1426         if (v3) {
 1427                 va.va_mode = 0;
 1428                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
 1429                 how = fxdr_unsigned(int, *tl);
 1430                 switch (how) {
 1431                 case NFSV3CREATE_GUARDED:
 1432                         if (nd.ni_vp) {
 1433                                 error = EEXIST;
 1434                                 break;
 1435                         }
 1436                 case NFSV3CREATE_UNCHECKED:
 1437                         nfsm_srvsattr(&va);
 1438                         break;
 1439                 case NFSV3CREATE_EXCLUSIVE:
 1440                         nfsm_dissect(cp, caddr_t, NFSX_V3CREATEVERF);
 1441                         memcpy(cverf, cp, NFSX_V3CREATEVERF);
 1442                         exclusive_flag = 1;
 1443                         break;
 1444                 };
 1445                 va.va_type = VREG;
 1446         } else {
 1447                 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
 1448                 va.va_type = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode));
 1449                 if (va.va_type == VNON)
 1450                         va.va_type = VREG;
 1451                 va.va_mode = nfstov_mode(sp->sa_mode);
 1452                 switch (va.va_type) {
 1453                 case VREG:
 1454                         tsize = fxdr_unsigned(int32_t, sp->sa_size);
 1455                         if (tsize != -1)
 1456                                 va.va_size = (u_quad_t)tsize;
 1457                         break;
 1458                 case VCHR:
 1459                 case VBLK:
 1460                 case VFIFO:
 1461                         rdev = fxdr_unsigned(int32_t, sp->sa_size);
 1462                         break;
 1463                 default:
 1464                         break;
 1465                 };
 1466         }
 1467 
 1468         /*
 1469          * Iff doesn't exist, create it
 1470          * otherwise just truncate to 0 length
 1471          *   should I set the mode too ??
 1472          */
 1473         if (nd.ni_vp == NULL) {
 1474                 if (va.va_type == VREG || va.va_type == VSOCK) {
 1475                         nqsrv_getl(nd.ni_dvp, ND_WRITE);
 1476                         error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
 1477                         if (!error) {
 1478                                 if (exclusive_flag) {
 1479                                         exclusive_flag = 0;
 1480                                         VATTR_NULL(&va);
 1481                                         /*
 1482                                          * XXX
 1483                                          * assuming NFSX_V3CREATEVERF
 1484                                          * == sizeof(nfstime3)
 1485                                          */
 1486                                         fxdr_nfsv3time(cverf, &va.va_atime);
 1487                                         error = VOP_SETATTR(nd.ni_vp, &va, cred,
 1488                                                 procp);
 1489                                 }
 1490                         }
 1491                 } else if (va.va_type == VCHR || va.va_type == VBLK ||
 1492                         va.va_type == VFIFO) {
 1493                         if (va.va_type == VCHR && rdev == 0xffffffff)
 1494                                 va.va_type = VFIFO;
 1495                         if (va.va_type != VFIFO &&
 1496                             (error = suser(cred, (u_short *)0))) {
 1497                                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 1498                                 vput(nd.ni_dvp);
 1499                                 nfsm_reply(0);
 1500                                 vn_finished_write(mp, 0);
 1501                                 return (error);
 1502                         } else
 1503                                 va.va_rdev = (dev_t)rdev;
 1504                         nqsrv_getl(nd.ni_dvp, ND_WRITE);
 1505                         error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd,
 1506                             &va);
 1507                         if (error) {
 1508                                 nfsm_reply(0);
 1509                         }
 1510                         if (nd.ni_cnd.cn_flags & ISSYMLINK) {
 1511                                 vrele(nd.ni_dvp);
 1512                                 vput(nd.ni_vp);
 1513                                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 1514                                 error = EINVAL;
 1515                                 nfsm_reply(0);
 1516                         }
 1517                 } else {
 1518                         VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 1519                         vput(nd.ni_dvp);
 1520                         error = ENXIO;
 1521                 }
 1522                 vp = nd.ni_vp;
 1523         } else {
 1524                 vp = nd.ni_vp;
 1525                 if (nd.ni_dvp == vp)
 1526                         vrele(nd.ni_dvp);
 1527                 else
 1528                         vput(nd.ni_dvp);
 1529                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 1530                 if (!error && va.va_size != -1) {
 1531                         error = nfsrv_access(vp, VWRITE, cred,
 1532                             (nd.ni_cnd.cn_flags & RDONLY), procp, 0);
 1533                         if (!error) {
 1534                                 nqsrv_getl(vp, ND_WRITE);
 1535                                 tempsize = va.va_size;
 1536                                 VATTR_NULL(&va);
 1537                                 va.va_size = tempsize;
 1538                                 error = VOP_SETATTR(vp, &va, cred,
 1539                                          procp);
 1540                         }
 1541                 }
 1542                 if (error)
 1543                         vput(vp);
 1544         }
 1545         if (!error) {
 1546                 memset((caddr_t)fhp, 0, sizeof(nfh));
 1547                 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsidx;
 1548                 error = VFS_VPTOFH(vp, &fhp->fh_fid);
 1549                 if (!error)
 1550                         error = VOP_GETATTR(vp, &va, cred, procp);
 1551                 vput(vp);
 1552         }
 1553         if (v3) {
 1554                 if (exclusive_flag && !error) {
 1555                         /*
 1556                          * XXX assuming NFSX_V3CREATEVERF == sizeof(nfstime3)
 1557                          */
 1558                         char oldverf[NFSX_V3CREATEVERF];
 1559 
 1560                         txdr_nfsv3time(&va.va_atime, oldverf);
 1561                         if (memcmp(cverf, oldverf, NFSX_V3CREATEVERF))
 1562                                 error = EEXIST;
 1563                 }
 1564                 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
 1565                 vrele(dirp);
 1566         }
 1567         nfsm_reply(NFSX_SRVFH(v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3));
 1568         if (v3) {
 1569                 if (!error) {
 1570                         nfsm_srvpostop_fh(fhp);
 1571                         nfsm_srvpostop_attr(0, &va);
 1572                 }
 1573                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 1574         } else {
 1575                 nfsm_srvfhtom(fhp, v3);
 1576                 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
 1577                 nfsm_srvfillattr(&va, fp);
 1578         }
 1579         vn_finished_write(mp, 0);
 1580         return (0);
 1581 nfsmout:
 1582         if (dirp)
 1583                 vrele(dirp);
 1584         VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 1585         if (nd.ni_dvp == nd.ni_vp)
 1586                 vrele(nd.ni_dvp);
 1587         else
 1588                 vput(nd.ni_dvp);
 1589         if (nd.ni_vp)
 1590                 vput(nd.ni_vp);
 1591         vn_finished_write(mp, 0);
 1592         return (error);
 1593 }
 1594 
 1595 /*
 1596  * nfs v3 mknod service
 1597  */
 1598 int
 1599 nfsrv_mknod(nfsd, slp, procp, mrq)
 1600         struct nfsrv_descript *nfsd;
 1601         struct nfssvc_sock *slp;
 1602         struct proc *procp;
 1603         struct mbuf **mrq;
 1604 {
 1605         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 1606         struct mbuf *nam = nfsd->nd_nam;
 1607         caddr_t dpos = nfsd->nd_dpos;
 1608         struct ucred *cred = &nfsd->nd_cr;
 1609         struct vattr va, dirfor, diraft;
 1610         u_int32_t *tl;
 1611         struct nameidata nd;
 1612         int32_t t1;
 1613         caddr_t bpos;
 1614         int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
 1615         u_int32_t major, minor;
 1616         enum vtype vtyp;
 1617         char *cp2;
 1618         struct mbuf *mb, *mreq;
 1619         struct vnode *vp, *dirp = (struct vnode *)0;
 1620         nfsfh_t nfh;
 1621         fhandle_t *fhp;
 1622         u_quad_t frev;
 1623         struct mount *mp = NULL;
 1624 
 1625         nd.ni_cnd.cn_nameiop = 0;
 1626         fhp = &nfh.fh_generic;
 1627         nfsm_srvmtofh(fhp);
 1628         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL)
 1629                 return (ESTALE);
 1630         vn_start_write(NULL, &mp, V_WAIT);
 1631         nfsm_srvnamesiz(len);
 1632         nd.ni_cnd.cn_cred = cred;
 1633         nd.ni_cnd.cn_nameiop = CREATE;
 1634         nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
 1635         error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
 1636                 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
 1637         if (dirp)
 1638                 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, procp);
 1639         if (error) {
 1640                 nfsm_reply(NFSX_WCCDATA(1));
 1641                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 1642                 if (dirp)
 1643                         vrele(dirp);
 1644                 vn_finished_write(mp, 0);
 1645                 return (0);
 1646         }
 1647         nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
 1648         vtyp = nfsv3tov_type(*tl);
 1649         if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
 1650                 error = NFSERR_BADTYPE;
 1651                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 1652                 if (nd.ni_dvp == nd.ni_vp)
 1653                         vrele(nd.ni_dvp);
 1654                 else
 1655                         vput(nd.ni_dvp);
 1656                 if (nd.ni_vp)
 1657                         vput(nd.ni_vp);
 1658                 goto out;
 1659         }
 1660         VATTR_NULL(&va);
 1661         va.va_mode = 0;
 1662         nfsm_srvsattr(&va);
 1663         if (vtyp == VCHR || vtyp == VBLK) {
 1664                 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 1665                 major = fxdr_unsigned(u_int32_t, *tl++);
 1666                 minor = fxdr_unsigned(u_int32_t, *tl);
 1667                 va.va_rdev = makedev(major, minor);
 1668         }
 1669 
 1670         /*
 1671          * Iff doesn't exist, create it.
 1672          */
 1673         if (nd.ni_vp) {
 1674                 error = EEXIST;
 1675                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 1676                 if (nd.ni_dvp == nd.ni_vp)
 1677                         vrele(nd.ni_dvp);
 1678                 else
 1679                         vput(nd.ni_dvp);
 1680                 vput(nd.ni_vp);
 1681                 goto out;
 1682         }
 1683         va.va_type = vtyp;
 1684         if (vtyp == VSOCK) {
 1685                 nqsrv_getl(nd.ni_dvp, ND_WRITE);
 1686                 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
 1687         } else {
 1688                 if (va.va_type != VFIFO &&
 1689                     (error = suser(cred, (u_short *)0))) {
 1690                         VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 1691                         vput(nd.ni_dvp);
 1692                         goto out;
 1693                 }
 1694                 nqsrv_getl(nd.ni_dvp, ND_WRITE);
 1695                 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
 1696                 if (error) {
 1697                         goto out;
 1698                 }
 1699                 if (error)
 1700                         goto out;
 1701                 if (nd.ni_cnd.cn_flags & ISSYMLINK) {
 1702                         vput(nd.ni_vp);
 1703                         VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 1704                         error = EINVAL;
 1705                 }
 1706         }
 1707 out:
 1708         vp = nd.ni_vp;
 1709         if (!error) {
 1710                 memset((caddr_t)fhp, 0, sizeof(nfh));
 1711                 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsidx;
 1712                 error = VFS_VPTOFH(vp, &fhp->fh_fid);
 1713                 if (!error)
 1714                         error = VOP_GETATTR(vp, &va, cred, procp);
 1715                 vput(vp);
 1716         }
 1717         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
 1718         vrele(dirp);
 1719         nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
 1720         if (!error) {
 1721                 nfsm_srvpostop_fh(fhp);
 1722                 nfsm_srvpostop_attr(0, &va);
 1723         }
 1724         nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 1725         vn_finished_write(mp, 0);
 1726         return (0);
 1727 nfsmout:
 1728         if (dirp)
 1729                 vrele(dirp);
 1730         VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 1731         if (nd.ni_dvp == nd.ni_vp)
 1732                 vrele(nd.ni_dvp);
 1733         else
 1734                 vput(nd.ni_dvp);
 1735         if (nd.ni_vp)
 1736                 vput(nd.ni_vp);
 1737         vn_finished_write(mp, 0);
 1738         return (error);
 1739 }
 1740 
 1741 /*
 1742  * nfs remove service
 1743  */
 1744 int
 1745 nfsrv_remove(nfsd, slp, procp, mrq)
 1746         struct nfsrv_descript *nfsd;
 1747         struct nfssvc_sock *slp;
 1748         struct proc *procp;
 1749         struct mbuf **mrq;
 1750 {
 1751         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 1752         struct mbuf *nam = nfsd->nd_nam;
 1753         caddr_t dpos = nfsd->nd_dpos;
 1754         struct ucred *cred = &nfsd->nd_cr;
 1755         struct nameidata nd;
 1756         u_int32_t *tl;
 1757         int32_t t1;
 1758         caddr_t bpos;
 1759         int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
 1760         int v3 = (nfsd->nd_flag & ND_NFSV3);
 1761         char *cp2;
 1762         struct mbuf *mb, *mreq;
 1763         struct vnode *vp, *dirp;
 1764         struct vattr dirfor, diraft;
 1765         nfsfh_t nfh;
 1766         fhandle_t *fhp;
 1767         u_quad_t frev;
 1768         struct mount *mp = NULL;
 1769 
 1770 #ifndef nolint
 1771         vp = (struct vnode *)0;
 1772 #endif
 1773         fhp = &nfh.fh_generic;
 1774         nfsm_srvmtofh(fhp);
 1775         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL)
 1776                 return (ESTALE);
 1777         vn_start_write(NULL, &mp, V_WAIT);
 1778         nfsm_srvnamesiz(len);
 1779         nd.ni_cnd.cn_cred = cred;
 1780         nd.ni_cnd.cn_nameiop = DELETE;
 1781         nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
 1782         error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
 1783                 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
 1784         if (dirp) {
 1785                 if (v3)
 1786                         dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
 1787                                 procp);
 1788                 else
 1789                         vrele(dirp);
 1790         }
 1791         if (!error) {
 1792                 vp = nd.ni_vp;
 1793                 if (vp->v_type == VDIR &&
 1794                     (error = suser(cred, (u_short *)0)) != 0)
 1795                         goto out;
 1796                 /*
 1797                  * The root of a mounted filesystem cannot be deleted.
 1798                  */
 1799                 if (vp->v_flag & VROOT) {
 1800                         error = EBUSY;
 1801                         goto out;
 1802                 }
 1803 out:
 1804                 if (!error) {
 1805                         nqsrv_getl(nd.ni_dvp, ND_WRITE);
 1806                         nqsrv_getl(vp, ND_WRITE);
 1807                         error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
 1808                 } else {
 1809                         VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 1810                         if (nd.ni_dvp == vp)
 1811                                 vrele(nd.ni_dvp);
 1812                         else
 1813                                 vput(nd.ni_dvp);
 1814                         vput(vp);
 1815                 }
 1816         }
 1817         if (dirp && v3) {
 1818                 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
 1819                 vrele(dirp);
 1820         }
 1821         nfsm_reply(NFSX_WCCDATA(v3));
 1822         if (v3) {
 1823                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 1824                 vn_finished_write(mp, 0);
 1825                 return (0);
 1826         }
 1827         vn_finished_write(mp, 0);
 1828         nfsm_srvdone;
 1829 }
 1830 
 1831 /*
 1832  * nfs rename service
 1833  */
 1834 int
 1835 nfsrv_rename(nfsd, slp, procp, mrq)
 1836         struct nfsrv_descript *nfsd;
 1837         struct nfssvc_sock *slp;
 1838         struct proc *procp;
 1839         struct mbuf **mrq;
 1840 {
 1841         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 1842         struct mbuf *nam = nfsd->nd_nam;
 1843         caddr_t dpos = nfsd->nd_dpos;
 1844         struct ucred *cred = &nfsd->nd_cr;
 1845         u_int32_t *tl;
 1846         int32_t t1;
 1847         caddr_t bpos;
 1848         int error = 0, cache, fdirfor_ret = 1, fdiraft_ret = 1;
 1849         uint32_t len, len2;
 1850         int tdirfor_ret = 1, tdiraft_ret = 1;
 1851         int v3 = (nfsd->nd_flag & ND_NFSV3);
 1852         char *cp2;
 1853         struct mbuf *mb, *mreq;
 1854         struct nameidata fromnd, tond;
 1855         struct vnode *fvp, *tvp, *tdvp, *fdirp = (struct vnode *)0;
 1856         struct vnode *tdirp = (struct vnode *)0;
 1857         struct vattr fdirfor, fdiraft, tdirfor, tdiraft;
 1858         nfsfh_t fnfh, tnfh;
 1859         fhandle_t *ffhp, *tfhp;
 1860         u_quad_t frev;
 1861         uid_t saved_uid;
 1862         struct mount *mp = NULL;
 1863 
 1864 #ifndef nolint
 1865         fvp = (struct vnode *)0;
 1866 #endif
 1867         ffhp = &fnfh.fh_generic;
 1868         tfhp = &tnfh.fh_generic;
 1869         fromnd.ni_cnd.cn_nameiop = 0;
 1870         tond.ni_cnd.cn_nameiop = 0;
 1871         nfsm_srvmtofh(ffhp);
 1872         if ((mp = vfs_getvfs(&ffhp->fh_fsid)) == NULL)
 1873                 return (ESTALE);
 1874         vn_start_write(NULL, &mp, V_WAIT);
 1875         nfsm_srvnamesiz(len);
 1876         /*
 1877          * Remember our original uid so that we can reset cr_uid before
 1878          * the second nfs_namei() call, in case it is remapped.
 1879          */
 1880         saved_uid = cred->cr_uid;
 1881         fromnd.ni_cnd.cn_cred = cred;
 1882         fromnd.ni_cnd.cn_nameiop = DELETE;
 1883         fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART;
 1884         error = nfs_namei(&fromnd, ffhp, len, slp, nam, &md,
 1885                 &dpos, &fdirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
 1886         if (fdirp) {
 1887                 if (v3)
 1888                         fdirfor_ret = VOP_GETATTR(fdirp, &fdirfor, cred,
 1889                                 procp);
 1890                 else {
 1891                         vrele(fdirp);
 1892                         fdirp = (struct vnode *)0;
 1893                 }
 1894         }
 1895         if (error) {
 1896                 nfsm_reply(2 * NFSX_WCCDATA(v3));
 1897                 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
 1898                 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
 1899                 if (fdirp)
 1900                         vrele(fdirp);
 1901                 vn_finished_write(mp, 0);
 1902                 return (0);
 1903         }
 1904         fvp = fromnd.ni_vp;
 1905         nfsm_srvmtofh(tfhp);
 1906         if (v3) {
 1907                 nfsm_dissect(tl, uint32_t *, NFSX_UNSIGNED);
 1908                 len2 = fxdr_unsigned(uint32_t, *tl);
 1909                 /* len2 will be checked by nfs_namei */
 1910         }
 1911         else {
 1912                 /* NFSv2 */
 1913                 nfsm_strsiz(len2, NFS_MAXNAMLEN);
 1914         }
 1915         cred->cr_uid = saved_uid;
 1916         tond.ni_cnd.cn_cred = cred;
 1917         tond.ni_cnd.cn_nameiop = RENAME;
 1918         tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
 1919         error = nfs_namei(&tond, tfhp, len2, slp, nam, &md,
 1920                 &dpos, &tdirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
 1921         if (tdirp) {
 1922                 if (v3)
 1923                         tdirfor_ret = VOP_GETATTR(tdirp, &tdirfor, cred,
 1924                                 procp);
 1925                 else {
 1926                         vrele(tdirp);
 1927                         tdirp = (struct vnode *)0;
 1928                 }
 1929         }
 1930         if (error) {
 1931                 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
 1932                 vrele(fromnd.ni_dvp);
 1933                 vrele(fvp);
 1934                 goto out1;
 1935         }
 1936         tdvp = tond.ni_dvp;
 1937         tvp = tond.ni_vp;
 1938         if (tvp != NULL) {
 1939                 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
 1940                         if (v3)
 1941                                 error = EEXIST;
 1942                         else
 1943                                 error = EISDIR;
 1944                         goto out;
 1945                 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
 1946                         if (v3)
 1947                                 error = EEXIST;
 1948                         else
 1949                                 error = ENOTDIR;
 1950                         goto out;
 1951                 }
 1952                 if (tvp->v_type == VDIR && tvp->v_mountedhere) {
 1953                         if (v3)
 1954                                 error = EXDEV;
 1955                         else
 1956                                 error = ENOTEMPTY;
 1957                         goto out;
 1958                 }
 1959         }
 1960         if (fvp->v_type == VDIR && fvp->v_mountedhere) {
 1961                 if (v3)
 1962                         error = EXDEV;
 1963                 else
 1964                         error = ENOTEMPTY;
 1965                 goto out;
 1966         }
 1967         if (fvp->v_mount != tdvp->v_mount) {
 1968                 if (v3)
 1969                         error = EXDEV;
 1970                 else
 1971                         error = ENOTEMPTY;
 1972                 goto out;
 1973         }
 1974         if (fvp == tdvp) {
 1975                 if (v3)
 1976                         error = EINVAL;
 1977                 else
 1978                         error = ENOTEMPTY;
 1979         }
 1980         /*
 1981          * If source is the same as the destination (that is the
 1982          * same vnode with the same name in the same directory),
 1983          * then there is nothing to do.
 1984          */
 1985         if (fvp == tvp && fromnd.ni_dvp == tdvp &&
 1986             fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
 1987             !memcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
 1988               fromnd.ni_cnd.cn_namelen))
 1989                 error = -1;
 1990 out:
 1991         if (!error) {
 1992                 nqsrv_getl(fromnd.ni_dvp, ND_WRITE);
 1993                 nqsrv_getl(tdvp, ND_WRITE);
 1994                 if (tvp) {
 1995                         nqsrv_getl(tvp, ND_WRITE);
 1996                 }
 1997                 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
 1998                                    tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
 1999         } else {
 2000                 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
 2001                 if (tdvp == tvp)
 2002                         vrele(tdvp);
 2003                 else
 2004                         vput(tdvp);
 2005                 if (tvp)
 2006                         vput(tvp);
 2007                 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
 2008                 vrele(fromnd.ni_dvp);
 2009                 vrele(fvp);
 2010                 if (error == -1)
 2011                         error = 0;
 2012         }
 2013         vrele(tond.ni_startdir);
 2014         PNBUF_PUT(tond.ni_cnd.cn_pnbuf);
 2015 out1:
 2016         if (fdirp) {
 2017                 fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, cred, procp);
 2018                 vrele(fdirp);
 2019         }
 2020         if (tdirp) {
 2021                 tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, cred, procp);
 2022                 vrele(tdirp);
 2023         }
 2024         vrele(fromnd.ni_startdir);
 2025         PNBUF_PUT(fromnd.ni_cnd.cn_pnbuf);
 2026         nfsm_reply(2 * NFSX_WCCDATA(v3));
 2027         if (v3) {
 2028                 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
 2029                 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
 2030         }
 2031         vn_finished_write(mp, 0);
 2032         return (0);
 2033 
 2034 nfsmout:
 2035         if (fdirp)
 2036                 vrele(fdirp);
 2037         if (tdirp)
 2038                 vrele(tdirp);
 2039         if (tond.ni_cnd.cn_nameiop) {
 2040                 vrele(tond.ni_startdir);
 2041                 PNBUF_PUT(tond.ni_cnd.cn_pnbuf);
 2042         }
 2043         if (fromnd.ni_cnd.cn_nameiop) {
 2044                 vrele(fromnd.ni_startdir);
 2045                 PNBUF_PUT(fromnd.ni_cnd.cn_pnbuf);
 2046                 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
 2047                 vrele(fromnd.ni_dvp);
 2048                 vrele(fvp);
 2049         }
 2050         return (error);
 2051 }
 2052 
 2053 /*
 2054  * nfs link service
 2055  */
 2056 int
 2057 nfsrv_link(nfsd, slp, procp, mrq)
 2058         struct nfsrv_descript *nfsd;
 2059         struct nfssvc_sock *slp;
 2060         struct proc *procp;
 2061         struct mbuf **mrq;
 2062 {
 2063         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 2064         struct mbuf *nam = nfsd->nd_nam;
 2065         caddr_t dpos = nfsd->nd_dpos;
 2066         struct ucred *cred = &nfsd->nd_cr;
 2067         struct nameidata nd;
 2068         u_int32_t *tl;
 2069         int32_t t1;
 2070         caddr_t bpos;
 2071         int error = 0, rdonly, cache, len, dirfor_ret = 1, diraft_ret = 1;
 2072         int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3);
 2073         char *cp2;
 2074         struct mbuf *mb, *mreq;
 2075         struct vnode *vp, *xp, *dirp = (struct vnode *)0;
 2076         struct vattr dirfor, diraft, at;
 2077         nfsfh_t nfh, dnfh;
 2078         fhandle_t *fhp, *dfhp;
 2079         u_quad_t frev;
 2080         struct mount *mp = NULL;
 2081 
 2082         fhp = &nfh.fh_generic;
 2083         dfhp = &dnfh.fh_generic;
 2084         nfsm_srvmtofh(fhp);
 2085         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL)
 2086                 return (ESTALE);
 2087         vn_start_write(NULL, &mp, V_WAIT);
 2088         nfsm_srvmtofh(dfhp);
 2089         nfsm_srvnamesiz(len);
 2090         error = nfsrv_fhtovp(fhp, FALSE, &vp, cred, slp, nam,
 2091                  &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
 2092         if (error) {
 2093                 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
 2094                 nfsm_srvpostop_attr(getret, &at);
 2095                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 2096                 vn_finished_write(mp, 0);
 2097                 return (0);
 2098         }
 2099         if (vp->v_type == VDIR && (error = suser(cred, (u_short *)0)) != 0)
 2100                 goto out1;
 2101         nd.ni_cnd.cn_cred = cred;
 2102         nd.ni_cnd.cn_nameiop = CREATE;
 2103         nd.ni_cnd.cn_flags = LOCKPARENT;
 2104         error = nfs_namei(&nd, dfhp, len, slp, nam, &md, &dpos,
 2105                 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
 2106         if (dirp) {
 2107                 if (v3)
 2108                         dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
 2109                                 procp);
 2110                 else {
 2111                         vrele(dirp);
 2112                         dirp = (struct vnode *)0;
 2113                 }
 2114         }
 2115         if (error)
 2116                 goto out1;
 2117         xp = nd.ni_vp;
 2118         if (xp != NULL) {
 2119                 error = EEXIST;
 2120                 goto out;
 2121         }
 2122         xp = nd.ni_dvp;
 2123         if (vp->v_mount != xp->v_mount)
 2124                 error = EXDEV;
 2125 out:
 2126         if (!error) {
 2127                 nqsrv_getl(vp, ND_WRITE);
 2128                 nqsrv_getl(xp, ND_WRITE);
 2129                 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
 2130         } else {
 2131                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 2132                 if (nd.ni_dvp == nd.ni_vp)
 2133                         vrele(nd.ni_dvp);
 2134                 else
 2135                         vput(nd.ni_dvp);
 2136                 if (nd.ni_vp)
 2137                         vrele(nd.ni_vp);
 2138         }
 2139 out1:
 2140         if (v3)
 2141                 getret = VOP_GETATTR(vp, &at, cred, procp);
 2142         if (dirp) {
 2143                 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
 2144                 vrele(dirp);
 2145         }
 2146         vrele(vp);
 2147         nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
 2148         if (v3) {
 2149                 nfsm_srvpostop_attr(getret, &at);
 2150                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 2151                 vn_finished_write(mp, 0);
 2152                 return (0);
 2153         }
 2154         vn_finished_write(mp, 0);
 2155         nfsm_srvdone;
 2156 }
 2157 
 2158 /*
 2159  * nfs symbolic link service
 2160  */
 2161 int
 2162 nfsrv_symlink(nfsd, slp, procp, mrq)
 2163         struct nfsrv_descript *nfsd;
 2164         struct nfssvc_sock *slp;
 2165         struct proc *procp;
 2166         struct mbuf **mrq;
 2167 {
 2168         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 2169         struct mbuf *nam = nfsd->nd_nam;
 2170         caddr_t dpos = nfsd->nd_dpos;
 2171         struct ucred *cred = &nfsd->nd_cr;
 2172         struct vattr va, dirfor, diraft;
 2173         struct nameidata nd;
 2174         u_int32_t *tl;
 2175         int32_t t1;
 2176         struct nfsv2_sattr *sp;
 2177         char *bpos, *pathcp = NULL, *cp2;
 2178         struct uio io;
 2179         struct iovec iv;
 2180         int error = 0, cache, dirfor_ret = 1, diraft_ret = 1;
 2181         uint32_t len, len2;
 2182         int v3 = (nfsd->nd_flag & ND_NFSV3);
 2183         struct mbuf *mb, *mreq;
 2184         struct vnode *dirp = (struct vnode *)0;
 2185         nfsfh_t nfh;
 2186         fhandle_t *fhp;
 2187         u_quad_t frev;
 2188         struct mount *mp = NULL;
 2189 
 2190         nd.ni_cnd.cn_nameiop = 0;
 2191         fhp = &nfh.fh_generic;
 2192         nfsm_srvmtofh(fhp);
 2193         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL)
 2194                 return (ESTALE);
 2195         vn_start_write(NULL, &mp, V_WAIT);
 2196         nfsm_srvnamesiz(len);
 2197         nd.ni_cnd.cn_cred = cred;
 2198         nd.ni_cnd.cn_nameiop = CREATE;
 2199         nd.ni_cnd.cn_flags = LOCKPARENT;
 2200         error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
 2201                 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
 2202         if (dirp) {
 2203                 if (v3)
 2204                         dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
 2205                                 procp);
 2206                 else {
 2207                         vrele(dirp);
 2208                         dirp = (struct vnode *)0;
 2209                 }
 2210         }
 2211         if (error)
 2212                 goto out;
 2213         VATTR_NULL(&va);
 2214         if (v3) {
 2215                 va.va_mode = 0;
 2216                 nfsm_srvsattr(&va);
 2217                 nfsm_dissect(tl, uint32_t *, NFSX_UNSIGNED);
 2218                 len2 = fxdr_unsigned(uint32_t, *tl);
 2219                 if (len2 > PATH_MAX) {
 2220                         /* XXX should check _PC_NO_TRUNC */
 2221                         error = ENAMETOOLONG;
 2222                         goto abortop;
 2223                 }
 2224         }
 2225         else {
 2226                 /* NFSv2 */
 2227                 nfsm_strsiz(len2, NFS_MAXPATHLEN);
 2228         }
 2229         pathcp = malloc(len2 + 1, M_TEMP, M_WAITOK);
 2230         iv.iov_base = pathcp;
 2231         iv.iov_len = len2;
 2232         io.uio_resid = len2;
 2233         io.uio_offset = 0;
 2234         io.uio_iov = &iv;
 2235         io.uio_iovcnt = 1;
 2236         io.uio_segflg = UIO_SYSSPACE;
 2237         io.uio_rw = UIO_READ;
 2238         io.uio_procp = NULL;
 2239         nfsm_mtouio(&io, len2);
 2240         if (!v3) {
 2241                 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
 2242                 va.va_mode = fxdr_unsigned(u_int16_t, sp->sa_mode);
 2243         }
 2244         *(pathcp + len2) = '\0';
 2245         if (nd.ni_vp) {
 2246                 error = EEXIST;
 2247 abortop:
 2248                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 2249                 if (nd.ni_dvp == nd.ni_vp)
 2250                         vrele(nd.ni_dvp);
 2251                 else
 2252                         vput(nd.ni_dvp);
 2253                 if (nd.ni_vp)
 2254                         vrele(nd.ni_vp);
 2255                 goto out;
 2256         }
 2257         nqsrv_getl(nd.ni_dvp, ND_WRITE);
 2258         error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va, pathcp);
 2259         if (!error) {
 2260             if (v3) {
 2261                 memset((caddr_t)fhp, 0, sizeof(nfh));
 2262                 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsidx;
 2263                 error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
 2264                 if (!error)
 2265                     error = VOP_GETATTR(nd.ni_vp, &va, cred,
 2266                                         procp);
 2267                 vput(nd.ni_vp);
 2268             } else {
 2269                 vput(nd.ni_vp);
 2270             }
 2271         }
 2272 out:
 2273         if (pathcp)
 2274                 free(pathcp, M_TEMP);
 2275         if (dirp) {
 2276                 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
 2277                 vrele(dirp);
 2278         }
 2279         nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
 2280         if (v3) {
 2281                 if (!error) {
 2282                         nfsm_srvpostop_fh(fhp);
 2283                         nfsm_srvpostop_attr(0, &va);
 2284                 }
 2285                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 2286         }
 2287         vn_finished_write(mp, 0);
 2288         return (0);
 2289 nfsmout:
 2290         if (dirp)
 2291                 vrele(dirp);
 2292         VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 2293         if (nd.ni_dvp == nd.ni_vp)
 2294                 vrele(nd.ni_dvp);
 2295         else
 2296                 vput(nd.ni_dvp);
 2297         if (nd.ni_vp)
 2298                 vrele(nd.ni_vp);
 2299         if (pathcp)
 2300                 free(pathcp, M_TEMP);
 2301         vn_finished_write(mp, 0);
 2302         return (error);
 2303 }
 2304 
 2305 /*
 2306  * nfs mkdir service
 2307  */
 2308 int
 2309 nfsrv_mkdir(nfsd, slp, procp, mrq)
 2310         struct nfsrv_descript *nfsd;
 2311         struct nfssvc_sock *slp;
 2312         struct proc *procp;
 2313         struct mbuf **mrq;
 2314 {
 2315         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 2316         struct mbuf *nam = nfsd->nd_nam;
 2317         caddr_t dpos = nfsd->nd_dpos;
 2318         struct ucred *cred = &nfsd->nd_cr;
 2319         struct vattr va, dirfor, diraft;
 2320         struct nfs_fattr *fp;
 2321         struct nameidata nd;
 2322         caddr_t cp;
 2323         u_int32_t *tl;
 2324         int32_t t1;
 2325         caddr_t bpos;
 2326         int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
 2327         int v3 = (nfsd->nd_flag & ND_NFSV3);
 2328         char *cp2;
 2329         struct mbuf *mb, *mreq;
 2330         struct vnode *vp, *dirp = (struct vnode *)0;
 2331         nfsfh_t nfh;
 2332         fhandle_t *fhp;
 2333         u_quad_t frev;
 2334         struct mount *mp = NULL;
 2335 
 2336         fhp = &nfh.fh_generic;
 2337         nfsm_srvmtofh(fhp);
 2338         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL)
 2339                 return (ESTALE);
 2340         vn_start_write(NULL, &mp, V_WAIT);
 2341         nfsm_srvnamesiz(len);
 2342         nd.ni_cnd.cn_cred = cred;
 2343         nd.ni_cnd.cn_nameiop = CREATE;
 2344         nd.ni_cnd.cn_flags = LOCKPARENT;
 2345         error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
 2346                 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
 2347         if (dirp) {
 2348                 if (v3)
 2349                         dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
 2350                                 procp);
 2351                 else {
 2352                         vrele(dirp);
 2353                         dirp = (struct vnode *)0;
 2354                 }
 2355         }
 2356         if (error) {
 2357                 nfsm_reply(NFSX_WCCDATA(v3));
 2358                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 2359                 if (dirp)
 2360                         vrele(dirp);
 2361                 vn_finished_write(mp, 0);
 2362                 return (0);
 2363         }
 2364         VATTR_NULL(&va);
 2365         if (v3) {
 2366                 va.va_mode = 0;
 2367                 nfsm_srvsattr(&va);
 2368         } else {
 2369                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
 2370                 va.va_mode = nfstov_mode(*tl++);
 2371         }
 2372         va.va_type = VDIR;
 2373         vp = nd.ni_vp;
 2374         if (vp != NULL) {
 2375                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 2376                 if (nd.ni_dvp == vp)
 2377                         vrele(nd.ni_dvp);
 2378                 else
 2379                         vput(nd.ni_dvp);
 2380                 vrele(vp);
 2381                 error = EEXIST;
 2382                 goto out;
 2383         }
 2384         nqsrv_getl(nd.ni_dvp, ND_WRITE);
 2385         error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
 2386         if (!error) {
 2387                 vp = nd.ni_vp;
 2388                 memset((caddr_t)fhp, 0, sizeof(nfh));
 2389                 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsidx;
 2390                 error = VFS_VPTOFH(vp, &fhp->fh_fid);
 2391                 if (!error)
 2392                         error = VOP_GETATTR(vp, &va, cred, procp);
 2393                 vput(vp);
 2394         }
 2395 out:
 2396         if (dirp) {
 2397                 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
 2398                 vrele(dirp);
 2399         }
 2400         nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
 2401         if (v3) {
 2402                 if (!error) {
 2403                         nfsm_srvpostop_fh(fhp);
 2404                         nfsm_srvpostop_attr(0, &va);
 2405                 }
 2406                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 2407         } else {
 2408                 nfsm_srvfhtom(fhp, v3);
 2409                 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
 2410                 nfsm_srvfillattr(&va, fp);
 2411         }
 2412         vn_finished_write(mp, 0);
 2413         return (0);
 2414 nfsmout:
 2415         if (dirp)
 2416                 vrele(dirp);
 2417         VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 2418         if (nd.ni_dvp == nd.ni_vp)
 2419                 vrele(nd.ni_dvp);
 2420         else
 2421                 vput(nd.ni_dvp);
 2422         if (nd.ni_vp)
 2423                 vrele(nd.ni_vp);
 2424         vn_finished_write(mp, 0);
 2425         return (error);
 2426 }
 2427 
 2428 /*
 2429  * nfs rmdir service
 2430  */
 2431 int
 2432 nfsrv_rmdir(nfsd, slp, procp, mrq)
 2433         struct nfsrv_descript *nfsd;
 2434         struct nfssvc_sock *slp;
 2435         struct proc *procp;
 2436         struct mbuf **mrq;
 2437 {
 2438         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 2439         struct mbuf *nam = nfsd->nd_nam;
 2440         caddr_t dpos = nfsd->nd_dpos;
 2441         struct ucred *cred = &nfsd->nd_cr;
 2442         u_int32_t *tl;
 2443         int32_t t1;
 2444         caddr_t bpos;
 2445         int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
 2446         int v3 = (nfsd->nd_flag & ND_NFSV3);
 2447         char *cp2;
 2448         struct mbuf *mb, *mreq;
 2449         struct vnode *vp, *dirp = (struct vnode *)0;
 2450         struct vattr dirfor, diraft;
 2451         nfsfh_t nfh;
 2452         fhandle_t *fhp;
 2453         struct nameidata nd;
 2454         u_quad_t frev;
 2455         struct mount *mp = NULL;
 2456 
 2457         fhp = &nfh.fh_generic;
 2458         nfsm_srvmtofh(fhp);
 2459         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL)
 2460                 return (ESTALE);
 2461         vn_start_write(NULL, &mp, V_WAIT);
 2462         nfsm_srvnamesiz(len);
 2463         nd.ni_cnd.cn_cred = cred;
 2464         nd.ni_cnd.cn_nameiop = DELETE;
 2465         nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
 2466         error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
 2467                 &dirp, procp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
 2468         if (dirp) {
 2469                 if (v3)
 2470                         dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
 2471                                 procp);
 2472                 else {
 2473                         vrele(dirp);
 2474                         dirp = (struct vnode *)0;
 2475                 }
 2476         }
 2477         if (error) {
 2478                 nfsm_reply(NFSX_WCCDATA(v3));
 2479                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 2480                 if (dirp)
 2481                         vrele(dirp);
 2482                 vn_finished_write(mp, 0);
 2483                 return (0);
 2484         }
 2485         vp = nd.ni_vp;
 2486         if (vp->v_type != VDIR) {
 2487                 error = ENOTDIR;
 2488                 goto out;
 2489         }
 2490         /*
 2491          * No rmdir "." please.
 2492          */
 2493         if (nd.ni_dvp == vp) {
 2494                 error = EINVAL;
 2495                 goto out;
 2496         }
 2497         /*
 2498          * The root of a mounted filesystem cannot be deleted.
 2499          */
 2500         if (vp->v_flag & VROOT)
 2501                 error = EBUSY;
 2502 out:
 2503         if (!error) {
 2504                 nqsrv_getl(nd.ni_dvp, ND_WRITE);
 2505                 nqsrv_getl(vp, ND_WRITE);
 2506                 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
 2507         } else {
 2508                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
 2509                 if (nd.ni_dvp == nd.ni_vp)
 2510                         vrele(nd.ni_dvp);
 2511                 else
 2512                         vput(nd.ni_dvp);
 2513                 vput(vp);
 2514         }
 2515         if (dirp) {
 2516                 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
 2517                 vrele(dirp);
 2518         }
 2519         nfsm_reply(NFSX_WCCDATA(v3));
 2520         if (v3) {
 2521                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
 2522                 vn_finished_write(mp, 0);
 2523                 return (0);
 2524         }
 2525         vn_finished_write(mp, 0);
 2526         nfsm_srvdone;
 2527 }
 2528 
 2529 /*
 2530  * nfs readdir service
 2531  * - mallocs what it thinks is enough to read
 2532  *      count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
 2533  * - calls VOP_READDIR()
 2534  * - loops around building the reply
 2535  *      if the output generated exceeds count break out of loop
 2536  *      The nfsm_clget macro is used here so that the reply will be packed
 2537  *      tightly in mbuf clusters.
 2538  * - it only knows that it has encountered eof when the VOP_READDIR()
 2539  *      reads nothing
 2540  * - as such one readdir rpc will return eof false although you are there
 2541  *      and then the next will return eof
 2542  * - it trims out records with d_fileno == 0
 2543  *      this doesn't matter for Unix clients, but they might confuse clients
 2544  *      for other os'.
 2545  * - it trims out records with d_type == DT_WHT
 2546  *      these cannot be seen through NFS (unless we extend the protocol)
 2547  * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
 2548  *      than requested, but this may not apply to all filesystems. For
 2549  *      example, client NFS does not { although it is never remote mounted
 2550  *      anyhow }
 2551  *     The alternate call nfsrv_readdirplus() does lookups as well.
 2552  * PS: The NFS protocol spec. does not clarify what the "count" byte
 2553  *      argument is a count of.. just name strings and file id's or the
 2554  *      entire reply rpc or ...
 2555  *      I tried just file name and id sizes and it confused the Sun client,
 2556  *      so I am using the full rpc size now. The "paranoia.." comment refers
 2557  *      to including the status longwords that are not a part of the dir.
 2558  *      "entry" structures, but are in the rpc.
 2559  */
 2560 struct flrep {
 2561         nfsuint64 fl_off;
 2562         u_int32_t fl_postopok;
 2563         u_int32_t fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)];
 2564         u_int32_t fl_fhok;
 2565         u_int32_t fl_fhsize;
 2566         u_int32_t fl_nfh[NFSX_V3FH / sizeof (u_int32_t)];
 2567 };
 2568 
 2569 int
 2570 nfsrv_readdir(nfsd, slp, procp, mrq)
 2571         struct nfsrv_descript *nfsd;
 2572         struct nfssvc_sock *slp;
 2573         struct proc *procp;
 2574         struct mbuf **mrq;
 2575 {
 2576         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 2577         struct mbuf *nam = nfsd->nd_nam;
 2578         caddr_t dpos = nfsd->nd_dpos;
 2579         struct ucred *cred = &nfsd->nd_cr;
 2580         char *bp, *be;
 2581         struct mbuf *mp;
 2582         struct dirent *dp;
 2583         caddr_t cp;
 2584         u_int32_t *tl;
 2585         int32_t t1;
 2586         caddr_t bpos;
 2587         struct mbuf *mb, *mreq, *mp2;
 2588         char *cpos, *cend, *cp2, *rbuf;
 2589         struct vnode *vp;
 2590         struct vattr at;
 2591         nfsfh_t nfh;
 2592         fhandle_t *fhp;
 2593         struct uio io;
 2594         struct iovec iv;
 2595         int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
 2596         int siz, cnt, fullsiz, eofflag, rdonly, cache, ncookies;
 2597         int v3 = (nfsd->nd_flag & ND_NFSV3);
 2598         u_quad_t frev, off, toff, verf;
 2599         off_t *cookies = NULL, *cookiep;
 2600         nfsuint64 jar;
 2601 
 2602         fhp = &nfh.fh_generic;
 2603         nfsm_srvmtofh(fhp);
 2604         if (v3) {
 2605                 nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
 2606                 toff = fxdr_hyper(tl);
 2607                 tl += 2;
 2608                 verf = fxdr_hyper(tl);
 2609                 tl += 2;
 2610         } else {
 2611                 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 2612                 toff = fxdr_unsigned(u_quad_t, *tl++);
 2613         }
 2614         off = toff;
 2615         cnt = fxdr_unsigned(int, *tl);
 2616         siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
 2617         xfer = NFS_SRVMAXDATA(nfsd);
 2618         if (siz > xfer)
 2619                 siz = xfer;
 2620         fullsiz = siz;
 2621         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
 2622                  &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
 2623         if (!error && vp->v_type != VDIR) {
 2624                 error = ENOTDIR;
 2625                 vput(vp);
 2626         }
 2627         if (error) {
 2628                 nfsm_reply(NFSX_UNSIGNED);
 2629                 nfsm_srvpostop_attr(getret, &at);
 2630                 return (0);
 2631         }
 2632         nqsrv_getl(vp, ND_READ);
 2633         if (v3) {
 2634                 error = getret = VOP_GETATTR(vp, &at, cred, procp);
 2635 #ifdef NFS3_STRICTVERF
 2636                 /*
 2637                  * XXX This check is too strict for Solaris 2.5 clients.
 2638                  */
 2639                 if (!error && toff && verf != at.va_filerev)
 2640                         error = NFSERR_BAD_COOKIE;
 2641 #endif
 2642         }
 2643         if (!error)
 2644                 error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0);
 2645         if (error) {
 2646                 vput(vp);
 2647                 nfsm_reply(NFSX_POSTOPATTR(v3));
 2648                 nfsm_srvpostop_attr(getret, &at);
 2649                 return (0);
 2650         }
 2651         VOP_UNLOCK(vp, 0);
 2652         rbuf = malloc(siz, M_TEMP, M_WAITOK);
 2653 again:
 2654         iv.iov_base = rbuf;
 2655         iv.iov_len = fullsiz;
 2656         io.uio_iov = &iv;
 2657         io.uio_iovcnt = 1;
 2658         io.uio_offset = (off_t)off;
 2659         io.uio_resid = fullsiz;
 2660         io.uio_segflg = UIO_SYSSPACE;
 2661         io.uio_rw = UIO_READ;
 2662         io.uio_procp = NULL;
 2663         eofflag = 0;
 2664         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 2665 
 2666         error = VOP_READDIR(vp, &io, cred, &eofflag, &cookies, &ncookies);
 2667 
 2668         off = (off_t)io.uio_offset;
 2669         if (!cookies && !error)
 2670                 error = NFSERR_PERM;
 2671         if (v3) {
 2672                 getret = VOP_GETATTR(vp, &at, cred, procp);
 2673                 if (!error)
 2674                         error = getret;
 2675         }
 2676 
 2677         VOP_UNLOCK(vp, 0);
 2678         if (error) {
 2679                 vrele(vp);
 2680                 free((caddr_t)rbuf, M_TEMP);
 2681                 if (cookies)
 2682                         free((caddr_t)cookies, M_TEMP);
 2683                 nfsm_reply(NFSX_POSTOPATTR(v3));
 2684                 nfsm_srvpostop_attr(getret, &at);
 2685                 return (0);
 2686         }
 2687         if (io.uio_resid) {
 2688                 siz -= io.uio_resid;
 2689 
 2690                 /*
 2691                  * If nothing read, return eof
 2692                  * rpc reply
 2693                  */
 2694                 if (siz == 0) {
 2695                         vrele(vp);
 2696                         nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) +
 2697                                 2 * NFSX_UNSIGNED);
 2698                         if (v3) {
 2699                                 nfsm_srvpostop_attr(getret, &at);
 2700                                 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
 2701                                 txdr_hyper(at.va_filerev, tl);
 2702                                 tl += 2;
 2703                         } else
 2704                                 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 2705                         *tl++ = nfs_false;
 2706                         *tl = nfs_true;
 2707                         free((caddr_t)rbuf, M_TEMP);
 2708                         free((caddr_t)cookies, M_TEMP);
 2709                         return (0);
 2710                 }
 2711         }
 2712 
 2713         /*
 2714          * Check for degenerate cases of nothing useful read.
 2715          * If so go try again
 2716          */
 2717         cpos = rbuf;
 2718         cend = rbuf + siz;
 2719         dp = (struct dirent *)cpos;
 2720         cookiep = cookies;
 2721 
 2722         while (cpos < cend && ncookies > 0 &&
 2723                 (dp->d_fileno == 0 || dp->d_type == DT_WHT)) {
 2724                 cpos += dp->d_reclen;
 2725                 dp = (struct dirent *)cpos;
 2726                 cookiep++;
 2727                 ncookies--;
 2728         }
 2729         if (cpos >= cend || ncookies == 0) {
 2730                 toff = off;
 2731                 siz = fullsiz;
 2732                 goto again;
 2733         }
 2734 
 2735         len = 3 * NFSX_UNSIGNED;        /* paranoia, probably can be 0 */
 2736         nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz);
 2737         if (v3) {
 2738                 nfsm_srvpostop_attr(getret, &at);
 2739                 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 2740                 txdr_hyper(at.va_filerev, tl);
 2741         }
 2742         mp = mp2 = mb;
 2743         bp = bpos;
 2744         be = bp + M_TRAILINGSPACE(mp);
 2745 
 2746         /* Loop through the records and build reply */
 2747         while (cpos < cend && ncookies > 0) {
 2748                 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
 2749                         nlen = dp->d_namlen;
 2750                         rem = nfsm_rndup(nlen)-nlen;
 2751                         len += (4 * NFSX_UNSIGNED + nlen + rem);
 2752                         if (v3)
 2753                                 len += 2 * NFSX_UNSIGNED;
 2754                         if (len > cnt) {
 2755                                 eofflag = 0;
 2756                                 break;
 2757                         }
 2758                         /*
 2759                          * Build the directory record xdr from
 2760                          * the dirent entry.
 2761                          */
 2762                         nfsm_clget;
 2763                         *tl = nfs_true;
 2764                         bp += NFSX_UNSIGNED;
 2765                         if (v3) {
 2766                                 nfsm_clget;
 2767                                 *tl = 0;
 2768                                 bp += NFSX_UNSIGNED;
 2769                         }
 2770                         nfsm_clget;
 2771                         *tl = txdr_unsigned(dp->d_fileno);
 2772                         bp += NFSX_UNSIGNED;
 2773                         nfsm_clget;
 2774                         *tl = txdr_unsigned(nlen);
 2775                         bp += NFSX_UNSIGNED;
 2776 
 2777                         /* And loop around copying the name */
 2778                         xfer = nlen;
 2779                         cp = dp->d_name;
 2780                         while (xfer > 0) {
 2781                                 nfsm_clget;
 2782                                 if ((bp+xfer) > be)
 2783                                         tsiz = be-bp;
 2784                                 else
 2785                                         tsiz = xfer;
 2786                                 memcpy(bp, cp, tsiz);
 2787                                 bp += tsiz;
 2788                                 xfer -= tsiz;
 2789                                 if (xfer > 0)
 2790                                         cp += tsiz;
 2791                         }
 2792                         /* And null pad to an int32_t boundary */
 2793                         for (i = 0; i < rem; i++)
 2794                                 *bp++ = '\0';
 2795                         nfsm_clget;
 2796 
 2797                         /* Finish off the record */
 2798                         txdr_hyper(*cookiep, &jar);
 2799                         if (v3) {
 2800                                 *tl = jar.nfsuquad[0];
 2801                                 bp += NFSX_UNSIGNED;
 2802                                 nfsm_clget;
 2803                         }
 2804                         *tl = jar.nfsuquad[1];
 2805                         bp += NFSX_UNSIGNED;
 2806                 }
 2807                 cpos += dp->d_reclen;
 2808                 dp = (struct dirent *)cpos;
 2809                 cookiep++;
 2810                 ncookies--;
 2811         }
 2812         vrele(vp);
 2813         nfsm_clget;
 2814         *tl = nfs_false;
 2815         bp += NFSX_UNSIGNED;
 2816         nfsm_clget;
 2817         if (eofflag)
 2818                 *tl = nfs_true;
 2819         else
 2820                 *tl = nfs_false;
 2821         bp += NFSX_UNSIGNED;
 2822         if (mp != mb) {
 2823                 if (bp < be)
 2824                         mp->m_len = bp - mtod(mp, caddr_t);
 2825         } else
 2826                 mp->m_len += bp - bpos;
 2827         free((caddr_t)rbuf, M_TEMP);
 2828         free((caddr_t)cookies, M_TEMP);
 2829         nfsm_srvdone;
 2830 }
 2831 
 2832 int
 2833 nfsrv_readdirplus(nfsd, slp, procp, mrq)
 2834         struct nfsrv_descript *nfsd;
 2835         struct nfssvc_sock *slp;
 2836         struct proc *procp;
 2837         struct mbuf **mrq;
 2838 {
 2839         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 2840         struct mbuf *nam = nfsd->nd_nam;
 2841         caddr_t dpos = nfsd->nd_dpos;
 2842         struct ucred *cred = &nfsd->nd_cr;
 2843         char *bp, *be;
 2844         struct mbuf *mp;
 2845         struct dirent *dp;
 2846         caddr_t cp;
 2847         u_int32_t *tl;
 2848         int32_t t1;
 2849         caddr_t bpos;
 2850         struct mbuf *mb, *mreq, *mp2;
 2851         char *cpos, *cend, *cp2, *rbuf;
 2852         struct vnode *vp, *nvp;
 2853         struct flrep fl;
 2854         nfsfh_t nfh;
 2855         fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh;
 2856         struct uio io;
 2857         struct iovec iv;
 2858         struct vattr va, at, *vap = &va;
 2859         struct nfs_fattr *fp;
 2860         int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
 2861         int siz, cnt, fullsiz, eofflag, rdonly, cache, dirlen, ncookies;
 2862         u_quad_t frev, off, toff, verf;
 2863         off_t *cookies = NULL, *cookiep;
 2864 
 2865         fhp = &nfh.fh_generic;
 2866         nfsm_srvmtofh(fhp);
 2867         nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
 2868         toff = fxdr_hyper(tl);
 2869         tl += 2;
 2870         verf = fxdr_hyper(tl);
 2871         tl += 2;
 2872         siz = fxdr_unsigned(int, *tl++);
 2873         cnt = fxdr_unsigned(int, *tl);
 2874         off = toff;
 2875         siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
 2876         xfer = NFS_SRVMAXDATA(nfsd);
 2877         if (siz > xfer)
 2878                 siz = xfer;
 2879         fullsiz = siz;
 2880         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
 2881                  &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
 2882         if (!error && vp->v_type != VDIR) {
 2883                 error = ENOTDIR;
 2884                 vput(vp);
 2885         }
 2886         if (error) {
 2887                 nfsm_reply(NFSX_UNSIGNED);
 2888                 nfsm_srvpostop_attr(getret, &at);
 2889                 return (0);
 2890         }
 2891         error = getret = VOP_GETATTR(vp, &at, cred, procp);
 2892 #ifdef NFS3_STRICTVERF
 2893         /*
 2894          * XXX This check is too strict for Solaris 2.5 clients.
 2895          */
 2896         if (!error && toff && verf != at.va_filerev)
 2897                 error = NFSERR_BAD_COOKIE;
 2898 #endif
 2899         if (!error) {
 2900                 nqsrv_getl(vp, ND_READ);
 2901                 error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0);
 2902         }
 2903         if (error) {
 2904                 vput(vp);
 2905                 nfsm_reply(NFSX_V3POSTOPATTR);
 2906                 nfsm_srvpostop_attr(getret, &at);
 2907                 return (0);
 2908         }
 2909         VOP_UNLOCK(vp, 0);
 2910 
 2911         rbuf = malloc(siz, M_TEMP, M_WAITOK);
 2912 again:
 2913         iv.iov_base = rbuf;
 2914         iv.iov_len = fullsiz;
 2915         io.uio_iov = &iv;
 2916         io.uio_iovcnt = 1;
 2917         io.uio_offset = (off_t)off;
 2918         io.uio_resid = fullsiz;
 2919         io.uio_segflg = UIO_SYSSPACE;
 2920         io.uio_rw = UIO_READ;
 2921         io.uio_procp = NULL;
 2922         eofflag = 0;
 2923 
 2924         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 2925 
 2926         error = VOP_READDIR(vp, &io, cred, &eofflag, &cookies, &ncookies);
 2927 
 2928         off = (u_quad_t)io.uio_offset;
 2929         getret = VOP_GETATTR(vp, &at, cred, procp);
 2930 
 2931         VOP_UNLOCK(vp, 0);
 2932 
 2933         /*
 2934          * If the VGET operation doesn't work for this filesystem,
 2935          * we can't support readdirplus. Returning NOTSUPP should
 2936          * make clients fall back to plain readdir.
 2937          * There's no need to check for VPTOFH as well, we wouldn't
 2938          * even be here otherwise.
 2939          */
 2940         if (!getret) {
 2941                 if ((getret = VFS_VGET(vp->v_mount, at.va_fileid, &nvp)))
 2942                         getret = (getret == EOPNOTSUPP) ?
 2943                                 NFSERR_NOTSUPP : NFSERR_IO;
 2944                 else
 2945                         vput(nvp);
 2946         }
 2947 
 2948         if (!cookies && !error)
 2949                 error = NFSERR_PERM;
 2950         if (!error)
 2951                 error = getret;
 2952         if (error) {
 2953                 vrele(vp);
 2954                 if (cookies)
 2955                         free((caddr_t)cookies, M_TEMP);
 2956                 free((caddr_t)rbuf, M_TEMP);
 2957                 nfsm_reply(NFSX_V3POSTOPATTR);
 2958                 nfsm_srvpostop_attr(getret, &at);
 2959                 return (0);
 2960         }
 2961         if (io.uio_resid) {
 2962                 siz -= io.uio_resid;
 2963 
 2964                 /*
 2965                  * If nothing read, return eof
 2966                  * rpc reply
 2967                  */
 2968                 if (siz == 0) {
 2969                         vrele(vp);
 2970                         nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
 2971                                 2 * NFSX_UNSIGNED);
 2972                         nfsm_srvpostop_attr(getret, &at);
 2973                         nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
 2974                         txdr_hyper(at.va_filerev, tl);
 2975                         tl += 2;
 2976                         *tl++ = nfs_false;
 2977                         *tl = nfs_true;
 2978                         free((caddr_t)cookies, M_TEMP);
 2979                         free((caddr_t)rbuf, M_TEMP);
 2980                         return (0);
 2981                 }
 2982         }
 2983 
 2984         /*
 2985          * Check for degenerate cases of nothing useful read.
 2986          * If so go try again
 2987          */
 2988         cpos = rbuf;
 2989         cend = rbuf + siz;
 2990         dp = (struct dirent *)cpos;
 2991         cookiep = cookies;
 2992 
 2993         while (cpos < cend && ncookies > 0 &&
 2994                 (dp->d_fileno == 0 || dp->d_type == DT_WHT)) {
 2995                 cpos += dp->d_reclen;
 2996                 dp = (struct dirent *)cpos;
 2997                 cookiep++;
 2998                 ncookies--;
 2999         }
 3000         if (cpos >= cend || ncookies == 0) {
 3001                 toff = off;
 3002                 siz = fullsiz;
 3003                 goto again;
 3004         }
 3005 
 3006         dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 2 * NFSX_UNSIGNED;
 3007         nfsm_reply(cnt);
 3008         nfsm_srvpostop_attr(getret, &at);
 3009         nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 3010         txdr_hyper(at.va_filerev, tl);
 3011         mp = mp2 = mb;
 3012         bp = bpos;
 3013         be = bp + M_TRAILINGSPACE(mp);
 3014 
 3015         /* Loop through the records and build reply */
 3016         while (cpos < cend && ncookies > 0) {
 3017                 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
 3018                         nlen = dp->d_namlen;
 3019                         rem = nfsm_rndup(nlen)-nlen;
 3020 
 3021                         /*
 3022                          * For readdir_and_lookup get the vnode using
 3023                          * the file number.
 3024                          */
 3025                         if (VFS_VGET(vp->v_mount, dp->d_fileno, &nvp))
 3026                                 goto invalid;
 3027                         memset((caddr_t)nfhp, 0, NFSX_V3FH);
 3028                         nfhp->fh_fsid =
 3029                                 nvp->v_mount->mnt_stat.f_fsidx;
 3030                         if (VFS_VPTOFH(nvp, &nfhp->fh_fid)) {
 3031                                 vput(nvp);
 3032                                 goto invalid;
 3033                         }
 3034                         if (VOP_GETATTR(nvp, vap, cred, procp)) {
 3035                                 vput(nvp);
 3036                                 goto invalid;
 3037                         }
 3038                         vput(nvp);
 3039 
 3040                         /*
 3041                          * If either the dircount or maxcount will be
 3042                          * exceeded, get out now. Both of these lengths
 3043                          * are calculated conservatively, including all
 3044                          * XDR overheads.
 3045                          */
 3046                         len += (8 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH +
 3047                                 NFSX_V3POSTOPATTR);
 3048                         dirlen += (6 * NFSX_UNSIGNED + nlen + rem);
 3049                         if (len > cnt || dirlen > fullsiz) {
 3050                                 eofflag = 0;
 3051                                 break;
 3052                         }
 3053 
 3054                         /*
 3055                          * Build the directory record xdr from
 3056                          * the dirent entry.
 3057                          */
 3058                         fp = (struct nfs_fattr *)&fl.fl_fattr;
 3059                         nfsm_srvfillattr(vap, fp);
 3060                         fl.fl_fhsize = txdr_unsigned(NFSX_V3FH);
 3061                         fl.fl_fhok = nfs_true;
 3062                         fl.fl_postopok = nfs_true;
 3063                         txdr_hyper(*cookiep, fl.fl_off.nfsuquad);
 3064 
 3065                         nfsm_clget;
 3066                         *tl = nfs_true;
 3067                         bp += NFSX_UNSIGNED;
 3068                         nfsm_clget;
 3069                         *tl = 0;
 3070                         bp += NFSX_UNSIGNED;
 3071                         nfsm_clget;
 3072                         *tl = txdr_unsigned(dp->d_fileno);
 3073                         bp += NFSX_UNSIGNED;
 3074                         nfsm_clget;
 3075                         *tl = txdr_unsigned(nlen);
 3076                         bp += NFSX_UNSIGNED;
 3077 
 3078                         /* And loop around copying the name */
 3079                         xfer = nlen;
 3080                         cp = dp->d_name;
 3081                         while (xfer > 0) {
 3082                                 nfsm_clget;
 3083                                 if ((bp + xfer) > be)
 3084                                         tsiz = be - bp;
 3085                                 else
 3086                                         tsiz = xfer;
 3087                                 memcpy(bp, cp, tsiz);
 3088                                 bp += tsiz;
 3089                                 xfer -= tsiz;
 3090                                 if (xfer > 0)
 3091                                         cp += tsiz;
 3092                         }
 3093                         /* And null pad to an int32_t boundary */
 3094                         for (i = 0; i < rem; i++)
 3095                                 *bp++ = '\0';
 3096 
 3097                         /*
 3098                          * Now copy the flrep structure out.
 3099                          */
 3100                         xfer = sizeof (struct flrep);
 3101                         cp = (caddr_t)&fl;
 3102                         while (xfer > 0) {
 3103                                 nfsm_clget;
 3104                                 if ((bp + xfer) > be)
 3105                                         tsiz = be - bp;
 3106                                 else
 3107                                         tsiz = xfer;
 3108                                 memcpy(bp, cp, tsiz);
 3109                                 bp += tsiz;
 3110                                 xfer -= tsiz;
 3111                                 if (xfer > 0)
 3112                                         cp += tsiz;
 3113                         }
 3114                 }
 3115 invalid:
 3116                 cpos += dp->d_reclen;
 3117                 dp = (struct dirent *)cpos;
 3118                 cookiep++;
 3119                 ncookies--;
 3120         }
 3121         vrele(vp);
 3122         nfsm_clget;
 3123         *tl = nfs_false;
 3124         bp += NFSX_UNSIGNED;
 3125         nfsm_clget;
 3126         if (eofflag)
 3127                 *tl = nfs_true;
 3128         else
 3129                 *tl = nfs_false;
 3130         bp += NFSX_UNSIGNED;
 3131         if (mp != mb) {
 3132                 if (bp < be)
 3133                         mp->m_len = bp - mtod(mp, caddr_t);
 3134         } else
 3135                 mp->m_len += bp - bpos;
 3136         free((caddr_t)cookies, M_TEMP);
 3137         free((caddr_t)rbuf, M_TEMP);
 3138         nfsm_srvdone;
 3139 }
 3140 
 3141 /*
 3142  * nfs commit service
 3143  */
 3144 int
 3145 nfsrv_commit(nfsd, slp, procp, mrq)
 3146         struct nfsrv_descript *nfsd;
 3147         struct nfssvc_sock *slp;
 3148         struct proc *procp;
 3149         struct mbuf **mrq;
 3150 {
 3151         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 3152         struct mbuf *nam = nfsd->nd_nam;
 3153         caddr_t dpos = nfsd->nd_dpos;
 3154         struct ucred *cred = &nfsd->nd_cr;
 3155         struct vattr bfor, aft;
 3156         struct vnode *vp;
 3157         nfsfh_t nfh;
 3158         fhandle_t *fhp;
 3159         u_int32_t *tl;
 3160         int32_t t1;
 3161         caddr_t bpos;
 3162         int error = 0, rdonly, for_ret = 1, aft_ret = 1, cache;
 3163         uint32_t cnt;
 3164         char *cp2;
 3165         struct mbuf *mb, *mreq;
 3166         u_quad_t frev, off, end;
 3167         struct mount *mp = NULL;
 3168 
 3169 #ifndef nolint
 3170         cache = 0;
 3171 #endif
 3172         fhp = &nfh.fh_generic;
 3173         nfsm_srvmtofh(fhp);
 3174         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL)
 3175                 return (ESTALE);
 3176         vn_start_write(NULL, &mp, V_WAIT);
 3177         nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
 3178 
 3179         off = fxdr_hyper(tl);
 3180         tl += 2;
 3181         cnt = fxdr_unsigned(uint32_t, *tl);
 3182         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
 3183                  &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
 3184         if (error) {
 3185                 nfsm_reply(2 * NFSX_UNSIGNED);
 3186                 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
 3187                 vn_finished_write(mp, 0);
 3188                 return (0);
 3189         }
 3190         for_ret = VOP_GETATTR(vp, &bfor, cred, procp);
 3191         end = (cnt > 0) ? off + cnt : vp->v_size;
 3192         if (end < off || end > vp->v_size)
 3193                 end = vp->v_size;
 3194         if (off < vp->v_size)
 3195                 error = VOP_FSYNC(vp, cred, FSYNC_WAIT, off, end, procp);
 3196         /* else error == 0, from nfsrv_fhtovp() */
 3197         aft_ret = VOP_GETATTR(vp, &aft, cred, procp);
 3198         vput(vp);
 3199         nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF);
 3200         nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
 3201         if (!error) {
 3202                 nfsm_build(tl, u_int32_t *, NFSX_V3WRITEVERF);
 3203                 *tl++ = txdr_unsigned(boottime.tv_sec);
 3204                 *tl = txdr_unsigned(boottime.tv_usec);
 3205         } else {
 3206                 vn_finished_write(mp, 0);
 3207                 return (0);
 3208         }
 3209         vn_finished_write(mp, 0);
 3210         nfsm_srvdone;
 3211 }
 3212 
 3213 /*
 3214  * nfs statfs service
 3215  */
 3216 int
 3217 nfsrv_statfs(nfsd, slp, procp, mrq)
 3218         struct nfsrv_descript *nfsd;
 3219         struct nfssvc_sock *slp;
 3220         struct proc *procp;
 3221         struct mbuf **mrq;
 3222 {
 3223         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 3224         struct mbuf *nam = nfsd->nd_nam;
 3225         caddr_t dpos = nfsd->nd_dpos;
 3226         struct ucred *cred = &nfsd->nd_cr;
 3227         struct statvfs *sf;
 3228         struct nfs_statfs *sfp;
 3229         u_int32_t *tl;
 3230         int32_t t1;
 3231         caddr_t bpos;
 3232         int error = 0, rdonly, cache, getret = 1;
 3233         int v3 = (nfsd->nd_flag & ND_NFSV3);
 3234         char *cp2;
 3235         struct mbuf *mb, *mreq;
 3236         struct vnode *vp;
 3237         struct vattr at;
 3238         nfsfh_t nfh;
 3239         fhandle_t *fhp;
 3240         struct statvfs statvfs;
 3241         u_quad_t frev, tval;
 3242 
 3243 #ifndef nolint
 3244         cache = 0;
 3245 #endif
 3246         fhp = &nfh.fh_generic;
 3247         nfsm_srvmtofh(fhp);
 3248         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
 3249                  &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
 3250         if (error) {
 3251                 nfsm_reply(NFSX_UNSIGNED);
 3252                 nfsm_srvpostop_attr(getret, &at);
 3253                 return (0);
 3254         }
 3255         sf = &statvfs;
 3256         error = VFS_STATVFS(vp->v_mount, sf, procp);
 3257         getret = VOP_GETATTR(vp, &at, cred, procp);
 3258         vput(vp);
 3259         nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3));
 3260         if (v3)
 3261                 nfsm_srvpostop_attr(getret, &at);
 3262         if (error)
 3263                 return (0);
 3264         nfsm_build(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
 3265         if (v3) {
 3266                 tval = (u_quad_t)((quad_t)sf->f_blocks * (quad_t)sf->f_frsize);
 3267                 txdr_hyper(tval, &sfp->sf_tbytes);
 3268                 tval = (u_quad_t)((quad_t)sf->f_bfree * (quad_t)sf->f_frsize);
 3269                 txdr_hyper(tval, &sfp->sf_fbytes);
 3270                 tval = (u_quad_t)((quad_t)sf->f_bavail * (quad_t)sf->f_frsize);
 3271                 txdr_hyper(tval, &sfp->sf_abytes);
 3272                 tval = (u_quad_t)sf->f_files;
 3273                 txdr_hyper(tval, &sfp->sf_tfiles);
 3274                 tval = (u_quad_t)sf->f_ffree;
 3275                 txdr_hyper(tval, &sfp->sf_ffiles);
 3276                 txdr_hyper(tval, &sfp->sf_afiles);
 3277                 sfp->sf_invarsec = 0;
 3278         } else {
 3279                 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
 3280                 sfp->sf_bsize = txdr_unsigned(sf->f_frsize);
 3281                 sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
 3282                 sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
 3283                 sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
 3284         }
 3285         nfsm_srvdone;
 3286 }
 3287 
 3288 /*
 3289  * nfs fsinfo service
 3290  */
 3291 int
 3292 nfsrv_fsinfo(nfsd, slp, procp, mrq)
 3293         struct nfsrv_descript *nfsd;
 3294         struct nfssvc_sock *slp;
 3295         struct proc *procp;
 3296         struct mbuf **mrq;
 3297 {
 3298         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 3299         struct mbuf *nam = nfsd->nd_nam;
 3300         caddr_t dpos = nfsd->nd_dpos;
 3301         struct ucred *cred = &nfsd->nd_cr;
 3302         u_int32_t *tl;
 3303         struct nfsv3_fsinfo *sip;
 3304         int32_t t1;
 3305         caddr_t bpos;
 3306         int error = 0, rdonly, cache, getret = 1;
 3307         uint32_t maxdata;
 3308         char *cp2;
 3309         struct mbuf *mb, *mreq;
 3310         struct vnode *vp;
 3311         struct vattr at;
 3312         nfsfh_t nfh;
 3313         fhandle_t *fhp;
 3314         u_quad_t frev, maxfsize;
 3315         struct statvfs sb;
 3316 
 3317 #ifndef nolint
 3318         cache = 0;
 3319 #endif
 3320         fhp = &nfh.fh_generic;
 3321         nfsm_srvmtofh(fhp);
 3322         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
 3323                  &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
 3324         if (error) {
 3325                 nfsm_reply(NFSX_UNSIGNED);
 3326                 nfsm_srvpostop_attr(getret, &at);
 3327                 return (0);
 3328         }
 3329 
 3330         /* XXX Try to make a guess on the max file size. */
 3331         VFS_STATVFS(vp->v_mount, &sb, (struct proc *)0);
 3332         maxfsize = (u_quad_t)0x80000000 * sb.f_frsize - 1;
 3333 
 3334         getret = VOP_GETATTR(vp, &at, cred, procp);
 3335         vput(vp);
 3336         nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO);
 3337         nfsm_srvpostop_attr(getret, &at);
 3338         nfsm_build(sip, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
 3339 
 3340         /*
 3341          * XXX
 3342          * There should be file system VFS OP(s) to get this information.
 3343          * For now, assume ufs.
 3344          */
 3345         if (slp->ns_so->so_type == SOCK_DGRAM)
 3346                 maxdata = NFS_MAXDGRAMDATA;
 3347         else
 3348                 maxdata = NFS_MAXDATA;
 3349         sip->fs_rtmax = txdr_unsigned(maxdata);
 3350         sip->fs_rtpref = txdr_unsigned(maxdata);
 3351         sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE);
 3352         sip->fs_wtmax = txdr_unsigned(maxdata);
 3353         sip->fs_wtpref = txdr_unsigned(maxdata);
 3354         sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE);
 3355         sip->fs_dtpref = txdr_unsigned(maxdata);
 3356         txdr_hyper(maxfsize, &sip->fs_maxfilesize);
 3357         sip->fs_timedelta.nfsv3_sec = 0;
 3358         sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1);
 3359         sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK |
 3360                 NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS |
 3361                 NFSV3FSINFO_CANSETTIME);
 3362         nfsm_srvdone;
 3363 }
 3364 
 3365 /*
 3366  * nfs pathconf service
 3367  */
 3368 int
 3369 nfsrv_pathconf(nfsd, slp, procp, mrq)
 3370         struct nfsrv_descript *nfsd;
 3371         struct nfssvc_sock *slp;
 3372         struct proc *procp;
 3373         struct mbuf **mrq;
 3374 {
 3375         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
 3376         struct mbuf *nam = nfsd->nd_nam;
 3377         caddr_t dpos = nfsd->nd_dpos;
 3378         struct ucred *cred = &nfsd->nd_cr;
 3379         u_int32_t *tl;
 3380         struct nfsv3_pathconf *pc;
 3381         int32_t t1;
 3382         caddr_t bpos;
 3383         int error = 0, rdonly, cache, getret = 1;
 3384         register_t linkmax, namemax, chownres, notrunc;
 3385         char *cp2;
 3386         struct mbuf *mb, *mreq;
 3387         struct vnode *vp;
 3388         struct vattr at;
 3389         nfsfh_t nfh;
 3390         fhandle_t *fhp;
 3391         u_quad_t frev;
 3392 
 3393 #ifndef nolint
 3394         cache = 0;
 3395 #endif
 3396         fhp = &nfh.fh_generic;
 3397         nfsm_srvmtofh(fhp);
 3398         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
 3399                  &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
 3400         if (error) {
 3401                 nfsm_reply(NFSX_UNSIGNED);
 3402                 nfsm_srvpostop_attr(getret, &at);
 3403                 return (0);
 3404         }
 3405         error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax);
 3406         if (!error)
 3407                 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax);
 3408         if (!error)
 3409                 error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres);
 3410         if (!error)
 3411                 error = VOP_PATHCONF(vp, _PC_NO_TRUNC, &notrunc);
 3412         getret = VOP_GETATTR(vp, &at, cred, procp);
 3413         vput(vp);
 3414         nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF);
 3415         nfsm_srvpostop_attr(getret, &at);
 3416         if (error)
 3417                 return (0);
 3418         nfsm_build(pc, struct nfsv3_pathconf *, NFSX_V3PATHCONF);
 3419 
 3420         pc->pc_linkmax = txdr_unsigned(linkmax);
 3421         pc->pc_namemax = txdr_unsigned(namemax);
 3422         pc->pc_notrunc = txdr_unsigned(notrunc);
 3423         pc->pc_chownrestricted = txdr_unsigned(chownres);
 3424 
 3425         /*
 3426          * These should probably be supported by VOP_PATHCONF(), but
 3427          * until msdosfs is exportable (why would you want to?), the
 3428          * Unix defaults should be ok.
 3429          */
 3430         pc->pc_caseinsensitive = nfs_false;
 3431         pc->pc_casepreserving = nfs_true;
 3432         nfsm_srvdone;
 3433 }
 3434 
 3435 /*
 3436  * Null operation, used by clients to ping server
 3437  */
 3438 /* ARGSUSED */
 3439 int
 3440 nfsrv_null(nfsd, slp, procp, mrq)
 3441         struct nfsrv_descript *nfsd;
 3442         struct nfssvc_sock *slp;
 3443         struct proc *procp;
 3444         struct mbuf **mrq;
 3445 {
 3446         struct mbuf *mrep = nfsd->nd_mrep;
 3447         caddr_t bpos;
 3448         int error = NFSERR_RETVOID, cache = 0;
 3449         struct mbuf *mb, *mreq;
 3450         u_quad_t frev;
 3451 
 3452         nfsm_reply(0);
 3453         return (0);
 3454 }
 3455 
 3456 /*
 3457  * No operation, used for obsolete procedures
 3458  */
 3459 /* ARGSUSED */
 3460 int
 3461 nfsrv_noop(nfsd, slp, procp, mrq)
 3462         struct nfsrv_descript *nfsd;
 3463         struct nfssvc_sock *slp;
 3464         struct proc *procp;
 3465         struct mbuf **mrq;
 3466 {
 3467         struct mbuf *mrep = nfsd->nd_mrep;
 3468         caddr_t bpos;
 3469         int error, cache = 0;
 3470         struct mbuf *mb, *mreq;
 3471         u_quad_t frev;
 3472 
 3473         if (nfsd->nd_repstat)
 3474                 error = nfsd->nd_repstat;
 3475         else
 3476                 error = EPROCUNAVAIL;
 3477         nfsm_reply(0);
 3478         return (0);
 3479 }
 3480 
 3481 /*
 3482  * Perform access checking for vnodes obtained from file handles that would
 3483  * refer to files already opened by a Unix client. You cannot just use
 3484  * vn_writechk() and VOP_ACCESS() for two reasons.
 3485  * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case
 3486  * 2 - The owner is to be given access irrespective of mode bits for some
 3487  *     operations, so that processes that chmod after opening a file don't
 3488  *     break. I don't like this because it opens a security hole, but since
 3489  *     the nfs server opens a security hole the size of a barn door anyhow,
 3490  *     what the heck.
 3491  *
 3492  * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS()
 3493  * will return EPERM instead of EACCESS. EPERM is always an error.
 3494  */
 3495 int
 3496 nfsrv_access(vp, flags, cred, rdonly, p, override)
 3497         struct vnode *vp;
 3498         int flags;
 3499         struct ucred *cred;
 3500         int rdonly;
 3501         struct proc *p;
 3502 {
 3503         struct vattr vattr;
 3504         int error;
 3505         if (flags & VWRITE) {
 3506                 /* Just vn_writechk() changed to check rdonly */
 3507                 /*
 3508                  * Disallow write attempts on read-only file systems;
 3509                  * unless the file is a socket or a block or character
 3510                  * device resident on the file system.
 3511                  */
 3512                 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
 3513                         switch (vp->v_type) {
 3514                         case VREG:
 3515                         case VDIR:
 3516                         case VLNK:
 3517                                 return (EROFS);
 3518                         default:
 3519                                 break;
 3520                         }
 3521                 }
 3522 
 3523                 /*
 3524                  * If the vnode is in use as a process's text,
 3525                  * we can't allow writing.
 3526                  */
 3527                 if (vp->v_flag & VTEXT)
 3528                         return (ETXTBSY);
 3529         }
 3530         error = VOP_GETATTR(vp, &vattr, cred, p);
 3531         if (error)
 3532                 return (error);
 3533         error = VOP_ACCESS(vp, flags, cred, p);
 3534         /*
 3535          * Allow certain operations for the owner (reads and writes
 3536          * on files that are already open).
 3537          */
 3538         if (override && error == EACCES && cred->cr_uid == vattr.va_uid)
 3539                 error = 0;
 3540         return error;
 3541 }

Cache object: 8ae13824dc2accbc48ffd40dbfdbe475


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