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/nfs4client/nfs4_subs.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 /* $FreeBSD$ */
    2 /* $Id: nfs4_subs.c,v 1.52 2003/11/05 14:58:59 rees Exp $ */
    3 
    4 /*-
    5  * copyright (c) 2003
    6  * the regents of the university of michigan
    7  * all rights reserved
    8  * 
    9  * permission is granted to use, copy, create derivative works and redistribute
   10  * this software and such derivative works for any purpose, so long as the name
   11  * of the university of michigan is not used in any advertising or publicity
   12  * pertaining to the use or distribution of this software without specific,
   13  * written prior authorization.  if the above copyright notice or any other
   14  * identification of the university of michigan is included in any copy of any
   15  * portion of this software, then the disclaimer below must also be included.
   16  * 
   17  * this software is provided as is, without representation from the university
   18  * of michigan as to its fitness for any purpose, and without warranty by the
   19  * university of michigan of any kind, either express or implied, including
   20  * without limitation the implied warranties of merchantability and fitness for
   21  * a particular purpose. the regents of the university of michigan shall not be
   22  * liable for any damages, including special, indirect, incidental, or
   23  * consequential damages, with respect to any claim arising out of or in
   24  * connection with the use of the software, even if it has been or is hereafter
   25  * advised of the possibility of such damages.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/kernel.h>
   33 #include <sys/bio.h>
   34 #include <sys/buf.h>
   35 #include <sys/proc.h>
   36 #include <sys/mount.h>
   37 #include <sys/vnode.h>
   38 #include <sys/namei.h>
   39 #include <sys/mbuf.h>
   40 #include <sys/socket.h>
   41 #include <sys/stat.h>
   42 #include <sys/malloc.h>
   43 #include <sys/sysent.h>
   44 #include <sys/syscall.h>
   45 #include <sys/sysproto.h>
   46 #include <sys/fcntl.h>
   47 
   48 #include <machine/stdarg.h>
   49 
   50 #include <vm/vm.h>
   51 #include <vm/vm_object.h>
   52 #include <vm/vm_extern.h>
   53 #include <vm/uma.h>
   54 
   55 #include <rpc/rpcclnt.h>
   56 
   57 #include <nfs/rpcv2.h>
   58 #include <nfs/nfsproto.h>
   59 #include <nfsclient/nfs.h>
   60 #include <nfs4client/nfs4.h>
   61 #include <nfsclient/nfsnode.h>
   62 #include <nfsclient/nfsmount.h>
   63 #include <nfs/xdr_subs.h>
   64 #include <nfsclient/nfsm_subs.h>
   65 
   66 #include <nfs4client/nfs4_dev.h>
   67 #include <nfs4client/nfs4_idmap.h>
   68 #include <nfs4client/nfs4m_subs.h>
   69 
   70 #include <netinet/in.h>
   71 
   72 #define NFSM_DISSECT(s) do {                                                    \
   73         tl = nfsm_dissect_xx((s), md, dpos);                                    \
   74         if (tl == NULL) {                                                       \
   75                 printf("NFSM_DISSECT error; allocation (%s/%d) (%s:%d)\n", #s, s, __FILE__, __LINE__);  \
   76                 return (EBADRPC);                                               \
   77         }                                                                       \
   78 } while (0)
   79 
   80 #define NFSM_ADV(s) do {                                                \
   81         t1 = nfsm_adv_xx((s), md, dpos);                                \
   82         if (t1 != 0) {                                                  \
   83                 printf("NFSM_ADV error; allocation (%s/%d) (%s:%d)\n", #s, s, __FILE__, __LINE__);      \
   84                 return (EBADRPC);                                       \
   85         }                                                               \
   86 } while (0)
   87 
   88 #define NFSM_MTOTIME(t) do {                            \
   89         NFSM_DISSECT(3 * NFSX_UNSIGNED);                \
   90         (t).tv_sec = fxdr_hyper(tl);                    \
   91         tl += 2;                                        \
   92         (t).tv_nsec = fxdr_unsigned(long, *tl++);       \
   93 } while (0)
   94 
   95 static uint32_t __fsinfo_bm[2], __fsattr_bm[2], __getattr_bm[2], __readdir_bm[2];
   96 
   97 nfsv4bitmap nfsv4_fsinfobm = { 2, __fsinfo_bm };
   98 nfsv4bitmap nfsv4_fsattrbm = { 2, __fsattr_bm };
   99 nfsv4bitmap nfsv4_getattrbm = { 2, __getattr_bm };
  100 nfsv4bitmap nfsv4_readdirbm = { 2, __readdir_bm };
  101 
  102 /* Helper routines */
  103 int nfsm_v4build_attrs_xx(struct vattr *, struct mbuf **, caddr_t *);
  104 int nfsm_v4dissect_changeinfo_xx(nfsv4changeinfo *,  struct mbuf **, caddr_t *);
  105 
  106 void
  107 nfsm_v4init(void)
  108 {
  109 
  110         /* Set up bitmasks */
  111         FA4_SET(FA4_FSID, __fsinfo_bm);
  112         FA4_SET(FA4_MAXREAD, __fsinfo_bm);
  113         FA4_SET(FA4_MAXWRITE, __fsinfo_bm);
  114         FA4_SET(FA4_LEASE_TIME, __fsinfo_bm);
  115 
  116         FA4_SET(FA4_FSID, __fsattr_bm);
  117         FA4_SET(FA4_FILES_FREE, __fsattr_bm);
  118         FA4_SET(FA4_FILES_TOTAL, __fsattr_bm);
  119         FA4_SET(FA4_SPACE_AVAIL, __fsattr_bm);
  120         FA4_SET(FA4_SPACE_FREE, __fsattr_bm);
  121         FA4_SET(FA4_SPACE_TOTAL, __fsattr_bm);
  122 
  123         FA4_SET(FA4_TYPE, __getattr_bm);
  124         FA4_SET(FA4_FSID, __getattr_bm);
  125         FA4_SET(FA4_SIZE, __getattr_bm);
  126         FA4_SET(FA4_MODE, __getattr_bm);
  127         FA4_SET(FA4_RAWDEV, __getattr_bm);
  128         FA4_SET(FA4_NUMLINKS, __getattr_bm);
  129         FA4_SET(FA4_OWNER, __getattr_bm);
  130         FA4_SET(FA4_OWNER_GROUP, __getattr_bm);
  131         FA4_SET(FA4_FILEID, __getattr_bm);
  132         FA4_SET(FA4_TIME_MODIFY, __getattr_bm);
  133         FA4_SET(FA4_TIME_ACCESS, __getattr_bm);
  134 
  135         FA4_SET(FA4_TYPE, __readdir_bm);
  136         FA4_SET(FA4_FSID, __readdir_bm);
  137         FA4_SET(FA4_FILEID, __readdir_bm);
  138         FA4_SET(FA4_RDATTR_ERROR, __readdir_bm);
  139 }
  140 
  141 /*
  142  * Util
  143  */
  144 
  145 uint32_t
  146 nfs_v4fileid4_to_fileid(uint64_t fid)
  147 {
  148         return ((uint32_t)((fid >> 32) | fid));
  149 }
  150 
  151 void
  152 nfs_v4initcompound(struct nfs4_compound *cp)
  153 {
  154         bzero(cp, sizeof(*cp));
  155 }
  156 
  157 /*
  158  * Build/dissect XDR buffer with a format string.
  159  *
  160  *    u - unsigned
  161  *    h - hyper
  162  *    s - stringlength, string
  163  *    k - skip length (bytes)
  164  *    a - arraylength, componentlenght, array
  165  *    o - opaque fix length
  166  *    O - opaque var length in bytes
  167  */
  168 
  169 void
  170 nfsm_buildf_xx(struct mbuf **mb, caddr_t *bpos, char *fmt, ...)
  171 {
  172         uint32_t *tl, t1, len, uval;
  173         uint64_t hval;
  174         va_list args;
  175         char *p, *which;
  176 
  177         va_start(args, fmt);
  178         for (which = fmt; *which != '\0'; which++)
  179                 switch (*which) {
  180                 case 'u':       /* Unsigned */
  181                         tl = nfsm_build_xx(NFSX_UNSIGNED, mb, bpos);
  182                         uval = va_arg(args, uint32_t);
  183                         *tl++ = txdr_unsigned(uval);
  184                         break;
  185                 case 'h':       /* Hyper */
  186                         tl = nfsm_build_xx(2 * NFSX_UNSIGNED, mb, bpos);
  187                         hval = va_arg(args, uint64_t);
  188                         txdr_hyper(hval, tl);
  189                         break;
  190                 case 'o':       /* Fixed-length opaque */
  191                         len = va_arg(args, uint32_t);
  192                         p = va_arg(args, char *);
  193                         tl = nfsm_build_xx(nfsm_rndup(len), mb, bpos);
  194                         bcopy(p, tl, len);
  195                         break;
  196                 case 'O':       /* Variable-length opaque */
  197                 case 's':       /* String */
  198                         len = va_arg(args, uint32_t);
  199                         p = va_arg(args, char *);
  200                         t1 = nfsm_strtom_xx(p, len, len, mb, bpos);
  201                         break;
  202                 case 'k':       /* Skip */
  203                         len = va_arg(args, uint32_t);
  204                         nfsm_build_xx(nfsm_rndup(len), mb, bpos);
  205                         break;
  206                 default:
  207                         panic("Invalid buildf string %s[%c]", fmt, *which);
  208                         break;
  209                 }
  210         va_end(args);
  211 }
  212 
  213 int
  214 nfsm_dissectf_xx(struct mbuf **md, caddr_t *dpos, char *fmt, ...)
  215 {
  216         uint32_t *tl, t1, len, *uval;
  217         uint64_t *hval;
  218         va_list args;
  219         char *p, *which;
  220 
  221         va_start(args, fmt);
  222         for (which = fmt; *which != '\0'; which++)
  223                 switch (*which) {
  224                 case 'u':       /* Unsigned */
  225                         tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
  226                         if (tl == NULL)
  227                                 return (EBADRPC);
  228                         uval = va_arg(args, uint32_t *);
  229                         *uval = fxdr_unsigned(uint32_t, *tl++);
  230                         break;
  231                 case 'h':       /* Hyper */
  232                         tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
  233                         if (tl == NULL)
  234                                 return (EBADRPC);
  235                         hval = va_arg(args, uint64_t *);
  236                         *hval = fxdr_hyper(tl);
  237                         break;
  238                 case 'o':       /* Fixed-length opaque */
  239                         len = va_arg(args, uint32_t);
  240                         p = va_arg(args, void *);
  241                         tl = nfsm_dissect_xx(nfsm_rndup(len), md, dpos);
  242                         if (tl == NULL)
  243                                 return (EBADRPC);
  244                         bcopy(tl, p, len);
  245                         break;
  246                 case 'O':       /* Variable-length opaque */
  247                 case 's':       /* String */
  248                         len = va_arg(args, uint32_t);
  249                         p = va_arg(args, char *);
  250                         tl = nfsm_dissect_xx(nfsm_rndup(len), md, dpos);
  251                         if (tl == NULL)
  252                                 return (EBADRPC);
  253                         bcopy(tl, p, len);
  254                         break;
  255                 case 'k':       /* Skip bytes */
  256                         len = va_arg(args, uint32_t);
  257                         t1 = nfsm_adv_xx(nfsm_rndup(len), md, dpos);
  258                         break;
  259                 default:
  260                         panic("Invalid dissectf string %s[%c]", fmt, *which);
  261                         break;
  262                 }
  263         va_end(args);
  264 
  265         return (0);
  266 }
  267 
  268 /*
  269  * XXX - There are a few problems with the way the postops are places
  270  * in the code.  Ideally, they should be taken care of immediately, as
  271  * to avoid uneceesary waits for mutexes, but then we would be
  272  * introducing even more complexity by having to handle two separate
  273  * cases.  Also, since they are placed at the end of the vnops', there
  274  * may be operations which sleep in between, further extending this
  275  * wait.  It is conceivable that there is a deadlock condition there,
  276  * too.
  277  *
  278  * Also, for vnops that do multiple operations, it's inconvenient
  279  * since on error, individual decoding will got nfsmout.
  280  */
  281 
  282 int
  283 nfs_v4postop(struct nfs4_compound *cp, int status)
  284 {
  285         struct nfs4_fctx *fcp = cp->fcp;
  286 
  287         /*
  288          * XXX does the previous result need to be stores with the
  289          * lockowner?  ack, spec is unclear ..
  290          */
  291 
  292         if (fcp != NULL)
  293                 if (cp->seqidused < cp->rep_nops ||
  294                     (cp->seqidused + 1 == cp->rep_nops &&
  295                         NFS4_SEQIDMUTATINGERROR(status)))
  296                         fcp->lop->lo_seqid++;
  297 
  298         return (status);
  299 }
  300 
  301 int
  302 nfs_v4handlestatus(int status, struct nfs4_compound *cp)
  303 {
  304         return (status);
  305 }
  306 
  307 /*
  308  * Initial setup of compound.
  309  */
  310 
  311 int
  312 nfsm_v4build_compound_xx(struct nfs4_compound *cp, char *tag,
  313     struct mbuf **mb, caddr_t *bpos)
  314 {
  315         uint32_t t1, *tl, siz;
  316 
  317         /* Tag */
  318         siz = strlen(tag);
  319         t1 = nfsm_rndup(siz) + NFSX_UNSIGNED;
  320         if (t1 <= M_TRAILINGSPACE(*mb)) {
  321                 tl = nfsm_build_xx(t1, mb, bpos);
  322                 *tl++ = txdr_unsigned(siz);
  323                 *(tl + ((t1 >> 2) - 2)) = 0;
  324                 bcopy(tag, tl, siz);
  325         } else {
  326                 t1 = nfsm_strtmbuf(mb, bpos, (const char *)tag, siz);
  327                 if (t1 != 0)
  328                         return (t1);
  329         }
  330 
  331         /* Minor version and argarray*/
  332         tl = nfsm_build_xx(2 * NFSX_UNSIGNED, mb, bpos);
  333         *tl++ = txdr_unsigned(NFS4_MINOR_VERSION);
  334         /* Save for backfill */
  335         cp->req_nopsp = tl;
  336         *tl = txdr_unsigned(0);
  337 
  338         cp->curvp = NULL;
  339         cp->savevp = NULL;
  340 
  341         return (0);
  342 }
  343 
  344 /*
  345  * XXX
  346  * - backfill for stateid, and such
  347  */
  348 int
  349 nfsm_v4build_finalize_xx(struct nfs4_compound *cp, struct mbuf **mb, caddr_t *bpos)
  350 {
  351         *cp->req_nopsp = txdr_unsigned(cp->req_nops);
  352 
  353         return (0);
  354 }
  355 
  356 int
  357 nfsm_v4build_putfh_xx(struct nfs4_compound *cp, struct vnode *vp,
  358     struct mbuf **mb, caddr_t *bpos)
  359 {
  360         uint32_t t1;
  361 
  362         /* Op */
  363         nfsm_buildf_xx(mb, bpos, "u", NFSV4OP_PUTFH);
  364 
  365         /* FH */
  366         t1 = nfsm_fhtom_xx(vp, 1, mb, bpos);
  367         if (t1 != 0)
  368                 return (t1);
  369 
  370         cp->req_nops++;
  371         cp->curvp = vp;
  372 
  373         return (0);
  374 }
  375 
  376 int
  377 nfsm_v4build_putfh_nv_xx(struct nfs4_compound *cp, struct nfs4_oparg_getfh *gfh,
  378     struct mbuf **mb, caddr_t *bpos)
  379 {
  380         nfsm_buildf_xx(mb, bpos, "uuo",
  381             NFSV4OP_PUTFH,
  382             gfh->fh_len,
  383             gfh->fh_len,
  384             &gfh->fh_val);
  385 
  386         cp->req_nops++;
  387 
  388         return (0);
  389 }
  390 
  391 int
  392 nfsm_v4build_simple_xx(struct nfs4_compound *cp, uint32_t op,
  393     struct mbuf **mb, caddr_t *bpos)
  394 {
  395         nfsm_buildf_xx(mb, bpos, "u", op);
  396 
  397         cp->req_nops++;
  398 
  399         return (0);
  400 }
  401 
  402 int
  403 nfsm_v4build_getattr_xx(struct nfs4_compound *cp, struct nfs4_oparg_getattr *ga,
  404     struct mbuf **mb, caddr_t *bpos)
  405 {
  406         int i;
  407 
  408         /* Op + bitmap length + bitmap */
  409         nfsm_buildf_xx(mb, bpos, "uu", NFSV4OP_GETATTR, ga->bm->bmlen);
  410         for (i = 0; i < ga->bm->bmlen; i++)
  411                 nfsm_buildf_xx(mb, bpos, "u", ga->bm->bmval[i]);
  412 
  413         ga->vp = cp->curvp;
  414         cp->req_nops++;          
  415 
  416         return (0);
  417 }
  418 
  419 int
  420 nfsm_v4build_setattr_xx(struct nfs4_compound *cp, struct vattr *vap,
  421     struct nfs4_fctx *fcp, struct mbuf **mb, caddr_t *bpos)
  422 {
  423         int error;
  424         static char zero_stateid[NFSX_V4STATEID];
  425 
  426         nfsm_buildf_xx(mb, bpos, "uo",
  427             NFSV4OP_SETATTR,
  428             NFSX_V4STATEID, fcp ? fcp->stateid : zero_stateid);
  429         error = nfsm_v4build_attrs_xx(vap, mb, bpos);
  430         if (error == 0)
  431                 cp->req_nops++;
  432 
  433         return (error);
  434 }
  435 
  436 int
  437 nfsm_v4build_getfh_xx(struct nfs4_compound *cp, struct nfs4_oparg_getfh *gfh,
  438     struct mbuf **mb, caddr_t *bpos)
  439 {
  440         nfsm_buildf_xx(mb, bpos, "u", NFSV4OP_GETFH);
  441 
  442         gfh->vp = cp->curvp;
  443         cp->req_nops++;
  444 
  445         return (0);
  446 }
  447 
  448 int
  449 nfsm_v4build_lookup_xx(struct nfs4_compound *cp, struct nfs4_oparg_lookup *l,
  450     struct mbuf **mb, caddr_t *bpos)
  451 {
  452         nfsm_buildf_xx(mb, bpos, "us", NFSV4OP_LOOKUP, l->namelen, l->name);
  453 
  454         cp->curvp = l->vp;
  455         cp->req_nops++;
  456 
  457         return (0);
  458 }
  459 
  460 int
  461 nfsm_v4build_setclientid_xx(struct nfs4_compound *cp,
  462     struct nfs4_oparg_setclientid *sci, struct mbuf **mb, caddr_t *bpos)
  463 {
  464         struct timeval tv;
  465 
  466         microtime(&tv);
  467 
  468         nfsm_buildf_xx(mb, bpos, "uuusussu",
  469             NFSV4OP_SETCLIENTID,
  470             tv.tv_sec, tv.tv_usec,
  471             sci->namelen, sci->name,
  472             sci->cb_prog,
  473             sci->cb_netidlen, sci->cb_netid,
  474             sci->cb_univaddrlen, sci->cb_univaddr,
  475             0xCA11BACC);
  476 
  477         cp->req_nops++;
  478 
  479         return (0);
  480 }
  481 
  482 int
  483 nfsm_v4build_setclientid_confirm_xx(struct nfs4_compound *cp,
  484     struct nfs4_oparg_setclientid *sci, struct mbuf **mb, caddr_t *bpos)
  485 {
  486         nfsm_buildf_xx(mb, bpos, "uho",
  487             NFSV4OP_SETCLIENTID_CONFIRM,
  488             sci->clientid,
  489             sizeof(sci->verf), sci->verf);
  490 
  491         cp->req_nops++;
  492 
  493         return (0);
  494 }
  495 
  496 int
  497 nfsm_v4build_open_xx(struct nfs4_compound *cp, struct nfs4_oparg_open *op,
  498     struct mbuf **mb, caddr_t *bpos)
  499 {
  500         int error = 0;
  501         struct nfs4_lowner *lop = op->fcp->lop;
  502 
  503         nfsm_buildf_xx(mb, bpos, "uuuuhuu",
  504             NFSV4OP_OPEN,
  505             lop->lo_seqid,
  506             op->flags & O_ACCMODE,
  507             NFSV4OPENSHARE_DENY_NONE,
  508             cp->nmp->nm_clientid,
  509             4, lop->lo_id);
  510 
  511         if (op->flags & O_CREAT) {
  512                 nfsm_buildf_xx(mb, bpos, "u", OTCREATE);
  513                 /* openflag4: mode */
  514                 nfsm_buildf_xx(mb, bpos, "u", CMUNCHECKED);
  515                 /* openflag4: createattrs... */
  516                 if (op->vap != NULL) {
  517                         if (op->flags & O_TRUNC)
  518                                 op->vap->va_size = 0;
  519                         error = nfsm_v4build_attrs_xx(op->vap, mb, bpos);
  520                         if (error != 0)
  521                                 return (error);
  522                 } else
  523                         nfsm_buildf_xx(mb, bpos, "uu", 0, 0);
  524         } else
  525                 nfsm_buildf_xx(mb, bpos, "u", OTNOCREATE);
  526 
  527         nfsm_buildf_xx(mb, bpos, "us", op->ctype,
  528             op->cnp->cn_namelen, op->cnp->cn_nameptr);
  529 
  530         cp->seqidused = cp->req_nops++;
  531         cp->fcp = op->fcp;
  532 
  533         return (error);
  534 }
  535 
  536 /*
  537  * XXX
  538  * - Wait on recovery
  539  */
  540 int
  541 nfsm_v4build_open_confirm_xx(struct nfs4_compound *cp, struct nfs4_oparg_open *op,
  542     struct mbuf **mb, caddr_t *bpos)
  543 {
  544         nfsm_buildf_xx(mb, bpos, "uou",
  545             NFSV4OP_OPEN_CONFIRM,
  546             NFSX_V4STATEID, op->fcp->stateid,
  547             op->fcp->lop->lo_seqid);
  548 
  549         cp->seqidused = cp->req_nops++;
  550         cp->fcp = op->fcp;
  551 
  552         return (0);
  553 }
  554 
  555 /*
  556  * XXX
  557  * - Wait on recovery
  558  */
  559 int
  560 nfsm_v4build_close_xx(struct nfs4_compound *cp, struct nfs4_fctx *fcp,
  561     struct mbuf **mb, caddr_t *bpos)
  562 {
  563         struct nfs4_lowner *lop = fcp->lop;
  564 
  565         nfsm_buildf_xx(mb, bpos, "uuo",
  566             NFSV4OP_CLOSE,
  567             lop->lo_seqid,
  568             NFSX_V4STATEID, fcp->stateid);
  569 
  570         cp->seqidused = cp->req_nops++;
  571         cp->fcp = fcp;
  572 
  573         return (0);
  574 }
  575 
  576 int
  577 nfsm_v4build_access_xx(struct nfs4_compound *cp, struct nfs4_oparg_access *acc,
  578     struct mbuf **mb, caddr_t *bpos)
  579 {
  580         nfsm_buildf_xx(mb, bpos, "uu", NFSV4OP_ACCESS, acc->mode);
  581         cp->req_nops++;
  582 
  583         return (0);
  584 }
  585 
  586 int
  587 nfsm_v4build_read_xx(struct nfs4_compound *cp, struct nfs4_oparg_read *r,
  588     struct mbuf **mb, caddr_t *bpos)
  589 {
  590         nfsm_buildf_xx(mb, bpos, "uohu",
  591             NFSV4OP_READ,
  592             NFSX_V4STATEID, r->fcp->stateid,
  593             r->off,
  594             r->maxcnt);
  595         cp->req_nops++;
  596 
  597         return (0);
  598 }
  599 
  600 int
  601 nfsm_v4build_write_xx(struct nfs4_compound *cp, struct nfs4_oparg_write *w,
  602     struct mbuf **mb, caddr_t *bpos)
  603 {
  604         nfsm_buildf_xx(mb, bpos, "uohuu",
  605             NFSV4OP_WRITE,
  606             NFSX_V4STATEID, w->fcp->stateid,
  607             w->off,
  608             w->stable,
  609             w->cnt);
  610         cp->req_nops++;
  611         return (nfsm_uiotombuf(w->uiop, mb, w->cnt, bpos));
  612 }
  613 
  614 int
  615 nfsm_v4build_commit_xx(struct nfs4_compound *cp, struct nfs4_oparg_commit *c,
  616     struct mbuf **mb, caddr_t *bpos)
  617 {
  618         nfsm_buildf_xx(mb, bpos, "uhu", NFSV4OP_COMMIT, c->start, c->len);
  619         cp->req_nops++;
  620 
  621         return (0);
  622 }
  623 
  624 int
  625 nfsm_v4build_readdir_xx(struct nfs4_compound *cp, struct nfs4_oparg_readdir *r,
  626     struct mbuf **mb, caddr_t *bpos)
  627 {
  628         int i;
  629 
  630         nfsm_buildf_xx(mb, bpos, "uhouuu",
  631             NFSV4OP_READDIR,
  632             r->cookie,
  633             sizeof(r->verf), r->verf,
  634             r->cnt >> 4,        /* meaningless "dircount" field */
  635             r->cnt,
  636             r->bm->bmlen);
  637 
  638         for (i = 0; i < r->bm->bmlen; i++)
  639                 nfsm_buildf_xx(mb, bpos, "u", r->bm->bmval[i]);
  640 
  641         cp->req_nops++;
  642 
  643         return (0);
  644 }
  645 
  646 int
  647 nfsm_v4build_renew_xx(struct nfs4_compound *cp, uint64_t cid,
  648     struct mbuf **mb, caddr_t *bpos)
  649 {
  650         nfsm_buildf_xx(mb, bpos, "uh", NFSV4OP_RENEW, cid);
  651         cp->req_nops++;
  652 
  653         return (0);
  654 }
  655 
  656 int
  657 nfsm_v4build_create_xx(struct nfs4_compound *cp, struct nfs4_oparg_create *c,
  658     struct mbuf **mb, caddr_t *bpos)
  659 {
  660         uint32_t t1;
  661 
  662         nfsm_buildf_xx(mb, bpos, "uu", NFSV4OP_CREATE, c->type);
  663 
  664         if (c->type == NFLNK)
  665                 /* XXX strlen */
  666                 nfsm_buildf_xx(mb, bpos, "s", strlen(c->linktext), c->linktext);
  667         else if (c->type == NFCHR || c->type == NFBLK)
  668                 nfsm_buildf_xx(mb, bpos, "uu",
  669                     umajor(c->vap->va_rdev), uminor(c->vap->va_rdev));
  670 
  671         /* Name */
  672         nfsm_buildf_xx(mb, bpos, "s", c->namelen, c->name);     
  673 
  674         /* Attributes */
  675         t1 = nfsm_v4build_attrs_xx(c->vap, mb, bpos);
  676         if (t1 != 0)
  677                 return (t1);
  678 
  679         cp->req_nops++;
  680 
  681         return (0);
  682 }
  683 
  684 int
  685 nfsm_v4build_rename_xx(struct nfs4_compound *cp, struct nfs4_oparg_rename *r,
  686     struct mbuf **mb, caddr_t *bpos)
  687 {
  688         nfsm_buildf_xx(mb, bpos, "uss", NFSV4OP_RENAME, r->fnamelen, r->fname,
  689             r->tnamelen, r->tname);
  690 
  691         cp->req_nops++;
  692 
  693         return (0);
  694 }
  695 
  696 int
  697 nfsm_v4build_link_xx(struct nfs4_compound *cp, struct nfs4_oparg_link *l,
  698     struct mbuf **mb, caddr_t *bpos)
  699 {
  700         nfsm_buildf_xx(mb, bpos, "us", NFSV4OP_LINK, l->namelen, l->name);
  701 
  702         cp->req_nops++;
  703 
  704         return (0);
  705 }
  706 
  707 int
  708 nfsm_v4build_remove_xx(struct nfs4_compound *cp, const char *name, u_int namelen,
  709     struct mbuf **mb, caddr_t *bpos)
  710 {
  711         nfsm_buildf_xx(mb, bpos, "us", NFSV4OP_REMOVE, namelen, name);
  712 
  713         cp->req_nops++;
  714 
  715         return (0);
  716 }
  717 
  718 int
  719 nfsm_v4build_attrs_xx(struct vattr *vap, struct mbuf **mb, caddr_t *bpos)
  720 {
  721         uint32_t *tl, *attrlenp, *bmvalp, len;
  722         size_t siz;
  723 
  724         tl = nfsm_build_xx(4 * NFSX_UNSIGNED, mb, bpos);
  725 
  726         *tl++ = txdr_unsigned(2);    /* bitmap length */
  727         bmvalp = tl;
  728         bzero(bmvalp, 8);
  729         tl += 2;
  730         attrlenp = tl;
  731 
  732         len = 0;
  733         if (vap->va_size != VNOVAL) {
  734                 tl = nfsm_build_xx(2 * NFSX_UNSIGNED, mb, bpos);
  735                 FA4_SET(FA4_SIZE, bmvalp);
  736                 txdr_hyper(vap->va_size, tl); tl += 2;
  737                 len += 2 * NFSX_UNSIGNED;
  738         }
  739         if (vap->va_mode != (u_short)VNOVAL) {
  740                 tl = nfsm_build_xx(NFSX_UNSIGNED, mb, bpos);
  741                 FA4_SET(FA4_MODE, bmvalp);
  742                 *tl++ = txdr_unsigned(vap->va_mode);
  743                 len += NFSX_UNSIGNED;
  744         }
  745         if (vap->va_uid != VNOVAL) {
  746                 int error;
  747                 char *name;
  748                 error = idmap_uid_to_name(vap->va_uid, &name, &siz);
  749                 if (error || name == NULL || siz == 0) {
  750                         /* XXX */
  751                         siz = sizeof("nobody") - 1;
  752                         tl = nfsm_build_xx(NFSX_UNSIGNED + nfsm_rndup(siz), mb, 
  753                             bpos);
  754                         *tl++ = txdr_unsigned(siz);
  755                         bcopy("nobody", tl, siz);
  756                         len += NFSX_UNSIGNED + nfsm_rndup(siz);
  757                 } else {
  758                         tl = nfsm_build_xx(NFSX_UNSIGNED + nfsm_rndup(siz), mb,
  759                             bpos);
  760                         *tl++ = txdr_unsigned(siz);
  761                         bcopy(name, tl, siz);
  762                         len += NFSX_UNSIGNED + nfsm_rndup(siz);
  763                 }
  764                 FA4_SET(FA4_OWNER, bmvalp);
  765         }
  766         if (vap->va_gid != VNOVAL) {
  767                 int error;
  768                 char *name;
  769                 error = idmap_gid_to_name(vap->va_gid, &name, &siz);
  770                 if (error || name == NULL || siz == 0) {
  771                         /* XXX */
  772                         siz = sizeof("nogroup") - 1;
  773                         tl = nfsm_build_xx(NFSX_UNSIGNED + nfsm_rndup(siz), mb, 
  774                             bpos);
  775                         *tl++ = txdr_unsigned(siz);
  776                         bcopy("nogroup", tl, siz);
  777                         len += NFSX_UNSIGNED + nfsm_rndup(siz);
  778                 } else {
  779                         tl = nfsm_build_xx(NFSX_UNSIGNED + nfsm_rndup(siz), mb,
  780                             bpos);
  781                         *tl++ = txdr_unsigned(siz);
  782                         bcopy(name, tl, siz);
  783                         len += NFSX_UNSIGNED + nfsm_rndup(siz);
  784                 }
  785                 FA4_SET(FA4_OWNER_GROUP, bmvalp);
  786         }
  787         if (vap->va_atime.tv_sec != VNOVAL) {
  788                 uint64_t val = vap->va_atime.tv_sec;
  789                 tl = nfsm_build_xx(4 * NFSX_UNSIGNED, mb, bpos);
  790                 FA4_SET(FA4_TIME_ACCESS_SET, bmvalp);
  791                 *tl++ = txdr_unsigned(THCLIENTTIME);
  792                 txdr_hyper(val, tl); tl += 2;
  793                 *tl++ = txdr_unsigned(vap->va_atime.tv_nsec);
  794                 len += 4 * NFSX_UNSIGNED;
  795         }
  796         if (vap->va_mtime.tv_sec != VNOVAL) {
  797                 uint64_t val = vap->va_mtime.tv_sec;
  798                 tl = nfsm_build_xx(4 * NFSX_UNSIGNED, mb, bpos);
  799                 FA4_SET(FA4_TIME_MODIFY_SET, bmvalp);
  800                 *tl++ = txdr_unsigned(THCLIENTTIME);
  801                 txdr_hyper(val, tl); tl += 2;
  802                 *tl++ = txdr_unsigned(vap->va_mtime.tv_nsec);
  803                 len += 4 * NFSX_UNSIGNED;
  804         }
  805 
  806         bmvalp[0] = txdr_unsigned(bmvalp[0]);
  807         bmvalp[1] = txdr_unsigned(bmvalp[1]);
  808 
  809         *attrlenp = txdr_unsigned(len);
  810 
  811         return (0);
  812 }
  813 
  814 int
  815 nfsm_v4dissect_compound_xx(struct nfs4_compound *cp, struct mbuf **md, caddr_t *dpos)
  816 {
  817         uint32_t taglen, t1, *tl;
  818 
  819         tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
  820         if (tl == NULL)
  821                 return (EBADRPC);
  822 
  823         /* Reply status is handled by the RPC code */
  824 
  825         taglen = fxdr_unsigned(uint32_t, *tl++);
  826         t1 = nfsm_adv_xx(nfsm_rndup(taglen), md, dpos);
  827         if (t1 != 0)
  828                 return (EBADRPC);
  829 
  830         tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
  831         if (tl == NULL)
  832                 return (EBADRPC);
  833 
  834         cp->rep_nops = fxdr_unsigned(uint32_t, *tl++);
  835 
  836         return (0);
  837 }
  838 
  839 int
  840 nfsm_v4dissect_simple_xx(struct nfs4_compound *cp, uint32_t op,
  841     uint32_t skipbytes, struct mbuf **md, caddr_t *dpos)
  842 {
  843         uint32_t t1, dop, status;
  844 
  845         t1 = nfsm_dissectf_xx(md, dpos, "uu", &dop, &status);
  846         if (t1 != 0)
  847                 return (t1);
  848 
  849         if (dop != op || status != 0)
  850                 return (EBADRPC);
  851 
  852         if (skipbytes > 0)
  853                 NFSM_ADV(nfsm_rndup(skipbytes));
  854 
  855         return (0);
  856 }
  857 
  858 int
  859 nfsm_v4dissect_getattr_xx(struct nfs4_compound *cp, struct nfs4_oparg_getattr *ga,
  860     struct mbuf **md, caddr_t *dpos)
  861 {
  862         uint32_t *tl;
  863 
  864         tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
  865         if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_GETATTR ||
  866             *tl++ != 0)
  867                 return (EBADRPC);
  868 
  869         return (nfsm_v4dissect_attrs_xx(&ga->fa, md, dpos));
  870 }
  871 
  872 int
  873 nfsm_v4dissect_setattr_xx(struct nfs4_compound *cp, struct mbuf **md, caddr_t *dpos)
  874 {
  875         uint32_t t1, op, bmlen, status;
  876 
  877         t1 = nfsm_dissectf_xx(md, dpos, "uu", &op, &status);
  878         if (t1 != 0)
  879                 return (t1);
  880 
  881         if (op != NFSV4OP_SETATTR || status != 0)
  882                 return (EBADRPC);
  883 
  884         t1 = nfsm_dissectf_xx(md, dpos, "u", &bmlen);
  885         if (t1 != 0)
  886                 return (t1);
  887 
  888         return (nfsm_dissectf_xx(md, dpos, "k", bmlen << 2));
  889 }
  890 
  891 int
  892 nfsm_v4dissect_getfh_xx(struct nfs4_compound *cp, struct nfs4_oparg_getfh *gfh,
  893     struct mbuf **md, caddr_t *dpos)
  894 {
  895         uint32_t *tl, len, xdrlen;
  896 
  897         tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
  898         if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_GETFH)
  899                 return (EBADRPC);
  900 
  901         if (*tl++ != 0)
  902                 return (EBADRPC);
  903 
  904         NFSM_DISSECT(NFSX_UNSIGNED);
  905         len = fxdr_unsigned(uint32_t, *tl++);
  906         if (len > NFSX_V4FH)
  907                 return (EBADRPC);
  908 
  909         /* XXX integrate this into nfs_mtofh()? */
  910 
  911         gfh->fh_len = len;
  912         xdrlen = nfsm_rndup(len);
  913 
  914         NFSM_DISSECT(xdrlen);
  915         bcopy(tl, &gfh->fh_val, xdrlen);
  916 
  917         return (0);
  918 }
  919 
  920 int
  921 nfsm_v4dissect_setclientid_xx(struct nfs4_compound *cp,
  922     struct nfs4_oparg_setclientid *sci, struct mbuf **md, caddr_t *dpos)
  923 {
  924         uint32_t *tl;
  925 
  926         tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
  927         if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_SETCLIENTID)
  928                 return (EBADRPC);
  929 
  930         /* Handle NFS4ERR_CLID_INUSE specially */
  931         if (*tl++ != 0)
  932                 return (EBADRPC);
  933 
  934         NFSM_DISSECT(2 * NFSX_UNSIGNED);
  935         sci->clientid = fxdr_hyper(tl);
  936 
  937         NFSM_DISSECT(nfsm_rndup(NFSX_V4VERF));
  938         bcopy(tl, sci->verf, NFSX_V4VERF);
  939 
  940         return (0);
  941 }
  942 
  943 int
  944 nfsm_v4dissect_close_xx(struct nfs4_compound *cp, struct nfs4_fctx *fcp,
  945     struct mbuf **md, caddr_t *dpos)
  946 {
  947         uint32_t *tl, t1;
  948 
  949         tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
  950         if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_CLOSE ||
  951             *tl++ != 0)
  952                 return (EBADRPC);
  953 
  954         /* Copy stateid */
  955         t1 = nfsm_dissectf_xx(md, dpos, "o", NFSX_V4STATEID, fcp->stateid);
  956         if (t1 != 0)
  957                 return (t1);
  958 
  959         return (0);
  960 }
  961 
  962 int
  963 nfsm_v4dissect_access_xx(struct nfs4_compound *cp, struct nfs4_oparg_access *acc,
  964     struct mbuf **md, caddr_t *dpos)
  965 {
  966         uint32_t *tl;
  967 
  968         tl = nfsm_dissect_xx(4 * NFSX_UNSIGNED, md, dpos);
  969         if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_ACCESS ||
  970             *tl++ != 0)
  971                 return (EBADRPC);
  972 
  973         acc->supported = fxdr_unsigned(uint32_t, *tl++);
  974         acc->rmode = fxdr_unsigned(uint32_t, *tl++);
  975 
  976         return (0);
  977 }
  978 
  979 int
  980 nfsm_v4dissect_open_xx(struct nfs4_compound *cp, struct nfs4_oparg_open *op,
  981     struct mbuf **md, caddr_t *dpos)
  982 {
  983         uint32_t *tl, t1, bmlen, delegtype = ODNONE;
  984         int error = 0;
  985         nfsv4changeinfo cinfo;
  986         struct nfs4_fctx *fcp = op->fcp;
  987 
  988         tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
  989         if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_OPEN ||
  990             *tl++ != 0)
  991                 return (EBADRPC);
  992 
  993         t1 = nfsm_dissectf_xx(md, dpos, "o", NFSX_V4STATEID, fcp->stateid);
  994         if (t1 != 0)
  995                 return (t1);
  996 
  997         error = nfsm_v4dissect_changeinfo_xx(&cinfo, md, dpos);
  998         if (error != 0)
  999                 goto nfsmout;
 1000 
 1001         NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1002 
 1003         op->rflags = fxdr_unsigned(uint32_t, *tl++);
 1004         bmlen = fxdr_unsigned(uint32_t, *tl++);
 1005         if (bmlen > 2) {
 1006                 error = EBADRPC;
 1007                 goto nfsmout;
 1008         }
 1009 
 1010         /* Skip */
 1011         NFSM_ADV(nfsm_rndup(bmlen << 2));
 1012 
 1013         NFSM_DISSECT(NFSX_UNSIGNED);
 1014         delegtype = fxdr_unsigned(uint32_t, *tl++);
 1015         switch (delegtype) {
 1016         case ODREAD:
 1017         case ODWRITE:
 1018                 printf("nfs4: client delegation not yet supported\n");
 1019                 error = EOPNOTSUPP;
 1020                 goto nfsmout;
 1021                 break;
 1022         case ODNONE:
 1023         default:
 1024                 break;
 1025         }
 1026 
 1027  nfsmout:
 1028         return (error);
 1029 }
 1030 
 1031 int
 1032 nfsm_v4dissect_open_confirm_xx(struct nfs4_compound *cp, struct nfs4_oparg_open *op,
 1033     struct mbuf **md, caddr_t *dpos)
 1034 {
 1035         uint32_t *tl;
 1036 
 1037         tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
 1038         if (tl == NULL || fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_OPEN_CONFIRM ||
 1039             *tl++ != 0)
 1040                 return (EBADRPC);
 1041 
 1042         return nfsm_dissectf_xx(md, dpos, "o", NFSX_V4STATEID, op->fcp->stateid);
 1043 }
 1044 
 1045 int
 1046 nfsm_v4dissect_read_xx(struct nfs4_compound *cp, struct nfs4_oparg_read *r,
 1047     struct mbuf **md, caddr_t *dpos)
 1048 {
 1049         uint32_t op, status, t1;
 1050 
 1051         t1 = nfsm_dissectf_xx(md, dpos, "uu", &op, &status);
 1052         if (t1 != 0)
 1053                 return (t1);
 1054 
 1055         if (op != NFSV4OP_READ || status != 0)
 1056                 return (EBADRPC);
 1057 
 1058         t1 = nfsm_dissectf_xx(md, dpos, "uu", &r->eof, &r->retlen);
 1059         if (t1 != 0)
 1060                 return (t1);
 1061 
 1062         return (nfsm_mbuftouio(md, r->uiop, r->retlen, dpos));
 1063 }
 1064 
 1065 int
 1066 nfsm_v4dissect_write_xx(struct nfs4_compound *cp, struct nfs4_oparg_write *w,
 1067     struct mbuf **md, caddr_t *dpos)
 1068 {
 1069         uint32_t op, status, t1;
 1070 
 1071         t1 = nfsm_dissectf_xx(md, dpos, "uu", &op, &status);
 1072         if (t1 != 0)
 1073                 return (t1);
 1074 
 1075         if (op != NFSV4OP_WRITE || status != 0)
 1076                 return (EBADRPC);
 1077 
 1078         return (nfsm_dissectf_xx(md, dpos, "uuo", &w->retlen, &w->committed,
 1079                     NFSX_V4VERF, w->wverf));
 1080 }
 1081 
 1082 int
 1083 nfsm_v4dissect_commit_xx(struct nfs4_compound *cp, struct nfs4_oparg_commit *c,
 1084     struct mbuf **md, caddr_t *dpos)
 1085 {
 1086         uint32_t t1, op, status;
 1087 
 1088         t1 = nfsm_dissectf_xx(md, dpos, "uu", &op, &status);
 1089         if (t1 != 0)
 1090                 return (t1);
 1091 
 1092         if (op != NFSV4OP_COMMIT || status != 0)
 1093                 return (EBADRPC);
 1094 
 1095         return (nfsm_dissectf_xx(md, dpos, "o", NFSX_V4VERF, c->verf));
 1096 }
 1097 
 1098 int
 1099 nfsm_v4dissect_create_xx(struct nfs4_compound *cp, struct nfs4_oparg_create *c,
 1100     struct mbuf **md, caddr_t *dpos)
 1101 {
 1102         uint32_t t1, *tl, op, status, bmlen;
 1103         nfsv4changeinfo ci;
 1104 
 1105         t1 = nfsm_dissectf_xx(md, dpos, "uu", &op, &status);
 1106         if (t1 != 0)
 1107                 return (t1);
 1108 
 1109         if (op != NFSV4OP_CREATE || status != 0)
 1110                 return (EBADRPC);
 1111 
 1112         /* Just throw this away for now */
 1113         t1 = nfsm_v4dissect_changeinfo_xx(&ci, md, dpos);
 1114         if (t1 != 0)
 1115                 return (t1);
 1116 
 1117         /* Throw this away too */
 1118         NFSM_DISSECT(NFSX_UNSIGNED);
 1119         bmlen = fxdr_unsigned(uint32_t, *tl++);
 1120         NFSM_DISSECT(bmlen * NFSX_UNSIGNED);
 1121         tl += bmlen;
 1122 
 1123         return 0;
 1124 }
 1125 
 1126 int
 1127 nfsm_v4dissect_readlink_xx(struct nfs4_compound *cp, struct uio *uiop, 
 1128     struct mbuf **md, caddr_t *dpos)
 1129 {
 1130         uint32_t t1, *tl, op, status, linklen;
 1131 
 1132         t1 = nfsm_dissectf_xx(md, dpos, "uu", &op, &status);
 1133         if (t1 != 0)
 1134                 return (t1);
 1135 
 1136         if (op != NFSV4OP_READLINK || status != 0)
 1137                 return (EBADRPC);
 1138 
 1139         /* Do this one manually for careful checking of sizes. */
 1140         NFSM_DISSECT(NFSX_UNSIGNED);
 1141         linklen = fxdr_unsigned(uint32_t, *tl++);
 1142         if (linklen <= 0)
 1143                 return (EBADRPC);
 1144 
 1145         return (nfsm_mbuftouio(md, uiop, MIN(linklen, uiop->uio_resid), dpos));
 1146 }
 1147 
 1148 int
 1149 nfsm_v4dissect_changeinfo_xx(nfsv4changeinfo *ci,
 1150     struct mbuf **md, caddr_t *dpos)
 1151 {
 1152         uint32_t *tl;
 1153 
 1154         NFSM_DISSECT(5 * NFSX_UNSIGNED);
 1155 
 1156         ci->ciatomic = fxdr_unsigned(uint32_t, *tl++);
 1157         ci->cibefore = fxdr_hyper(tl); tl += 2;
 1158         ci->ciafter = fxdr_hyper(tl); tl += 2;
 1159 
 1160         return (0);
 1161 }
 1162 
 1163 int
 1164 nfsm_v4dissect_attrs_xx(struct nfsv4_fattr *fa, struct mbuf **md, caddr_t *dpos)
 1165 {
 1166         uint32_t t1, *tl, bmlen, bmval[2], attrlen, len = 0;
 1167 
 1168         /* Bitmap length + value */
 1169         NFSM_DISSECT(NFSX_UNSIGNED);
 1170 
 1171         bmlen = fxdr_unsigned(uint32_t, *tl++);
 1172         if (bmlen > 2)
 1173                 return (EBADRPC);
 1174 
 1175         if (bmlen == 0)
 1176                 return (0);
 1177 
 1178         NFSM_DISSECT(nfsm_rndup(bmlen << 2) + NFSX_UNSIGNED);
 1179 
 1180         bmval[0] = bmlen > 0 ? fxdr_unsigned(uint32_t, *tl++) : 0;
 1181         bmval[1] = bmlen > 1 ? fxdr_unsigned(uint32_t, *tl++) : 0;
 1182 
 1183         /* Attribute length */
 1184         attrlen = fxdr_unsigned(uint32_t, *tl++);
 1185 
 1186         /*
 1187          * XXX check for correct (<=) attributes mask return from
 1188          * server.  need to pass this in.
 1189          */
 1190 
 1191         if (FA4_ISSET(FA4_TYPE, bmval)) {
 1192                 /* overflow check */
 1193                 NFSM_DISSECT(NFSX_UNSIGNED);
 1194                 fa->fa4_type = fxdr_unsigned(uint32_t, *tl++);
 1195                 fa->fa4_valid |= FA4V_TYPE;
 1196                 len += NFSX_UNSIGNED;
 1197         }
 1198         if (FA4_ISSET(FA4_CHANGE, bmval)) {
 1199                 NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1200                 fa->fa4_changeid = fxdr_hyper(tl);
 1201                 fa->fa4_valid |= FA4V_CHANGEID;
 1202                 len += 2 * NFSX_UNSIGNED;
 1203         }
 1204         if (FA4_ISSET(FA4_SIZE, bmval)) {
 1205                 NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1206                 fa->fa4_size = fxdr_hyper(tl);
 1207                 fa->fa4_valid |= FA4V_SIZE;
 1208                 len += 2 * NFSX_UNSIGNED;
 1209         }
 1210         if (FA4_ISSET(FA4_FSID, bmval)) {
 1211                 NFSM_DISSECT(4 * NFSX_UNSIGNED);
 1212                 fa->fa4_fsid_major = fxdr_hyper(tl); tl += 2;
 1213                 fa->fa4_fsid_minor = fxdr_hyper(tl);
 1214                 fa->fa4_valid |= FA4V_SIZE;
 1215                 len += 4 * NFSX_UNSIGNED;
 1216         }
 1217         if (FA4_ISSET(FA4_LEASE_TIME, bmval)) {
 1218                 NFSM_DISSECT(NFSX_UNSIGNED);
 1219                 fa->fa4_lease_time = fxdr_unsigned(uint32_t, *tl++);
 1220                 fa->fa4_valid |= FA4V_LEASE_TIME;
 1221                 len += NFSX_UNSIGNED;
 1222         }
 1223         if (FA4_ISSET(FA4_RDATTR_ERROR, bmval)) {
 1224                 /* ignore for now; we only ask for it so the compound won't fail */
 1225                 NFSM_DISSECT(NFSX_UNSIGNED);
 1226                 tl++;
 1227                 len += NFSX_UNSIGNED;
 1228         }
 1229         if (FA4_ISSET(FA4_FILEID, bmval)) {
 1230                 NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1231                 fa->fa4_fileid = fxdr_hyper(tl);
 1232                 fa->fa4_valid |= FA4V_FILEID;
 1233                 len += 2 * NFSX_UNSIGNED;
 1234         }
 1235         if (FA4_ISSET(FA4_FILES_FREE, bmval)) {
 1236                 NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1237                 fa->fa4_ffree = fxdr_hyper(tl);
 1238                 fa->fa4_valid |= FA4V_FFREE;
 1239                 len += 2 * NFSX_UNSIGNED;
 1240         }
 1241         if (FA4_ISSET(FA4_FILES_TOTAL, bmval)) {
 1242                 NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1243                 fa->fa4_ftotal = fxdr_hyper(tl);
 1244                 fa->fa4_valid |= FA4V_FTOTAL;
 1245                 len += 2 * NFSX_UNSIGNED;
 1246         }
 1247         if (FA4_ISSET(FA4_MAXFILESIZE, bmval)) {
 1248                 NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1249                 fa->fa4_maxfilesize = fxdr_hyper(tl);
 1250                 fa->fa4_valid |= FA4V_MAXFILESIZE;
 1251                 len += 2 * NFSX_UNSIGNED;
 1252         }
 1253         if (FA4_ISSET(FA4_MAXNAME, bmval)) {
 1254                 NFSM_DISSECT(NFSX_UNSIGNED);
 1255                 fa->fa4_maxname = fxdr_unsigned(uint32_t, *tl++);
 1256                 fa->fa4_valid |= FA4V_MAXNAME;
 1257                 len += NFSX_UNSIGNED;
 1258         }
 1259         if (FA4_ISSET(FA4_MAXREAD, bmval)) {
 1260                 NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1261                 fa->fa4_maxread = fxdr_hyper(tl);
 1262                 fa->fa4_valid |= FA4V_MAXREAD;
 1263                 len += 2 * NFSX_UNSIGNED;
 1264         }
 1265         if (FA4_ISSET(FA4_MAXWRITE, bmval)) {
 1266                 NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1267                 fa->fa4_maxwrite = fxdr_hyper(tl);
 1268                 fa->fa4_valid |= FA4V_MAXWRITE;
 1269                 len += 2 * NFSX_UNSIGNED;
 1270         }
 1271 
 1272         if (FA4_ISSET(FA4_MODE, bmval)) {
 1273                 NFSM_DISSECT(NFSX_UNSIGNED);
 1274                 fa->fa4_mode = fxdr_unsigned(mode_t, *tl++);
 1275                 fa->fa4_valid |= FA4V_MODE;
 1276                 len += NFSX_UNSIGNED;
 1277         }
 1278         if (FA4_ISSET(FA4_NUMLINKS, bmval)) {
 1279                 NFSM_DISSECT(NFSX_UNSIGNED);
 1280                 fa->fa4_nlink = fxdr_unsigned(nlink_t, *tl++);
 1281                 fa->fa4_valid |= FA4V_NLINK;
 1282                 len += NFSX_UNSIGNED;
 1283         }
 1284         if (FA4_ISSET(FA4_OWNER, bmval)) {
 1285                 uint32_t ownerlen;
 1286                 int error;
 1287 
 1288                 NFSM_DISSECT(NFSX_UNSIGNED);
 1289 
 1290                 ownerlen = fxdr_unsigned(uint32_t, *tl++);
 1291                 NFSM_DISSECT(nfsm_rndup(ownerlen));
 1292                 error = idmap_name_to_uid((char *)tl, ownerlen, &fa->fa4_uid);
 1293                 if (error) 
 1294                         fa->fa4_uid = -2;
 1295                 fa->fa4_valid |= FA4V_UID;
 1296                 len += NFSX_UNSIGNED + nfsm_rndup(ownerlen);
 1297         }
 1298         if (FA4_ISSET(FA4_OWNER_GROUP, bmval)) {
 1299                 uint32_t ownergrouplen;
 1300                 int error;
 1301 
 1302                 NFSM_DISSECT(NFSX_UNSIGNED);
 1303                 ownergrouplen = fxdr_unsigned(uint32_t, *tl++);
 1304                 NFSM_DISSECT(nfsm_rndup(ownergrouplen));
 1305                 error = idmap_name_to_gid((char *)tl, ownergrouplen, &fa->fa4_gid);
 1306                 if (error) 
 1307                         fa->fa4_gid = -2;
 1308                 fa->fa4_valid |= FA4V_GID;
 1309                 len += NFSX_UNSIGNED + nfsm_rndup(ownergrouplen);
 1310         }
 1311         if (FA4_ISSET(FA4_RAWDEV, bmval)) {
 1312                 NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1313                 fa->fa4_rdev_major = fxdr_unsigned(uint32_t, *tl++);
 1314                 fa->fa4_rdev_minor = fxdr_unsigned(uint32_t, *tl++);
 1315                 fa->fa4_valid |= FA4V_RDEV;
 1316                 len += 2 * NFSX_UNSIGNED;
 1317         }
 1318         if (FA4_ISSET(FA4_SPACE_AVAIL, bmval)) {
 1319                 NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1320                 fa->fa4_savail = fxdr_hyper(tl);
 1321                 fa->fa4_valid |= FA4V_SAVAIL;
 1322                 len += 2 * NFSX_UNSIGNED;
 1323         }
 1324         if (FA4_ISSET(FA4_SPACE_FREE, bmval)) {
 1325                 NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1326                 fa->fa4_sfree = fxdr_hyper(tl);
 1327                 fa->fa4_valid |= FA4V_SFREE;
 1328                 len += 2 * NFSX_UNSIGNED;
 1329         }
 1330         if (FA4_ISSET(FA4_SPACE_TOTAL, bmval)) {
 1331                 NFSM_DISSECT(2 * NFSX_UNSIGNED);
 1332                 fa->fa4_stotal = fxdr_hyper(tl);
 1333                 fa->fa4_valid |= FA4V_STOTAL;
 1334                 len += 2 * NFSX_UNSIGNED;
 1335         }
 1336         if (FA4_ISSET(FA4_SPACE_USED, bmval)) {
 1337                 NFSM_ADV(2 * NFSX_UNSIGNED);
 1338                 len += 2 * NFSX_UNSIGNED;
 1339         }
 1340         if (FA4_ISSET(FA4_TIME_ACCESS, bmval)) {
 1341                 NFSM_MTOTIME(fa->fa4_atime);
 1342                 fa->fa4_valid |= FA4V_ATIME;
 1343                 len += 3 * NFSX_UNSIGNED;
 1344         }
 1345         if (FA4_ISSET(FA4_TIME_CREATE, bmval)) {
 1346                 NFSM_MTOTIME(fa->fa4_ctime);
 1347                 fa->fa4_valid |= FA4V_CTIME;
 1348                 len += 3 * NFSX_UNSIGNED;
 1349         }
 1350         if (FA4_ISSET(FA4_TIME_MODIFY, bmval)) {
 1351                 NFSM_MTOTIME(fa->fa4_mtime);
 1352                 fa->fa4_valid |= FA4V_MTIME;
 1353                 len += 3 * NFSX_UNSIGNED;
 1354         }
 1355 
 1356         if (len != attrlen)
 1357                 return (EBADRPC);
 1358 
 1359         return (0);
 1360 }

Cache object: 90d19353221b2d53141d8bea8f9be1b0


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


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.