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/fs/nfsclient/nfs_clrpcops.c

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

    1 /*-
    2  * SPDX-License-Identifier: BSD-3-Clause
    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  */
   35 
   36 #include <sys/cdefs.h>
   37 __FBSDID("$FreeBSD$");
   38 
   39 /*
   40  * Rpc op calls, generally called from the vnode op calls or through the
   41  * buffer cache, for NFS v2, 3 and 4.
   42  * These do not normally make any changes to vnode arguments or use
   43  * structures that might change between the VFS variants. The returned
   44  * arguments are all at the end, after the NFSPROC_T *p one.
   45  */
   46 
   47 #include "opt_inet6.h"
   48 
   49 #include <fs/nfs/nfsport.h>
   50 #include <sys/sysctl.h>
   51 #include <sys/taskqueue.h>
   52 
   53 SYSCTL_DECL(_vfs_nfs);
   54 
   55 static int      nfsignore_eexist = 0;
   56 SYSCTL_INT(_vfs_nfs, OID_AUTO, ignore_eexist, CTLFLAG_RW,
   57     &nfsignore_eexist, 0, "NFS ignore EEXIST replies for mkdir/symlink");
   58 
   59 static int      nfscl_dssameconn = 0;
   60 SYSCTL_INT(_vfs_nfs, OID_AUTO, dssameconn, CTLFLAG_RW,
   61     &nfscl_dssameconn, 0, "Use same TCP connection to multiple DSs");
   62 
   63 /*
   64  * Global variables
   65  */
   66 extern struct nfsstatsv1 nfsstatsv1;
   67 extern int nfs_numnfscbd;
   68 extern struct timeval nfsboottime;
   69 extern u_int32_t newnfs_false, newnfs_true;
   70 extern nfstype nfsv34_type[9];
   71 extern int nfsrv_useacl;
   72 extern char nfsv4_callbackaddr[INET6_ADDRSTRLEN];
   73 extern int nfscl_debuglevel;
   74 extern int nfs_pnfsiothreads;
   75 NFSCLSTATEMUTEX;
   76 int nfstest_outofseq = 0;
   77 int nfscl_assumeposixlocks = 1;
   78 int nfscl_enablecallb = 0;
   79 short nfsv4_cbport = NFSV4_CBPORT;
   80 int nfstest_openallsetattr = 0;
   81 
   82 #define DIRHDSIZ        offsetof(struct dirent, d_name)
   83 
   84 /*
   85  * nfscl_getsameserver() can return one of three values:
   86  * NFSDSP_USETHISSESSION - Use this session for the DS.
   87  * NFSDSP_SEQTHISSESSION - Use the nfsclds_sequence field of this dsp for new
   88  *     session.
   89  * NFSDSP_NOTFOUND - No matching server was found.
   90  */
   91 enum nfsclds_state {
   92         NFSDSP_USETHISSESSION = 0,
   93         NFSDSP_SEQTHISSESSION = 1,
   94         NFSDSP_NOTFOUND = 2,
   95 };
   96 
   97 /*
   98  * Do a write RPC on a DS data file, using this structure for the arguments,
   99  * so that this function can be executed by a separate kernel process.
  100  */
  101 struct nfsclwritedsdorpc {
  102         int                     done;
  103         int                     inprog;
  104         struct task             tsk;
  105         struct vnode            *vp;
  106         int                     iomode;
  107         int                     must_commit;
  108         nfsv4stateid_t          *stateidp;
  109         struct nfsclds          *dsp;
  110         uint64_t                off;
  111         int                     len;
  112         struct nfsfh            *fhp;
  113         struct mbuf             *m;
  114         int                     vers;
  115         int                     minorvers;
  116         struct ucred            *cred;
  117         NFSPROC_T               *p;
  118         int                     err;
  119 };
  120 
  121 static int nfsrpc_setattrrpc(vnode_t , struct vattr *, nfsv4stateid_t *,
  122     struct ucred *, NFSPROC_T *, struct nfsvattr *, int *, void *);
  123 static int nfsrpc_readrpc(vnode_t , struct uio *, struct ucred *,
  124     nfsv4stateid_t *, NFSPROC_T *, struct nfsvattr *, int *, void *);
  125 static int nfsrpc_writerpc(vnode_t , struct uio *, int *, int *,
  126     struct ucred *, nfsv4stateid_t *, NFSPROC_T *, struct nfsvattr *, int *,
  127     void *);
  128 static int nfsrpc_createv23(vnode_t , char *, int, struct vattr *,
  129     nfsquad_t, int, struct ucred *, NFSPROC_T *, struct nfsvattr *,
  130     struct nfsvattr *, struct nfsfh **, int *, int *, void *);
  131 static int nfsrpc_createv4(vnode_t , char *, int, struct vattr *,
  132     nfsquad_t, int, struct nfsclowner *, struct nfscldeleg **, struct ucred *,
  133     NFSPROC_T *, struct nfsvattr *, struct nfsvattr *, struct nfsfh **, int *,
  134     int *, void *, int *);
  135 static int nfsrpc_locku(struct nfsrv_descript *, struct nfsmount *,
  136     struct nfscllockowner *, u_int64_t, u_int64_t,
  137     u_int32_t, struct ucred *, NFSPROC_T *, int);
  138 static int nfsrpc_setaclrpc(vnode_t, struct ucred *, NFSPROC_T *,
  139     struct acl *, nfsv4stateid_t *, void *);
  140 static int nfsrpc_getlayout(struct nfsmount *, vnode_t, struct nfsfh *, int,
  141     uint32_t, uint32_t *, nfsv4stateid_t *, uint64_t, struct nfscllayout **,
  142     struct ucred *, NFSPROC_T *);
  143 static int nfsrpc_fillsa(struct nfsmount *, struct sockaddr_in *,
  144     struct sockaddr_in6 *, sa_family_t, int, struct nfsclds **, NFSPROC_T *);
  145 static void nfscl_initsessionslots(struct nfsclsession *);
  146 static int nfscl_doflayoutio(vnode_t, struct uio *, int *, int *, int *,
  147     nfsv4stateid_t *, int, struct nfscldevinfo *, struct nfscllayout *,
  148     struct nfsclflayout *, uint64_t, uint64_t, int, struct ucred *,
  149     NFSPROC_T *);
  150 static int nfscl_dofflayoutio(vnode_t, struct uio *, int *, int *, int *,
  151     nfsv4stateid_t *, int, struct nfscldevinfo *, struct nfscllayout *,
  152     struct nfsclflayout *, uint64_t, uint64_t, int, int, struct mbuf *,
  153     struct nfsclwritedsdorpc *, struct ucred *, NFSPROC_T *);
  154 static struct mbuf *nfsm_copym(struct mbuf *, int, int);
  155 static int nfsrpc_readds(vnode_t, struct uio *, nfsv4stateid_t *, int *,
  156     struct nfsclds *, uint64_t, int, struct nfsfh *, int, int, int,
  157     struct ucred *, NFSPROC_T *);
  158 static int nfsrpc_writeds(vnode_t, struct uio *, int *, int *,
  159     nfsv4stateid_t *, struct nfsclds *, uint64_t, int,
  160     struct nfsfh *, int, int, int, int, struct ucred *, NFSPROC_T *);
  161 static int nfsio_writedsmir(vnode_t, int *, int *, nfsv4stateid_t *,
  162     struct nfsclds *, uint64_t, int, struct nfsfh *, struct mbuf *, int, int,
  163     struct nfsclwritedsdorpc *, struct ucred *, NFSPROC_T *);
  164 static int nfsrpc_writedsmir(vnode_t, int *, int *, nfsv4stateid_t *,
  165     struct nfsclds *, uint64_t, int, struct nfsfh *, struct mbuf *, int, int,
  166     struct ucred *, NFSPROC_T *);
  167 static enum nfsclds_state nfscl_getsameserver(struct nfsmount *,
  168     struct nfsclds *, struct nfsclds **, uint32_t *);
  169 static int nfsio_commitds(vnode_t, uint64_t, int, struct nfsclds *,
  170     struct nfsfh *, int, int, struct nfsclwritedsdorpc *, struct ucred *,
  171     NFSPROC_T *);
  172 static int nfsrpc_commitds(vnode_t, uint64_t, int, struct nfsclds *,
  173     struct nfsfh *, int, int, struct ucred *, NFSPROC_T *);
  174 static void nfsrv_setuplayoutget(struct nfsrv_descript *, int, uint64_t,
  175     uint64_t, uint64_t, nfsv4stateid_t *, int, int, int);
  176 static int nfsrv_parseug(struct nfsrv_descript *, int, uid_t *, gid_t *,
  177     NFSPROC_T *);
  178 static int nfsrv_parselayoutget(struct nfsrv_descript *, nfsv4stateid_t *,
  179     int *, struct nfsclflayouthead *);
  180 static int nfsrpc_getopenlayout(struct nfsmount *, vnode_t, u_int8_t *,
  181     int, uint8_t *, int, uint32_t, struct nfsclopen *, uint8_t *, int,
  182     struct nfscldeleg **, struct ucred *, NFSPROC_T *);
  183 static int nfsrpc_getcreatelayout(vnode_t, char *, int, struct vattr *,
  184     nfsquad_t, int, struct nfsclowner *, struct nfscldeleg **,
  185     struct ucred *, NFSPROC_T *, struct nfsvattr *, struct nfsvattr *,
  186     struct nfsfh **, int *, int *, void *, int *);
  187 static int nfsrpc_openlayoutrpc(struct nfsmount *, vnode_t, u_int8_t *,
  188     int, uint8_t *, int, uint32_t, struct nfsclopen *, uint8_t *, int,
  189     struct nfscldeleg **, nfsv4stateid_t *, int, int, int, int *,
  190     struct nfsclflayouthead *, int *, struct ucred *, NFSPROC_T *);
  191 static int nfsrpc_createlayout(vnode_t, char *, int, struct vattr *,
  192     nfsquad_t, int, struct nfsclowner *, struct nfscldeleg **,
  193     struct ucred *, NFSPROC_T *, struct nfsvattr *, struct nfsvattr *,
  194     struct nfsfh **, int *, int *, void *, int *, nfsv4stateid_t *,
  195     int, int, int, int *, struct nfsclflayouthead *, int *);
  196 static int nfsrpc_layoutget(struct nfsmount *, uint8_t *, int, int, uint64_t,
  197     uint64_t, uint64_t, int, int, nfsv4stateid_t *, int *,
  198     struct nfsclflayouthead *, struct ucred *, NFSPROC_T *, void *);
  199 static int nfsrpc_layoutgetres(struct nfsmount *, vnode_t, uint8_t *,
  200     int, nfsv4stateid_t *, int, uint32_t *, struct nfscllayout **,
  201     struct nfsclflayouthead *, int, int, int *, struct ucred *, NFSPROC_T *);
  202 
  203 int nfs_pnfsio(task_fn_t *, void *);
  204 
  205 /*
  206  * nfs null call from vfs.
  207  */
  208 int
  209 nfsrpc_null(vnode_t vp, struct ucred *cred, NFSPROC_T *p)
  210 {
  211         int error;
  212         struct nfsrv_descript nfsd, *nd = &nfsd;
  213         
  214         NFSCL_REQSTART(nd, NFSPROC_NULL, vp);
  215         error = nfscl_request(nd, vp, p, cred, NULL);
  216         if (nd->nd_repstat && !error)
  217                 error = nd->nd_repstat;
  218         mbuf_freem(nd->nd_mrep);
  219         return (error);
  220 }
  221 
  222 /*
  223  * nfs access rpc op.
  224  * For nfs version 3 and 4, use the access rpc to check accessibility. If file
  225  * modes are changed on the server, accesses might still fail later.
  226  */
  227 int
  228 nfsrpc_access(vnode_t vp, int acmode, struct ucred *cred,
  229     NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp)
  230 {
  231         int error;
  232         u_int32_t mode, rmode;
  233 
  234         if (acmode & VREAD)
  235                 mode = NFSACCESS_READ;
  236         else
  237                 mode = 0;
  238         if (vnode_vtype(vp) == VDIR) {
  239                 if (acmode & VWRITE)
  240                         mode |= (NFSACCESS_MODIFY | NFSACCESS_EXTEND |
  241                                  NFSACCESS_DELETE);
  242                 if (acmode & VEXEC)
  243                         mode |= NFSACCESS_LOOKUP;
  244         } else {
  245                 if (acmode & VWRITE)
  246                         mode |= (NFSACCESS_MODIFY | NFSACCESS_EXTEND);
  247                 if (acmode & VEXEC)
  248                         mode |= NFSACCESS_EXECUTE;
  249         }
  250 
  251         /*
  252          * Now, just call nfsrpc_accessrpc() to do the actual RPC.
  253          */
  254         error = nfsrpc_accessrpc(vp, mode, cred, p, nap, attrflagp, &rmode,
  255             NULL);
  256 
  257         /*
  258          * The NFS V3 spec does not clarify whether or not
  259          * the returned access bits can be a superset of
  260          * the ones requested, so...
  261          */
  262         if (!error && (rmode & mode) != mode)
  263                 error = EACCES;
  264         return (error);
  265 }
  266 
  267 /*
  268  * The actual rpc, separated out for Darwin.
  269  */
  270 int
  271 nfsrpc_accessrpc(vnode_t vp, u_int32_t mode, struct ucred *cred,
  272     NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp, u_int32_t *rmodep,
  273     void *stuff)
  274 {
  275         u_int32_t *tl;
  276         u_int32_t supported, rmode;
  277         int error;
  278         struct nfsrv_descript nfsd, *nd = &nfsd;
  279         nfsattrbit_t attrbits;
  280 
  281         *attrflagp = 0;
  282         supported = mode;
  283         NFSCL_REQSTART(nd, NFSPROC_ACCESS, vp);
  284         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
  285         *tl = txdr_unsigned(mode);
  286         if (nd->nd_flag & ND_NFSV4) {
  287                 /*
  288                  * And do a Getattr op.
  289                  */
  290                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
  291                 *tl = txdr_unsigned(NFSV4OP_GETATTR);
  292                 NFSGETATTR_ATTRBIT(&attrbits);
  293                 (void) nfsrv_putattrbit(nd, &attrbits);
  294         }
  295         error = nfscl_request(nd, vp, p, cred, stuff);
  296         if (error)
  297                 return (error);
  298         if (nd->nd_flag & ND_NFSV3) {
  299                 error = nfscl_postop_attr(nd, nap, attrflagp, stuff);
  300                 if (error)
  301                         goto nfsmout;
  302         }
  303         if (!nd->nd_repstat) {
  304                 if (nd->nd_flag & ND_NFSV4) {
  305                         NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
  306                         supported = fxdr_unsigned(u_int32_t, *tl++);
  307                 } else {
  308                         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
  309                 }
  310                 rmode = fxdr_unsigned(u_int32_t, *tl);
  311                 if (nd->nd_flag & ND_NFSV4)
  312                         error = nfscl_postop_attr(nd, nap, attrflagp, stuff);
  313 
  314                 /*
  315                  * It's not obvious what should be done about
  316                  * unsupported access modes. For now, be paranoid
  317                  * and clear the unsupported ones.
  318                  */
  319                 rmode &= supported;
  320                 *rmodep = rmode;
  321         } else
  322                 error = nd->nd_repstat;
  323 nfsmout:
  324         mbuf_freem(nd->nd_mrep);
  325         return (error);
  326 }
  327 
  328 /*
  329  * nfs open rpc
  330  */
  331 int
  332 nfsrpc_open(vnode_t vp, int amode, struct ucred *cred, NFSPROC_T *p)
  333 {
  334         struct nfsclopen *op;
  335         struct nfscldeleg *dp;
  336         struct nfsfh *nfhp;
  337         struct nfsnode *np = VTONFS(vp);
  338         struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
  339         u_int32_t mode, clidrev;
  340         int ret, newone, error, expireret = 0, retrycnt;
  341 
  342         /*
  343          * For NFSv4, Open Ops are only done on Regular Files.
  344          */
  345         if (vnode_vtype(vp) != VREG)
  346                 return (0);
  347         mode = 0;
  348         if (amode & FREAD)
  349                 mode |= NFSV4OPEN_ACCESSREAD;
  350         if (amode & FWRITE)
  351                 mode |= NFSV4OPEN_ACCESSWRITE;
  352         nfhp = np->n_fhp;
  353 
  354         retrycnt = 0;
  355 #ifdef notdef
  356 { char name[100]; int namel;
  357 namel = (np->n_v4->n4_namelen < 100) ? np->n_v4->n4_namelen : 99;
  358 bcopy(NFS4NODENAME(np->n_v4), name, namel);
  359 name[namel] = '\0';
  360 printf("rpcopen p=0x%x name=%s",p->p_pid,name);
  361 if (nfhp->nfh_len > 0) printf(" fh=0x%x\n",nfhp->nfh_fh[12]);
  362 else printf(" fhl=0\n");
  363 }
  364 #endif
  365         do {
  366             dp = NULL;
  367             error = nfscl_open(vp, nfhp->nfh_fh, nfhp->nfh_len, mode, 1,
  368                 cred, p, NULL, &op, &newone, &ret, 1, true);
  369             if (error) {
  370                 return (error);
  371             }
  372             if (nmp->nm_clp != NULL)
  373                 clidrev = nmp->nm_clp->nfsc_clientidrev;
  374             else
  375                 clidrev = 0;
  376             if (ret == NFSCLOPEN_DOOPEN) {
  377                 if (np->n_v4 != NULL) {
  378                         /*
  379                          * For the first attempt, try and get a layout, if
  380                          * pNFS is enabled for the mount.
  381                          */
  382                         if (!NFSHASPNFS(nmp) || nfscl_enablecallb == 0 ||
  383                             nfs_numnfscbd == 0 ||
  384                             (np->n_flag & NNOLAYOUT) != 0 || retrycnt > 0)
  385                                 error = nfsrpc_openrpc(nmp, vp,
  386                                     np->n_v4->n4_data,
  387                                     np->n_v4->n4_fhlen, np->n_fhp->nfh_fh,
  388                                     np->n_fhp->nfh_len, mode, op,
  389                                     NFS4NODENAME(np->n_v4),
  390                                     np->n_v4->n4_namelen,
  391                                     &dp, 0, 0x0, cred, p, 0, 0);
  392                         else
  393                                 error = nfsrpc_getopenlayout(nmp, vp,
  394                                     np->n_v4->n4_data,
  395                                     np->n_v4->n4_fhlen, np->n_fhp->nfh_fh,
  396                                     np->n_fhp->nfh_len, mode, op,
  397                                     NFS4NODENAME(np->n_v4),
  398                                     np->n_v4->n4_namelen, &dp, cred, p);
  399                         if (dp != NULL) {
  400 #ifdef APPLE
  401                                 OSBitAndAtomic((int32_t)~NDELEGMOD, (UInt32 *)&np->n_flag);
  402 #else
  403                                 NFSLOCKNODE(np);
  404                                 np->n_flag &= ~NDELEGMOD;
  405                                 /*
  406                                  * Invalidate the attribute cache, so that
  407                                  * attributes that pre-date the issue of a
  408                                  * delegation are not cached, since the
  409                                  * cached attributes will remain valid while
  410                                  * the delegation is held.
  411                                  */
  412                                 NFSINVALATTRCACHE(np);
  413                                 NFSUNLOCKNODE(np);
  414 #endif
  415                                 (void) nfscl_deleg(nmp->nm_mountp,
  416                                     op->nfso_own->nfsow_clp,
  417                                     nfhp->nfh_fh, nfhp->nfh_len, cred, p, &dp);
  418                         }
  419                 } else {
  420                         error = EIO;
  421                 }
  422                 newnfs_copyincred(cred, &op->nfso_cred);
  423             } else if (ret == NFSCLOPEN_SETCRED)
  424                 /*
  425                  * This is a new local open on a delegation. It needs
  426                  * to have credentials so that an open can be done
  427                  * against the server during recovery.
  428                  */
  429                 newnfs_copyincred(cred, &op->nfso_cred);
  430 
  431             /*
  432              * nfso_opencnt is the count of how many VOP_OPEN()s have
  433              * been done on this Open successfully and a VOP_CLOSE()
  434              * is expected for each of these.
  435              * If error is non-zero, don't increment it, since the Open
  436              * hasn't succeeded yet.
  437              */
  438             if (!error)
  439                 op->nfso_opencnt++;
  440             nfscl_openrelease(nmp, op, error, newone);
  441             if (error == NFSERR_GRACE || error == NFSERR_STALECLIENTID ||
  442                 error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
  443                 error == NFSERR_BADSESSION) {
  444                 (void) nfs_catnap(PZERO, error, "nfs_open");
  445             } else if ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID)
  446                 && clidrev != 0) {
  447                 expireret = nfscl_hasexpired(nmp->nm_clp, clidrev, p);
  448                 retrycnt++;
  449             }
  450         } while (error == NFSERR_GRACE || error == NFSERR_STALECLIENTID ||
  451             error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
  452             error == NFSERR_BADSESSION ||
  453             ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) &&
  454              expireret == 0 && clidrev != 0 && retrycnt < 4));
  455         if (error && retrycnt >= 4)
  456                 error = EIO;
  457         return (error);
  458 }
  459 
  460 /*
  461  * the actual open rpc
  462  */
  463 int
  464 nfsrpc_openrpc(struct nfsmount *nmp, vnode_t vp, u_int8_t *nfhp, int fhlen,
  465     u_int8_t *newfhp, int newfhlen, u_int32_t mode, struct nfsclopen *op,
  466     u_int8_t *name, int namelen, struct nfscldeleg **dpp,
  467     int reclaim, u_int32_t delegtype, struct ucred *cred, NFSPROC_T *p,
  468     int syscred, int recursed)
  469 {
  470         u_int32_t *tl;
  471         struct nfsrv_descript nfsd, *nd = &nfsd;
  472         struct nfscldeleg *dp, *ndp = NULL;
  473         struct nfsvattr nfsva;
  474         u_int32_t rflags, deleg;
  475         nfsattrbit_t attrbits;
  476         int error, ret, acesize, limitby;
  477         struct nfsclsession *tsep;
  478 
  479         dp = *dpp;
  480         *dpp = NULL;
  481         nfscl_reqstart(nd, NFSPROC_OPEN, nmp, nfhp, fhlen, NULL, NULL, 0, 0);
  482         NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
  483         *tl++ = txdr_unsigned(op->nfso_own->nfsow_seqid);
  484         *tl++ = txdr_unsigned(mode & NFSV4OPEN_ACCESSBOTH);
  485         *tl++ = txdr_unsigned((mode >> NFSLCK_SHIFT) & NFSV4OPEN_DENYBOTH);
  486         tsep = nfsmnt_mdssession(nmp);
  487         *tl++ = tsep->nfsess_clientid.lval[0];
  488         *tl = tsep->nfsess_clientid.lval[1];
  489         (void) nfsm_strtom(nd, op->nfso_own->nfsow_owner, NFSV4CL_LOCKNAMELEN);
  490         NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
  491         *tl++ = txdr_unsigned(NFSV4OPEN_NOCREATE);
  492         if (reclaim) {
  493                 *tl = txdr_unsigned(NFSV4OPEN_CLAIMPREVIOUS);
  494                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
  495                 *tl = txdr_unsigned(delegtype);
  496         } else {
  497                 if (dp != NULL) {
  498                         *tl = txdr_unsigned(NFSV4OPEN_CLAIMDELEGATECUR);
  499                         NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
  500                         if (NFSHASNFSV4N(nmp))
  501                                 *tl++ = 0;
  502                         else
  503                                 *tl++ = dp->nfsdl_stateid.seqid;
  504                         *tl++ = dp->nfsdl_stateid.other[0];
  505                         *tl++ = dp->nfsdl_stateid.other[1];
  506                         *tl = dp->nfsdl_stateid.other[2];
  507                 } else {
  508                         *tl = txdr_unsigned(NFSV4OPEN_CLAIMNULL);
  509                 }
  510                 (void) nfsm_strtom(nd, name, namelen);
  511         }
  512         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
  513         *tl = txdr_unsigned(NFSV4OP_GETATTR);
  514         NFSZERO_ATTRBIT(&attrbits);
  515         NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_CHANGE);
  516         NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFY);
  517         (void) nfsrv_putattrbit(nd, &attrbits);
  518         if (syscred)
  519                 nd->nd_flag |= ND_USEGSSNAME;
  520         error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, vp, p, cred,
  521             NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
  522         if (error)
  523                 return (error);
  524         NFSCL_INCRSEQID(op->nfso_own->nfsow_seqid, nd);
  525         if (!nd->nd_repstat) {
  526                 NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID +
  527                     6 * NFSX_UNSIGNED);
  528                 op->nfso_stateid.seqid = *tl++;
  529                 op->nfso_stateid.other[0] = *tl++;
  530                 op->nfso_stateid.other[1] = *tl++;
  531                 op->nfso_stateid.other[2] = *tl;
  532                 rflags = fxdr_unsigned(u_int32_t, *(tl + 6));
  533                 error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
  534                 if (error)
  535                         goto nfsmout;
  536                 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
  537                 deleg = fxdr_unsigned(u_int32_t, *tl);
  538                 if (deleg == NFSV4OPEN_DELEGATEREAD ||
  539                     deleg == NFSV4OPEN_DELEGATEWRITE) {
  540                         if (!(op->nfso_own->nfsow_clp->nfsc_flags &
  541                               NFSCLFLAGS_FIRSTDELEG))
  542                                 op->nfso_own->nfsow_clp->nfsc_flags |=
  543                                   (NFSCLFLAGS_FIRSTDELEG | NFSCLFLAGS_GOTDELEG);
  544                         ndp = malloc(
  545                             sizeof (struct nfscldeleg) + newfhlen,
  546                             M_NFSCLDELEG, M_WAITOK);
  547                         LIST_INIT(&ndp->nfsdl_owner);
  548                         LIST_INIT(&ndp->nfsdl_lock);
  549                         ndp->nfsdl_clp = op->nfso_own->nfsow_clp;
  550                         ndp->nfsdl_fhlen = newfhlen;
  551                         NFSBCOPY(newfhp, ndp->nfsdl_fh, newfhlen);
  552                         newnfs_copyincred(cred, &ndp->nfsdl_cred);
  553                         nfscl_lockinit(&ndp->nfsdl_rwlock);
  554                         NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID +
  555                             NFSX_UNSIGNED);
  556                         ndp->nfsdl_stateid.seqid = *tl++;
  557                         ndp->nfsdl_stateid.other[0] = *tl++;
  558                         ndp->nfsdl_stateid.other[1] = *tl++;
  559                         ndp->nfsdl_stateid.other[2] = *tl++;
  560                         ret = fxdr_unsigned(int, *tl);
  561                         if (deleg == NFSV4OPEN_DELEGATEWRITE) {
  562                                 ndp->nfsdl_flags = NFSCLDL_WRITE;
  563                                 /*
  564                                  * Indicates how much the file can grow.
  565                                  */
  566                                 NFSM_DISSECT(tl, u_int32_t *,
  567                                     3 * NFSX_UNSIGNED);
  568                                 limitby = fxdr_unsigned(int, *tl++);
  569                                 switch (limitby) {
  570                                 case NFSV4OPEN_LIMITSIZE:
  571                                         ndp->nfsdl_sizelimit = fxdr_hyper(tl);
  572                                         break;
  573                                 case NFSV4OPEN_LIMITBLOCKS:
  574                                         ndp->nfsdl_sizelimit =
  575                                             fxdr_unsigned(u_int64_t, *tl++);
  576                                         ndp->nfsdl_sizelimit *=
  577                                             fxdr_unsigned(u_int64_t, *tl);
  578                                         break;
  579                                 default:
  580                                         error = NFSERR_BADXDR;
  581                                         goto nfsmout;
  582                                 }
  583                         } else {
  584                                 ndp->nfsdl_flags = NFSCLDL_READ;
  585                         }
  586                         if (ret)
  587                                 ndp->nfsdl_flags |= NFSCLDL_RECALL;
  588                         error = nfsrv_dissectace(nd, &ndp->nfsdl_ace, &ret,
  589                             &acesize, p);
  590                         if (error)
  591                                 goto nfsmout;
  592                 } else if (deleg != NFSV4OPEN_DELEGATENONE) {
  593                         error = NFSERR_BADXDR;
  594                         goto nfsmout;
  595                 }
  596                 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
  597                 error = nfsv4_loadattr(nd, NULL, &nfsva, NULL,
  598                     NULL, 0, NULL, NULL, NULL, NULL, NULL, 0,
  599                     NULL, NULL, NULL, p, cred);
  600                 if (error)
  601                         goto nfsmout;
  602                 if (ndp != NULL) {
  603                         ndp->nfsdl_change = nfsva.na_filerev;
  604                         ndp->nfsdl_modtime = nfsva.na_mtime;
  605                         ndp->nfsdl_flags |= NFSCLDL_MODTIMESET;
  606                 }
  607                 if (!reclaim && (rflags & NFSV4OPEN_RESULTCONFIRM)) {
  608                     do {
  609                         ret = nfsrpc_openconfirm(vp, newfhp, newfhlen, op,
  610                             cred, p);
  611                         if (ret == NFSERR_DELAY)
  612                             (void) nfs_catnap(PZERO, ret, "nfs_open");
  613                     } while (ret == NFSERR_DELAY);
  614                     error = ret;
  615                 }
  616                 if ((rflags & NFSV4OPEN_LOCKTYPEPOSIX) ||
  617                     nfscl_assumeposixlocks)
  618                     op->nfso_posixlock = 1;
  619                 else
  620                     op->nfso_posixlock = 0;
  621 
  622                 /*
  623                  * If the server is handing out delegations, but we didn't
  624                  * get one because an OpenConfirm was required, try the
  625                  * Open again, to get a delegation. This is a harmless no-op,
  626                  * from a server's point of view.
  627                  */
  628                 if (!reclaim && (rflags & NFSV4OPEN_RESULTCONFIRM) &&
  629                     (op->nfso_own->nfsow_clp->nfsc_flags & NFSCLFLAGS_GOTDELEG)
  630                     && !error && dp == NULL && ndp == NULL && !recursed) {
  631                     do {
  632                         ret = nfsrpc_openrpc(nmp, vp, nfhp, fhlen, newfhp,
  633                             newfhlen, mode, op, name, namelen, &ndp, 0, 0x0,
  634                             cred, p, syscred, 1);
  635                         if (ret == NFSERR_DELAY)
  636                             (void) nfs_catnap(PZERO, ret, "nfs_open2");
  637                     } while (ret == NFSERR_DELAY);
  638                     if (ret) {
  639                         if (ndp != NULL) {
  640                                 free(ndp, M_NFSCLDELEG);
  641                                 ndp = NULL;
  642                         }
  643                         if (ret == NFSERR_STALECLIENTID ||
  644                             ret == NFSERR_STALEDONTRECOVER ||
  645                             ret == NFSERR_BADSESSION)
  646                                 error = ret;
  647                     }
  648                 }
  649         }
  650         if (nd->nd_repstat != 0 && error == 0)
  651                 error = nd->nd_repstat;
  652         if (error == NFSERR_STALECLIENTID)
  653                 nfscl_initiate_recovery(op->nfso_own->nfsow_clp);
  654 nfsmout:
  655         if (!error)
  656                 *dpp = ndp;
  657         else if (ndp != NULL)
  658                 free(ndp, M_NFSCLDELEG);
  659         mbuf_freem(nd->nd_mrep);
  660         return (error);
  661 }
  662 
  663 /*
  664  * open downgrade rpc
  665  */
  666 int
  667 nfsrpc_opendowngrade(vnode_t vp, u_int32_t mode, struct nfsclopen *op,
  668     struct ucred *cred, NFSPROC_T *p)
  669 {
  670         u_int32_t *tl;
  671         struct nfsrv_descript nfsd, *nd = &nfsd;
  672         int error;
  673 
  674         NFSCL_REQSTART(nd, NFSPROC_OPENDOWNGRADE, vp);
  675         NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID + 3 * NFSX_UNSIGNED);
  676         if (NFSHASNFSV4N(VFSTONFS(vnode_mount(vp))))
  677                 *tl++ = 0;
  678         else
  679                 *tl++ = op->nfso_stateid.seqid;
  680         *tl++ = op->nfso_stateid.other[0];
  681         *tl++ = op->nfso_stateid.other[1];
  682         *tl++ = op->nfso_stateid.other[2];
  683         *tl++ = txdr_unsigned(op->nfso_own->nfsow_seqid);
  684         *tl++ = txdr_unsigned(mode & NFSV4OPEN_ACCESSBOTH);
  685         *tl = txdr_unsigned((mode >> NFSLCK_SHIFT) & NFSV4OPEN_DENYBOTH);
  686         error = nfscl_request(nd, vp, p, cred, NULL);
  687         if (error)
  688                 return (error);
  689         NFSCL_INCRSEQID(op->nfso_own->nfsow_seqid, nd);
  690         if (!nd->nd_repstat) {
  691                 NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID);
  692                 op->nfso_stateid.seqid = *tl++;
  693                 op->nfso_stateid.other[0] = *tl++;
  694                 op->nfso_stateid.other[1] = *tl++;
  695                 op->nfso_stateid.other[2] = *tl;
  696         }
  697         if (nd->nd_repstat && error == 0)
  698                 error = nd->nd_repstat;
  699         if (error == NFSERR_STALESTATEID)
  700                 nfscl_initiate_recovery(op->nfso_own->nfsow_clp);
  701 nfsmout:
  702         mbuf_freem(nd->nd_mrep);
  703         return (error);
  704 }
  705 
  706 /*
  707  * V4 Close operation.
  708  */
  709 int
  710 nfsrpc_close(vnode_t vp, int doclose, NFSPROC_T *p)
  711 {
  712         struct nfsclclient *clp;
  713         int error;
  714 
  715         if (vnode_vtype(vp) != VREG)
  716                 return (0);
  717         if (doclose)
  718                 error = nfscl_doclose(vp, &clp, p);
  719         else {
  720                 error = nfscl_getclose(vp, &clp);
  721                 if (error == 0)
  722                         nfscl_clientrelease(clp);
  723         }
  724         return (error);
  725 }
  726 
  727 /*
  728  * Close the open.
  729  */
  730 int
  731 nfsrpc_doclose(struct nfsmount *nmp, struct nfsclopen *op, NFSPROC_T *p,
  732     bool loop_on_delayed, bool freeop)
  733 {
  734         struct nfsrv_descript nfsd, *nd = &nfsd;
  735         struct nfscllockowner *lp, *nlp;
  736         struct nfscllock *lop, *nlop;
  737         struct ucred *tcred;
  738         u_int64_t off = 0, len = 0;
  739         u_int32_t type = NFSV4LOCKT_READ;
  740         int error, do_unlock, trycnt;
  741 
  742         tcred = newnfs_getcred();
  743         newnfs_copycred(&op->nfso_cred, tcred);
  744         /*
  745          * (Theoretically this could be done in the same
  746          *  compound as the close, but having multiple
  747          *  sequenced Ops in the same compound might be
  748          *  too scary for some servers.)
  749          */
  750         if (op->nfso_posixlock) {
  751                 off = 0;
  752                 len = NFS64BITSSET;
  753                 type = NFSV4LOCKT_READ;
  754         }
  755 
  756         /*
  757          * Since this function is only called from VOP_INACTIVE(), no
  758          * other thread will be manipulating this Open. As such, the
  759          * lock lists are not being changed by other threads, so it should
  760          * be safe to do this without locking.
  761          */
  762         LIST_FOREACH(lp, &op->nfso_lock, nfsl_list) {
  763                 do_unlock = 1;
  764                 LIST_FOREACH_SAFE(lop, &lp->nfsl_lock, nfslo_list, nlop) {
  765                         if (op->nfso_posixlock == 0) {
  766                                 off = lop->nfslo_first;
  767                                 len = lop->nfslo_end - lop->nfslo_first;
  768                                 if (lop->nfslo_type == F_WRLCK)
  769                                         type = NFSV4LOCKT_WRITE;
  770                                 else
  771                                         type = NFSV4LOCKT_READ;
  772                         }
  773                         if (do_unlock) {
  774                                 trycnt = 0;
  775                                 do {
  776                                         error = nfsrpc_locku(nd, nmp, lp, off,
  777                                             len, type, tcred, p, 0);
  778                                         if ((nd->nd_repstat == NFSERR_GRACE ||
  779                                             nd->nd_repstat == NFSERR_DELAY) &&
  780                                             error == 0)
  781                                                 (void) nfs_catnap(PZERO,
  782                                                     (int)nd->nd_repstat,
  783                                                     "nfs_close");
  784                                 } while ((nd->nd_repstat == NFSERR_GRACE ||
  785                                     nd->nd_repstat == NFSERR_DELAY) &&
  786                                     error == 0 && trycnt++ < 5);
  787                                 if (op->nfso_posixlock)
  788                                         do_unlock = 0;
  789                         }
  790                         nfscl_freelock(lop, 0);
  791                 }
  792                 /*
  793                  * Do a ReleaseLockOwner.
  794                  * The lock owner name nfsl_owner may be used by other opens for
  795                  * other files but the lock_owner4 name that nfsrpc_rellockown()
  796                  * puts on the wire has the file handle for this file appended
  797                  * to it, so it can be done now.
  798                  */
  799                 (void)nfsrpc_rellockown(nmp, lp, lp->nfsl_open->nfso_fh,
  800                     lp->nfsl_open->nfso_fhlen, tcred, p);
  801         }
  802 
  803         /*
  804          * There could be other Opens for different files on the same
  805          * OpenOwner, so locking is required.
  806          */
  807         NFSLOCKCLSTATE();
  808         nfscl_lockexcl(&op->nfso_own->nfsow_rwlock, NFSCLSTATEMUTEXPTR);
  809         NFSUNLOCKCLSTATE();
  810         do {
  811                 error = nfscl_tryclose(op, tcred, nmp, p, loop_on_delayed);
  812                 if (error == NFSERR_GRACE)
  813                         (void) nfs_catnap(PZERO, error, "nfs_close");
  814         } while (error == NFSERR_GRACE);
  815         NFSLOCKCLSTATE();
  816         nfscl_lockunlock(&op->nfso_own->nfsow_rwlock);
  817 
  818         LIST_FOREACH_SAFE(lp, &op->nfso_lock, nfsl_list, nlp)
  819                 nfscl_freelockowner(lp, 0);
  820         if (freeop && error != NFSERR_DELAY)
  821                 nfscl_freeopen(op, 0, true);
  822         NFSUNLOCKCLSTATE();
  823         NFSFREECRED(tcred);
  824         return (error);
  825 }
  826 
  827 /*
  828  * The actual Close RPC.
  829  */
  830 int
  831 nfsrpc_closerpc(struct nfsrv_descript *nd, struct nfsmount *nmp,
  832     struct nfsclopen *op, struct ucred *cred, NFSPROC_T *p,
  833     int syscred)
  834 {
  835         u_int32_t *tl;
  836         int error;
  837 
  838         nfscl_reqstart(nd, NFSPROC_CLOSE, nmp, op->nfso_fh,
  839             op->nfso_fhlen, NULL, NULL, 0, 0);
  840         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_STATEID);
  841         if (NFSHASNFSV4N(nmp)) {
  842                 *tl++ = 0;
  843                 *tl++ = 0;
  844         } else {
  845                 *tl++ = txdr_unsigned(op->nfso_own->nfsow_seqid);
  846                 *tl++ = op->nfso_stateid.seqid;
  847         }
  848         *tl++ = op->nfso_stateid.other[0];
  849         *tl++ = op->nfso_stateid.other[1];
  850         *tl = op->nfso_stateid.other[2];
  851         if (syscred)
  852                 nd->nd_flag |= ND_USEGSSNAME;
  853         error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
  854             NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
  855         if (error)
  856                 return (error);
  857         if (!NFSHASNFSV4N(nmp))
  858                 NFSCL_INCRSEQID(op->nfso_own->nfsow_seqid, nd);
  859         if (nd->nd_repstat == 0)
  860                 NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID);
  861         error = nd->nd_repstat;
  862         if (!NFSHASNFSV4N(nmp) && error == NFSERR_STALESTATEID)
  863                 nfscl_initiate_recovery(op->nfso_own->nfsow_clp);
  864 nfsmout:
  865         mbuf_freem(nd->nd_mrep);
  866         return (error);
  867 }
  868 
  869 /*
  870  * V4 Open Confirm RPC.
  871  */
  872 int
  873 nfsrpc_openconfirm(vnode_t vp, u_int8_t *nfhp, int fhlen,
  874     struct nfsclopen *op, struct ucred *cred, NFSPROC_T *p)
  875 {
  876         u_int32_t *tl;
  877         struct nfsrv_descript nfsd, *nd = &nfsd;
  878         struct nfsmount *nmp;
  879         int error;
  880 
  881         nmp = VFSTONFS(vnode_mount(vp));
  882         if (NFSHASNFSV4N(nmp))
  883                 return (0);             /* No confirmation for NFSv4.1. */
  884         nfscl_reqstart(nd, NFSPROC_OPENCONFIRM, nmp, nfhp, fhlen, NULL, NULL,
  885             0, 0);
  886         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_STATEID);
  887         *tl++ = op->nfso_stateid.seqid;
  888         *tl++ = op->nfso_stateid.other[0];
  889         *tl++ = op->nfso_stateid.other[1];
  890         *tl++ = op->nfso_stateid.other[2];
  891         *tl = txdr_unsigned(op->nfso_own->nfsow_seqid);
  892         error = nfscl_request(nd, vp, p, cred, NULL);
  893         if (error)
  894                 return (error);
  895         NFSCL_INCRSEQID(op->nfso_own->nfsow_seqid, nd);
  896         if (!nd->nd_repstat) {
  897                 NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID);
  898                 op->nfso_stateid.seqid = *tl++;
  899                 op->nfso_stateid.other[0] = *tl++;
  900                 op->nfso_stateid.other[1] = *tl++;
  901                 op->nfso_stateid.other[2] = *tl;
  902         }
  903         error = nd->nd_repstat;
  904         if (error == NFSERR_STALESTATEID)
  905                 nfscl_initiate_recovery(op->nfso_own->nfsow_clp);
  906 nfsmout:
  907         mbuf_freem(nd->nd_mrep);
  908         return (error);
  909 }
  910 
  911 /*
  912  * Do the setclientid and setclientid confirm RPCs. Called from nfs_statfs()
  913  * when a mount has just occurred and when the server replies NFSERR_EXPIRED.
  914  */
  915 int
  916 nfsrpc_setclient(struct nfsmount *nmp, struct nfsclclient *clp, int reclaim,
  917     struct ucred *cred, NFSPROC_T *p)
  918 {
  919         u_int32_t *tl;
  920         struct nfsrv_descript nfsd;
  921         struct nfsrv_descript *nd = &nfsd;
  922         nfsattrbit_t attrbits;
  923         u_int8_t *cp = NULL, *cp2, addr[INET6_ADDRSTRLEN + 9];
  924         u_short port;
  925         int error, isinet6 = 0, callblen;
  926         nfsquad_t confirm;
  927         u_int32_t lease;
  928         static u_int32_t rev = 0;
  929         struct nfsclds *dsp;
  930         struct in6_addr a6;
  931         struct nfsclsession *tsep;
  932         struct rpc_reconupcall recon;
  933         struct nfscl_reconarg *rcp;
  934 
  935         if (nfsboottime.tv_sec == 0)
  936                 NFSSETBOOTTIME(nfsboottime);
  937         clp->nfsc_rev = rev++;
  938         if (NFSHASNFSV4N(nmp)) {
  939                 /*
  940                  * Either there was no previous session or the
  941                  * previous session has failed, so...
  942                  * do an ExchangeID followed by the CreateSession.
  943                  */
  944                 error = nfsrpc_exchangeid(nmp, clp, &nmp->nm_sockreq,
  945                     NFSV4EXCH_USEPNFSMDS | NFSV4EXCH_USENONPNFS, &dsp, cred, p);
  946                 NFSCL_DEBUG(1, "aft exch=%d\n", error);
  947                 if (error == 0)
  948                         error = nfsrpc_createsession(nmp, &dsp->nfsclds_sess,
  949                             &nmp->nm_sockreq,
  950                             dsp->nfsclds_sess.nfsess_sequenceid, 1, cred, p);
  951                 if (error == 0) {
  952                         /*
  953                          * If the session supports a backchannel, set up
  954                          * the BindConnectionToSession call in the krpc
  955                          * so that it is done on a reconnection.
  956                          */
  957                         if (nfscl_enablecallb != 0 && nfs_numnfscbd > 0) {
  958                                 rcp = mem_alloc(sizeof(*rcp));
  959                                 rcp->minorvers = nmp->nm_minorvers;
  960                                 memcpy(rcp->sessionid,
  961                                     dsp->nfsclds_sess.nfsess_sessionid,
  962                                     NFSX_V4SESSIONID);
  963                                 recon.call = nfsrpc_bindconnsess;
  964                                 recon.arg = rcp;
  965                                 CLNT_CONTROL(nmp->nm_client, CLSET_RECONUPCALL,
  966                                     &recon);
  967                         }
  968 
  969                         NFSLOCKMNT(nmp);
  970                         /*
  971                          * The old sessions cannot be safely free'd
  972                          * here, since they may still be used by
  973                          * in-progress RPCs.
  974                          */
  975                         tsep = NULL;
  976                         if (TAILQ_FIRST(&nmp->nm_sess) != NULL) {
  977                                 /*
  978                                  * Mark the old session defunct.  Needed
  979                                  * when called from nfscl_hasexpired().
  980                                  */
  981                                 tsep = NFSMNT_MDSSESSION(nmp);
  982                                 tsep->nfsess_defunct = 1;
  983                         }
  984                         TAILQ_INSERT_HEAD(&nmp->nm_sess, dsp,
  985                             nfsclds_list);
  986                         /*
  987                          * Wake up RPCs waiting for a slot on the
  988                          * old session. These will then fail with
  989                          * NFSERR_BADSESSION and be retried with the
  990                          * new session by nfsv4_setsequence().
  991                          * Also wakeup() processes waiting for the
  992                          * new session.
  993                          */
  994                         if (tsep != NULL)
  995                                 wakeup(&tsep->nfsess_slots);
  996                         wakeup(&nmp->nm_sess);
  997                         NFSUNLOCKMNT(nmp);
  998                 } else
  999                         nfscl_freenfsclds(dsp);
 1000                 NFSCL_DEBUG(1, "aft createsess=%d\n", error);
 1001                 if (error == 0 && reclaim == 0) {
 1002                         error = nfsrpc_reclaimcomplete(nmp, cred, p);
 1003                         NFSCL_DEBUG(1, "aft reclaimcomp=%d\n", error);
 1004                         if (error == NFSERR_COMPLETEALREADY ||
 1005                             error == NFSERR_NOTSUPP)
 1006                                 /* Ignore this error. */
 1007                                 error = 0;
 1008                 }
 1009                 return (error);
 1010         }
 1011 
 1012         /*
 1013          * Allocate a single session structure for NFSv4.0, because some of
 1014          * the fields are used by NFSv4.0 although it doesn't do a session.
 1015          */
 1016         dsp = malloc(sizeof(struct nfsclds), M_NFSCLDS, M_WAITOK | M_ZERO);
 1017         mtx_init(&dsp->nfsclds_mtx, "nfsds", NULL, MTX_DEF);
 1018         mtx_init(&dsp->nfsclds_sess.nfsess_mtx, "nfssession", NULL, MTX_DEF);
 1019         NFSLOCKMNT(nmp);
 1020         TAILQ_INSERT_HEAD(&nmp->nm_sess, dsp, nfsclds_list);
 1021         tsep = NFSMNT_MDSSESSION(nmp);
 1022         NFSUNLOCKMNT(nmp);
 1023 
 1024         nfscl_reqstart(nd, NFSPROC_SETCLIENTID, nmp, NULL, 0, NULL, NULL, 0, 0);
 1025         NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 1026         *tl++ = txdr_unsigned(nfsboottime.tv_sec);
 1027         *tl = txdr_unsigned(clp->nfsc_rev);
 1028         (void) nfsm_strtom(nd, clp->nfsc_id, clp->nfsc_idlen);
 1029 
 1030         /*
 1031          * set up the callback address
 1032          */
 1033         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 1034         *tl = txdr_unsigned(NFS_CALLBCKPROG);
 1035         callblen = strlen(nfsv4_callbackaddr);
 1036         if (callblen == 0)
 1037                 cp = nfscl_getmyip(nmp, &a6, &isinet6);
 1038         if (nfscl_enablecallb && nfs_numnfscbd > 0 &&
 1039             (callblen > 0 || cp != NULL)) {
 1040                 port = htons(nfsv4_cbport);
 1041                 cp2 = (u_int8_t *)&port;
 1042 #ifdef INET6
 1043                 if ((callblen > 0 &&
 1044                      strchr(nfsv4_callbackaddr, ':')) || isinet6) {
 1045                         char ip6buf[INET6_ADDRSTRLEN], *ip6add;
 1046 
 1047                         (void) nfsm_strtom(nd, "tcp6", 4);
 1048                         if (callblen == 0) {
 1049                                 ip6_sprintf(ip6buf, (struct in6_addr *)cp);
 1050                                 ip6add = ip6buf;
 1051                         } else {
 1052                                 ip6add = nfsv4_callbackaddr;
 1053                         }
 1054                         snprintf(addr, INET6_ADDRSTRLEN + 9, "%s.%d.%d",
 1055                             ip6add, cp2[0], cp2[1]);
 1056                 } else
 1057 #endif
 1058                 {
 1059                         (void) nfsm_strtom(nd, "tcp", 3);
 1060                         if (callblen == 0)
 1061                                 snprintf(addr, INET6_ADDRSTRLEN + 9,
 1062                                     "%d.%d.%d.%d.%d.%d", cp[0], cp[1],
 1063                                     cp[2], cp[3], cp2[0], cp2[1]);
 1064                         else
 1065                                 snprintf(addr, INET6_ADDRSTRLEN + 9,
 1066                                     "%s.%d.%d", nfsv4_callbackaddr,
 1067                                     cp2[0], cp2[1]);
 1068                 }
 1069                 (void) nfsm_strtom(nd, addr, strlen(addr));
 1070         } else {
 1071                 (void) nfsm_strtom(nd, "tcp", 3);
 1072                 (void) nfsm_strtom(nd, "0.0.0.0.0.0", 11);
 1073         }
 1074         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 1075         *tl = txdr_unsigned(clp->nfsc_cbident);
 1076         nd->nd_flag |= ND_USEGSSNAME;
 1077         error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 1078                 NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 1079         if (error)
 1080                 return (error);
 1081         if (nd->nd_repstat == 0) {
 1082             NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
 1083             tsep->nfsess_clientid.lval[0] = *tl++;
 1084             tsep->nfsess_clientid.lval[1] = *tl++;
 1085             confirm.lval[0] = *tl++;
 1086             confirm.lval[1] = *tl;
 1087             mbuf_freem(nd->nd_mrep);
 1088             nd->nd_mrep = NULL;
 1089 
 1090             /*
 1091              * and confirm it.
 1092              */
 1093             nfscl_reqstart(nd, NFSPROC_SETCLIENTIDCFRM, nmp, NULL, 0, NULL,
 1094                 NULL, 0, 0);
 1095             NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
 1096             *tl++ = tsep->nfsess_clientid.lval[0];
 1097             *tl++ = tsep->nfsess_clientid.lval[1];
 1098             *tl++ = confirm.lval[0];
 1099             *tl = confirm.lval[1];
 1100             nd->nd_flag |= ND_USEGSSNAME;
 1101             error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p,
 1102                 cred, NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 1103             if (error)
 1104                 return (error);
 1105             mbuf_freem(nd->nd_mrep);
 1106             nd->nd_mrep = NULL;
 1107             if (nd->nd_repstat == 0) {
 1108                 nfscl_reqstart(nd, NFSPROC_GETATTR, nmp, nmp->nm_fh,
 1109                     nmp->nm_fhsize, NULL, NULL, 0, 0);
 1110                 NFSZERO_ATTRBIT(&attrbits);
 1111                 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_LEASETIME);
 1112                 (void) nfsrv_putattrbit(nd, &attrbits);
 1113                 nd->nd_flag |= ND_USEGSSNAME;
 1114                 error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p,
 1115                     cred, NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 1116                 if (error)
 1117                     return (error);
 1118                 if (nd->nd_repstat == 0) {
 1119                     error = nfsv4_loadattr(nd, NULL, NULL, NULL, NULL, 0, NULL,
 1120                         NULL, NULL, NULL, NULL, 0, NULL, &lease, NULL, p, cred);
 1121                     if (error)
 1122                         goto nfsmout;
 1123                     clp->nfsc_renew = NFSCL_RENEW(lease);
 1124                     clp->nfsc_expire = NFSD_MONOSEC + clp->nfsc_renew;
 1125                     clp->nfsc_clientidrev++;
 1126                     if (clp->nfsc_clientidrev == 0)
 1127                         clp->nfsc_clientidrev++;
 1128                 }
 1129             }
 1130         }
 1131         error = nd->nd_repstat;
 1132 nfsmout:
 1133         mbuf_freem(nd->nd_mrep);
 1134         return (error);
 1135 }
 1136 
 1137 /*
 1138  * nfs getattr call.
 1139  */
 1140 int
 1141 nfsrpc_getattr(vnode_t vp, struct ucred *cred, NFSPROC_T *p,
 1142     struct nfsvattr *nap, void *stuff)
 1143 {
 1144         struct nfsrv_descript nfsd, *nd = &nfsd;
 1145         int error;
 1146         nfsattrbit_t attrbits;
 1147         
 1148         NFSCL_REQSTART(nd, NFSPROC_GETATTR, vp);
 1149         if (nd->nd_flag & ND_NFSV4) {
 1150                 NFSGETATTR_ATTRBIT(&attrbits);
 1151                 (void) nfsrv_putattrbit(nd, &attrbits);
 1152         }
 1153         error = nfscl_request(nd, vp, p, cred, stuff);
 1154         if (error)
 1155                 return (error);
 1156         if (!nd->nd_repstat)
 1157                 error = nfsm_loadattr(nd, nap);
 1158         else
 1159                 error = nd->nd_repstat;
 1160         mbuf_freem(nd->nd_mrep);
 1161         return (error);
 1162 }
 1163 
 1164 /*
 1165  * nfs getattr call with non-vnode arguments.
 1166  */
 1167 int
 1168 nfsrpc_getattrnovp(struct nfsmount *nmp, u_int8_t *fhp, int fhlen, int syscred,
 1169     struct ucred *cred, NFSPROC_T *p, struct nfsvattr *nap, u_int64_t *xidp,
 1170     uint32_t *leasep)
 1171 {
 1172         struct nfsrv_descript nfsd, *nd = &nfsd;
 1173         int error, vers = NFS_VER2;
 1174         nfsattrbit_t attrbits;
 1175         
 1176         nfscl_reqstart(nd, NFSPROC_GETATTR, nmp, fhp, fhlen, NULL, NULL, 0, 0);
 1177         if (nd->nd_flag & ND_NFSV4) {
 1178                 vers = NFS_VER4;
 1179                 NFSGETATTR_ATTRBIT(&attrbits);
 1180                 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_LEASETIME);
 1181                 (void) nfsrv_putattrbit(nd, &attrbits);
 1182         } else if (nd->nd_flag & ND_NFSV3) {
 1183                 vers = NFS_VER3;
 1184         }
 1185         if (syscred)
 1186                 nd->nd_flag |= ND_USEGSSNAME;
 1187         error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 1188             NFS_PROG, vers, NULL, 1, xidp, NULL);
 1189         if (error)
 1190                 return (error);
 1191         if (nd->nd_repstat == 0) {
 1192                 if ((nd->nd_flag & ND_NFSV4) != 0)
 1193                         error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0,
 1194                             NULL, NULL, NULL, NULL, NULL, 0, NULL, leasep, NULL,
 1195                             NULL, NULL);
 1196                 else
 1197                         error = nfsm_loadattr(nd, nap);
 1198         } else
 1199                 error = nd->nd_repstat;
 1200         mbuf_freem(nd->nd_mrep);
 1201         return (error);
 1202 }
 1203 
 1204 /*
 1205  * Do an nfs setattr operation.
 1206  */
 1207 int
 1208 nfsrpc_setattr(vnode_t vp, struct vattr *vap, NFSACL_T *aclp,
 1209     struct ucred *cred, NFSPROC_T *p, struct nfsvattr *rnap, int *attrflagp,
 1210     void *stuff)
 1211 {
 1212         int error, expireret = 0, openerr, retrycnt;
 1213         u_int32_t clidrev = 0, mode;
 1214         struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
 1215         struct nfsfh *nfhp;
 1216         nfsv4stateid_t stateid;
 1217         void *lckp;
 1218 
 1219         if (nmp->nm_clp != NULL)
 1220                 clidrev = nmp->nm_clp->nfsc_clientidrev;
 1221         if (vap != NULL && NFSATTRISSET(u_quad_t, vap, va_size))
 1222                 mode = NFSV4OPEN_ACCESSWRITE;
 1223         else
 1224                 mode = NFSV4OPEN_ACCESSREAD;
 1225         retrycnt = 0;
 1226         do {
 1227                 lckp = NULL;
 1228                 openerr = 1;
 1229                 if (NFSHASNFSV4(nmp)) {
 1230                         nfhp = VTONFS(vp)->n_fhp;
 1231                         error = nfscl_getstateid(vp, nfhp->nfh_fh,
 1232                             nfhp->nfh_len, mode, 0, cred, p, &stateid, &lckp);
 1233                         if (error && vnode_vtype(vp) == VREG &&
 1234                             (mode == NFSV4OPEN_ACCESSWRITE ||
 1235                              nfstest_openallsetattr)) {
 1236                                 /*
 1237                                  * No Open stateid, so try and open the file
 1238                                  * now.
 1239                                  */
 1240                                 if (mode == NFSV4OPEN_ACCESSWRITE)
 1241                                         openerr = nfsrpc_open(vp, FWRITE, cred,
 1242                                             p);
 1243                                 else
 1244                                         openerr = nfsrpc_open(vp, FREAD, cred,
 1245                                             p);
 1246                                 if (!openerr)
 1247                                         (void) nfscl_getstateid(vp,
 1248                                             nfhp->nfh_fh, nfhp->nfh_len,
 1249                                             mode, 0, cred, p, &stateid, &lckp);
 1250                         }
 1251                 }
 1252                 if (vap != NULL)
 1253                         error = nfsrpc_setattrrpc(vp, vap, &stateid, cred, p,
 1254                             rnap, attrflagp, stuff);
 1255                 else
 1256                         error = nfsrpc_setaclrpc(vp, cred, p, aclp, &stateid,
 1257                             stuff);
 1258                 if (error == NFSERR_OPENMODE && mode == NFSV4OPEN_ACCESSREAD) {
 1259                         NFSLOCKMNT(nmp);
 1260                         nmp->nm_state |= NFSSTA_OPENMODE;
 1261                         NFSUNLOCKMNT(nmp);
 1262                 }
 1263                 if (error == NFSERR_STALESTATEID)
 1264                         nfscl_initiate_recovery(nmp->nm_clp);
 1265                 if (lckp != NULL)
 1266                         nfscl_lockderef(lckp);
 1267                 if (!openerr)
 1268                         (void) nfsrpc_close(vp, 0, p);
 1269                 if (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
 1270                     error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
 1271                     error == NFSERR_OLDSTATEID || error == NFSERR_BADSESSION) {
 1272                         (void) nfs_catnap(PZERO, error, "nfs_setattr");
 1273                 } else if ((error == NFSERR_EXPIRED ||
 1274                     error == NFSERR_BADSTATEID) && clidrev != 0) {
 1275                         expireret = nfscl_hasexpired(nmp->nm_clp, clidrev, p);
 1276                 }
 1277                 retrycnt++;
 1278         } while (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
 1279             error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
 1280             error == NFSERR_BADSESSION ||
 1281             (error == NFSERR_OLDSTATEID && retrycnt < 20) ||
 1282             ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) &&
 1283              expireret == 0 && clidrev != 0 && retrycnt < 4) ||
 1284             (error == NFSERR_OPENMODE && mode == NFSV4OPEN_ACCESSREAD &&
 1285              retrycnt < 4));
 1286         if (error && retrycnt >= 4)
 1287                 error = EIO;
 1288         return (error);
 1289 }
 1290 
 1291 static int
 1292 nfsrpc_setattrrpc(vnode_t vp, struct vattr *vap,
 1293     nfsv4stateid_t *stateidp, struct ucred *cred, NFSPROC_T *p,
 1294     struct nfsvattr *rnap, int *attrflagp, void *stuff)
 1295 {
 1296         u_int32_t *tl;
 1297         struct nfsrv_descript nfsd, *nd = &nfsd;
 1298         int error;
 1299         nfsattrbit_t attrbits;
 1300 
 1301         *attrflagp = 0;
 1302         NFSCL_REQSTART(nd, NFSPROC_SETATTR, vp);
 1303         if (nd->nd_flag & ND_NFSV4)
 1304                 nfsm_stateidtom(nd, stateidp, NFSSTATEID_PUTSTATEID);
 1305         vap->va_type = vnode_vtype(vp);
 1306         nfscl_fillsattr(nd, vap, vp, NFSSATTR_FULL, 0);
 1307         if (nd->nd_flag & ND_NFSV3) {
 1308                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 1309                 *tl = newnfs_false;
 1310         } else if (nd->nd_flag & ND_NFSV4) {
 1311                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 1312                 *tl = txdr_unsigned(NFSV4OP_GETATTR);
 1313                 NFSGETATTR_ATTRBIT(&attrbits);
 1314                 (void) nfsrv_putattrbit(nd, &attrbits);
 1315         }
 1316         error = nfscl_request(nd, vp, p, cred, stuff);
 1317         if (error)
 1318                 return (error);
 1319         if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4))
 1320                 error = nfscl_wcc_data(nd, vp, rnap, attrflagp, NULL, stuff);
 1321         if ((nd->nd_flag & (ND_NFSV4 | ND_NOMOREDATA)) == ND_NFSV4 && !error)
 1322                 error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
 1323         if (!(nd->nd_flag & ND_NFSV3) && !nd->nd_repstat && !error)
 1324                 error = nfscl_postop_attr(nd, rnap, attrflagp, stuff);
 1325         mbuf_freem(nd->nd_mrep);
 1326         if (nd->nd_repstat && !error)
 1327                 error = nd->nd_repstat;
 1328         return (error);
 1329 }
 1330 
 1331 /*
 1332  * nfs lookup rpc
 1333  */
 1334 int
 1335 nfsrpc_lookup(vnode_t dvp, char *name, int len, struct ucred *cred,
 1336     NFSPROC_T *p, struct nfsvattr *dnap, struct nfsvattr *nap,
 1337     struct nfsfh **nfhpp, int *attrflagp, int *dattrflagp, void *stuff)
 1338 {
 1339         u_int32_t *tl;
 1340         struct nfsrv_descript nfsd, *nd = &nfsd;
 1341         struct nfsmount *nmp;
 1342         struct nfsnode *np;
 1343         struct nfsfh *nfhp;
 1344         nfsattrbit_t attrbits;
 1345         int error = 0, lookupp = 0;
 1346 
 1347         *attrflagp = 0;
 1348         *dattrflagp = 0;
 1349         if (vnode_vtype(dvp) != VDIR)
 1350                 return (ENOTDIR);
 1351         nmp = VFSTONFS(vnode_mount(dvp));
 1352         if (len > NFS_MAXNAMLEN)
 1353                 return (ENAMETOOLONG);
 1354         if (NFSHASNFSV4(nmp) && len == 1 &&
 1355                 name[0] == '.') {
 1356                 /*
 1357                  * Just return the current dir's fh.
 1358                  */
 1359                 np = VTONFS(dvp);
 1360                 nfhp = malloc(sizeof (struct nfsfh) +
 1361                         np->n_fhp->nfh_len, M_NFSFH, M_WAITOK);
 1362                 nfhp->nfh_len = np->n_fhp->nfh_len;
 1363                 NFSBCOPY(np->n_fhp->nfh_fh, nfhp->nfh_fh, nfhp->nfh_len);
 1364                 *nfhpp = nfhp;
 1365                 return (0);
 1366         }
 1367         if (NFSHASNFSV4(nmp) && len == 2 &&
 1368                 name[0] == '.' && name[1] == '.') {
 1369                 lookupp = 1;
 1370                 NFSCL_REQSTART(nd, NFSPROC_LOOKUPP, dvp);
 1371         } else {
 1372                 NFSCL_REQSTART(nd, NFSPROC_LOOKUP, dvp);
 1373                 (void) nfsm_strtom(nd, name, len);
 1374         }
 1375         if (nd->nd_flag & ND_NFSV4) {
 1376                 NFSGETATTR_ATTRBIT(&attrbits);
 1377                 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 1378                 *tl++ = txdr_unsigned(NFSV4OP_GETFH);
 1379                 *tl = txdr_unsigned(NFSV4OP_GETATTR);
 1380                 (void) nfsrv_putattrbit(nd, &attrbits);
 1381         }
 1382         error = nfscl_request(nd, dvp, p, cred, stuff);
 1383         if (error)
 1384                 return (error);
 1385         if (nd->nd_repstat) {
 1386                 /*
 1387                  * When an NFSv4 Lookupp returns ENOENT, it means that
 1388                  * the lookup is at the root of an fs, so return this dir.
 1389                  */
 1390                 if (nd->nd_repstat == NFSERR_NOENT && lookupp) {
 1391                     np = VTONFS(dvp);
 1392                     nfhp = malloc(sizeof (struct nfsfh) +
 1393                         np->n_fhp->nfh_len, M_NFSFH, M_WAITOK);
 1394                     nfhp->nfh_len = np->n_fhp->nfh_len;
 1395                     NFSBCOPY(np->n_fhp->nfh_fh, nfhp->nfh_fh, nfhp->nfh_len);
 1396                     *nfhpp = nfhp;
 1397                     mbuf_freem(nd->nd_mrep);
 1398                     return (0);
 1399                 }
 1400                 if (nd->nd_flag & ND_NFSV3)
 1401                     error = nfscl_postop_attr(nd, dnap, dattrflagp, stuff);
 1402                 else if ((nd->nd_flag & (ND_NFSV4 | ND_NOMOREDATA)) ==
 1403                     ND_NFSV4) {
 1404                         /* Load the directory attributes. */
 1405                         error = nfsm_loadattr(nd, dnap);
 1406                         if (error == 0)
 1407                                 *dattrflagp = 1;
 1408                 }
 1409                 goto nfsmout;
 1410         }
 1411         if ((nd->nd_flag & (ND_NFSV4 | ND_NOMOREDATA)) == ND_NFSV4) {
 1412                 /* Load the directory attributes. */
 1413                 error = nfsm_loadattr(nd, dnap);
 1414                 if (error != 0)
 1415                         goto nfsmout;
 1416                 *dattrflagp = 1;
 1417                 /* Skip over the Lookup and GetFH operation status values. */
 1418                 NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
 1419         }
 1420         error = nfsm_getfh(nd, nfhpp);
 1421         if (error)
 1422                 goto nfsmout;
 1423 
 1424         error = nfscl_postop_attr(nd, nap, attrflagp, stuff);
 1425         if ((nd->nd_flag & ND_NFSV3) && !error)
 1426                 error = nfscl_postop_attr(nd, dnap, dattrflagp, stuff);
 1427 nfsmout:
 1428         mbuf_freem(nd->nd_mrep);
 1429         if (!error && nd->nd_repstat)
 1430                 error = nd->nd_repstat;
 1431         return (error);
 1432 }
 1433 
 1434 /*
 1435  * Do a readlink rpc.
 1436  */
 1437 int
 1438 nfsrpc_readlink(vnode_t vp, struct uio *uiop, struct ucred *cred,
 1439     NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp, void *stuff)
 1440 {
 1441         u_int32_t *tl;
 1442         struct nfsrv_descript nfsd, *nd = &nfsd;
 1443         struct nfsnode *np = VTONFS(vp);
 1444         nfsattrbit_t attrbits;
 1445         int error, len, cangetattr = 1;
 1446 
 1447         *attrflagp = 0;
 1448         NFSCL_REQSTART(nd, NFSPROC_READLINK, vp);
 1449         if (nd->nd_flag & ND_NFSV4) {
 1450                 /*
 1451                  * And do a Getattr op.
 1452                  */
 1453                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 1454                 *tl = txdr_unsigned(NFSV4OP_GETATTR);
 1455                 NFSGETATTR_ATTRBIT(&attrbits);
 1456                 (void) nfsrv_putattrbit(nd, &attrbits);
 1457         }
 1458         error = nfscl_request(nd, vp, p, cred, stuff);
 1459         if (error)
 1460                 return (error);
 1461         if (nd->nd_flag & ND_NFSV3)
 1462                 error = nfscl_postop_attr(nd, nap, attrflagp, stuff);
 1463         if (!nd->nd_repstat && !error) {
 1464                 NFSM_STRSIZ(len, NFS_MAXPATHLEN);
 1465                 /*
 1466                  * This seems weird to me, but must have been added to
 1467                  * FreeBSD for some reason. The only thing I can think of
 1468                  * is that there was/is some server that replies with
 1469                  * more link data than it should?
 1470                  */
 1471                 if (len == NFS_MAXPATHLEN) {
 1472                         NFSLOCKNODE(np);
 1473                         if (np->n_size > 0 && np->n_size < NFS_MAXPATHLEN) {
 1474                                 len = np->n_size;
 1475                                 cangetattr = 0;
 1476                         }
 1477                         NFSUNLOCKNODE(np);
 1478                 }
 1479                 error = nfsm_mbufuio(nd, uiop, len);
 1480                 if ((nd->nd_flag & ND_NFSV4) && !error && cangetattr)
 1481                         error = nfscl_postop_attr(nd, nap, attrflagp, stuff);
 1482         }
 1483         if (nd->nd_repstat && !error)
 1484                 error = nd->nd_repstat;
 1485 nfsmout:
 1486         mbuf_freem(nd->nd_mrep);
 1487         return (error);
 1488 }
 1489 
 1490 /*
 1491  * Read operation.
 1492  */
 1493 int
 1494 nfsrpc_read(vnode_t vp, struct uio *uiop, struct ucred *cred,
 1495     NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp, void *stuff)
 1496 {
 1497         int error, expireret = 0, retrycnt;
 1498         u_int32_t clidrev = 0;
 1499         struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
 1500         struct nfsnode *np = VTONFS(vp);
 1501         struct ucred *newcred;
 1502         struct nfsfh *nfhp = NULL;
 1503         nfsv4stateid_t stateid;
 1504         void *lckp;
 1505 
 1506         if (nmp->nm_clp != NULL)
 1507                 clidrev = nmp->nm_clp->nfsc_clientidrev;
 1508         newcred = cred;
 1509         if (NFSHASNFSV4(nmp)) {
 1510                 nfhp = np->n_fhp;
 1511                 newcred = NFSNEWCRED(cred);
 1512         }
 1513         retrycnt = 0;
 1514         do {
 1515                 lckp = NULL;
 1516                 if (NFSHASNFSV4(nmp))
 1517                         (void)nfscl_getstateid(vp, nfhp->nfh_fh, nfhp->nfh_len,
 1518                             NFSV4OPEN_ACCESSREAD, 0, newcred, p, &stateid,
 1519                             &lckp);
 1520                 error = nfsrpc_readrpc(vp, uiop, newcred, &stateid, p, nap,
 1521                     attrflagp, stuff);
 1522                 if (error == NFSERR_OPENMODE) {
 1523                         NFSLOCKMNT(nmp);
 1524                         nmp->nm_state |= NFSSTA_OPENMODE;
 1525                         NFSUNLOCKMNT(nmp);
 1526                 }
 1527                 if (error == NFSERR_STALESTATEID)
 1528                         nfscl_initiate_recovery(nmp->nm_clp);
 1529                 if (lckp != NULL)
 1530                         nfscl_lockderef(lckp);
 1531                 if (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
 1532                     error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
 1533                     error == NFSERR_OLDSTATEID || error == NFSERR_BADSESSION) {
 1534                         (void) nfs_catnap(PZERO, error, "nfs_read");
 1535                 } else if ((error == NFSERR_EXPIRED ||
 1536                     error == NFSERR_BADSTATEID) && clidrev != 0) {
 1537                         expireret = nfscl_hasexpired(nmp->nm_clp, clidrev, p);
 1538                 }
 1539                 retrycnt++;
 1540         } while (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
 1541             error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
 1542             error == NFSERR_BADSESSION ||
 1543             (error == NFSERR_OLDSTATEID && retrycnt < 20) ||
 1544             ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) &&
 1545              expireret == 0 && clidrev != 0 && retrycnt < 4) ||
 1546             (error == NFSERR_OPENMODE && retrycnt < 4));
 1547         if (error && retrycnt >= 4)
 1548                 error = EIO;
 1549         if (NFSHASNFSV4(nmp))
 1550                 NFSFREECRED(newcred);
 1551         return (error);
 1552 }
 1553 
 1554 /*
 1555  * The actual read RPC.
 1556  */
 1557 static int
 1558 nfsrpc_readrpc(vnode_t vp, struct uio *uiop, struct ucred *cred,
 1559     nfsv4stateid_t *stateidp, NFSPROC_T *p, struct nfsvattr *nap,
 1560     int *attrflagp, void *stuff)
 1561 {
 1562         u_int32_t *tl;
 1563         int error = 0, len, retlen, tsiz, eof = 0;
 1564         struct nfsrv_descript nfsd;
 1565         struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
 1566         struct nfsrv_descript *nd = &nfsd;
 1567         int rsize;
 1568         off_t tmp_off;
 1569 
 1570         *attrflagp = 0;
 1571         tsiz = uio_uio_resid(uiop);
 1572         tmp_off = uiop->uio_offset + tsiz;
 1573         NFSLOCKMNT(nmp);
 1574         if (tmp_off > nmp->nm_maxfilesize || tmp_off < uiop->uio_offset) {
 1575                 NFSUNLOCKMNT(nmp);
 1576                 return (EFBIG);
 1577         }
 1578         rsize = nmp->nm_rsize;
 1579         NFSUNLOCKMNT(nmp);
 1580         nd->nd_mrep = NULL;
 1581         while (tsiz > 0) {
 1582                 *attrflagp = 0;
 1583                 len = (tsiz > rsize) ? rsize : tsiz;
 1584                 NFSCL_REQSTART(nd, NFSPROC_READ, vp);
 1585                 if (nd->nd_flag & ND_NFSV4)
 1586                         nfsm_stateidtom(nd, stateidp, NFSSTATEID_PUTSTATEID);
 1587                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED * 3);
 1588                 if (nd->nd_flag & ND_NFSV2) {
 1589                         *tl++ = txdr_unsigned(uiop->uio_offset);
 1590                         *tl++ = txdr_unsigned(len);
 1591                         *tl = 0;
 1592                 } else {
 1593                         txdr_hyper(uiop->uio_offset, tl);
 1594                         *(tl + 2) = txdr_unsigned(len);
 1595                 }
 1596                 /*
 1597                  * Since I can't do a Getattr for NFSv4 for Write, there
 1598                  * doesn't seem any point in doing one here, either.
 1599                  * (See the comment in nfsrpc_writerpc() for more info.)
 1600                  */
 1601                 error = nfscl_request(nd, vp, p, cred, stuff);
 1602                 if (error)
 1603                         return (error);
 1604                 if (nd->nd_flag & ND_NFSV3) {
 1605                         error = nfscl_postop_attr(nd, nap, attrflagp, stuff);
 1606                 } else if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
 1607                         error = nfsm_loadattr(nd, nap);
 1608                         if (!error)
 1609                                 *attrflagp = 1;
 1610                 }
 1611                 if (nd->nd_repstat || error) {
 1612                         if (!error)
 1613                                 error = nd->nd_repstat;
 1614                         goto nfsmout;
 1615                 }
 1616                 if (nd->nd_flag & ND_NFSV3) {
 1617                         NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 1618                         eof = fxdr_unsigned(int, *(tl + 1));
 1619                 } else if (nd->nd_flag & ND_NFSV4) {
 1620                         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 1621                         eof = fxdr_unsigned(int, *tl);
 1622                 }
 1623                 NFSM_STRSIZ(retlen, len);
 1624                 error = nfsm_mbufuio(nd, uiop, retlen);
 1625                 if (error)
 1626                         goto nfsmout;
 1627                 mbuf_freem(nd->nd_mrep);
 1628                 nd->nd_mrep = NULL;
 1629                 tsiz -= retlen;
 1630                 if (!(nd->nd_flag & ND_NFSV2)) {
 1631                         if (eof || retlen == 0)
 1632                                 tsiz = 0;
 1633                 } else if (retlen < len)
 1634                         tsiz = 0;
 1635         }
 1636         return (0);
 1637 nfsmout:
 1638         if (nd->nd_mrep != NULL)
 1639                 mbuf_freem(nd->nd_mrep);
 1640         return (error);
 1641 }
 1642 
 1643 /*
 1644  * nfs write operation
 1645  * When called_from_strategy != 0, it should return EIO for an error that
 1646  * indicates recovery is in progress, so that the buffer will be left
 1647  * dirty and be written back to the server later. If it loops around,
 1648  * the recovery thread could get stuck waiting for the buffer and recovery
 1649  * will then deadlock.
 1650  */
 1651 int
 1652 nfsrpc_write(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
 1653     struct ucred *cred, NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp,
 1654     void *stuff, int called_from_strategy)
 1655 {
 1656         int error, expireret = 0, retrycnt, nostateid;
 1657         u_int32_t clidrev = 0;
 1658         struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
 1659         struct nfsnode *np = VTONFS(vp);
 1660         struct ucred *newcred;
 1661         struct nfsfh *nfhp = NULL;
 1662         nfsv4stateid_t stateid;
 1663         void *lckp;
 1664 
 1665         KASSERT(*must_commit >= 0 && *must_commit <= 2,
 1666             ("nfsrpc_write: must_commit out of range=%d", *must_commit));
 1667         if (nmp->nm_clp != NULL)
 1668                 clidrev = nmp->nm_clp->nfsc_clientidrev;
 1669         newcred = cred;
 1670         if (NFSHASNFSV4(nmp)) {
 1671                 newcred = NFSNEWCRED(cred);
 1672                 nfhp = np->n_fhp;
 1673         }
 1674         retrycnt = 0;
 1675         do {
 1676                 lckp = NULL;
 1677                 nostateid = 0;
 1678                 if (NFSHASNFSV4(nmp)) {
 1679                         (void)nfscl_getstateid(vp, nfhp->nfh_fh, nfhp->nfh_len,
 1680                             NFSV4OPEN_ACCESSWRITE, 0, newcred, p, &stateid,
 1681                             &lckp);
 1682                         if (stateid.other[0] == 0 && stateid.other[1] == 0 &&
 1683                             stateid.other[2] == 0) {
 1684                                 nostateid = 1;
 1685                                 NFSCL_DEBUG(1, "stateid0 in write\n");
 1686                         }
 1687                 }
 1688 
 1689                 /*
 1690                  * If there is no stateid for NFSv4, it means this is an
 1691                  * extraneous write after close. Basically a poorly
 1692                  * implemented buffer cache. Just don't do the write.
 1693                  */
 1694                 if (nostateid)
 1695                         error = 0;
 1696                 else
 1697                         error = nfsrpc_writerpc(vp, uiop, iomode, must_commit,
 1698                             newcred, &stateid, p, nap, attrflagp, stuff);
 1699                 if (error == NFSERR_STALESTATEID)
 1700                         nfscl_initiate_recovery(nmp->nm_clp);
 1701                 if (lckp != NULL)
 1702                         nfscl_lockderef(lckp);
 1703                 if (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
 1704                     error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
 1705                     error == NFSERR_OLDSTATEID || error == NFSERR_BADSESSION) {
 1706                         (void) nfs_catnap(PZERO, error, "nfs_write");
 1707                 } else if ((error == NFSERR_EXPIRED ||
 1708                     error == NFSERR_BADSTATEID) && clidrev != 0) {
 1709                         expireret = nfscl_hasexpired(nmp->nm_clp, clidrev, p);
 1710                 }
 1711                 retrycnt++;
 1712         } while (error == NFSERR_GRACE || error == NFSERR_DELAY ||
 1713             ((error == NFSERR_STALESTATEID || error == NFSERR_BADSESSION ||
 1714               error == NFSERR_STALEDONTRECOVER) && called_from_strategy == 0) ||
 1715             (error == NFSERR_OLDSTATEID && retrycnt < 20) ||
 1716             ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) &&
 1717              expireret == 0 && clidrev != 0 && retrycnt < 4));
 1718         if (error != 0 && (retrycnt >= 4 ||
 1719             ((error == NFSERR_STALESTATEID || error == NFSERR_BADSESSION ||
 1720               error == NFSERR_STALEDONTRECOVER) && called_from_strategy != 0)))
 1721                 error = EIO;
 1722         if (NFSHASNFSV4(nmp))
 1723                 NFSFREECRED(newcred);
 1724         return (error);
 1725 }
 1726 
 1727 /*
 1728  * The actual write RPC.
 1729  */
 1730 static int
 1731 nfsrpc_writerpc(vnode_t vp, struct uio *uiop, int *iomode,
 1732     int *must_commit, struct ucred *cred, nfsv4stateid_t *stateidp,
 1733     NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp, void *stuff)
 1734 {
 1735         u_int32_t *tl;
 1736         struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
 1737         struct nfsnode *np = VTONFS(vp);
 1738         int error = 0, len, tsiz, rlen, commit, committed = NFSWRITE_FILESYNC;
 1739         int wccflag = 0, wsize;
 1740         int32_t backup;
 1741         struct nfsrv_descript nfsd;
 1742         struct nfsrv_descript *nd = &nfsd;
 1743         nfsattrbit_t attrbits;
 1744         off_t tmp_off;
 1745 
 1746         KASSERT(uiop->uio_iovcnt == 1, ("nfs: writerpc iovcnt > 1"));
 1747         *attrflagp = 0;
 1748         tsiz = uio_uio_resid(uiop);
 1749         tmp_off = uiop->uio_offset + tsiz;
 1750         NFSLOCKMNT(nmp);
 1751         if (tmp_off > nmp->nm_maxfilesize || tmp_off < uiop->uio_offset) {
 1752                 NFSUNLOCKMNT(nmp);
 1753                 return (EFBIG);
 1754         }
 1755         wsize = nmp->nm_wsize;
 1756         NFSUNLOCKMNT(nmp);
 1757         nd->nd_mrep = NULL;     /* NFSv2 sometimes does a write with */
 1758         nd->nd_repstat = 0;     /* uio_resid == 0, so the while is not done */
 1759         while (tsiz > 0) {
 1760                 *attrflagp = 0;
 1761                 len = (tsiz > wsize) ? wsize : tsiz;
 1762                 NFSCL_REQSTART(nd, NFSPROC_WRITE, vp);
 1763                 if (nd->nd_flag & ND_NFSV4) {
 1764                         nfsm_stateidtom(nd, stateidp, NFSSTATEID_PUTSTATEID);
 1765                         NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER+2*NFSX_UNSIGNED);
 1766                         txdr_hyper(uiop->uio_offset, tl);
 1767                         tl += 2;
 1768                         *tl++ = txdr_unsigned(*iomode);
 1769                         *tl = txdr_unsigned(len);
 1770                 } else if (nd->nd_flag & ND_NFSV3) {
 1771                         NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER+3*NFSX_UNSIGNED);
 1772                         txdr_hyper(uiop->uio_offset, tl);
 1773                         tl += 2;
 1774                         *tl++ = txdr_unsigned(len);
 1775                         *tl++ = txdr_unsigned(*iomode);
 1776                         *tl = txdr_unsigned(len);
 1777                 } else {
 1778                         u_int32_t x;
 1779 
 1780                         NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
 1781                         /*
 1782                          * Not sure why someone changed this, since the
 1783                          * RFC clearly states that "beginoffset" and
 1784                          * "totalcount" are ignored, but it wouldn't
 1785                          * surprise me if there's a busted server out there.
 1786                          */
 1787                         /* Set both "begin" and "current" to non-garbage. */
 1788                         x = txdr_unsigned((u_int32_t)uiop->uio_offset);
 1789                         *tl++ = x;      /* "begin offset" */
 1790                         *tl++ = x;      /* "current offset" */
 1791                         x = txdr_unsigned(len);
 1792                         *tl++ = x;      /* total to this offset */
 1793                         *tl = x;        /* size of this write */
 1794 
 1795                 }
 1796                 nfsm_uiombuf(nd, uiop, len);
 1797                 /*
 1798                  * Although it is tempting to do a normal Getattr Op in the
 1799                  * NFSv4 compound, the result can be a nearly hung client
 1800                  * system if the Getattr asks for Owner and/or OwnerGroup.
 1801                  * It occurs when the client can't map either the Owner or
 1802                  * Owner_group name in the Getattr reply to a uid/gid. When
 1803                  * there is a cache miss, the kernel does an upcall to the
 1804                  * nfsuserd. Then, it can try and read the local /etc/passwd
 1805                  * or /etc/group file. It can then block in getnewbuf(),
 1806                  * waiting for dirty writes to be pushed to the NFS server.
 1807                  * The only reason this doesn't result in a complete
 1808                  * deadlock, is that the upcall times out and allows
 1809                  * the write to complete. However, progress is so slow
 1810                  * that it might just as well be deadlocked.
 1811                  * As such, we get the rest of the attributes, but not
 1812                  * Owner or Owner_group.
 1813                  * nb: nfscl_loadattrcache() needs to be told that these
 1814                  *     partial attributes from a write rpc are being
 1815                  *     passed in, via a argument flag.
 1816                  */
 1817                 if (nd->nd_flag & ND_NFSV4) {
 1818                         NFSWRITEGETATTR_ATTRBIT(&attrbits);
 1819                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 1820                         *tl = txdr_unsigned(NFSV4OP_GETATTR);
 1821                         (void) nfsrv_putattrbit(nd, &attrbits);
 1822                 }
 1823                 error = nfscl_request(nd, vp, p, cred, stuff);
 1824                 if (error)
 1825                         return (error);
 1826                 if (nd->nd_repstat) {
 1827                         /*
 1828                          * In case the rpc gets retried, roll
 1829                          * the uio fileds changed by nfsm_uiombuf()
 1830                          * back.
 1831                          */
 1832                         uiop->uio_offset -= len;
 1833                         uio_uio_resid_add(uiop, len);
 1834                         uio_iov_base_add(uiop, -len);
 1835                         uio_iov_len_add(uiop, len);
 1836                 }
 1837                 if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
 1838                         error = nfscl_wcc_data(nd, vp, nap, attrflagp,
 1839                             &wccflag, stuff);
 1840                         if (error)
 1841                                 goto nfsmout;
 1842                 }
 1843                 if (!nd->nd_repstat) {
 1844                         if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
 1845                                 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED
 1846                                         + NFSX_VERF);
 1847                                 rlen = fxdr_unsigned(int, *tl++);
 1848                                 if (rlen == 0) {
 1849                                         error = NFSERR_IO;
 1850                                         goto nfsmout;
 1851                                 } else if (rlen < len) {
 1852                                         backup = len - rlen;
 1853                                         uio_iov_base_add(uiop, -(backup));
 1854                                         uio_iov_len_add(uiop, backup);
 1855                                         uiop->uio_offset -= backup;
 1856                                         uio_uio_resid_add(uiop, backup);
 1857                                         len = rlen;
 1858                                 }
 1859                                 commit = fxdr_unsigned(int, *tl++);
 1860 
 1861                                 /*
 1862                                  * Return the lowest commitment level
 1863                                  * obtained by any of the RPCs.
 1864                                  */
 1865                                 if (committed == NFSWRITE_FILESYNC)
 1866                                         committed = commit;
 1867                                 else if (committed == NFSWRITE_DATASYNC &&
 1868                                         commit == NFSWRITE_UNSTABLE)
 1869                                         committed = commit;
 1870                                 NFSLOCKMNT(nmp);
 1871                                 if (!NFSHASWRITEVERF(nmp)) {
 1872                                         NFSBCOPY((caddr_t)tl,
 1873                                             (caddr_t)&nmp->nm_verf[0],
 1874                                             NFSX_VERF);
 1875                                         NFSSETWRITEVERF(nmp);
 1876                                 } else if (NFSBCMP(tl, nmp->nm_verf,
 1877                                     NFSX_VERF) && *must_commit != 2) {
 1878                                         *must_commit = 1;
 1879                                         NFSBCOPY(tl, nmp->nm_verf, NFSX_VERF);
 1880                                 }
 1881                                 NFSUNLOCKMNT(nmp);
 1882                         }
 1883                         if (nd->nd_flag & ND_NFSV4)
 1884                                 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 1885                         if (nd->nd_flag & (ND_NFSV2 | ND_NFSV4)) {
 1886                                 error = nfsm_loadattr(nd, nap);
 1887                                 if (!error)
 1888                                         *attrflagp = NFS_LATTR_NOSHRINK;
 1889                         }
 1890                 } else {
 1891                         error = nd->nd_repstat;
 1892                 }
 1893                 if (error)
 1894                         goto nfsmout;
 1895                 NFSWRITERPC_SETTIME(wccflag, np, nap, (nd->nd_flag & ND_NFSV4));
 1896                 mbuf_freem(nd->nd_mrep);
 1897                 nd->nd_mrep = NULL;
 1898                 tsiz -= len;
 1899         }
 1900 nfsmout:
 1901         if (nd->nd_mrep != NULL)
 1902                 mbuf_freem(nd->nd_mrep);
 1903         *iomode = committed;
 1904         if (nd->nd_repstat && !error)
 1905                 error = nd->nd_repstat;
 1906         return (error);
 1907 }
 1908 
 1909 /*
 1910  * nfs mknod rpc
 1911  * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the
 1912  * mode set to specify the file type and the size field for rdev.
 1913  */
 1914 int
 1915 nfsrpc_mknod(vnode_t dvp, char *name, int namelen, struct vattr *vap,
 1916     u_int32_t rdev, enum vtype vtyp, struct ucred *cred, NFSPROC_T *p,
 1917     struct nfsvattr *dnap, struct nfsvattr *nnap, struct nfsfh **nfhpp,
 1918     int *attrflagp, int *dattrflagp, void *dstuff)
 1919 {
 1920         u_int32_t *tl;
 1921         int error = 0;
 1922         struct nfsrv_descript nfsd, *nd = &nfsd;
 1923         nfsattrbit_t attrbits;
 1924 
 1925         *nfhpp = NULL;
 1926         *attrflagp = 0;
 1927         *dattrflagp = 0;
 1928         if (namelen > NFS_MAXNAMLEN)
 1929                 return (ENAMETOOLONG);
 1930         NFSCL_REQSTART(nd, NFSPROC_MKNOD, dvp);
 1931         if (nd->nd_flag & ND_NFSV4) {
 1932                 if (vtyp == VBLK || vtyp == VCHR) {
 1933                         NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
 1934                         *tl++ = vtonfsv34_type(vtyp);
 1935                         *tl++ = txdr_unsigned(NFSMAJOR(rdev));
 1936                         *tl = txdr_unsigned(NFSMINOR(rdev));
 1937                 } else {
 1938                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 1939                         *tl = vtonfsv34_type(vtyp);
 1940                 }
 1941         }
 1942         (void) nfsm_strtom(nd, name, namelen);
 1943         if (nd->nd_flag & ND_NFSV3) {
 1944                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 1945                 *tl = vtonfsv34_type(vtyp);
 1946         }
 1947         if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4))
 1948                 nfscl_fillsattr(nd, vap, dvp, 0, 0);
 1949         if ((nd->nd_flag & ND_NFSV3) &&
 1950             (vtyp == VCHR || vtyp == VBLK)) {
 1951                 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 1952                 *tl++ = txdr_unsigned(NFSMAJOR(rdev));
 1953                 *tl = txdr_unsigned(NFSMINOR(rdev));
 1954         }
 1955         if (nd->nd_flag & ND_NFSV4) {
 1956                 NFSGETATTR_ATTRBIT(&attrbits);
 1957                 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 1958                 *tl++ = txdr_unsigned(NFSV4OP_GETFH);
 1959                 *tl = txdr_unsigned(NFSV4OP_GETATTR);
 1960                 (void) nfsrv_putattrbit(nd, &attrbits);
 1961         }
 1962         if (nd->nd_flag & ND_NFSV2)
 1963                 nfscl_fillsattr(nd, vap, dvp, NFSSATTR_SIZERDEV, rdev);
 1964         error = nfscl_request(nd, dvp, p, cred, dstuff);
 1965         if (error)
 1966                 return (error);
 1967         if (nd->nd_flag & ND_NFSV4)
 1968                 error = nfscl_wcc_data(nd, dvp, dnap, dattrflagp, NULL, dstuff);
 1969         if (!nd->nd_repstat) {
 1970                 if (nd->nd_flag & ND_NFSV4) {
 1971                         NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
 1972                         error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
 1973                         if (error)
 1974                                 goto nfsmout;
 1975                 }
 1976                 error = nfscl_mtofh(nd, nfhpp, nnap, attrflagp);
 1977                 if (error)
 1978                         goto nfsmout;
 1979         }
 1980         if (nd->nd_flag & ND_NFSV3)
 1981                 error = nfscl_wcc_data(nd, dvp, dnap, dattrflagp, NULL, dstuff);
 1982         if (!error && nd->nd_repstat)
 1983                 error = nd->nd_repstat;
 1984 nfsmout:
 1985         mbuf_freem(nd->nd_mrep);
 1986         return (error);
 1987 }
 1988 
 1989 /*
 1990  * nfs file create call
 1991  * Mostly just call the approriate routine. (I separated out v4, so that
 1992  * error recovery wouldn't be as difficult.)
 1993  */
 1994 int
 1995 nfsrpc_create(vnode_t dvp, char *name, int namelen, struct vattr *vap,
 1996     nfsquad_t cverf, int fmode, struct ucred *cred, NFSPROC_T *p,
 1997     struct nfsvattr *dnap, struct nfsvattr *nnap, struct nfsfh **nfhpp,
 1998     int *attrflagp, int *dattrflagp, void *dstuff)
 1999 {
 2000         int error = 0, newone, expireret = 0, retrycnt, unlocked;
 2001         struct nfsclowner *owp;
 2002         struct nfscldeleg *dp;
 2003         struct nfsmount *nmp = VFSTONFS(vnode_mount(dvp));
 2004         u_int32_t clidrev;
 2005 
 2006         if (NFSHASNFSV4(nmp)) {
 2007             retrycnt = 0;
 2008             do {
 2009                 dp = NULL;
 2010                 error = nfscl_open(dvp, NULL, 0, (NFSV4OPEN_ACCESSWRITE |
 2011                     NFSV4OPEN_ACCESSREAD), 0, cred, p, &owp, NULL, &newone,
 2012                     NULL, 1, true);
 2013                 if (error)
 2014                         return (error);
 2015                 if (nmp->nm_clp != NULL)
 2016                         clidrev = nmp->nm_clp->nfsc_clientidrev;
 2017                 else
 2018                         clidrev = 0;
 2019                 if (!NFSHASPNFS(nmp) || nfscl_enablecallb == 0 ||
 2020                     nfs_numnfscbd == 0 || retrycnt > 0)
 2021                         error = nfsrpc_createv4(dvp, name, namelen, vap, cverf,
 2022                           fmode, owp, &dp, cred, p, dnap, nnap, nfhpp,
 2023                           attrflagp, dattrflagp, dstuff, &unlocked);
 2024                 else
 2025                         error = nfsrpc_getcreatelayout(dvp, name, namelen, vap,
 2026                           cverf, fmode, owp, &dp, cred, p, dnap, nnap, nfhpp,
 2027                           attrflagp, dattrflagp, dstuff, &unlocked);
 2028                 /*
 2029                  * There is no need to invalidate cached attributes here,
 2030                  * since new post-delegation issue attributes are always
 2031                  * returned by nfsrpc_createv4() and these will update the
 2032                  * attribute cache.
 2033                  */
 2034                 if (dp != NULL)
 2035                         (void) nfscl_deleg(nmp->nm_mountp, owp->nfsow_clp,
 2036                             (*nfhpp)->nfh_fh, (*nfhpp)->nfh_len, cred, p, &dp);
 2037                 nfscl_ownerrelease(nmp, owp, error, newone, unlocked);
 2038                 if (error == NFSERR_GRACE || error == NFSERR_STALECLIENTID ||
 2039                     error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
 2040                     error == NFSERR_BADSESSION) {
 2041                         (void) nfs_catnap(PZERO, error, "nfs_open");
 2042                 } else if ((error == NFSERR_EXPIRED ||
 2043                     error == NFSERR_BADSTATEID) && clidrev != 0) {
 2044                         expireret = nfscl_hasexpired(nmp->nm_clp, clidrev, p);
 2045                         retrycnt++;
 2046                 }
 2047             } while (error == NFSERR_GRACE || error == NFSERR_STALECLIENTID ||
 2048                 error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
 2049                 error == NFSERR_BADSESSION ||
 2050                 ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) &&
 2051                  expireret == 0 && clidrev != 0 && retrycnt < 4));
 2052             if (error && retrycnt >= 4)
 2053                     error = EIO;
 2054         } else {
 2055                 error = nfsrpc_createv23(dvp, name, namelen, vap, cverf,
 2056                     fmode, cred, p, dnap, nnap, nfhpp, attrflagp, dattrflagp,
 2057                     dstuff);
 2058         }
 2059         return (error);
 2060 }
 2061 
 2062 /*
 2063  * The create rpc for v2 and 3.
 2064  */
 2065 static int
 2066 nfsrpc_createv23(vnode_t dvp, char *name, int namelen, struct vattr *vap,
 2067     nfsquad_t cverf, int fmode, struct ucred *cred, NFSPROC_T *p,
 2068     struct nfsvattr *dnap, struct nfsvattr *nnap, struct nfsfh **nfhpp,
 2069     int *attrflagp, int *dattrflagp, void *dstuff)
 2070 {
 2071         u_int32_t *tl;
 2072         int error = 0;
 2073         struct nfsrv_descript nfsd, *nd = &nfsd;
 2074 
 2075         *nfhpp = NULL;
 2076         *attrflagp = 0;
 2077         *dattrflagp = 0;
 2078         if (namelen > NFS_MAXNAMLEN)
 2079                 return (ENAMETOOLONG);
 2080         NFSCL_REQSTART(nd, NFSPROC_CREATE, dvp);
 2081         (void) nfsm_strtom(nd, name, namelen);
 2082         if (nd->nd_flag & ND_NFSV3) {
 2083                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 2084                 if (fmode & O_EXCL) {
 2085                         *tl = txdr_unsigned(NFSCREATE_EXCLUSIVE);
 2086                         NFSM_BUILD(tl, u_int32_t *, NFSX_VERF);
 2087                         *tl++ = cverf.lval[0];
 2088                         *tl = cverf.lval[1];
 2089                 } else {
 2090                         *tl = txdr_unsigned(NFSCREATE_UNCHECKED);
 2091                         nfscl_fillsattr(nd, vap, dvp, 0, 0);
 2092                 }
 2093         } else {
 2094                 nfscl_fillsattr(nd, vap, dvp, NFSSATTR_SIZE0, 0);
 2095         }
 2096         error = nfscl_request(nd, dvp, p, cred, dstuff);
 2097         if (error)
 2098                 return (error);
 2099         if (nd->nd_repstat == 0) {
 2100                 error = nfscl_mtofh(nd, nfhpp, nnap, attrflagp);
 2101                 if (error)
 2102                         goto nfsmout;
 2103         }
 2104         if (nd->nd_flag & ND_NFSV3)
 2105                 error = nfscl_wcc_data(nd, dvp, dnap, dattrflagp, NULL, dstuff);
 2106         if (nd->nd_repstat != 0 && error == 0)
 2107                 error = nd->nd_repstat;
 2108 nfsmout:
 2109         mbuf_freem(nd->nd_mrep);
 2110         return (error);
 2111 }
 2112 
 2113 static int
 2114 nfsrpc_createv4(vnode_t dvp, char *name, int namelen, struct vattr *vap,
 2115     nfsquad_t cverf, int fmode, struct nfsclowner *owp, struct nfscldeleg **dpp,
 2116     struct ucred *cred, NFSPROC_T *p, struct nfsvattr *dnap,
 2117     struct nfsvattr *nnap, struct nfsfh **nfhpp, int *attrflagp,
 2118     int *dattrflagp, void *dstuff, int *unlockedp)
 2119 {
 2120         u_int32_t *tl;
 2121         int error = 0, deleg, newone, ret, acesize, limitby;
 2122         struct nfsrv_descript nfsd, *nd = &nfsd;
 2123         struct nfsclopen *op;
 2124         struct nfscldeleg *dp = NULL;
 2125         struct nfsnode *np;
 2126         struct nfsfh *nfhp;
 2127         nfsattrbit_t attrbits;
 2128         nfsv4stateid_t stateid;
 2129         u_int32_t rflags;
 2130         struct nfsmount *nmp;
 2131         struct nfsclsession *tsep;
 2132 
 2133         nmp = VFSTONFS(dvp->v_mount);
 2134         np = VTONFS(dvp);
 2135         *unlockedp = 0;
 2136         *nfhpp = NULL;
 2137         *dpp = NULL;
 2138         *attrflagp = 0;
 2139         *dattrflagp = 0;
 2140         if (namelen > NFS_MAXNAMLEN)
 2141                 return (ENAMETOOLONG);
 2142         NFSCL_REQSTART(nd, NFSPROC_CREATE, dvp);
 2143         /*
 2144          * For V4, this is actually an Open op.
 2145          */
 2146         NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
 2147         *tl++ = txdr_unsigned(owp->nfsow_seqid);
 2148         *tl++ = txdr_unsigned(NFSV4OPEN_ACCESSWRITE |
 2149             NFSV4OPEN_ACCESSREAD);
 2150         *tl++ = txdr_unsigned(NFSV4OPEN_DENYNONE);
 2151         tsep = nfsmnt_mdssession(nmp);
 2152         *tl++ = tsep->nfsess_clientid.lval[0];
 2153         *tl = tsep->nfsess_clientid.lval[1];
 2154         (void) nfsm_strtom(nd, owp->nfsow_owner, NFSV4CL_LOCKNAMELEN);
 2155         NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 2156         *tl++ = txdr_unsigned(NFSV4OPEN_CREATE);
 2157         if (fmode & O_EXCL) {
 2158                 if (NFSHASNFSV4N(nmp)) {
 2159                         if (NFSHASSESSPERSIST(nmp)) {
 2160                                 /* Use GUARDED for persistent sessions. */
 2161                                 *tl = txdr_unsigned(NFSCREATE_GUARDED);
 2162                                 nfscl_fillsattr(nd, vap, dvp, 0, 0);
 2163                         } else {
 2164                                 /* Otherwise, use EXCLUSIVE4_1. */
 2165                                 *tl = txdr_unsigned(NFSCREATE_EXCLUSIVE41);
 2166                                 NFSM_BUILD(tl, u_int32_t *, NFSX_VERF);
 2167                                 *tl++ = cverf.lval[0];
 2168                                 *tl = cverf.lval[1];
 2169                                 nfscl_fillsattr(nd, vap, dvp, 0, 0);
 2170                         }
 2171                 } else {
 2172                         /* NFSv4.0 */
 2173                         *tl = txdr_unsigned(NFSCREATE_EXCLUSIVE);
 2174                         NFSM_BUILD(tl, u_int32_t *, NFSX_VERF);
 2175                         *tl++ = cverf.lval[0];
 2176                         *tl = cverf.lval[1];
 2177                 }
 2178         } else {
 2179                 *tl = txdr_unsigned(NFSCREATE_UNCHECKED);
 2180                 nfscl_fillsattr(nd, vap, dvp, 0, 0);
 2181         }
 2182         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 2183         *tl = txdr_unsigned(NFSV4OPEN_CLAIMNULL);
 2184         (void) nfsm_strtom(nd, name, namelen);
 2185         /* Get the new file's handle and attributes. */
 2186         NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 2187         *tl++ = txdr_unsigned(NFSV4OP_GETFH);
 2188         *tl = txdr_unsigned(NFSV4OP_GETATTR);
 2189         NFSGETATTR_ATTRBIT(&attrbits);
 2190         (void) nfsrv_putattrbit(nd, &attrbits);
 2191         /* Get the directory's post-op attributes. */
 2192         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 2193         *tl = txdr_unsigned(NFSV4OP_PUTFH);
 2194         (void) nfsm_fhtom(nd, np->n_fhp->nfh_fh, np->n_fhp->nfh_len, 0);
 2195         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 2196         *tl = txdr_unsigned(NFSV4OP_GETATTR);
 2197         (void) nfsrv_putattrbit(nd, &attrbits);
 2198         error = nfscl_request(nd, dvp, p, cred, dstuff);
 2199         if (error)
 2200                 return (error);
 2201         NFSCL_INCRSEQID(owp->nfsow_seqid, nd);
 2202         if (nd->nd_repstat == 0) {
 2203                 NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID +
 2204                     6 * NFSX_UNSIGNED);
 2205                 stateid.seqid = *tl++;
 2206                 stateid.other[0] = *tl++;
 2207                 stateid.other[1] = *tl++;
 2208                 stateid.other[2] = *tl;
 2209                 rflags = fxdr_unsigned(u_int32_t, *(tl + 6));
 2210                 error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
 2211                 if (error)
 2212                         goto nfsmout;
 2213                 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 2214                 deleg = fxdr_unsigned(int, *tl);
 2215                 if (deleg == NFSV4OPEN_DELEGATEREAD ||
 2216                     deleg == NFSV4OPEN_DELEGATEWRITE) {
 2217                         if (!(owp->nfsow_clp->nfsc_flags &
 2218                               NFSCLFLAGS_FIRSTDELEG))
 2219                                 owp->nfsow_clp->nfsc_flags |=
 2220                                   (NFSCLFLAGS_FIRSTDELEG | NFSCLFLAGS_GOTDELEG);
 2221                         dp = malloc(
 2222                             sizeof (struct nfscldeleg) + NFSX_V4FHMAX,
 2223                             M_NFSCLDELEG, M_WAITOK);
 2224                         LIST_INIT(&dp->nfsdl_owner);
 2225                         LIST_INIT(&dp->nfsdl_lock);
 2226                         dp->nfsdl_clp = owp->nfsow_clp;
 2227                         newnfs_copyincred(cred, &dp->nfsdl_cred);
 2228                         nfscl_lockinit(&dp->nfsdl_rwlock);
 2229                         NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID +
 2230                             NFSX_UNSIGNED);
 2231                         dp->nfsdl_stateid.seqid = *tl++;
 2232                         dp->nfsdl_stateid.other[0] = *tl++;
 2233                         dp->nfsdl_stateid.other[1] = *tl++;
 2234                         dp->nfsdl_stateid.other[2] = *tl++;
 2235                         ret = fxdr_unsigned(int, *tl);
 2236                         if (deleg == NFSV4OPEN_DELEGATEWRITE) {
 2237                                 dp->nfsdl_flags = NFSCLDL_WRITE;
 2238                                 /*
 2239                                  * Indicates how much the file can grow.
 2240                                  */
 2241                                 NFSM_DISSECT(tl, u_int32_t *,
 2242                                     3 * NFSX_UNSIGNED);
 2243                                 limitby = fxdr_unsigned(int, *tl++);
 2244                                 switch (limitby) {
 2245                                 case NFSV4OPEN_LIMITSIZE:
 2246                                         dp->nfsdl_sizelimit = fxdr_hyper(tl);
 2247                                         break;
 2248                                 case NFSV4OPEN_LIMITBLOCKS:
 2249                                         dp->nfsdl_sizelimit =
 2250                                             fxdr_unsigned(u_int64_t, *tl++);
 2251                                         dp->nfsdl_sizelimit *=
 2252                                             fxdr_unsigned(u_int64_t, *tl);
 2253                                         break;
 2254                                 default:
 2255                                         error = NFSERR_BADXDR;
 2256                                         goto nfsmout;
 2257                                 }
 2258                         } else {
 2259                                 dp->nfsdl_flags = NFSCLDL_READ;
 2260                         }
 2261                         if (ret)
 2262                                 dp->nfsdl_flags |= NFSCLDL_RECALL;
 2263                         error = nfsrv_dissectace(nd, &dp->nfsdl_ace, &ret,
 2264                             &acesize, p);
 2265                         if (error)
 2266                                 goto nfsmout;
 2267                 } else if (deleg != NFSV4OPEN_DELEGATENONE) {
 2268                         error = NFSERR_BADXDR;
 2269                         goto nfsmout;
 2270                 }
 2271                 error = nfscl_mtofh(nd, nfhpp, nnap, attrflagp);
 2272                 if (error)
 2273                         goto nfsmout;
 2274                 /* Get rid of the PutFH and Getattr status values. */
 2275                 NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
 2276                 /* Load the directory attributes. */
 2277                 error = nfsm_loadattr(nd, dnap);
 2278                 if (error)
 2279                         goto nfsmout;
 2280                 *dattrflagp = 1;
 2281                 if (dp != NULL && *attrflagp) {
 2282                         dp->nfsdl_change = nnap->na_filerev;
 2283                         dp->nfsdl_modtime = nnap->na_mtime;
 2284                         dp->nfsdl_flags |= NFSCLDL_MODTIMESET;
 2285                 }
 2286                 /*
 2287                  * We can now complete the Open state.
 2288                  */
 2289                 nfhp = *nfhpp;
 2290                 if (dp != NULL) {
 2291                         dp->nfsdl_fhlen = nfhp->nfh_len;
 2292                         NFSBCOPY(nfhp->nfh_fh, dp->nfsdl_fh, nfhp->nfh_len);
 2293                 }
 2294                 /*
 2295                  * Get an Open structure that will be
 2296                  * attached to the OpenOwner, acquired already.
 2297                  */
 2298                 error = nfscl_open(dvp, nfhp->nfh_fh, nfhp->nfh_len, 
 2299                     (NFSV4OPEN_ACCESSWRITE | NFSV4OPEN_ACCESSREAD), 0,
 2300                     cred, p, NULL, &op, &newone, NULL, 0, false);
 2301                 if (error)
 2302                         goto nfsmout;
 2303                 op->nfso_stateid = stateid;
 2304                 newnfs_copyincred(cred, &op->nfso_cred);
 2305                 if ((rflags & NFSV4OPEN_RESULTCONFIRM)) {
 2306                     do {
 2307                         ret = nfsrpc_openconfirm(dvp, nfhp->nfh_fh,
 2308                             nfhp->nfh_len, op, cred, p);
 2309                         if (ret == NFSERR_DELAY)
 2310                             (void) nfs_catnap(PZERO, ret, "nfs_create");
 2311                     } while (ret == NFSERR_DELAY);
 2312                     error = ret;
 2313                 }
 2314 
 2315                 /*
 2316                  * If the server is handing out delegations, but we didn't
 2317                  * get one because an OpenConfirm was required, try the
 2318                  * Open again, to get a delegation. This is a harmless no-op,
 2319                  * from a server's point of view.
 2320                  */
 2321                 if ((rflags & NFSV4OPEN_RESULTCONFIRM) &&
 2322                     (owp->nfsow_clp->nfsc_flags & NFSCLFLAGS_GOTDELEG) &&
 2323                     !error && dp == NULL) {
 2324                     do {
 2325                         ret = nfsrpc_openrpc(VFSTONFS(vnode_mount(dvp)), dvp,
 2326                             np->n_fhp->nfh_fh, np->n_fhp->nfh_len,
 2327                             nfhp->nfh_fh, nfhp->nfh_len,
 2328                             (NFSV4OPEN_ACCESSWRITE | NFSV4OPEN_ACCESSREAD), op,
 2329                             name, namelen, &dp, 0, 0x0, cred, p, 0, 1);
 2330                         if (ret == NFSERR_DELAY)
 2331                             (void) nfs_catnap(PZERO, ret, "nfs_crt2");
 2332                     } while (ret == NFSERR_DELAY);
 2333                     if (ret) {
 2334                         if (dp != NULL) {
 2335                                 free(dp, M_NFSCLDELEG);
 2336                                 dp = NULL;
 2337                         }
 2338                         if (ret == NFSERR_STALECLIENTID ||
 2339                             ret == NFSERR_STALEDONTRECOVER ||
 2340                             ret == NFSERR_BADSESSION)
 2341                                 error = ret;
 2342                     }
 2343                 }
 2344                 nfscl_openrelease(nmp, op, error, newone);
 2345                 *unlockedp = 1;
 2346         }
 2347         if (nd->nd_repstat != 0 && error == 0)
 2348                 error = nd->nd_repstat;
 2349         if (error == NFSERR_STALECLIENTID)
 2350                 nfscl_initiate_recovery(owp->nfsow_clp);
 2351 nfsmout:
 2352         if (!error)
 2353                 *dpp = dp;
 2354         else if (dp != NULL)
 2355                 free(dp, M_NFSCLDELEG);
 2356         mbuf_freem(nd->nd_mrep);
 2357         return (error);
 2358 }
 2359 
 2360 /*
 2361  * Nfs remove rpc
 2362  */
 2363 int
 2364 nfsrpc_remove(vnode_t dvp, char *name, int namelen, vnode_t vp,
 2365     struct ucred *cred, NFSPROC_T *p, struct nfsvattr *dnap, int *dattrflagp,
 2366     void *dstuff)
 2367 {
 2368         u_int32_t *tl;
 2369         struct nfsrv_descript nfsd, *nd = &nfsd;
 2370         struct nfsnode *np;
 2371         struct nfsmount *nmp;
 2372         nfsv4stateid_t dstateid;
 2373         int error, ret = 0, i;
 2374 
 2375         *dattrflagp = 0;
 2376         if (namelen > NFS_MAXNAMLEN)
 2377                 return (ENAMETOOLONG);
 2378         nmp = VFSTONFS(vnode_mount(dvp));
 2379 tryagain:
 2380         if (NFSHASNFSV4(nmp) && ret == 0) {
 2381                 ret = nfscl_removedeleg(vp, p, &dstateid);
 2382                 if (ret == 1) {
 2383                         NFSCL_REQSTART(nd, NFSPROC_RETDELEGREMOVE, vp);
 2384                         NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID +
 2385                             NFSX_UNSIGNED);
 2386                         if (NFSHASNFSV4N(nmp))
 2387                                 *tl++ = 0;
 2388                         else
 2389                                 *tl++ = dstateid.seqid;
 2390                         *tl++ = dstateid.other[0];
 2391                         *tl++ = dstateid.other[1];
 2392                         *tl++ = dstateid.other[2];
 2393                         *tl = txdr_unsigned(NFSV4OP_PUTFH);
 2394                         np = VTONFS(dvp);
 2395                         (void) nfsm_fhtom(nd, np->n_fhp->nfh_fh,
 2396                             np->n_fhp->nfh_len, 0);
 2397                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 2398                         *tl = txdr_unsigned(NFSV4OP_REMOVE);
 2399                 }
 2400         } else {
 2401                 ret = 0;
 2402         }
 2403         if (ret == 0)
 2404                 NFSCL_REQSTART(nd, NFSPROC_REMOVE, dvp);
 2405         (void) nfsm_strtom(nd, name, namelen);
 2406         error = nfscl_request(nd, dvp, p, cred, dstuff);
 2407         if (error)
 2408                 return (error);
 2409         if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
 2410                 /* For NFSv4, parse out any Delereturn replies. */
 2411                 if (ret > 0 && nd->nd_repstat != 0 &&
 2412                     (nd->nd_flag & ND_NOMOREDATA)) {
 2413                         /*
 2414                          * If the Delegreturn failed, try again without
 2415                          * it. The server will Recall, as required.
 2416                          */
 2417                         mbuf_freem(nd->nd_mrep);
 2418                         goto tryagain;
 2419                 }
 2420                 for (i = 0; i < (ret * 2); i++) {
 2421                         if ((nd->nd_flag & (ND_NFSV4 | ND_NOMOREDATA)) ==
 2422                             ND_NFSV4) {
 2423                             NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 2424                             if (*(tl + 1))
 2425                                 nd->nd_flag |= ND_NOMOREDATA;
 2426                         }
 2427                 }
 2428                 error = nfscl_wcc_data(nd, dvp, dnap, dattrflagp, NULL, dstuff);
 2429         }
 2430         if (nd->nd_repstat && !error)
 2431                 error = nd->nd_repstat;
 2432 nfsmout:
 2433         mbuf_freem(nd->nd_mrep);
 2434         return (error);
 2435 }
 2436 
 2437 /*
 2438  * Do an nfs rename rpc.
 2439  */
 2440 int
 2441 nfsrpc_rename(vnode_t fdvp, vnode_t fvp, char *fnameptr, int fnamelen,
 2442     vnode_t tdvp, vnode_t tvp, char *tnameptr, int tnamelen, struct ucred *cred,
 2443     NFSPROC_T *p, struct nfsvattr *fnap, struct nfsvattr *tnap,
 2444     int *fattrflagp, int *tattrflagp, void *fstuff, void *tstuff)
 2445 {
 2446         u_int32_t *tl;
 2447         struct nfsrv_descript nfsd, *nd = &nfsd;
 2448         struct nfsmount *nmp;
 2449         struct nfsnode *np;
 2450         nfsattrbit_t attrbits;
 2451         nfsv4stateid_t fdstateid, tdstateid;
 2452         int error = 0, ret = 0, gottd = 0, gotfd = 0, i;
 2453         
 2454         *fattrflagp = 0;
 2455         *tattrflagp = 0;
 2456         nmp = VFSTONFS(vnode_mount(fdvp));
 2457         if (fnamelen > NFS_MAXNAMLEN || tnamelen > NFS_MAXNAMLEN)
 2458                 return (ENAMETOOLONG);
 2459 tryagain:
 2460         if (NFSHASNFSV4(nmp) && ret == 0) {
 2461                 ret = nfscl_renamedeleg(fvp, &fdstateid, &gotfd, tvp,
 2462                     &tdstateid, &gottd, p);
 2463                 if (gotfd && gottd) {
 2464                         NFSCL_REQSTART(nd, NFSPROC_RETDELEGRENAME2, fvp);
 2465                 } else if (gotfd) {
 2466                         NFSCL_REQSTART(nd, NFSPROC_RETDELEGRENAME1, fvp);
 2467                 } else if (gottd) {
 2468                         NFSCL_REQSTART(nd, NFSPROC_RETDELEGRENAME1, tvp);
 2469                 }
 2470                 if (gotfd) {
 2471                         NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
 2472                         if (NFSHASNFSV4N(nmp))
 2473                                 *tl++ = 0;
 2474                         else
 2475                                 *tl++ = fdstateid.seqid;
 2476                         *tl++ = fdstateid.other[0];
 2477                         *tl++ = fdstateid.other[1];
 2478                         *tl = fdstateid.other[2];
 2479                         if (gottd) {
 2480                                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 2481                                 *tl = txdr_unsigned(NFSV4OP_PUTFH);
 2482                                 np = VTONFS(tvp);
 2483                                 (void) nfsm_fhtom(nd, np->n_fhp->nfh_fh,
 2484                                     np->n_fhp->nfh_len, 0);
 2485                                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 2486                                 *tl = txdr_unsigned(NFSV4OP_DELEGRETURN);
 2487                         }
 2488                 }
 2489                 if (gottd) {
 2490                         NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
 2491                         if (NFSHASNFSV4N(nmp))
 2492                                 *tl++ = 0;
 2493                         else
 2494                                 *tl++ = tdstateid.seqid;
 2495                         *tl++ = tdstateid.other[0];
 2496                         *tl++ = tdstateid.other[1];
 2497                         *tl = tdstateid.other[2];
 2498                 }
 2499                 if (ret > 0) {
 2500                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 2501                         *tl = txdr_unsigned(NFSV4OP_PUTFH);
 2502                         np = VTONFS(fdvp);
 2503                         (void) nfsm_fhtom(nd, np->n_fhp->nfh_fh,
 2504                             np->n_fhp->nfh_len, 0);
 2505                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 2506                         *tl = txdr_unsigned(NFSV4OP_SAVEFH);
 2507                 }
 2508         } else {
 2509                 ret = 0;
 2510         }
 2511         if (ret == 0)
 2512                 NFSCL_REQSTART(nd, NFSPROC_RENAME, fdvp);
 2513         if (nd->nd_flag & ND_NFSV4) {
 2514                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 2515                 *tl = txdr_unsigned(NFSV4OP_GETATTR);
 2516                 NFSWCCATTR_ATTRBIT(&attrbits);
 2517                 (void) nfsrv_putattrbit(nd, &attrbits);
 2518                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 2519                 *tl = txdr_unsigned(NFSV4OP_PUTFH);
 2520                 (void) nfsm_fhtom(nd, VTONFS(tdvp)->n_fhp->nfh_fh,
 2521                     VTONFS(tdvp)->n_fhp->nfh_len, 0);
 2522                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 2523                 *tl = txdr_unsigned(NFSV4OP_GETATTR);
 2524                 (void) nfsrv_putattrbit(nd, &attrbits);
 2525                 nd->nd_flag |= ND_V4WCCATTR;
 2526                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 2527                 *tl = txdr_unsigned(NFSV4OP_RENAME);
 2528         }
 2529         (void) nfsm_strtom(nd, fnameptr, fnamelen);
 2530         if (!(nd->nd_flag & ND_NFSV4))
 2531                 (void) nfsm_fhtom(nd, VTONFS(tdvp)->n_fhp->nfh_fh,
 2532                         VTONFS(tdvp)->n_fhp->nfh_len, 0);
 2533         (void) nfsm_strtom(nd, tnameptr, tnamelen);
 2534         error = nfscl_request(nd, fdvp, p, cred, fstuff);
 2535         if (error)
 2536                 return (error);
 2537         if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
 2538                 /* For NFSv4, parse out any Delereturn replies. */
 2539                 if (ret > 0 && nd->nd_repstat != 0 &&
 2540                     (nd->nd_flag & ND_NOMOREDATA)) {
 2541                         /*
 2542                          * If the Delegreturn failed, try again without
 2543                          * it. The server will Recall, as required.
 2544                          */
 2545                         mbuf_freem(nd->nd_mrep);
 2546                         goto tryagain;
 2547                 }
 2548                 for (i = 0; i < (ret * 2); i++) {
 2549                         if ((nd->nd_flag & (ND_NFSV4 | ND_NOMOREDATA)) ==
 2550                             ND_NFSV4) {
 2551                             NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 2552                             if (*(tl + 1)) {
 2553                                 if (i == 0 && ret > 1) {
 2554                                     /*
 2555                                      * If the Delegreturn failed, try again
 2556                                      * without it. The server will Recall, as
 2557                                      * required.
 2558                                      * If ret > 1, the first iteration of this
 2559                                      * loop is the second DelegReturn result.
 2560                                      */
 2561                                     mbuf_freem(nd->nd_mrep);
 2562                                     goto tryagain;
 2563                                 } else {
 2564                                     nd->nd_flag |= ND_NOMOREDATA;
 2565                                 }
 2566                             }
 2567                         }
 2568                 }
 2569                 /* Now, the first wcc attribute reply. */
 2570                 if ((nd->nd_flag & (ND_NFSV4 | ND_NOMOREDATA)) == ND_NFSV4) {
 2571                         NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 2572                         if (*(tl + 1))
 2573                                 nd->nd_flag |= ND_NOMOREDATA;
 2574                 }
 2575                 error = nfscl_wcc_data(nd, fdvp, fnap, fattrflagp, NULL,
 2576                     fstuff);
 2577                 /* and the second wcc attribute reply. */
 2578                 if ((nd->nd_flag & (ND_NFSV4 | ND_NOMOREDATA)) == ND_NFSV4 &&
 2579                     !error) {
 2580                         NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 2581                         if (*(tl + 1))
 2582                                 nd->nd_flag |= ND_NOMOREDATA;
 2583                 }
 2584                 if (!error)
 2585                         error = nfscl_wcc_data(nd, tdvp, tnap, tattrflagp,
 2586                             NULL, tstuff);
 2587         }
 2588         if (nd->nd_repstat && !error)
 2589                 error = nd->nd_repstat;
 2590 nfsmout:
 2591         mbuf_freem(nd->nd_mrep);
 2592         return (error);
 2593 }
 2594 
 2595 /*
 2596  * nfs hard link create rpc
 2597  */
 2598 int
 2599 nfsrpc_link(vnode_t dvp, vnode_t vp, char *name, int namelen,
 2600     struct ucred *cred, NFSPROC_T *p, struct nfsvattr *dnap,
 2601     struct nfsvattr *nap, int *attrflagp, int *dattrflagp, void *dstuff)
 2602 {
 2603         u_int32_t *tl;
 2604         struct nfsrv_descript nfsd, *nd = &nfsd;
 2605         nfsattrbit_t attrbits;
 2606         int error = 0;
 2607 
 2608         *attrflagp = 0;
 2609         *dattrflagp = 0;
 2610         if (namelen > NFS_MAXNAMLEN)
 2611                 return (ENAMETOOLONG);
 2612         NFSCL_REQSTART(nd, NFSPROC_LINK, vp);
 2613         if (nd->nd_flag & ND_NFSV4) {
 2614                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 2615                 *tl = txdr_unsigned(NFSV4OP_PUTFH);
 2616         }
 2617         (void) nfsm_fhtom(nd, VTONFS(dvp)->n_fhp->nfh_fh,
 2618                 VTONFS(dvp)->n_fhp->nfh_len, 0);
 2619         if (nd->nd_flag & ND_NFSV4) {
 2620                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 2621                 *tl = txdr_unsigned(NFSV4OP_GETATTR);
 2622                 NFSWCCATTR_ATTRBIT(&attrbits);
 2623                 (void) nfsrv_putattrbit(nd, &attrbits);
 2624                 nd->nd_flag |= ND_V4WCCATTR;
 2625                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 2626                 *tl = txdr_unsigned(NFSV4OP_LINK);
 2627         }
 2628         (void) nfsm_strtom(nd, name, namelen);
 2629         error = nfscl_request(nd, vp, p, cred, dstuff);
 2630         if (error)
 2631                 return (error);
 2632         if (nd->nd_flag & ND_NFSV3) {
 2633                 error = nfscl_postop_attr(nd, nap, attrflagp, dstuff);
 2634                 if (!error)
 2635                         error = nfscl_wcc_data(nd, dvp, dnap, dattrflagp,
 2636                             NULL, dstuff);
 2637         } else if ((nd->nd_flag & (ND_NFSV4 | ND_NOMOREDATA)) == ND_NFSV4) {
 2638                 /*
 2639                  * First, parse out the PutFH and Getattr result.
 2640                  */
 2641                 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 2642                 if (!(*(tl + 1)))
 2643                         NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 2644                 if (*(tl + 1))
 2645                         nd->nd_flag |= ND_NOMOREDATA;
 2646                 /*
 2647                  * Get the pre-op attributes.
 2648                  */
 2649                 error = nfscl_wcc_data(nd, dvp, dnap, dattrflagp, NULL, dstuff);
 2650         }
 2651         if (nd->nd_repstat && !error)
 2652                 error = nd->nd_repstat;
 2653 nfsmout:
 2654         mbuf_freem(nd->nd_mrep);
 2655         return (error);
 2656 }
 2657 
 2658 /*
 2659  * nfs symbolic link create rpc
 2660  */
 2661 int
 2662 nfsrpc_symlink(vnode_t dvp, char *name, int namelen, char *target,
 2663     struct vattr *vap, struct ucred *cred, NFSPROC_T *p, struct nfsvattr *dnap,
 2664     struct nfsvattr *nnap, struct nfsfh **nfhpp, int *attrflagp,
 2665     int *dattrflagp, void *dstuff)
 2666 {
 2667         u_int32_t *tl;
 2668         struct nfsrv_descript nfsd, *nd = &nfsd;
 2669         struct nfsmount *nmp;
 2670         int slen, error = 0;
 2671 
 2672         *nfhpp = NULL;
 2673         *attrflagp = 0;
 2674         *dattrflagp = 0;
 2675         nmp = VFSTONFS(vnode_mount(dvp));
 2676         slen = strlen(target);
 2677         if (slen > NFS_MAXPATHLEN || namelen > NFS_MAXNAMLEN)
 2678                 return (ENAMETOOLONG);
 2679         NFSCL_REQSTART(nd, NFSPROC_SYMLINK, dvp);
 2680         if (nd->nd_flag & ND_NFSV4) {
 2681                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 2682                 *tl = txdr_unsigned(NFLNK);
 2683                 (void) nfsm_strtom(nd, target, slen);
 2684         }
 2685         (void) nfsm_strtom(nd, name, namelen);
 2686         if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4))
 2687                 nfscl_fillsattr(nd, vap, dvp, 0, 0);
 2688         if (!(nd->nd_flag & ND_NFSV4))
 2689                 (void) nfsm_strtom(nd, target, slen);
 2690         if (nd->nd_flag & ND_NFSV2)
 2691                 nfscl_fillsattr(nd, vap, dvp, NFSSATTR_SIZENEG1, 0);
 2692         error = nfscl_request(nd, dvp, p, cred, dstuff);
 2693         if (error)
 2694                 return (error);
 2695         if (nd->nd_flag & ND_NFSV4)
 2696                 error = nfscl_wcc_data(nd, dvp, dnap, dattrflagp, NULL, dstuff);
 2697         if ((nd->nd_flag & ND_NFSV3) && !error) {
 2698                 if (!nd->nd_repstat)
 2699                         error = nfscl_mtofh(nd, nfhpp, nnap, attrflagp);
 2700                 if (!error)
 2701                         error = nfscl_wcc_data(nd, dvp, dnap, dattrflagp,
 2702                             NULL, dstuff);
 2703         }
 2704         if (nd->nd_repstat && !error)
 2705                 error = nd->nd_repstat;
 2706         mbuf_freem(nd->nd_mrep);
 2707         /*
 2708          * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
 2709          * Only do this if vfs.nfs.ignore_eexist is set.
 2710          * Never do this for NFSv4.1 or later minor versions, since sessions
 2711          * should guarantee "exactly once" RPC semantics.
 2712          */
 2713         if (error == EEXIST && nfsignore_eexist != 0 && (!NFSHASNFSV4(nmp) ||
 2714             nmp->nm_minorvers == 0))
 2715                 error = 0;
 2716         return (error);
 2717 }
 2718 
 2719 /*
 2720  * nfs make dir rpc
 2721  */
 2722 int
 2723 nfsrpc_mkdir(vnode_t dvp, char *name, int namelen, struct vattr *vap,
 2724     struct ucred *cred, NFSPROC_T *p, struct nfsvattr *dnap,
 2725     struct nfsvattr *nnap, struct nfsfh **nfhpp, int *attrflagp,
 2726     int *dattrflagp, void *dstuff)
 2727 {
 2728         u_int32_t *tl;
 2729         struct nfsrv_descript nfsd, *nd = &nfsd;
 2730         nfsattrbit_t attrbits;
 2731         int error = 0;
 2732         struct nfsfh *fhp;
 2733         struct nfsmount *nmp;
 2734 
 2735         *nfhpp = NULL;
 2736         *attrflagp = 0;
 2737         *dattrflagp = 0;
 2738         nmp = VFSTONFS(vnode_mount(dvp));
 2739         fhp = VTONFS(dvp)->n_fhp;
 2740         if (namelen > NFS_MAXNAMLEN)
 2741                 return (ENAMETOOLONG);
 2742         NFSCL_REQSTART(nd, NFSPROC_MKDIR, dvp);
 2743         if (nd->nd_flag & ND_NFSV4) {
 2744                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 2745                 *tl = txdr_unsigned(NFDIR);
 2746         }
 2747         (void) nfsm_strtom(nd, name, namelen);
 2748         nfscl_fillsattr(nd, vap, dvp, NFSSATTR_SIZENEG1, 0);
 2749         if (nd->nd_flag & ND_NFSV4) {
 2750                 NFSGETATTR_ATTRBIT(&attrbits);
 2751                 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 2752                 *tl++ = txdr_unsigned(NFSV4OP_GETFH);
 2753                 *tl = txdr_unsigned(NFSV4OP_GETATTR);
 2754                 (void) nfsrv_putattrbit(nd, &attrbits);
 2755                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 2756                 *tl = txdr_unsigned(NFSV4OP_PUTFH);
 2757                 (void) nfsm_fhtom(nd, fhp->nfh_fh, fhp->nfh_len, 0);
 2758                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 2759                 *tl = txdr_unsigned(NFSV4OP_GETATTR);
 2760                 (void) nfsrv_putattrbit(nd, &attrbits);
 2761         }
 2762         error = nfscl_request(nd, dvp, p, cred, dstuff);
 2763         if (error)
 2764                 return (error);
 2765         if (nd->nd_flag & ND_NFSV4)
 2766                 error = nfscl_wcc_data(nd, dvp, dnap, dattrflagp, NULL, dstuff);
 2767         if (!nd->nd_repstat && !error) {
 2768                 if (nd->nd_flag & ND_NFSV4) {
 2769                         NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
 2770                         error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
 2771                 }
 2772                 if (!error)
 2773                         error = nfscl_mtofh(nd, nfhpp, nnap, attrflagp);
 2774                 if (error == 0 && (nd->nd_flag & ND_NFSV4) != 0) {
 2775                         /* Get rid of the PutFH and Getattr status values. */
 2776                         NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
 2777                         /* Load the directory attributes. */
 2778                         error = nfsm_loadattr(nd, dnap);
 2779                         if (error == 0)
 2780                                 *dattrflagp = 1;
 2781                 }
 2782         }
 2783         if ((nd->nd_flag & ND_NFSV3) && !error)
 2784                 error = nfscl_wcc_data(nd, dvp, dnap, dattrflagp, NULL, dstuff);
 2785         if (nd->nd_repstat && !error)
 2786                 error = nd->nd_repstat;
 2787 nfsmout:
 2788         mbuf_freem(nd->nd_mrep);
 2789         /*
 2790          * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
 2791          * Only do this if vfs.nfs.ignore_eexist is set.
 2792          * Never do this for NFSv4.1 or later minor versions, since sessions
 2793          * should guarantee "exactly once" RPC semantics.
 2794          */
 2795         if (error == EEXIST && nfsignore_eexist != 0 && (!NFSHASNFSV4(nmp) ||
 2796             nmp->nm_minorvers == 0))
 2797                 error = 0;
 2798         return (error);
 2799 }
 2800 
 2801 /*
 2802  * nfs remove directory call
 2803  */
 2804 int
 2805 nfsrpc_rmdir(vnode_t dvp, char *name, int namelen, struct ucred *cred,
 2806     NFSPROC_T *p, struct nfsvattr *dnap, int *dattrflagp, void *dstuff)
 2807 {
 2808         struct nfsrv_descript nfsd, *nd = &nfsd;
 2809         int error = 0;
 2810 
 2811         *dattrflagp = 0;
 2812         if (namelen > NFS_MAXNAMLEN)
 2813                 return (ENAMETOOLONG);
 2814         NFSCL_REQSTART(nd, NFSPROC_RMDIR, dvp);
 2815         (void) nfsm_strtom(nd, name, namelen);
 2816         error = nfscl_request(nd, dvp, p, cred, dstuff);
 2817         if (error)
 2818                 return (error);
 2819         if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4))
 2820                 error = nfscl_wcc_data(nd, dvp, dnap, dattrflagp, NULL, dstuff);
 2821         if (nd->nd_repstat && !error)
 2822                 error = nd->nd_repstat;
 2823         mbuf_freem(nd->nd_mrep);
 2824         /*
 2825          * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry.
 2826          */
 2827         if (error == ENOENT)
 2828                 error = 0;
 2829         return (error);
 2830 }
 2831 
 2832 /*
 2833  * Readdir rpc.
 2834  * Always returns with either uio_resid unchanged, if you are at the
 2835  * end of the directory, or uio_resid == 0, with all DIRBLKSIZ chunks
 2836  * filled in.
 2837  * I felt this would allow caching of directory blocks more easily
 2838  * than returning a pertially filled block.
 2839  * Directory offset cookies:
 2840  * Oh my, what to do with them...
 2841  * I can think of three ways to deal with them:
 2842  * 1 - have the layer above these RPCs maintain a map between logical
 2843  *     directory byte offsets and the NFS directory offset cookies
 2844  * 2 - pass the opaque directory offset cookies up into userland
 2845  *     and let the libc functions deal with them, via the system call
 2846  * 3 - return them to userland in the "struct dirent", so future versions
 2847  *     of libc can use them and do whatever is necessary to make things work
 2848  *     above these rpc calls, in the meantime
 2849  * For now, I do #3 by "hiding" the directory offset cookies after the
 2850  * d_name field in struct dirent. This is space inside d_reclen that
 2851  * will be ignored by anything that doesn't know about them.
 2852  * The directory offset cookies are filled in as the last 8 bytes of
 2853  * each directory entry, after d_name. Someday, the userland libc
 2854  * functions may be able to use these. In the meantime, it satisfies
 2855  * OpenBSD's requirements for cookies being returned.
 2856  * If expects the directory offset cookie for the read to be in uio_offset
 2857  * and returns the one for the next entry after this directory block in
 2858  * there, as well.
 2859  */
 2860 int
 2861 nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
 2862     struct ucred *cred, NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp,
 2863     int *eofp, void *stuff)
 2864 {
 2865         int len, left;
 2866         struct dirent *dp = NULL;
 2867         u_int32_t *tl;
 2868         nfsquad_t cookie, ncookie;
 2869         struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
 2870         struct nfsnode *dnp = VTONFS(vp);
 2871         struct nfsvattr nfsva;
 2872         struct nfsrv_descript nfsd, *nd = &nfsd;
 2873         int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1;
 2874         int reqsize, tryformoredirs = 1, readsize, eof = 0, gotmnton = 0;
 2875         u_int64_t dotfileid, dotdotfileid = 0, fakefileno = UINT64_MAX;
 2876         char *cp;
 2877         nfsattrbit_t attrbits, dattrbits;
 2878         u_int32_t rderr, *tl2 = NULL;
 2879         size_t tresid;
 2880 
 2881         KASSERT(uiop->uio_iovcnt == 1 &&
 2882             (uio_uio_resid(uiop) & (DIRBLKSIZ - 1)) == 0,
 2883             ("nfs readdirrpc bad uio"));
 2884         ncookie.lval[0] = ncookie.lval[1] = 0;
 2885         /*
 2886          * There is no point in reading a lot more than uio_resid, however
 2887          * adding one additional DIRBLKSIZ makes sense. Since uio_resid
 2888          * and nm_readdirsize are both exact multiples of DIRBLKSIZ, this
 2889          * will never make readsize > nm_readdirsize.
 2890          */
 2891         readsize = nmp->nm_readdirsize;
 2892         if (readsize > uio_uio_resid(uiop))
 2893                 readsize = uio_uio_resid(uiop) + DIRBLKSIZ;
 2894 
 2895         *attrflagp = 0;
 2896         if (eofp)
 2897                 *eofp = 0;
 2898         tresid = uio_uio_resid(uiop);
 2899         cookie.lval[0] = cookiep->nfsuquad[0];
 2900         cookie.lval[1] = cookiep->nfsuquad[1];
 2901         nd->nd_mrep = NULL;
 2902 
 2903         /*
 2904          * For NFSv4, first create the "." and ".." entries.
 2905          */
 2906         if (NFSHASNFSV4(nmp)) {
 2907                 reqsize = 6 * NFSX_UNSIGNED;
 2908                 NFSGETATTR_ATTRBIT(&dattrbits);
 2909                 NFSZERO_ATTRBIT(&attrbits);
 2910                 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_FILEID);
 2911                 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TYPE);
 2912                 if (NFSISSET_ATTRBIT(&dnp->n_vattr.na_suppattr,
 2913                     NFSATTRBIT_MOUNTEDONFILEID)) {
 2914                         NFSSETBIT_ATTRBIT(&attrbits,
 2915                             NFSATTRBIT_MOUNTEDONFILEID);
 2916                         gotmnton = 1;
 2917                 } else {
 2918                         /*
 2919                          * Must fake it. Use the fileno, except when the
 2920                          * fsid is != to that of the directory. For that
 2921                          * case, generate a fake fileno that is not the same.
 2922                          */
 2923                         NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_FSID);
 2924                         gotmnton = 0;
 2925                 }
 2926 
 2927                 /*
 2928                  * Joy, oh joy. For V4 we get to hand craft '.' and '..'.
 2929                  */
 2930                 if (uiop->uio_offset == 0) {
 2931                         NFSCL_REQSTART(nd, NFSPROC_LOOKUPP, vp);
 2932                         NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 2933                         *tl++ = txdr_unsigned(NFSV4OP_GETFH);
 2934                         *tl = txdr_unsigned(NFSV4OP_GETATTR);
 2935                         (void) nfsrv_putattrbit(nd, &attrbits);
 2936                         error = nfscl_request(nd, vp, p, cred, stuff);
 2937                         if (error)
 2938                             return (error);
 2939                         dotfileid = 0;  /* Fake out the compiler. */
 2940                         if ((nd->nd_flag & ND_NOMOREDATA) == 0) {
 2941                             error = nfsm_loadattr(nd, &nfsva);
 2942                             if (error != 0)
 2943                                 goto nfsmout;
 2944                             dotfileid = nfsva.na_fileid;
 2945                         }
 2946                         if (nd->nd_repstat == 0) {
 2947                             NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
 2948                             len = fxdr_unsigned(int, *(tl + 4));
 2949                             if (len > 0 && len <= NFSX_V4FHMAX)
 2950                                 error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
 2951                             else
 2952                                 error = EPERM;
 2953                             if (!error) {
 2954                                 NFSM_DISSECT(tl, u_int32_t *, 2*NFSX_UNSIGNED);
 2955                                 nfsva.na_mntonfileno = UINT64_MAX;
 2956                                 error = nfsv4_loadattr(nd, NULL, &nfsva, NULL,
 2957                                     NULL, 0, NULL, NULL, NULL, NULL, NULL, 0,
 2958                                     NULL, NULL, NULL, p, cred);
 2959                                 if (error) {
 2960                                     dotdotfileid = dotfileid;
 2961                                 } else if (gotmnton) {
 2962                                     if (nfsva.na_mntonfileno != UINT64_MAX)
 2963                                         dotdotfileid = nfsva.na_mntonfileno;
 2964                                     else
 2965                                         dotdotfileid = nfsva.na_fileid;
 2966                                 } else if (nfsva.na_filesid[0] ==
 2967                                     dnp->n_vattr.na_filesid[0] &&
 2968                                     nfsva.na_filesid[1] ==
 2969                                     dnp->n_vattr.na_filesid[1]) {
 2970                                     dotdotfileid = nfsva.na_fileid;
 2971                                 } else {
 2972                                     do {
 2973                                         fakefileno--;
 2974                                     } while (fakefileno ==
 2975                                         nfsva.na_fileid);
 2976                                     dotdotfileid = fakefileno;
 2977                                 }
 2978                             }
 2979                         } else if (nd->nd_repstat == NFSERR_NOENT) {
 2980                             /*
 2981                              * Lookupp returns NFSERR_NOENT when we are
 2982                              * at the root, so just use the current dir.
 2983                              */
 2984                             nd->nd_repstat = 0;
 2985                             dotdotfileid = dotfileid;
 2986                         } else {
 2987                             error = nd->nd_repstat;
 2988                         }
 2989                         mbuf_freem(nd->nd_mrep);
 2990                         if (error)
 2991                             return (error);
 2992                         nd->nd_mrep = NULL;
 2993                         dp = (struct dirent *)uio_iov_base(uiop);
 2994                         dp->d_pad0 = dp->d_pad1 = 0;
 2995                         dp->d_off = 0;
 2996                         dp->d_type = DT_DIR;
 2997                         dp->d_fileno = dotfileid;
 2998                         dp->d_namlen = 1;
 2999                         *((uint64_t *)dp->d_name) = 0;  /* Zero pad it. */
 3000                         dp->d_name[0] = '.';
 3001                         dp->d_reclen = _GENERIC_DIRSIZ(dp) + NFSX_HYPER;
 3002                         /*
 3003                          * Just make these offset cookie 0.
 3004                          */
 3005                         tl = (u_int32_t *)&dp->d_name[8];
 3006                         *tl++ = 0;
 3007                         *tl = 0;
 3008                         blksiz += dp->d_reclen;
 3009                         uio_uio_resid_add(uiop, -(dp->d_reclen));
 3010                         uiop->uio_offset += dp->d_reclen;
 3011                         uio_iov_base_add(uiop, dp->d_reclen);
 3012                         uio_iov_len_add(uiop, -(dp->d_reclen));
 3013                         dp = (struct dirent *)uio_iov_base(uiop);
 3014                         dp->d_pad0 = dp->d_pad1 = 0;
 3015                         dp->d_off = 0;
 3016                         dp->d_type = DT_DIR;
 3017                         dp->d_fileno = dotdotfileid;
 3018                         dp->d_namlen = 2;
 3019                         *((uint64_t *)dp->d_name) = 0;
 3020                         dp->d_name[0] = '.';
 3021                         dp->d_name[1] = '.';
 3022                         dp->d_reclen = _GENERIC_DIRSIZ(dp) + NFSX_HYPER;
 3023                         /*
 3024                          * Just make these offset cookie 0.
 3025                          */
 3026                         tl = (u_int32_t *)&dp->d_name[8];
 3027                         *tl++ = 0;
 3028                         *tl = 0;
 3029                         blksiz += dp->d_reclen;
 3030                         uio_uio_resid_add(uiop, -(dp->d_reclen));
 3031                         uiop->uio_offset += dp->d_reclen;
 3032                         uio_iov_base_add(uiop, dp->d_reclen);
 3033                         uio_iov_len_add(uiop, -(dp->d_reclen));
 3034                 }
 3035                 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_RDATTRERROR);
 3036         } else {
 3037                 reqsize = 5 * NFSX_UNSIGNED;
 3038         }
 3039 
 3040 
 3041         /*
 3042          * Loop around doing readdir rpc's of size readsize.
 3043          * The stopping criteria is EOF or buffer full.
 3044          */
 3045         while (more_dirs && bigenough) {
 3046                 *attrflagp = 0;
 3047                 NFSCL_REQSTART(nd, NFSPROC_READDIR, vp);
 3048                 if (nd->nd_flag & ND_NFSV2) {
 3049                         NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 3050                         *tl++ = cookie.lval[1];
 3051                         *tl = txdr_unsigned(readsize);
 3052                 } else {
 3053                         NFSM_BUILD(tl, u_int32_t *, reqsize);
 3054                         *tl++ = cookie.lval[0];
 3055                         *tl++ = cookie.lval[1];
 3056                         if (cookie.qval == 0) {
 3057                                 *tl++ = 0;
 3058                                 *tl++ = 0;
 3059                         } else {
 3060                                 NFSLOCKNODE(dnp);
 3061                                 *tl++ = dnp->n_cookieverf.nfsuquad[0];
 3062                                 *tl++ = dnp->n_cookieverf.nfsuquad[1];
 3063                                 NFSUNLOCKNODE(dnp);
 3064                         }
 3065                         if (nd->nd_flag & ND_NFSV4) {
 3066                                 *tl++ = txdr_unsigned(readsize);
 3067                                 *tl = txdr_unsigned(readsize);
 3068                                 (void) nfsrv_putattrbit(nd, &attrbits);
 3069                                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 3070                                 *tl = txdr_unsigned(NFSV4OP_GETATTR);
 3071                                 (void) nfsrv_putattrbit(nd, &dattrbits);
 3072                         } else {
 3073                                 *tl = txdr_unsigned(readsize);
 3074                         }
 3075                 }
 3076                 error = nfscl_request(nd, vp, p, cred, stuff);
 3077                 if (error)
 3078                         return (error);
 3079                 if (!(nd->nd_flag & ND_NFSV2)) {
 3080                         if (nd->nd_flag & ND_NFSV3)
 3081                                 error = nfscl_postop_attr(nd, nap, attrflagp,
 3082                                     stuff);
 3083                         if (!nd->nd_repstat && !error) {
 3084                                 NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
 3085                                 NFSLOCKNODE(dnp);
 3086                                 dnp->n_cookieverf.nfsuquad[0] = *tl++;
 3087                                 dnp->n_cookieverf.nfsuquad[1] = *tl;
 3088                                 NFSUNLOCKNODE(dnp);
 3089                         }
 3090                 }
 3091                 if (nd->nd_repstat || error) {
 3092                         if (!error)
 3093                                 error = nd->nd_repstat;
 3094                         goto nfsmout;
 3095                 }
 3096                 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 3097                 more_dirs = fxdr_unsigned(int, *tl);
 3098                 if (!more_dirs)
 3099                         tryformoredirs = 0;
 3100         
 3101                 /* loop through the dir entries, doctoring them to 4bsd form */
 3102                 while (more_dirs && bigenough) {
 3103                         if (nd->nd_flag & ND_NFSV4) {
 3104                                 NFSM_DISSECT(tl, u_int32_t *, 3*NFSX_UNSIGNED);
 3105                                 ncookie.lval[0] = *tl++;
 3106                                 ncookie.lval[1] = *tl++;
 3107                                 len = fxdr_unsigned(int, *tl);
 3108                         } else if (nd->nd_flag & ND_NFSV3) {
 3109                                 NFSM_DISSECT(tl, u_int32_t *, 3*NFSX_UNSIGNED);
 3110                                 nfsva.na_fileid = fxdr_hyper(tl);
 3111                                 tl += 2;
 3112                                 len = fxdr_unsigned(int, *tl);
 3113                         } else {
 3114                                 NFSM_DISSECT(tl, u_int32_t *, 2*NFSX_UNSIGNED);
 3115                                 nfsva.na_fileid = fxdr_unsigned(uint64_t,
 3116                                     *tl++);
 3117                                 len = fxdr_unsigned(int, *tl);
 3118                         }
 3119                         if (len <= 0 || len > NFS_MAXNAMLEN) {
 3120                                 error = EBADRPC;
 3121                                 goto nfsmout;
 3122                         }
 3123                         tlen = roundup2(len, 8);
 3124                         if (tlen == len)
 3125                                 tlen += 8;  /* To ensure null termination. */
 3126                         left = DIRBLKSIZ - blksiz;
 3127                         if (_GENERIC_DIRLEN(len) + NFSX_HYPER > left) {
 3128                                 NFSBZERO(uio_iov_base(uiop), left);
 3129                                 dp->d_reclen += left;
 3130                                 uio_iov_base_add(uiop, left);
 3131                                 uio_iov_len_add(uiop, -(left));
 3132                                 uio_uio_resid_add(uiop, -(left));
 3133                                 uiop->uio_offset += left;
 3134                                 blksiz = 0;
 3135                         }
 3136                         if (_GENERIC_DIRLEN(len) + NFSX_HYPER >
 3137                             uio_uio_resid(uiop))
 3138                                 bigenough = 0;
 3139                         if (bigenough) {
 3140                                 dp = (struct dirent *)uio_iov_base(uiop);
 3141                                 dp->d_pad0 = dp->d_pad1 = 0;
 3142                                 dp->d_off = 0;
 3143                                 dp->d_namlen = len;
 3144                                 dp->d_reclen = _GENERIC_DIRLEN(len) +
 3145                                     NFSX_HYPER;
 3146                                 dp->d_type = DT_UNKNOWN;
 3147                                 blksiz += dp->d_reclen;
 3148                                 if (blksiz == DIRBLKSIZ)
 3149                                         blksiz = 0;
 3150                                 uio_uio_resid_add(uiop, -(DIRHDSIZ));
 3151                                 uiop->uio_offset += DIRHDSIZ;
 3152                                 uio_iov_base_add(uiop, DIRHDSIZ);
 3153                                 uio_iov_len_add(uiop, -(DIRHDSIZ));
 3154                                 error = nfsm_mbufuio(nd, uiop, len);
 3155                                 if (error)
 3156                                         goto nfsmout;
 3157                                 cp = uio_iov_base(uiop);
 3158                                 tlen -= len;
 3159                                 NFSBZERO(cp, tlen);
 3160                                 cp += tlen;     /* points to cookie storage */
 3161                                 tl2 = (u_int32_t *)cp;
 3162                                 uio_iov_base_add(uiop, (tlen + NFSX_HYPER));
 3163                                 uio_iov_len_add(uiop, -(tlen + NFSX_HYPER));
 3164                                 uio_uio_resid_add(uiop, -(tlen + NFSX_HYPER));
 3165                                 uiop->uio_offset += (tlen + NFSX_HYPER);
 3166                         } else {
 3167                                 error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
 3168                                 if (error)
 3169                                         goto nfsmout;
 3170                         }
 3171                         if (nd->nd_flag & ND_NFSV4) {
 3172                                 rderr = 0;
 3173                                 nfsva.na_mntonfileno = UINT64_MAX;
 3174                                 error = nfsv4_loadattr(nd, NULL, &nfsva, NULL,
 3175                                     NULL, 0, NULL, NULL, NULL, NULL, NULL, 0,
 3176                                     NULL, NULL, &rderr, p, cred);
 3177                                 if (error)
 3178                                         goto nfsmout;
 3179                                 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 3180                         } else if (nd->nd_flag & ND_NFSV3) {
 3181                                 NFSM_DISSECT(tl, u_int32_t *, 3*NFSX_UNSIGNED);
 3182                                 ncookie.lval[0] = *tl++;
 3183                                 ncookie.lval[1] = *tl++;
 3184                         } else {
 3185                                 NFSM_DISSECT(tl, u_int32_t *, 2*NFSX_UNSIGNED);
 3186                                 ncookie.lval[0] = 0;
 3187                                 ncookie.lval[1] = *tl++;
 3188                         }
 3189                         if (bigenough) {
 3190                             if (nd->nd_flag & ND_NFSV4) {
 3191                                 if (rderr) {
 3192                                     dp->d_fileno = 0;
 3193                                 } else {
 3194                                     if (gotmnton) {
 3195                                         if (nfsva.na_mntonfileno != UINT64_MAX)
 3196                                             dp->d_fileno = nfsva.na_mntonfileno;
 3197                                         else
 3198                                             dp->d_fileno = nfsva.na_fileid;
 3199                                     } else if (nfsva.na_filesid[0] ==
 3200                                         dnp->n_vattr.na_filesid[0] &&
 3201                                         nfsva.na_filesid[1] ==
 3202                                         dnp->n_vattr.na_filesid[1]) {
 3203                                         dp->d_fileno = nfsva.na_fileid;
 3204                                     } else {
 3205                                         do {
 3206                                             fakefileno--;
 3207                                         } while (fakefileno ==
 3208                                             nfsva.na_fileid);
 3209                                         dp->d_fileno = fakefileno;
 3210                                     }
 3211                                     dp->d_type = vtonfs_dtype(nfsva.na_type);
 3212                                 }
 3213                             } else {
 3214                                 dp->d_fileno = nfsva.na_fileid;
 3215                             }
 3216                             *tl2++ = cookiep->nfsuquad[0] = cookie.lval[0] =
 3217                                 ncookie.lval[0];
 3218                             *tl2 = cookiep->nfsuquad[1] = cookie.lval[1] =
 3219                                 ncookie.lval[1];
 3220                         }
 3221                         more_dirs = fxdr_unsigned(int, *tl);
 3222                 }
 3223                 /*
 3224                  * If at end of rpc data, get the eof boolean
 3225                  */
 3226                 if (!more_dirs) {
 3227                         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 3228                         eof = fxdr_unsigned(int, *tl);
 3229                         if (tryformoredirs)
 3230                                 more_dirs = !eof;
 3231                         if (nd->nd_flag & ND_NFSV4) {
 3232                                 error = nfscl_postop_attr(nd, nap, attrflagp,
 3233                                     stuff);
 3234                                 if (error)
 3235                                         goto nfsmout;
 3236                         }
 3237                 }
 3238                 mbuf_freem(nd->nd_mrep);
 3239                 nd->nd_mrep = NULL;
 3240         }
 3241         /*
 3242          * Fill last record, iff any, out to a multiple of DIRBLKSIZ
 3243          * by increasing d_reclen for the last record.
 3244          */
 3245         if (blksiz > 0) {
 3246                 left = DIRBLKSIZ - blksiz;
 3247                 NFSBZERO(uio_iov_base(uiop), left);
 3248                 dp->d_reclen += left;
 3249                 uio_iov_base_add(uiop, left);
 3250                 uio_iov_len_add(uiop, -(left));
 3251                 uio_uio_resid_add(uiop, -(left));
 3252                 uiop->uio_offset += left;
 3253         }
 3254 
 3255         /*
 3256          * If returning no data, assume end of file.
 3257          * If not bigenough, return not end of file, since you aren't
 3258          *    returning all the data
 3259          * Otherwise, return the eof flag from the server.
 3260          */
 3261         if (eofp) {
 3262                 if (tresid == ((size_t)(uio_uio_resid(uiop))))
 3263                         *eofp = 1;
 3264                 else if (!bigenough)
 3265                         *eofp = 0;
 3266                 else
 3267                         *eofp = eof;
 3268         }
 3269 
 3270         /*
 3271          * Add extra empty records to any remaining DIRBLKSIZ chunks.
 3272          */
 3273         while (uio_uio_resid(uiop) > 0 && uio_uio_resid(uiop) != tresid) {
 3274                 dp = (struct dirent *)uio_iov_base(uiop);
 3275                 NFSBZERO(dp, DIRBLKSIZ);
 3276                 dp->d_type = DT_UNKNOWN;
 3277                 tl = (u_int32_t *)&dp->d_name[4];
 3278                 *tl++ = cookie.lval[0];
 3279                 *tl = cookie.lval[1];
 3280                 dp->d_reclen = DIRBLKSIZ;
 3281                 uio_iov_base_add(uiop, DIRBLKSIZ);
 3282                 uio_iov_len_add(uiop, -(DIRBLKSIZ));
 3283                 uio_uio_resid_add(uiop, -(DIRBLKSIZ));
 3284                 uiop->uio_offset += DIRBLKSIZ;
 3285         }
 3286 
 3287 nfsmout:
 3288         if (nd->nd_mrep != NULL)
 3289                 mbuf_freem(nd->nd_mrep);
 3290         return (error);
 3291 }
 3292 
 3293 #ifndef APPLE
 3294 /*
 3295  * NFS V3 readdir plus RPC. Used in place of nfsrpc_readdir().
 3296  * (Also used for NFS V4 when mount flag set.)
 3297  * (ditto above w.r.t. multiple of DIRBLKSIZ, etc.)
 3298  */
 3299 int
 3300 nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
 3301     struct ucred *cred, NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp,
 3302     int *eofp, void *stuff)
 3303 {
 3304         int len, left;
 3305         struct dirent *dp = NULL;
 3306         u_int32_t *tl;
 3307         vnode_t newvp = NULLVP;
 3308         struct nfsrv_descript nfsd, *nd = &nfsd;
 3309         struct nameidata nami, *ndp = &nami;
 3310         struct componentname *cnp = &ndp->ni_cnd;
 3311         struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
 3312         struct nfsnode *dnp = VTONFS(vp), *np;
 3313         struct nfsvattr nfsva;
 3314         struct nfsfh *nfhp;
 3315         nfsquad_t cookie, ncookie;
 3316         int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1;
 3317         int attrflag, tryformoredirs = 1, eof = 0, gotmnton = 0;
 3318         int isdotdot = 0, unlocknewvp = 0;
 3319         u_int64_t dotfileid, dotdotfileid = 0, fakefileno = UINT64_MAX;
 3320         u_int64_t fileno = 0;
 3321         char *cp;
 3322         nfsattrbit_t attrbits, dattrbits;
 3323         size_t tresid;
 3324         u_int32_t *tl2 = NULL, rderr;
 3325         struct timespec dctime, ts;
 3326         bool attr_ok;
 3327 
 3328         KASSERT(uiop->uio_iovcnt == 1 &&
 3329             (uio_uio_resid(uiop) & (DIRBLKSIZ - 1)) == 0,
 3330             ("nfs readdirplusrpc bad uio"));
 3331         ncookie.lval[0] = ncookie.lval[1] = 0;
 3332         timespecclear(&dctime);
 3333         *attrflagp = 0;
 3334         if (eofp != NULL)
 3335                 *eofp = 0;
 3336         ndp->ni_dvp = vp;
 3337         nd->nd_mrep = NULL;
 3338         cookie.lval[0] = cookiep->nfsuquad[0];
 3339         cookie.lval[1] = cookiep->nfsuquad[1];
 3340         tresid = uio_uio_resid(uiop);
 3341 
 3342         /*
 3343          * For NFSv4, first create the "." and ".." entries.
 3344          */
 3345         if (NFSHASNFSV4(nmp)) {
 3346                 NFSGETATTR_ATTRBIT(&dattrbits);
 3347                 NFSZERO_ATTRBIT(&attrbits);
 3348                 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_FILEID);
 3349                 if (NFSISSET_ATTRBIT(&dnp->n_vattr.na_suppattr,
 3350                     NFSATTRBIT_MOUNTEDONFILEID)) {
 3351                         NFSSETBIT_ATTRBIT(&attrbits,
 3352                             NFSATTRBIT_MOUNTEDONFILEID);
 3353                         gotmnton = 1;
 3354                 } else {
 3355                         /*
 3356                          * Must fake it. Use the fileno, except when the
 3357                          * fsid is != to that of the directory. For that
 3358                          * case, generate a fake fileno that is not the same.
 3359                          */
 3360                         NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_FSID);
 3361                         gotmnton = 0;
 3362                 }
 3363 
 3364                 /*
 3365                  * Joy, oh joy. For V4 we get to hand craft '.' and '..'.
 3366                  */
 3367                 if (uiop->uio_offset == 0) {
 3368                         NFSCL_REQSTART(nd, NFSPROC_LOOKUPP, vp);
 3369                         NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 3370                         *tl++ = txdr_unsigned(NFSV4OP_GETFH);
 3371                         *tl = txdr_unsigned(NFSV4OP_GETATTR);
 3372                         (void) nfsrv_putattrbit(nd, &attrbits);
 3373                         error = nfscl_request(nd, vp, p, cred, stuff);
 3374                         if (error)
 3375                             return (error);
 3376                         dotfileid = 0;  /* Fake out the compiler. */
 3377                         if ((nd->nd_flag & ND_NOMOREDATA) == 0) {
 3378                             error = nfsm_loadattr(nd, &nfsva);
 3379                             if (error != 0)
 3380                                 goto nfsmout;
 3381                             dctime = nfsva.na_ctime;
 3382                             dotfileid = nfsva.na_fileid;
 3383                         }
 3384                         if (nd->nd_repstat == 0) {
 3385                             NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
 3386                             len = fxdr_unsigned(int, *(tl + 4));
 3387                             if (len > 0 && len <= NFSX_V4FHMAX)
 3388                                 error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
 3389                             else
 3390                                 error = EPERM;
 3391                             if (!error) {
 3392                                 NFSM_DISSECT(tl, u_int32_t *, 2*NFSX_UNSIGNED);
 3393                                 nfsva.na_mntonfileno = UINT64_MAX;
 3394                                 error = nfsv4_loadattr(nd, NULL, &nfsva, NULL,
 3395                                     NULL, 0, NULL, NULL, NULL, NULL, NULL, 0,
 3396                                     NULL, NULL, NULL, p, cred);
 3397                                 if (error) {
 3398                                     dotdotfileid = dotfileid;
 3399                                 } else if (gotmnton) {
 3400                                     if (nfsva.na_mntonfileno != UINT64_MAX)
 3401                                         dotdotfileid = nfsva.na_mntonfileno;
 3402                                     else
 3403                                         dotdotfileid = nfsva.na_fileid;
 3404                                 } else if (nfsva.na_filesid[0] ==
 3405                                     dnp->n_vattr.na_filesid[0] &&
 3406                                     nfsva.na_filesid[1] ==
 3407                                     dnp->n_vattr.na_filesid[1]) {
 3408                                     dotdotfileid = nfsva.na_fileid;
 3409                                 } else {
 3410                                     do {
 3411                                         fakefileno--;
 3412                                     } while (fakefileno ==
 3413                                         nfsva.na_fileid);
 3414                                     dotdotfileid = fakefileno;
 3415                                 }
 3416                             }
 3417                         } else if (nd->nd_repstat == NFSERR_NOENT) {
 3418                             /*
 3419                              * Lookupp returns NFSERR_NOENT when we are
 3420                              * at the root, so just use the current dir.
 3421                              */
 3422                             nd->nd_repstat = 0;
 3423                             dotdotfileid = dotfileid;
 3424                         } else {
 3425                             error = nd->nd_repstat;
 3426                         }
 3427                         mbuf_freem(nd->nd_mrep);
 3428                         if (error)
 3429                             return (error);
 3430                         nd->nd_mrep = NULL;
 3431                         dp = (struct dirent *)uio_iov_base(uiop);
 3432                         dp->d_pad0 = dp->d_pad1 = 0;
 3433                         dp->d_off = 0;
 3434                         dp->d_type = DT_DIR;
 3435                         dp->d_fileno = dotfileid;
 3436                         dp->d_namlen = 1;
 3437                         *((uint64_t *)dp->d_name) = 0;  /* Zero pad it. */
 3438                         dp->d_name[0] = '.';
 3439                         dp->d_reclen = _GENERIC_DIRSIZ(dp) + NFSX_HYPER;
 3440                         /*
 3441                          * Just make these offset cookie 0.
 3442                          */
 3443                         tl = (u_int32_t *)&dp->d_name[8];
 3444                         *tl++ = 0;
 3445                         *tl = 0;
 3446                         blksiz += dp->d_reclen;
 3447                         uio_uio_resid_add(uiop, -(dp->d_reclen));
 3448                         uiop->uio_offset += dp->d_reclen;
 3449                         uio_iov_base_add(uiop, dp->d_reclen);
 3450                         uio_iov_len_add(uiop, -(dp->d_reclen));
 3451                         dp = (struct dirent *)uio_iov_base(uiop);
 3452                         dp->d_pad0 = dp->d_pad1 = 0;
 3453                         dp->d_off = 0;
 3454                         dp->d_type = DT_DIR;
 3455                         dp->d_fileno = dotdotfileid;
 3456                         dp->d_namlen = 2;
 3457                         *((uint64_t *)dp->d_name) = 0;
 3458                         dp->d_name[0] = '.';
 3459                         dp->d_name[1] = '.';
 3460                         dp->d_reclen = _GENERIC_DIRSIZ(dp) + NFSX_HYPER;
 3461                         /*
 3462                          * Just make these offset cookie 0.
 3463                          */
 3464                         tl = (u_int32_t *)&dp->d_name[8];
 3465                         *tl++ = 0;
 3466                         *tl = 0;
 3467                         blksiz += dp->d_reclen;
 3468                         uio_uio_resid_add(uiop, -(dp->d_reclen));
 3469                         uiop->uio_offset += dp->d_reclen;
 3470                         uio_iov_base_add(uiop, dp->d_reclen);
 3471                         uio_iov_len_add(uiop, -(dp->d_reclen));
 3472                 }
 3473                 NFSREADDIRPLUS_ATTRBIT(&attrbits);
 3474                 if (gotmnton)
 3475                         NFSSETBIT_ATTRBIT(&attrbits,
 3476                             NFSATTRBIT_MOUNTEDONFILEID);
 3477         }
 3478 
 3479         /*
 3480          * Loop around doing readdir rpc's of size nm_readdirsize.
 3481          * The stopping criteria is EOF or buffer full.
 3482          */
 3483         while (more_dirs && bigenough) {
 3484                 *attrflagp = 0;
 3485                 NFSCL_REQSTART(nd, NFSPROC_READDIRPLUS, vp);
 3486                 NFSM_BUILD(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
 3487                 *tl++ = cookie.lval[0];
 3488                 *tl++ = cookie.lval[1];
 3489                 if (cookie.qval == 0) {
 3490                         *tl++ = 0;
 3491                         *tl++ = 0;
 3492                 } else {
 3493                         NFSLOCKNODE(dnp);
 3494                         *tl++ = dnp->n_cookieverf.nfsuquad[0];
 3495                         *tl++ = dnp->n_cookieverf.nfsuquad[1];
 3496                         NFSUNLOCKNODE(dnp);
 3497                 }
 3498                 *tl++ = txdr_unsigned(nmp->nm_readdirsize);
 3499                 *tl = txdr_unsigned(nmp->nm_readdirsize);
 3500                 if (nd->nd_flag & ND_NFSV4) {
 3501                         (void) nfsrv_putattrbit(nd, &attrbits);
 3502                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 3503                         *tl = txdr_unsigned(NFSV4OP_GETATTR);
 3504                         (void) nfsrv_putattrbit(nd, &dattrbits);
 3505                 }
 3506                 nanouptime(&ts);
 3507                 error = nfscl_request(nd, vp, p, cred, stuff);
 3508                 if (error)
 3509                         return (error);
 3510                 if (nd->nd_flag & ND_NFSV3)
 3511                         error = nfscl_postop_attr(nd, nap, attrflagp, stuff);
 3512                 if (nd->nd_repstat || error) {
 3513                         if (!error)
 3514                                 error = nd->nd_repstat;
 3515                         goto nfsmout;
 3516                 }
 3517                 if ((nd->nd_flag & ND_NFSV3) != 0 && *attrflagp != 0)
 3518                         dctime = nap->na_ctime;
 3519                 NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
 3520                 NFSLOCKNODE(dnp);
 3521                 dnp->n_cookieverf.nfsuquad[0] = *tl++;
 3522                 dnp->n_cookieverf.nfsuquad[1] = *tl++;
 3523                 NFSUNLOCKNODE(dnp);
 3524                 more_dirs = fxdr_unsigned(int, *tl);
 3525                 if (!more_dirs)
 3526                         tryformoredirs = 0;
 3527         
 3528                 /* loop through the dir entries, doctoring them to 4bsd form */
 3529                 while (more_dirs && bigenough) {
 3530                         NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
 3531                         if (nd->nd_flag & ND_NFSV4) {
 3532                                 ncookie.lval[0] = *tl++;
 3533                                 ncookie.lval[1] = *tl++;
 3534                         } else {
 3535                                 fileno = fxdr_hyper(tl);
 3536                                 tl += 2;
 3537                         }
 3538                         len = fxdr_unsigned(int, *tl);
 3539                         if (len <= 0 || len > NFS_MAXNAMLEN) {
 3540                                 error = EBADRPC;
 3541                                 goto nfsmout;
 3542                         }
 3543                         tlen = roundup2(len, 8);
 3544                         if (tlen == len)
 3545                                 tlen += 8;  /* To ensure null termination. */
 3546                         left = DIRBLKSIZ - blksiz;
 3547                         if (_GENERIC_DIRLEN(len) + NFSX_HYPER > left) {
 3548                                 NFSBZERO(uio_iov_base(uiop), left);
 3549                                 dp->d_reclen += left;
 3550                                 uio_iov_base_add(uiop, left);
 3551                                 uio_iov_len_add(uiop, -(left));
 3552                                 uio_uio_resid_add(uiop, -(left));
 3553                                 uiop->uio_offset += left;
 3554                                 blksiz = 0;
 3555                         }
 3556                         if (_GENERIC_DIRLEN(len) + NFSX_HYPER >
 3557                             uio_uio_resid(uiop))
 3558                                 bigenough = 0;
 3559                         if (bigenough) {
 3560                                 dp = (struct dirent *)uio_iov_base(uiop);
 3561                                 dp->d_pad0 = dp->d_pad1 = 0;
 3562                                 dp->d_off = 0;
 3563                                 dp->d_namlen = len;
 3564                                 dp->d_reclen = _GENERIC_DIRLEN(len) +
 3565                                     NFSX_HYPER;
 3566                                 dp->d_type = DT_UNKNOWN;
 3567                                 blksiz += dp->d_reclen;
 3568                                 if (blksiz == DIRBLKSIZ)
 3569                                         blksiz = 0;
 3570                                 uio_uio_resid_add(uiop, -(DIRHDSIZ));
 3571                                 uiop->uio_offset += DIRHDSIZ;
 3572                                 uio_iov_base_add(uiop, DIRHDSIZ);
 3573                                 uio_iov_len_add(uiop, -(DIRHDSIZ));
 3574                                 cnp->cn_nameptr = uio_iov_base(uiop);
 3575                                 cnp->cn_namelen = len;
 3576                                 NFSCNHASHZERO(cnp);
 3577                                 error = nfsm_mbufuio(nd, uiop, len);
 3578                                 if (error)
 3579                                         goto nfsmout;
 3580                                 cp = uio_iov_base(uiop);
 3581                                 tlen -= len;
 3582                                 NFSBZERO(cp, tlen);
 3583                                 cp += tlen;     /* points to cookie storage */
 3584                                 tl2 = (u_int32_t *)cp;
 3585                                 if (len == 2 && cnp->cn_nameptr[0] == '.' &&
 3586                                     cnp->cn_nameptr[1] == '.')
 3587                                         isdotdot = 1;
 3588                                 else
 3589                                         isdotdot = 0;
 3590                                 uio_iov_base_add(uiop, (tlen + NFSX_HYPER));
 3591                                 uio_iov_len_add(uiop, -(tlen + NFSX_HYPER));
 3592                                 uio_uio_resid_add(uiop, -(tlen + NFSX_HYPER));
 3593                                 uiop->uio_offset += (tlen + NFSX_HYPER);
 3594                         } else {
 3595                                 error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
 3596                                 if (error)
 3597                                         goto nfsmout;
 3598                         }
 3599                         nfhp = NULL;
 3600                         if (nd->nd_flag & ND_NFSV3) {
 3601                                 NFSM_DISSECT(tl, u_int32_t *, 3*NFSX_UNSIGNED);
 3602                                 ncookie.lval[0] = *tl++;
 3603                                 ncookie.lval[1] = *tl++;
 3604                                 attrflag = fxdr_unsigned(int, *tl);
 3605                                 if (attrflag) {
 3606                                   error = nfsm_loadattr(nd, &nfsva);
 3607                                   if (error)
 3608                                         goto nfsmout;
 3609                                 }
 3610                                 NFSM_DISSECT(tl,u_int32_t *,NFSX_UNSIGNED);
 3611                                 if (*tl) {
 3612                                         error = nfsm_getfh(nd, &nfhp);
 3613                                         if (error)
 3614                                             goto nfsmout;
 3615                                 }
 3616                                 if (!attrflag && nfhp != NULL) {
 3617                                         free(nfhp, M_NFSFH);
 3618                                         nfhp = NULL;
 3619                                 }
 3620                         } else {
 3621                                 rderr = 0;
 3622                                 nfsva.na_mntonfileno = 0xffffffff;
 3623                                 error = nfsv4_loadattr(nd, NULL, &nfsva, &nfhp,
 3624                                     NULL, 0, NULL, NULL, NULL, NULL, NULL, 0,
 3625                                     NULL, NULL, &rderr, p, cred);
 3626                                 if (error)
 3627                                         goto nfsmout;
 3628                         }
 3629 
 3630                         if (bigenough) {
 3631                             if (nd->nd_flag & ND_NFSV4) {
 3632                                 if (rderr) {
 3633                                     dp->d_fileno = 0;
 3634                                 } else if (gotmnton) {
 3635                                     if (nfsva.na_mntonfileno != 0xffffffff)
 3636                                         dp->d_fileno = nfsva.na_mntonfileno;
 3637                                     else
 3638                                         dp->d_fileno = nfsva.na_fileid;
 3639                                 } else if (nfsva.na_filesid[0] ==
 3640                                     dnp->n_vattr.na_filesid[0] &&
 3641                                     nfsva.na_filesid[1] ==
 3642                                     dnp->n_vattr.na_filesid[1]) {
 3643                                     dp->d_fileno = nfsva.na_fileid;
 3644                                 } else {
 3645                                     do {
 3646                                         fakefileno--;
 3647                                     } while (fakefileno ==
 3648                                         nfsva.na_fileid);
 3649                                     dp->d_fileno = fakefileno;
 3650                                 }
 3651                             } else {
 3652                                 dp->d_fileno = fileno;
 3653                             }
 3654                             *tl2++ = cookiep->nfsuquad[0] = cookie.lval[0] =
 3655                                 ncookie.lval[0];
 3656                             *tl2 = cookiep->nfsuquad[1] = cookie.lval[1] =
 3657                                 ncookie.lval[1];
 3658 
 3659                             if (nfhp != NULL) {
 3660                                 attr_ok = true;
 3661                                 if (NFSRV_CMPFH(nfhp->nfh_fh, nfhp->nfh_len,
 3662                                     dnp->n_fhp->nfh_fh, dnp->n_fhp->nfh_len)) {
 3663                                     VREF(vp);
 3664                                     newvp = vp;
 3665                                     unlocknewvp = 0;
 3666                                     free(nfhp, M_NFSFH);
 3667                                     np = dnp;
 3668                                 } else if (isdotdot != 0) {
 3669                                     /*
 3670                                      * Skip doing a nfscl_nget() call for "..".
 3671                                      * There's a race between acquiring the nfs
 3672                                      * node here and lookups that look for the
 3673                                      * directory being read (in the parent).
 3674                                      * It would try to get a lock on ".." here,
 3675                                      * owning the lock on the directory being
 3676                                      * read. Lookup will hold the lock on ".."
 3677                                      * and try to acquire the lock on the
 3678                                      * directory being read.
 3679                                      * If the directory is unlocked/relocked,
 3680                                      * then there is a LOR with the buflock
 3681                                      * vp is relocked.
 3682                                      */
 3683                                     free(nfhp, M_NFSFH);
 3684                                 } else {
 3685                                     error = nfscl_nget(vnode_mount(vp), vp,
 3686                                       nfhp, cnp, p, &np, NULL, LK_EXCLUSIVE);
 3687                                     if (!error) {
 3688                                         newvp = NFSTOV(np);
 3689                                         unlocknewvp = 1;
 3690                                         /*
 3691                                          * If n_localmodtime >= time before RPC,
 3692                                          * then a file modification operation,
 3693                                          * such as VOP_SETATTR() of size, has
 3694                                          * occurred while the Lookup RPC and
 3695                                          * acquisition of the vnode happened. As
 3696                                          * such, the attributes might be stale,
 3697                                          * with possibly an incorrect size.
 3698                                          */
 3699                                         NFSLOCKNODE(np);
 3700                                         if (timespecisset(
 3701                                             &np->n_localmodtime) &&
 3702                                             timespeccmp(&np->n_localmodtime,
 3703                                             &ts, >=)) {
 3704                                             NFSCL_DEBUG(4, "nfsrpc_readdirplus:"
 3705                                                 " localmod stale attributes\n");
 3706                                             attr_ok = false;
 3707                                         }
 3708                                         NFSUNLOCKNODE(np);
 3709                                     }
 3710                                 }
 3711                                 nfhp = NULL;
 3712                                 if (newvp != NULLVP) {
 3713                                     if (attr_ok)
 3714                                         error = nfscl_loadattrcache(&newvp,
 3715                                             &nfsva, NULL, NULL, 0, 0);
 3716                                     if (error) {
 3717                                         if (unlocknewvp)
 3718                                             vput(newvp);
 3719                                         else
 3720                                             vrele(newvp);
 3721                                         goto nfsmout;
 3722                                     }
 3723                                     dp->d_type =
 3724                                         vtonfs_dtype(np->n_vattr.na_type);
 3725                                     ndp->ni_vp = newvp;
 3726                                     NFSCNHASH(cnp, HASHINIT);
 3727                                     if (cnp->cn_namelen <= NCHNAMLEN &&
 3728                                         ndp->ni_dvp != ndp->ni_vp &&
 3729                                         (newvp->v_type != VDIR ||
 3730                                          dctime.tv_sec != 0)) {
 3731                                         cache_enter_time(ndp->ni_dvp,
 3732                                             ndp->ni_vp, cnp,
 3733                                             &nfsva.na_ctime,
 3734                                             newvp->v_type != VDIR ? NULL :
 3735                                             &dctime);
 3736                                     }
 3737                                     if (unlocknewvp)
 3738                                         vput(newvp);
 3739                                     else
 3740                                         vrele(newvp);
 3741                                     newvp = NULLVP;
 3742                                 }
 3743                             }
 3744                         } else if (nfhp != NULL) {
 3745                             free(nfhp, M_NFSFH);
 3746                         }
 3747                         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 3748                         more_dirs = fxdr_unsigned(int, *tl);
 3749                 }
 3750                 /*
 3751                  * If at end of rpc data, get the eof boolean
 3752                  */
 3753                 if (!more_dirs) {
 3754                         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 3755                         eof = fxdr_unsigned(int, *tl);
 3756                         if (tryformoredirs)
 3757                                 more_dirs = !eof;
 3758                         if (nd->nd_flag & ND_NFSV4) {
 3759                                 error = nfscl_postop_attr(nd, nap, attrflagp,
 3760                                     stuff);
 3761                                 if (error)
 3762                                         goto nfsmout;
 3763                         }
 3764                 }
 3765                 mbuf_freem(nd->nd_mrep);
 3766                 nd->nd_mrep = NULL;
 3767         }
 3768         /*
 3769          * Fill last record, iff any, out to a multiple of DIRBLKSIZ
 3770          * by increasing d_reclen for the last record.
 3771          */
 3772         if (blksiz > 0) {
 3773                 left = DIRBLKSIZ - blksiz;
 3774                 NFSBZERO(uio_iov_base(uiop), left);
 3775                 dp->d_reclen += left;
 3776                 uio_iov_base_add(uiop, left);
 3777                 uio_iov_len_add(uiop, -(left));
 3778                 uio_uio_resid_add(uiop, -(left));
 3779                 uiop->uio_offset += left;
 3780         }
 3781 
 3782         /*
 3783          * If returning no data, assume end of file.
 3784          * If not bigenough, return not end of file, since you aren't
 3785          *    returning all the data
 3786          * Otherwise, return the eof flag from the server.
 3787          */
 3788         if (eofp != NULL) {
 3789                 if (tresid == uio_uio_resid(uiop))
 3790                         *eofp = 1;
 3791                 else if (!bigenough)
 3792                         *eofp = 0;
 3793                 else
 3794                         *eofp = eof;
 3795         }
 3796 
 3797         /*
 3798          * Add extra empty records to any remaining DIRBLKSIZ chunks.
 3799          */
 3800         while (uio_uio_resid(uiop) > 0 && uio_uio_resid(uiop) != tresid) {
 3801                 dp = (struct dirent *)uio_iov_base(uiop);
 3802                 NFSBZERO(dp, DIRBLKSIZ);
 3803                 dp->d_type = DT_UNKNOWN;
 3804                 tl = (u_int32_t *)&dp->d_name[4];
 3805                 *tl++ = cookie.lval[0];
 3806                 *tl = cookie.lval[1];
 3807                 dp->d_reclen = DIRBLKSIZ;
 3808                 uio_iov_base_add(uiop, DIRBLKSIZ);
 3809                 uio_iov_len_add(uiop, -(DIRBLKSIZ));
 3810                 uio_uio_resid_add(uiop, -(DIRBLKSIZ));
 3811                 uiop->uio_offset += DIRBLKSIZ;
 3812         }
 3813 
 3814 nfsmout:
 3815         if (nd->nd_mrep != NULL)
 3816                 mbuf_freem(nd->nd_mrep);
 3817         return (error);
 3818 }
 3819 #endif  /* !APPLE */
 3820 
 3821 /*
 3822  * Nfs commit rpc
 3823  */
 3824 int
 3825 nfsrpc_commit(vnode_t vp, u_quad_t offset, int cnt, struct ucred *cred,
 3826     NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp, void *stuff)
 3827 {
 3828         u_int32_t *tl;
 3829         struct nfsrv_descript nfsd, *nd = &nfsd;
 3830         nfsattrbit_t attrbits;
 3831         int error;
 3832         struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
 3833         
 3834         *attrflagp = 0;
 3835         NFSCL_REQSTART(nd, NFSPROC_COMMIT, vp);
 3836         NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
 3837         txdr_hyper(offset, tl);
 3838         tl += 2;
 3839         *tl = txdr_unsigned(cnt);
 3840         if (nd->nd_flag & ND_NFSV4) {
 3841                 /*
 3842                  * And do a Getattr op.
 3843                  */
 3844                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 3845                 *tl = txdr_unsigned(NFSV4OP_GETATTR);
 3846                 NFSGETATTR_ATTRBIT(&attrbits);
 3847                 (void) nfsrv_putattrbit(nd, &attrbits);
 3848         }
 3849         error = nfscl_request(nd, vp, p, cred, stuff);
 3850         if (error)
 3851                 return (error);
 3852         error = nfscl_wcc_data(nd, vp, nap, attrflagp, NULL, stuff);
 3853         if (!error && !nd->nd_repstat) {
 3854                 NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF);
 3855                 NFSLOCKMNT(nmp);
 3856                 if (NFSBCMP(nmp->nm_verf, tl, NFSX_VERF)) {
 3857                         NFSBCOPY(tl, nmp->nm_verf, NFSX_VERF);
 3858                         nd->nd_repstat = NFSERR_STALEWRITEVERF;
 3859                 }
 3860                 NFSUNLOCKMNT(nmp);
 3861                 if (nd->nd_flag & ND_NFSV4)
 3862                         error = nfscl_postop_attr(nd, nap, attrflagp, stuff);
 3863         }
 3864 nfsmout:
 3865         if (!error && nd->nd_repstat)
 3866                 error = nd->nd_repstat;
 3867         mbuf_freem(nd->nd_mrep);
 3868         return (error);
 3869 }
 3870 
 3871 /*
 3872  * NFS byte range lock rpc.
 3873  * (Mostly just calls one of the three lower level RPC routines.)
 3874  */
 3875 int
 3876 nfsrpc_advlock(vnode_t vp, off_t size, int op, struct flock *fl,
 3877     int reclaim, struct ucred *cred, NFSPROC_T *p, void *id, int flags)
 3878 {
 3879         struct nfscllockowner *lp;
 3880         struct nfsclclient *clp;
 3881         struct nfsfh *nfhp;
 3882         struct nfsrv_descript nfsd, *nd = &nfsd;
 3883         struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
 3884         u_int64_t off, len;
 3885         off_t start, end;
 3886         u_int32_t clidrev = 0;
 3887         int error = 0, newone = 0, expireret = 0, retrycnt, donelocally;
 3888         int callcnt, dorpc;
 3889 
 3890         /*
 3891          * Convert the flock structure into a start and end and do POSIX
 3892          * bounds checking.
 3893          */
 3894         switch (fl->l_whence) {
 3895         case SEEK_SET:
 3896         case SEEK_CUR:
 3897                 /*
 3898                  * Caller is responsible for adding any necessary offset
 3899                  * when SEEK_CUR is used.
 3900                  */
 3901                 start = fl->l_start;
 3902                 off = fl->l_start;
 3903                 break;
 3904         case SEEK_END:
 3905                 start = size + fl->l_start;
 3906                 off = size + fl->l_start;
 3907                 break;
 3908         default:
 3909                 return (EINVAL);
 3910         }
 3911         if (start < 0)
 3912                 return (EINVAL);
 3913         if (fl->l_len != 0) {
 3914                 end = start + fl->l_len - 1;
 3915                 if (end < start)
 3916                         return (EINVAL);
 3917         }
 3918 
 3919         len = fl->l_len;
 3920         if (len == 0)
 3921                 len = NFS64BITSSET;
 3922         retrycnt = 0;
 3923         do {
 3924             nd->nd_repstat = 0;
 3925             if (op == F_GETLK) {
 3926                 error = nfscl_getcl(vnode_mount(vp), cred, p, 1, true, &clp);
 3927                 if (error)
 3928                         return (error);
 3929                 error = nfscl_lockt(vp, clp, off, len, fl, p, id, flags);
 3930                 if (!error) {
 3931                         clidrev = clp->nfsc_clientidrev;
 3932                         error = nfsrpc_lockt(nd, vp, clp, off, len, fl, cred,
 3933                             p, id, flags);
 3934                 } else if (error == -1) {
 3935                         error = 0;
 3936                 }
 3937                 nfscl_clientrelease(clp);
 3938             } else if (op == F_UNLCK && fl->l_type == F_UNLCK) {
 3939                 /*
 3940                  * We must loop around for all lockowner cases.
 3941                  */
 3942                 callcnt = 0;
 3943                 error = nfscl_getcl(vnode_mount(vp), cred, p, 1, true, &clp);
 3944                 if (error)
 3945                         return (error);
 3946                 do {
 3947                     error = nfscl_relbytelock(vp, off, len, cred, p, callcnt,
 3948                         clp, id, flags, &lp, &dorpc);
 3949                     /*
 3950                      * If it returns a NULL lp, we're done.
 3951                      */
 3952                     if (lp == NULL) {
 3953                         if (callcnt == 0)
 3954                             nfscl_clientrelease(clp);
 3955                         else
 3956                             nfscl_releasealllocks(clp, vp, p, id, flags);
 3957                         return (error);
 3958                     }
 3959                     if (nmp->nm_clp != NULL)
 3960                         clidrev = nmp->nm_clp->nfsc_clientidrev;
 3961                     else
 3962                         clidrev = 0;
 3963                     /*
 3964                      * If the server doesn't support Posix lock semantics,
 3965                      * only allow locks on the entire file, since it won't
 3966                      * handle overlapping byte ranges.
 3967                      * There might still be a problem when a lock
 3968                      * upgrade/downgrade (read<->write) occurs, since the
 3969                      * server "might" expect an unlock first?
 3970                      */
 3971                     if (dorpc && (lp->nfsl_open->nfso_posixlock ||
 3972                         (off == 0 && len == NFS64BITSSET))) {
 3973                         /*
 3974                          * Since the lock records will go away, we must
 3975                          * wait for grace and delay here.
 3976                          */
 3977                         do {
 3978                             error = nfsrpc_locku(nd, nmp, lp, off, len,
 3979                                 NFSV4LOCKT_READ, cred, p, 0);
 3980                             if ((nd->nd_repstat == NFSERR_GRACE ||
 3981                                  nd->nd_repstat == NFSERR_DELAY) &&
 3982                                 error == 0)
 3983                                 (void) nfs_catnap(PZERO, (int)nd->nd_repstat,
 3984                                     "nfs_advlock");
 3985                         } while ((nd->nd_repstat == NFSERR_GRACE ||
 3986                             nd->nd_repstat == NFSERR_DELAY) && error == 0);
 3987                     }
 3988                     callcnt++;
 3989                 } while (error == 0 && nd->nd_repstat == 0);
 3990                 nfscl_releasealllocks(clp, vp, p, id, flags);
 3991             } else if (op == F_SETLK) {
 3992                 error = nfscl_getbytelock(vp, off, len, fl->l_type, cred, p,
 3993                     NULL, 0, id, flags, NULL, NULL, &lp, &newone, &donelocally);
 3994                 if (error || donelocally) {
 3995                         return (error);
 3996                 }
 3997                 if (nmp->nm_clp != NULL)
 3998                         clidrev = nmp->nm_clp->nfsc_clientidrev;
 3999                 else
 4000                         clidrev = 0;
 4001                 nfhp = VTONFS(vp)->n_fhp;
 4002                 if (!lp->nfsl_open->nfso_posixlock &&
 4003                     (off != 0 || len != NFS64BITSSET)) {
 4004                         error = EINVAL;
 4005                 } else {
 4006                         error = nfsrpc_lock(nd, nmp, vp, nfhp->nfh_fh,
 4007                             nfhp->nfh_len, lp, newone, reclaim, off,
 4008                             len, fl->l_type, cred, p, 0);
 4009                 }
 4010                 if (!error)
 4011                         error = nd->nd_repstat;
 4012                 nfscl_lockrelease(lp, error, newone);
 4013             } else {
 4014                 error = EINVAL;
 4015             }
 4016             if (!error)
 4017                 error = nd->nd_repstat;
 4018             if (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
 4019                 error == NFSERR_STALEDONTRECOVER ||
 4020                 error == NFSERR_STALECLIENTID || error == NFSERR_DELAY ||
 4021                 error == NFSERR_BADSESSION) {
 4022                 (void) nfs_catnap(PZERO, error, "nfs_advlock");
 4023             } else if ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID)
 4024                 && clidrev != 0) {
 4025                 expireret = nfscl_hasexpired(nmp->nm_clp, clidrev, p);
 4026                 retrycnt++;
 4027             }
 4028         } while (error == NFSERR_GRACE ||
 4029             error == NFSERR_STALECLIENTID || error == NFSERR_DELAY ||
 4030             error == NFSERR_STALEDONTRECOVER || error == NFSERR_STALESTATEID ||
 4031             error == NFSERR_BADSESSION ||
 4032             ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) &&
 4033              expireret == 0 && clidrev != 0 && retrycnt < 4));
 4034         if (error && retrycnt >= 4)
 4035                 error = EIO;
 4036         return (error);
 4037 }
 4038 
 4039 /*
 4040  * The lower level routine for the LockT case.
 4041  */
 4042 int
 4043 nfsrpc_lockt(struct nfsrv_descript *nd, vnode_t vp,
 4044     struct nfsclclient *clp, u_int64_t off, u_int64_t len, struct flock *fl,
 4045     struct ucred *cred, NFSPROC_T *p, void *id, int flags)
 4046 {
 4047         u_int32_t *tl;
 4048         int error, type, size;
 4049         uint8_t own[NFSV4CL_LOCKNAMELEN + NFSX_V4FHMAX];
 4050         struct nfsnode *np;
 4051         struct nfsmount *nmp;
 4052         struct nfsclsession *tsep;
 4053 
 4054         nmp = VFSTONFS(vp->v_mount);
 4055         NFSCL_REQSTART(nd, NFSPROC_LOCKT, vp);
 4056         NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
 4057         if (fl->l_type == F_RDLCK)
 4058                 *tl++ = txdr_unsigned(NFSV4LOCKT_READ);
 4059         else
 4060                 *tl++ = txdr_unsigned(NFSV4LOCKT_WRITE);
 4061         txdr_hyper(off, tl);
 4062         tl += 2;
 4063         txdr_hyper(len, tl);
 4064         tl += 2;
 4065         tsep = nfsmnt_mdssession(nmp);
 4066         *tl++ = tsep->nfsess_clientid.lval[0];
 4067         *tl = tsep->nfsess_clientid.lval[1];
 4068         nfscl_filllockowner(id, own, flags);
 4069         np = VTONFS(vp);
 4070         NFSBCOPY(np->n_fhp->nfh_fh, &own[NFSV4CL_LOCKNAMELEN],
 4071             np->n_fhp->nfh_len);
 4072         (void)nfsm_strtom(nd, own, NFSV4CL_LOCKNAMELEN + np->n_fhp->nfh_len);
 4073         error = nfscl_request(nd, vp, p, cred, NULL);
 4074         if (error)
 4075                 return (error);
 4076         if (nd->nd_repstat == 0) {
 4077                 fl->l_type = F_UNLCK;
 4078         } else if (nd->nd_repstat == NFSERR_DENIED) {
 4079                 nd->nd_repstat = 0;
 4080                 fl->l_whence = SEEK_SET;
 4081                 NFSM_DISSECT(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
 4082                 fl->l_start = fxdr_hyper(tl);
 4083                 tl += 2;
 4084                 len = fxdr_hyper(tl);
 4085                 tl += 2;
 4086                 if (len == NFS64BITSSET)
 4087                         fl->l_len = 0;
 4088                 else
 4089                         fl->l_len = len;
 4090                 type = fxdr_unsigned(int, *tl++);
 4091                 if (type == NFSV4LOCKT_WRITE)
 4092                         fl->l_type = F_WRLCK;
 4093                 else
 4094                         fl->l_type = F_RDLCK;
 4095                 /*
 4096                  * XXX For now, I have no idea what to do with the
 4097                  * conflicting lock_owner, so I'll just set the pid == 0
 4098                  * and skip over the lock_owner.
 4099                  */
 4100                 fl->l_pid = (pid_t)0;
 4101                 tl += 2;
 4102                 size = fxdr_unsigned(int, *tl);
 4103                 if (size < 0 || size > NFSV4_OPAQUELIMIT)
 4104                         error = EBADRPC;
 4105                 if (!error)
 4106                         error = nfsm_advance(nd, NFSM_RNDUP(size), -1);
 4107         } else if (nd->nd_repstat == NFSERR_STALECLIENTID)
 4108                 nfscl_initiate_recovery(clp);
 4109 nfsmout:
 4110         mbuf_freem(nd->nd_mrep);
 4111         return (error);
 4112 }
 4113 
 4114 /*
 4115  * Lower level function that performs the LockU RPC.
 4116  */
 4117 static int
 4118 nfsrpc_locku(struct nfsrv_descript *nd, struct nfsmount *nmp,
 4119     struct nfscllockowner *lp, u_int64_t off, u_int64_t len,
 4120     u_int32_t type, struct ucred *cred, NFSPROC_T *p, int syscred)
 4121 {
 4122         u_int32_t *tl;
 4123         int error;
 4124 
 4125         nfscl_reqstart(nd, NFSPROC_LOCKU, nmp, lp->nfsl_open->nfso_fh,
 4126             lp->nfsl_open->nfso_fhlen, NULL, NULL, 0, 0);
 4127         NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID + 6 * NFSX_UNSIGNED);
 4128         *tl++ = txdr_unsigned(type);
 4129         *tl = txdr_unsigned(lp->nfsl_seqid);
 4130         if (nfstest_outofseq &&
 4131             (arc4random() % nfstest_outofseq) == 0)
 4132                 *tl = txdr_unsigned(lp->nfsl_seqid + 1);
 4133         tl++;
 4134         if (NFSHASNFSV4N(nmp))
 4135                 *tl++ = 0;
 4136         else
 4137                 *tl++ = lp->nfsl_stateid.seqid;
 4138         *tl++ = lp->nfsl_stateid.other[0];
 4139         *tl++ = lp->nfsl_stateid.other[1];
 4140         *tl++ = lp->nfsl_stateid.other[2];
 4141         txdr_hyper(off, tl);
 4142         tl += 2;
 4143         txdr_hyper(len, tl);
 4144         if (syscred)
 4145                 nd->nd_flag |= ND_USEGSSNAME;
 4146         error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 4147             NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 4148         NFSCL_INCRSEQID(lp->nfsl_seqid, nd);
 4149         if (error)
 4150                 return (error);
 4151         if (nd->nd_repstat == 0) {
 4152                 NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID);
 4153                 lp->nfsl_stateid.seqid = *tl++;
 4154                 lp->nfsl_stateid.other[0] = *tl++;
 4155                 lp->nfsl_stateid.other[1] = *tl++;
 4156                 lp->nfsl_stateid.other[2] = *tl;
 4157         } else if (nd->nd_repstat == NFSERR_STALESTATEID)
 4158                 nfscl_initiate_recovery(lp->nfsl_open->nfso_own->nfsow_clp);
 4159 nfsmout:
 4160         mbuf_freem(nd->nd_mrep);
 4161         return (error);
 4162 }
 4163 
 4164 /*
 4165  * The actual Lock RPC.
 4166  */
 4167 int
 4168 nfsrpc_lock(struct nfsrv_descript *nd, struct nfsmount *nmp, vnode_t vp,
 4169     u_int8_t *nfhp, int fhlen, struct nfscllockowner *lp, int newone,
 4170     int reclaim, u_int64_t off, u_int64_t len, short type, struct ucred *cred,
 4171     NFSPROC_T *p, int syscred)
 4172 {
 4173         u_int32_t *tl;
 4174         int error, size;
 4175         uint8_t own[NFSV4CL_LOCKNAMELEN + NFSX_V4FHMAX];
 4176         struct nfsclsession *tsep;
 4177 
 4178         nfscl_reqstart(nd, NFSPROC_LOCK, nmp, nfhp, fhlen, NULL, NULL, 0, 0);
 4179         NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
 4180         if (type == F_RDLCK)
 4181                 *tl++ = txdr_unsigned(NFSV4LOCKT_READ);
 4182         else
 4183                 *tl++ = txdr_unsigned(NFSV4LOCKT_WRITE);
 4184         *tl++ = txdr_unsigned(reclaim);
 4185         txdr_hyper(off, tl);
 4186         tl += 2;
 4187         txdr_hyper(len, tl);
 4188         tl += 2;
 4189         if (newone) {
 4190             *tl = newnfs_true;
 4191             NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID +
 4192                 2 * NFSX_UNSIGNED + NFSX_HYPER);
 4193             *tl++ = txdr_unsigned(lp->nfsl_open->nfso_own->nfsow_seqid);
 4194             if (NFSHASNFSV4N(nmp))
 4195                 *tl++ = 0;
 4196             else
 4197                 *tl++ = lp->nfsl_open->nfso_stateid.seqid;
 4198             *tl++ = lp->nfsl_open->nfso_stateid.other[0];
 4199             *tl++ = lp->nfsl_open->nfso_stateid.other[1];
 4200             *tl++ = lp->nfsl_open->nfso_stateid.other[2];
 4201             *tl++ = txdr_unsigned(lp->nfsl_seqid);
 4202             tsep = nfsmnt_mdssession(nmp);
 4203             *tl++ = tsep->nfsess_clientid.lval[0];
 4204             *tl = tsep->nfsess_clientid.lval[1];
 4205             NFSBCOPY(lp->nfsl_owner, own, NFSV4CL_LOCKNAMELEN);
 4206             NFSBCOPY(nfhp, &own[NFSV4CL_LOCKNAMELEN], fhlen);
 4207             (void)nfsm_strtom(nd, own, NFSV4CL_LOCKNAMELEN + fhlen);
 4208         } else {
 4209             *tl = newnfs_false;
 4210             NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID + NFSX_UNSIGNED);
 4211             if (NFSHASNFSV4N(nmp))
 4212                 *tl++ = 0;
 4213             else
 4214                 *tl++ = lp->nfsl_stateid.seqid;
 4215             *tl++ = lp->nfsl_stateid.other[0];
 4216             *tl++ = lp->nfsl_stateid.other[1];
 4217             *tl++ = lp->nfsl_stateid.other[2];
 4218             *tl = txdr_unsigned(lp->nfsl_seqid);
 4219             if (nfstest_outofseq &&
 4220                 (arc4random() % nfstest_outofseq) == 0)
 4221                     *tl = txdr_unsigned(lp->nfsl_seqid + 1);
 4222         }
 4223         if (syscred)
 4224                 nd->nd_flag |= ND_USEGSSNAME;
 4225         error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, vp, p, cred,
 4226             NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 4227         if (error)
 4228                 return (error);
 4229         if (newone)
 4230             NFSCL_INCRSEQID(lp->nfsl_open->nfso_own->nfsow_seqid, nd);
 4231         NFSCL_INCRSEQID(lp->nfsl_seqid, nd);
 4232         if (nd->nd_repstat == 0) {
 4233                 NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID);
 4234                 lp->nfsl_stateid.seqid = *tl++;
 4235                 lp->nfsl_stateid.other[0] = *tl++;
 4236                 lp->nfsl_stateid.other[1] = *tl++;
 4237                 lp->nfsl_stateid.other[2] = *tl;
 4238         } else if (nd->nd_repstat == NFSERR_DENIED) {
 4239                 NFSM_DISSECT(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
 4240                 size = fxdr_unsigned(int, *(tl + 7));
 4241                 if (size < 0 || size > NFSV4_OPAQUELIMIT)
 4242                         error = EBADRPC;
 4243                 if (!error)
 4244                         error = nfsm_advance(nd, NFSM_RNDUP(size), -1);
 4245         } else if (nd->nd_repstat == NFSERR_STALESTATEID)
 4246                 nfscl_initiate_recovery(lp->nfsl_open->nfso_own->nfsow_clp);
 4247 nfsmout:
 4248         mbuf_freem(nd->nd_mrep);
 4249         return (error);
 4250 }
 4251 
 4252 /*
 4253  * nfs statfs rpc
 4254  * (always called with the vp for the mount point)
 4255  */
 4256 int
 4257 nfsrpc_statfs(vnode_t vp, struct nfsstatfs *sbp, struct nfsfsinfo *fsp,
 4258     struct ucred *cred, NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp,
 4259     void *stuff)
 4260 {
 4261         u_int32_t *tl = NULL;
 4262         struct nfsrv_descript nfsd, *nd = &nfsd;
 4263         struct nfsmount *nmp;
 4264         nfsattrbit_t attrbits;
 4265         int error;
 4266 
 4267         *attrflagp = 0;
 4268         nmp = VFSTONFS(vnode_mount(vp));
 4269         if (NFSHASNFSV4(nmp)) {
 4270                 /*
 4271                  * For V4, you actually do a getattr.
 4272                  */
 4273                 NFSCL_REQSTART(nd, NFSPROC_GETATTR, vp);
 4274                 NFSSTATFS_GETATTRBIT(&attrbits);
 4275                 (void) nfsrv_putattrbit(nd, &attrbits);
 4276                 nd->nd_flag |= ND_USEGSSNAME;
 4277                 error = nfscl_request(nd, vp, p, cred, stuff);
 4278                 if (error)
 4279                         return (error);
 4280                 if (nd->nd_repstat == 0) {
 4281                         error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0,
 4282                             NULL, NULL, sbp, fsp, NULL, 0, NULL, NULL, NULL, p,
 4283                             cred);
 4284                         if (!error) {
 4285                                 nmp->nm_fsid[0] = nap->na_filesid[0];
 4286                                 nmp->nm_fsid[1] = nap->na_filesid[1];
 4287                                 NFSSETHASSETFSID(nmp);
 4288                                 *attrflagp = 1;
 4289                         }
 4290                 } else {
 4291                         error = nd->nd_repstat;
 4292                 }
 4293                 if (error)
 4294                         goto nfsmout;
 4295         } else {
 4296                 NFSCL_REQSTART(nd, NFSPROC_FSSTAT, vp);
 4297                 error = nfscl_request(nd, vp, p, cred, stuff);
 4298                 if (error)
 4299                         return (error);
 4300                 if (nd->nd_flag & ND_NFSV3) {
 4301                         error = nfscl_postop_attr(nd, nap, attrflagp, stuff);
 4302                         if (error)
 4303                                 goto nfsmout;
 4304                 }
 4305                 if (nd->nd_repstat) {
 4306                         error = nd->nd_repstat;
 4307                         goto nfsmout;
 4308                 }
 4309                 NFSM_DISSECT(tl, u_int32_t *,
 4310                     NFSX_STATFS(nd->nd_flag & ND_NFSV3));
 4311         }
 4312         if (NFSHASNFSV3(nmp)) {
 4313                 sbp->sf_tbytes = fxdr_hyper(tl); tl += 2;
 4314                 sbp->sf_fbytes = fxdr_hyper(tl); tl += 2;
 4315                 sbp->sf_abytes = fxdr_hyper(tl); tl += 2;
 4316                 sbp->sf_tfiles = fxdr_hyper(tl); tl += 2;
 4317                 sbp->sf_ffiles = fxdr_hyper(tl); tl += 2;
 4318                 sbp->sf_afiles = fxdr_hyper(tl); tl += 2;
 4319                 sbp->sf_invarsec = fxdr_unsigned(u_int32_t, *tl);
 4320         } else if (NFSHASNFSV4(nmp) == 0) {
 4321                 sbp->sf_tsize = fxdr_unsigned(u_int32_t, *tl++);
 4322                 sbp->sf_bsize = fxdr_unsigned(u_int32_t, *tl++);
 4323                 sbp->sf_blocks = fxdr_unsigned(u_int32_t, *tl++);
 4324                 sbp->sf_bfree = fxdr_unsigned(u_int32_t, *tl++);
 4325                 sbp->sf_bavail = fxdr_unsigned(u_int32_t, *tl);
 4326         }
 4327 nfsmout:
 4328         mbuf_freem(nd->nd_mrep);
 4329         return (error);
 4330 }
 4331 
 4332 /*
 4333  * nfs pathconf rpc
 4334  */
 4335 int
 4336 nfsrpc_pathconf(vnode_t vp, struct nfsv3_pathconf *pc,
 4337     struct ucred *cred, NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp,
 4338     void *stuff)
 4339 {
 4340         struct nfsrv_descript nfsd, *nd = &nfsd;
 4341         struct nfsmount *nmp;
 4342         u_int32_t *tl;
 4343         nfsattrbit_t attrbits;
 4344         int error;
 4345 
 4346         *attrflagp = 0;
 4347         nmp = VFSTONFS(vnode_mount(vp));
 4348         if (NFSHASNFSV4(nmp)) {
 4349                 /*
 4350                  * For V4, you actually do a getattr.
 4351                  */
 4352                 NFSCL_REQSTART(nd, NFSPROC_GETATTR, vp);
 4353                 NFSPATHCONF_GETATTRBIT(&attrbits);
 4354                 (void) nfsrv_putattrbit(nd, &attrbits);
 4355                 nd->nd_flag |= ND_USEGSSNAME;
 4356                 error = nfscl_request(nd, vp, p, cred, stuff);
 4357                 if (error)
 4358                         return (error);
 4359                 if (nd->nd_repstat == 0) {
 4360                         error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0,
 4361                             pc, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, p,
 4362                             cred);
 4363                         if (!error)
 4364                                 *attrflagp = 1;
 4365                 } else {
 4366                         error = nd->nd_repstat;
 4367                 }
 4368         } else {
 4369                 NFSCL_REQSTART(nd, NFSPROC_PATHCONF, vp);
 4370                 error = nfscl_request(nd, vp, p, cred, stuff);
 4371                 if (error)
 4372                         return (error);
 4373                 error = nfscl_postop_attr(nd, nap, attrflagp, stuff);
 4374                 if (nd->nd_repstat && !error)
 4375                         error = nd->nd_repstat;
 4376                 if (!error) {
 4377                         NFSM_DISSECT(tl, u_int32_t *, NFSX_V3PATHCONF);
 4378                         pc->pc_linkmax = fxdr_unsigned(u_int32_t, *tl++);
 4379                         pc->pc_namemax = fxdr_unsigned(u_int32_t, *tl++);
 4380                         pc->pc_notrunc = fxdr_unsigned(u_int32_t, *tl++);
 4381                         pc->pc_chownrestricted =
 4382                             fxdr_unsigned(u_int32_t, *tl++);
 4383                         pc->pc_caseinsensitive =
 4384                             fxdr_unsigned(u_int32_t, *tl++);
 4385                         pc->pc_casepreserving = fxdr_unsigned(u_int32_t, *tl);
 4386                 }
 4387         }
 4388 nfsmout:
 4389         mbuf_freem(nd->nd_mrep);
 4390         return (error);
 4391 }
 4392 
 4393 /*
 4394  * nfs version 3 fsinfo rpc call
 4395  */
 4396 int
 4397 nfsrpc_fsinfo(vnode_t vp, struct nfsfsinfo *fsp, struct ucred *cred,
 4398     NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp, void *stuff)
 4399 {
 4400         u_int32_t *tl;
 4401         struct nfsrv_descript nfsd, *nd = &nfsd;
 4402         int error;
 4403 
 4404         *attrflagp = 0;
 4405         NFSCL_REQSTART(nd, NFSPROC_FSINFO, vp);
 4406         error = nfscl_request(nd, vp, p, cred, stuff);
 4407         if (error)
 4408                 return (error);
 4409         error = nfscl_postop_attr(nd, nap, attrflagp, stuff);
 4410         if (nd->nd_repstat && !error)
 4411                 error = nd->nd_repstat;
 4412         if (!error) {
 4413                 NFSM_DISSECT(tl, u_int32_t *, NFSX_V3FSINFO);
 4414                 fsp->fs_rtmax = fxdr_unsigned(u_int32_t, *tl++);
 4415                 fsp->fs_rtpref = fxdr_unsigned(u_int32_t, *tl++);
 4416                 fsp->fs_rtmult = fxdr_unsigned(u_int32_t, *tl++);
 4417                 fsp->fs_wtmax = fxdr_unsigned(u_int32_t, *tl++);
 4418                 fsp->fs_wtpref = fxdr_unsigned(u_int32_t, *tl++);
 4419                 fsp->fs_wtmult = fxdr_unsigned(u_int32_t, *tl++);
 4420                 fsp->fs_dtpref = fxdr_unsigned(u_int32_t, *tl++);
 4421                 fsp->fs_maxfilesize = fxdr_hyper(tl);
 4422                 tl += 2;
 4423                 fxdr_nfsv3time(tl, &fsp->fs_timedelta);
 4424                 tl += 2;
 4425                 fsp->fs_properties = fxdr_unsigned(u_int32_t, *tl);
 4426         }
 4427 nfsmout:
 4428         mbuf_freem(nd->nd_mrep);
 4429         return (error);
 4430 }
 4431 
 4432 /*
 4433  * This function performs the Renew RPC.
 4434  */
 4435 int
 4436 nfsrpc_renew(struct nfsclclient *clp, struct nfsclds *dsp, struct ucred *cred,
 4437     NFSPROC_T *p)
 4438 {
 4439         u_int32_t *tl;
 4440         struct nfsrv_descript nfsd;
 4441         struct nfsrv_descript *nd = &nfsd;
 4442         struct nfsmount *nmp;
 4443         int error;
 4444         struct nfssockreq *nrp;
 4445         struct nfsclsession *tsep;
 4446 
 4447         nmp = clp->nfsc_nmp;
 4448         if (nmp == NULL)
 4449                 return (0);
 4450         if (dsp == NULL)
 4451                 nfscl_reqstart(nd, NFSPROC_RENEW, nmp, NULL, 0, NULL, NULL, 0,
 4452                     0);
 4453         else
 4454                 nfscl_reqstart(nd, NFSPROC_RENEW, nmp, NULL, 0, NULL,
 4455                     &dsp->nfsclds_sess, 0, 0);
 4456         if (!NFSHASNFSV4N(nmp)) {
 4457                 /* NFSv4.1 just uses a Sequence Op and not a Renew. */
 4458                 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 4459                 tsep = nfsmnt_mdssession(nmp);
 4460                 *tl++ = tsep->nfsess_clientid.lval[0];
 4461                 *tl = tsep->nfsess_clientid.lval[1];
 4462         }
 4463         nrp = NULL;
 4464         if (dsp != NULL)
 4465                 nrp = dsp->nfsclds_sockp;
 4466         if (nrp == NULL)
 4467                 /* If NULL, use the MDS socket. */
 4468                 nrp = &nmp->nm_sockreq;
 4469         nd->nd_flag |= ND_USEGSSNAME;
 4470         if (dsp == NULL)
 4471                 error = newnfs_request(nd, nmp, NULL, nrp, NULL, p, cred,
 4472                     NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 4473         else {
 4474                 error = newnfs_request(nd, nmp, NULL, nrp, NULL, p, cred,
 4475                     NFS_PROG, NFS_VER4, NULL, 1, NULL, &dsp->nfsclds_sess);
 4476                 if (error == ENXIO)
 4477                         nfscl_cancelreqs(dsp);
 4478         }
 4479         if (error)
 4480                 return (error);
 4481         error = nd->nd_repstat;
 4482         mbuf_freem(nd->nd_mrep);
 4483         return (error);
 4484 }
 4485 
 4486 /*
 4487  * This function performs the Releaselockowner RPC.
 4488  */
 4489 int
 4490 nfsrpc_rellockown(struct nfsmount *nmp, struct nfscllockowner *lp,
 4491     uint8_t *fh, int fhlen, struct ucred *cred, NFSPROC_T *p)
 4492 {
 4493         struct nfsrv_descript nfsd, *nd = &nfsd;
 4494         u_int32_t *tl;
 4495         int error;
 4496         uint8_t own[NFSV4CL_LOCKNAMELEN + NFSX_V4FHMAX];
 4497         struct nfsclsession *tsep;
 4498 
 4499         if (NFSHASNFSV4N(nmp)) {
 4500                 /* For NFSv4.1, do a FreeStateID. */
 4501                 nfscl_reqstart(nd, NFSPROC_FREESTATEID, nmp, NULL, 0, NULL,
 4502                     NULL, 0, 0);
 4503                 nfsm_stateidtom(nd, &lp->nfsl_stateid, NFSSTATEID_PUTSTATEID);
 4504         } else {
 4505                 nfscl_reqstart(nd, NFSPROC_RELEASELCKOWN, nmp, NULL, 0, NULL,
 4506                     NULL, 0, 0);
 4507                 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 4508                 tsep = nfsmnt_mdssession(nmp);
 4509                 *tl++ = tsep->nfsess_clientid.lval[0];
 4510                 *tl = tsep->nfsess_clientid.lval[1];
 4511                 NFSBCOPY(lp->nfsl_owner, own, NFSV4CL_LOCKNAMELEN);
 4512                 NFSBCOPY(fh, &own[NFSV4CL_LOCKNAMELEN], fhlen);
 4513                 (void)nfsm_strtom(nd, own, NFSV4CL_LOCKNAMELEN + fhlen);
 4514         }
 4515         nd->nd_flag |= ND_USEGSSNAME;
 4516         error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 4517             NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 4518         if (error)
 4519                 return (error);
 4520         error = nd->nd_repstat;
 4521         mbuf_freem(nd->nd_mrep);
 4522         return (error);
 4523 }
 4524 
 4525 /*
 4526  * This function performs the Compound to get the mount pt FH.
 4527  */
 4528 int
 4529 nfsrpc_getdirpath(struct nfsmount *nmp, u_char *dirpath, struct ucred *cred,
 4530     NFSPROC_T *p)
 4531 {
 4532         u_int32_t *tl;
 4533         struct nfsrv_descript nfsd;
 4534         struct nfsrv_descript *nd = &nfsd;
 4535         u_char *cp, *cp2;
 4536         int error, cnt, len, setnil;
 4537         u_int32_t *opcntp;
 4538 
 4539         nfscl_reqstart(nd, NFSPROC_PUTROOTFH, nmp, NULL, 0, &opcntp, NULL, 0,
 4540             0);
 4541         cp = dirpath;
 4542         cnt = 0;
 4543         do {
 4544                 setnil = 0;
 4545                 while (*cp == '/')
 4546                         cp++;
 4547                 cp2 = cp;
 4548                 while (*cp2 != '\0' && *cp2 != '/')
 4549                         cp2++;
 4550                 if (*cp2 == '/') {
 4551                         setnil = 1;
 4552                         *cp2 = '\0';
 4553                 }
 4554                 if (cp2 != cp) {
 4555                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 4556                         *tl = txdr_unsigned(NFSV4OP_LOOKUP);
 4557                         nfsm_strtom(nd, cp, strlen(cp));
 4558                         cnt++;
 4559                 }
 4560                 if (setnil)
 4561                         *cp2++ = '/';
 4562                 cp = cp2;
 4563         } while (*cp != '\0');
 4564         if (NFSHASNFSV4N(nmp))
 4565                 /* Has a Sequence Op done by nfscl_reqstart(). */
 4566                 *opcntp = txdr_unsigned(3 + cnt);
 4567         else
 4568                 *opcntp = txdr_unsigned(2 + cnt);
 4569         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 4570         *tl = txdr_unsigned(NFSV4OP_GETFH);
 4571         nd->nd_flag |= ND_USEGSSNAME;
 4572         error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 4573                 NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 4574         if (error)
 4575                 return (error);
 4576         if (nd->nd_repstat == 0) {
 4577                 NFSM_DISSECT(tl, u_int32_t *, (3 + 2 * cnt) * NFSX_UNSIGNED);
 4578                 tl += (2 + 2 * cnt);
 4579                 if ((len = fxdr_unsigned(int, *tl)) <= 0 ||
 4580                         len > NFSX_FHMAX) {
 4581                         nd->nd_repstat = NFSERR_BADXDR;
 4582                 } else {
 4583                         nd->nd_repstat = nfsrv_mtostr(nd, nmp->nm_fh, len);
 4584                         if (nd->nd_repstat == 0)
 4585                                 nmp->nm_fhsize = len;
 4586                 }
 4587         }
 4588         error = nd->nd_repstat;
 4589 nfsmout:
 4590         mbuf_freem(nd->nd_mrep);
 4591         return (error);
 4592 }
 4593 
 4594 /*
 4595  * This function performs the Delegreturn RPC.
 4596  */
 4597 int
 4598 nfsrpc_delegreturn(struct nfscldeleg *dp, struct ucred *cred,
 4599     struct nfsmount *nmp, NFSPROC_T *p, int syscred)
 4600 {
 4601         u_int32_t *tl;
 4602         struct nfsrv_descript nfsd;
 4603         struct nfsrv_descript *nd = &nfsd;
 4604         int error;
 4605 
 4606         nfscl_reqstart(nd, NFSPROC_DELEGRETURN, nmp, dp->nfsdl_fh,
 4607             dp->nfsdl_fhlen, NULL, NULL, 0, 0);
 4608         NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
 4609         if (NFSHASNFSV4N(nmp))
 4610                 *tl++ = 0;
 4611         else
 4612                 *tl++ = dp->nfsdl_stateid.seqid;
 4613         *tl++ = dp->nfsdl_stateid.other[0];
 4614         *tl++ = dp->nfsdl_stateid.other[1];
 4615         *tl = dp->nfsdl_stateid.other[2];
 4616         if (syscred)
 4617                 nd->nd_flag |= ND_USEGSSNAME;
 4618         error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 4619             NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 4620         if (error)
 4621                 return (error);
 4622         error = nd->nd_repstat;
 4623         mbuf_freem(nd->nd_mrep);
 4624         return (error);
 4625 }
 4626 
 4627 /*
 4628  * nfs getacl call.
 4629  */
 4630 int
 4631 nfsrpc_getacl(vnode_t vp, struct ucred *cred, NFSPROC_T *p,
 4632     struct acl *aclp, void *stuff)
 4633 {
 4634         struct nfsrv_descript nfsd, *nd = &nfsd;
 4635         int error;
 4636         nfsattrbit_t attrbits;
 4637         struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
 4638         
 4639         if (nfsrv_useacl == 0 || !NFSHASNFSV4(nmp))
 4640                 return (EOPNOTSUPP);
 4641         NFSCL_REQSTART(nd, NFSPROC_GETACL, vp);
 4642         NFSZERO_ATTRBIT(&attrbits);
 4643         NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_ACL);
 4644         (void) nfsrv_putattrbit(nd, &attrbits);
 4645         error = nfscl_request(nd, vp, p, cred, stuff);
 4646         if (error)
 4647                 return (error);
 4648         if (!nd->nd_repstat)
 4649                 error = nfsv4_loadattr(nd, vp, NULL, NULL, NULL, 0, NULL,
 4650                     NULL, NULL, NULL, aclp, 0, NULL, NULL, NULL, p, cred);
 4651         else
 4652                 error = nd->nd_repstat;
 4653         mbuf_freem(nd->nd_mrep);
 4654         return (error);
 4655 }
 4656 
 4657 /*
 4658  * nfs setacl call.
 4659  */
 4660 int
 4661 nfsrpc_setacl(vnode_t vp, struct ucred *cred, NFSPROC_T *p,
 4662     struct acl *aclp, void *stuff)
 4663 {
 4664         int error;
 4665         struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
 4666         
 4667         if (nfsrv_useacl == 0 || !NFSHASNFSV4(nmp))
 4668                 return (EOPNOTSUPP);
 4669         error = nfsrpc_setattr(vp, NULL, aclp, cred, p, NULL, NULL, stuff);
 4670         return (error);
 4671 }
 4672 
 4673 /*
 4674  * nfs setacl call.
 4675  */
 4676 static int
 4677 nfsrpc_setaclrpc(vnode_t vp, struct ucred *cred, NFSPROC_T *p,
 4678     struct acl *aclp, nfsv4stateid_t *stateidp, void *stuff)
 4679 {
 4680         struct nfsrv_descript nfsd, *nd = &nfsd;
 4681         int error;
 4682         nfsattrbit_t attrbits;
 4683         struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
 4684         
 4685         if (!NFSHASNFSV4(nmp))
 4686                 return (EOPNOTSUPP);
 4687         NFSCL_REQSTART(nd, NFSPROC_SETACL, vp);
 4688         nfsm_stateidtom(nd, stateidp, NFSSTATEID_PUTSTATEID);
 4689         NFSZERO_ATTRBIT(&attrbits);
 4690         NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_ACL);
 4691         (void) nfsv4_fillattr(nd, vnode_mount(vp), vp, aclp, NULL, NULL, 0,
 4692             &attrbits, NULL, NULL, 0, 0, 0, 0, (uint64_t)0, NULL);
 4693         error = nfscl_request(nd, vp, p, cred, stuff);
 4694         if (error)
 4695                 return (error);
 4696         /* Don't care about the pre/postop attributes */
 4697         mbuf_freem(nd->nd_mrep);
 4698         return (nd->nd_repstat);
 4699 }
 4700 
 4701 /*
 4702  * Do the NFSv4.1 Exchange ID.
 4703  */
 4704 int
 4705 nfsrpc_exchangeid(struct nfsmount *nmp, struct nfsclclient *clp,
 4706     struct nfssockreq *nrp, uint32_t exchflags, struct nfsclds **dspp,
 4707     struct ucred *cred, NFSPROC_T *p)
 4708 {
 4709         uint32_t *tl, v41flags;
 4710         struct nfsrv_descript nfsd;
 4711         struct nfsrv_descript *nd = &nfsd;
 4712         struct nfsclds *dsp;
 4713         struct timespec verstime;
 4714         int error, len;
 4715 
 4716         *dspp = NULL;
 4717         nfscl_reqstart(nd, NFSPROC_EXCHANGEID, nmp, NULL, 0, NULL, NULL, 0, 0);
 4718         NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 4719         *tl++ = txdr_unsigned(nfsboottime.tv_sec);      /* Client owner */
 4720         *tl = txdr_unsigned(clp->nfsc_rev);
 4721         (void) nfsm_strtom(nd, clp->nfsc_id, clp->nfsc_idlen);
 4722 
 4723         NFSM_BUILD(tl, uint32_t *, 3 * NFSX_UNSIGNED);
 4724         *tl++ = txdr_unsigned(exchflags);
 4725         *tl++ = txdr_unsigned(NFSV4EXCH_SP4NONE);
 4726 
 4727         /* Set the implementation id4 */
 4728         *tl = txdr_unsigned(1);
 4729         (void) nfsm_strtom(nd, "freebsd.org", strlen("freebsd.org"));
 4730         (void) nfsm_strtom(nd, version, strlen(version));
 4731         NFSM_BUILD(tl, uint32_t *, NFSX_V4TIME);
 4732         verstime.tv_sec = 1293840000;           /* Jan 1, 2011 */
 4733         verstime.tv_nsec = 0;
 4734         txdr_nfsv4time(&verstime, tl);
 4735         nd->nd_flag |= ND_USEGSSNAME;
 4736         error = newnfs_request(nd, nmp, NULL, nrp, NULL, p, cred,
 4737             NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 4738         NFSCL_DEBUG(1, "exchangeid err=%d reps=%d\n", error,
 4739             (int)nd->nd_repstat);
 4740         if (error != 0)
 4741                 return (error);
 4742         if (nd->nd_repstat == 0) {
 4743                 NFSM_DISSECT(tl, uint32_t *, 6 * NFSX_UNSIGNED + NFSX_HYPER);
 4744                 len = fxdr_unsigned(int, *(tl + 7));
 4745                 if (len < 0 || len > NFSV4_OPAQUELIMIT) {
 4746                         error = NFSERR_BADXDR;
 4747                         goto nfsmout;
 4748                 }
 4749                 dsp = malloc(sizeof(struct nfsclds) + len + 1, M_NFSCLDS,
 4750                     M_WAITOK | M_ZERO);
 4751                 dsp->nfsclds_expire = NFSD_MONOSEC + clp->nfsc_renew;
 4752                 dsp->nfsclds_servownlen = len;
 4753                 dsp->nfsclds_sess.nfsess_clientid.lval[0] = *tl++;
 4754                 dsp->nfsclds_sess.nfsess_clientid.lval[1] = *tl++;
 4755                 dsp->nfsclds_sess.nfsess_sequenceid =
 4756                     fxdr_unsigned(uint32_t, *tl++);
 4757                 v41flags = fxdr_unsigned(uint32_t, *tl);
 4758                 if ((v41flags & NFSV4EXCH_USEPNFSMDS) != 0 &&
 4759                     NFSHASPNFSOPT(nmp)) {
 4760                         NFSCL_DEBUG(1, "set PNFS\n");
 4761                         NFSLOCKMNT(nmp);
 4762                         nmp->nm_state |= NFSSTA_PNFS;
 4763                         NFSUNLOCKMNT(nmp);
 4764                         dsp->nfsclds_flags |= NFSCLDS_MDS;
 4765                 }
 4766                 if ((v41flags & NFSV4EXCH_USEPNFSDS) != 0)
 4767                         dsp->nfsclds_flags |= NFSCLDS_DS;
 4768                 if (len > 0)
 4769                         nd->nd_repstat = nfsrv_mtostr(nd,
 4770                             dsp->nfsclds_serverown, len);
 4771                 if (nd->nd_repstat == 0) {
 4772                         mtx_init(&dsp->nfsclds_mtx, "nfsds", NULL, MTX_DEF);
 4773                         mtx_init(&dsp->nfsclds_sess.nfsess_mtx, "nfssession",
 4774                             NULL, MTX_DEF);
 4775                         nfscl_initsessionslots(&dsp->nfsclds_sess);
 4776                         *dspp = dsp;
 4777                 } else
 4778                         free(dsp, M_NFSCLDS);
 4779         }
 4780         error = nd->nd_repstat;
 4781 nfsmout:
 4782         mbuf_freem(nd->nd_mrep);
 4783         return (error);
 4784 }
 4785 
 4786 /*
 4787  * Do the NFSv4.1 Create Session.
 4788  */
 4789 int
 4790 nfsrpc_createsession(struct nfsmount *nmp, struct nfsclsession *sep,
 4791     struct nfssockreq *nrp, uint32_t sequenceid, int mds, struct ucred *cred,
 4792     NFSPROC_T *p)
 4793 {
 4794         uint32_t crflags, maxval, *tl;
 4795         struct nfsrv_descript nfsd;
 4796         struct nfsrv_descript *nd = &nfsd;
 4797         int error, irdcnt;
 4798 
 4799         /* Make sure nm_rsize, nm_wsize is set. */
 4800         if (nmp->nm_rsize > NFS_MAXBSIZE || nmp->nm_rsize == 0)
 4801                 nmp->nm_rsize = NFS_MAXBSIZE;
 4802         if (nmp->nm_wsize > NFS_MAXBSIZE || nmp->nm_wsize == 0)
 4803                 nmp->nm_wsize = NFS_MAXBSIZE;
 4804         nfscl_reqstart(nd, NFSPROC_CREATESESSION, nmp, NULL, 0, NULL, NULL, 0,
 4805             0);
 4806         NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED);
 4807         *tl++ = sep->nfsess_clientid.lval[0];
 4808         *tl++ = sep->nfsess_clientid.lval[1];
 4809         *tl++ = txdr_unsigned(sequenceid);
 4810         crflags = (NFSMNT_RDONLY(nmp->nm_mountp) ? 0 : NFSV4CRSESS_PERSIST);
 4811         if (nfscl_enablecallb != 0 && nfs_numnfscbd > 0 && mds != 0)
 4812                 crflags |= NFSV4CRSESS_CONNBACKCHAN;
 4813         *tl = txdr_unsigned(crflags);
 4814 
 4815         /* Fill in fore channel attributes. */
 4816         NFSM_BUILD(tl, uint32_t *, 7 * NFSX_UNSIGNED);
 4817         *tl++ = 0;                              /* Header pad size */
 4818         *tl++ = txdr_unsigned(nmp->nm_wsize + NFS_MAXXDR);/* Max request size */
 4819         *tl++ = txdr_unsigned(nmp->nm_rsize + NFS_MAXXDR);/* Max reply size */
 4820         *tl++ = txdr_unsigned(4096);            /* Max response size cached */
 4821         *tl++ = txdr_unsigned(20);              /* Max operations */
 4822         *tl++ = txdr_unsigned(64);              /* Max slots */
 4823         *tl = 0;                                /* No rdma ird */
 4824 
 4825         /* Fill in back channel attributes. */
 4826         NFSM_BUILD(tl, uint32_t *, 7 * NFSX_UNSIGNED);
 4827         *tl++ = 0;                              /* Header pad size */
 4828         *tl++ = txdr_unsigned(10000);           /* Max request size */
 4829         *tl++ = txdr_unsigned(10000);           /* Max response size */
 4830         *tl++ = txdr_unsigned(4096);            /* Max response size cached */
 4831         *tl++ = txdr_unsigned(4);               /* Max operations */
 4832         *tl++ = txdr_unsigned(NFSV4_CBSLOTS);   /* Max slots */
 4833         *tl = 0;                                /* No rdma ird */
 4834 
 4835         NFSM_BUILD(tl, uint32_t *, 8 * NFSX_UNSIGNED);
 4836         *tl++ = txdr_unsigned(NFS_CALLBCKPROG); /* Call back prog # */
 4837 
 4838         /* Allow AUTH_SYS callbacks as uid, gid == 0. */
 4839         *tl++ = txdr_unsigned(1);               /* Auth_sys only */
 4840         *tl++ = txdr_unsigned(AUTH_SYS);        /* AUTH_SYS type */
 4841         *tl++ = txdr_unsigned(nfsboottime.tv_sec); /* time stamp */
 4842         *tl++ = 0;                              /* Null machine name */
 4843         *tl++ = 0;                              /* Uid == 0 */
 4844         *tl++ = 0;                              /* Gid == 0 */
 4845         *tl = 0;                                /* No additional gids */
 4846         nd->nd_flag |= ND_USEGSSNAME;
 4847         error = newnfs_request(nd, nmp, NULL, nrp, NULL, p, cred, NFS_PROG,
 4848             NFS_VER4, NULL, 1, NULL, NULL);
 4849         if (error != 0)
 4850                 return (error);
 4851         if (nd->nd_repstat == 0) {
 4852                 NFSM_DISSECT(tl, uint32_t *, NFSX_V4SESSIONID +
 4853                     2 * NFSX_UNSIGNED);
 4854                 bcopy(tl, sep->nfsess_sessionid, NFSX_V4SESSIONID);
 4855                 tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
 4856                 sep->nfsess_sequenceid = fxdr_unsigned(uint32_t, *tl++);
 4857                 crflags = fxdr_unsigned(uint32_t, *tl);
 4858                 if ((crflags & NFSV4CRSESS_PERSIST) != 0 && mds != 0) {
 4859                         NFSLOCKMNT(nmp);
 4860                         nmp->nm_state |= NFSSTA_SESSPERSIST;
 4861                         NFSUNLOCKMNT(nmp);
 4862                 }
 4863 
 4864                 /* Get the fore channel slot count. */
 4865                 NFSM_DISSECT(tl, uint32_t *, 7 * NFSX_UNSIGNED);
 4866                 tl++;                   /* Skip the header pad size. */
 4867 
 4868                 /* Make sure nm_wsize is small enough. */
 4869                 maxval = fxdr_unsigned(uint32_t, *tl++);
 4870                 while (maxval < nmp->nm_wsize + NFS_MAXXDR) {
 4871                         if (nmp->nm_wsize > 8096)
 4872                                 nmp->nm_wsize /= 2;
 4873                         else
 4874                                 break;
 4875                 }
 4876 
 4877                 /* Make sure nm_rsize is small enough. */
 4878                 maxval = fxdr_unsigned(uint32_t, *tl++);
 4879                 while (maxval < nmp->nm_rsize + NFS_MAXXDR) {
 4880                         if (nmp->nm_rsize > 8096)
 4881                                 nmp->nm_rsize /= 2;
 4882                         else
 4883                                 break;
 4884                 }
 4885 
 4886                 sep->nfsess_maxcache = fxdr_unsigned(int, *tl++);
 4887                 tl++;
 4888                 sep->nfsess_foreslots = fxdr_unsigned(uint16_t, *tl++);
 4889                 NFSCL_DEBUG(4, "fore slots=%d\n", (int)sep->nfsess_foreslots);
 4890                 irdcnt = fxdr_unsigned(int, *tl);
 4891                 if (irdcnt < 0 || irdcnt > 1) {
 4892                         error = NFSERR_BADXDR;
 4893                         goto nfsmout;
 4894                 }
 4895                 if (irdcnt > 0)
 4896                         NFSM_DISSECT(tl, uint32_t *, irdcnt * NFSX_UNSIGNED);
 4897 
 4898                 /* and the back channel slot count. */
 4899                 NFSM_DISSECT(tl, uint32_t *, 7 * NFSX_UNSIGNED);
 4900                 tl += 5;
 4901                 sep->nfsess_backslots = fxdr_unsigned(uint16_t, *tl);
 4902                 NFSCL_DEBUG(4, "back slots=%d\n", (int)sep->nfsess_backslots);
 4903         }
 4904         error = nd->nd_repstat;
 4905 nfsmout:
 4906         mbuf_freem(nd->nd_mrep);
 4907         return (error);
 4908 }
 4909 
 4910 /*
 4911  * Do the NFSv4.1 Destroy Session.
 4912  */
 4913 int
 4914 nfsrpc_destroysession(struct nfsmount *nmp, struct nfsclclient *clp,
 4915     struct ucred *cred, NFSPROC_T *p)
 4916 {
 4917         uint32_t *tl;
 4918         struct nfsrv_descript nfsd;
 4919         struct nfsrv_descript *nd = &nfsd;
 4920         int error;
 4921         struct nfsclsession *tsep;
 4922 
 4923         nfscl_reqstart(nd, NFSPROC_DESTROYSESSION, nmp, NULL, 0, NULL, NULL, 0,
 4924             0);
 4925         NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID);
 4926         tsep = nfsmnt_mdssession(nmp);
 4927         bcopy(tsep->nfsess_sessionid, tl, NFSX_V4SESSIONID);
 4928         nd->nd_flag |= ND_USEGSSNAME;
 4929         error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 4930             NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 4931         if (error != 0)
 4932                 return (error);
 4933         error = nd->nd_repstat;
 4934         mbuf_freem(nd->nd_mrep);
 4935         return (error);
 4936 }
 4937 
 4938 /*
 4939  * Do the NFSv4.1 Destroy Client.
 4940  */
 4941 int
 4942 nfsrpc_destroyclient(struct nfsmount *nmp, struct nfsclclient *clp,
 4943     struct ucred *cred, NFSPROC_T *p)
 4944 {
 4945         uint32_t *tl;
 4946         struct nfsrv_descript nfsd;
 4947         struct nfsrv_descript *nd = &nfsd;
 4948         int error;
 4949         struct nfsclsession *tsep;
 4950 
 4951         nfscl_reqstart(nd, NFSPROC_DESTROYCLIENT, nmp, NULL, 0, NULL, NULL, 0,
 4952             0);
 4953         NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 4954         tsep = nfsmnt_mdssession(nmp);
 4955         *tl++ = tsep->nfsess_clientid.lval[0];
 4956         *tl = tsep->nfsess_clientid.lval[1];
 4957         nd->nd_flag |= ND_USEGSSNAME;
 4958         error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 4959             NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 4960         if (error != 0)
 4961                 return (error);
 4962         error = nd->nd_repstat;
 4963         mbuf_freem(nd->nd_mrep);
 4964         return (error);
 4965 }
 4966 
 4967 /*
 4968  * Do the NFSv4.1 LayoutGet.
 4969  */
 4970 static int
 4971 nfsrpc_layoutget(struct nfsmount *nmp, uint8_t *fhp, int fhlen, int iomode,
 4972     uint64_t offset, uint64_t len, uint64_t minlen, int layouttype,
 4973     int layoutlen, nfsv4stateid_t *stateidp, int *retonclosep,
 4974     struct nfsclflayouthead *flhp, struct ucred *cred, NFSPROC_T *p,
 4975     void *stuff)
 4976 {
 4977         struct nfsrv_descript nfsd, *nd = &nfsd;
 4978         int error;
 4979 
 4980         nfscl_reqstart(nd, NFSPROC_LAYOUTGET, nmp, fhp, fhlen, NULL, NULL, 0,
 4981             0);
 4982         nfsrv_setuplayoutget(nd, iomode, offset, len, minlen, stateidp,
 4983             layouttype, layoutlen, 0);
 4984         nd->nd_flag |= ND_USEGSSNAME;
 4985         error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 4986             NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 4987         NFSCL_DEBUG(4, "layget err=%d st=%d\n", error, nd->nd_repstat);
 4988         if (error != 0)
 4989                 return (error);
 4990         if (nd->nd_repstat == 0)
 4991                 error = nfsrv_parselayoutget(nd, stateidp, retonclosep, flhp);
 4992         if (error == 0 && nd->nd_repstat != 0)
 4993                 error = nd->nd_repstat;
 4994         mbuf_freem(nd->nd_mrep);
 4995         return (error);
 4996 }