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_clcomsubs.c

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

    1 /*-
    2  * Copyright (c) 1989, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * This code is derived from software contributed to Berkeley by
    6  * Rick Macklem at The University of Guelph.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 4. Neither the name of the University nor the names of its contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __FBSDID("$FreeBSD: releng/11.1/sys/fs/nfsclient/nfs_clcomsubs.c 318684 2017-05-22 22:02:06Z rmacklem $");
   36 
   37 /*
   38  * These functions support the macros and help fiddle mbuf chains for
   39  * the nfs op functions. They do things like create the rpc header and
   40  * copy data between mbuf chains and uio lists.
   41  */
   42 #ifndef APPLEKEXT
   43 #include <fs/nfs/nfsport.h>
   44 
   45 extern struct nfsstatsv1 nfsstatsv1;
   46 extern struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS];
   47 extern int ncl_mbuf_mlen;
   48 extern enum vtype newnv2tov_type[8];
   49 extern enum vtype nv34tov_type[8];
   50 extern int      nfs_bigreply[NFSV41_NPROCS];
   51 NFSCLSTATEMUTEX;
   52 #endif  /* !APPLEKEXT */
   53 
   54 static nfsuint64 nfs_nullcookie = {{ 0, 0 }};
   55 static struct {
   56         int     op;
   57         int     opcnt;
   58         const u_char *tag;
   59         int     taglen;
   60 } nfsv4_opmap[NFSV41_NPROCS] = {
   61         { 0, 1, "Null", 4 },
   62         { NFSV4OP_GETATTR, 1, "Getattr", 7, },
   63         { NFSV4OP_SETATTR, 2, "Setattr", 7, },
   64         { NFSV4OP_LOOKUP, 3, "Lookup", 6, },
   65         { NFSV4OP_ACCESS, 2, "Access", 6, },
   66         { NFSV4OP_READLINK, 2, "Readlink", 8, },
   67         { NFSV4OP_READ, 1, "Read", 4, },
   68         { NFSV4OP_WRITE, 2, "Write", 5, },
   69         { NFSV4OP_OPEN, 5, "Open", 4, },
   70         { NFSV4OP_CREATE, 5, "Create", 6, },
   71         { NFSV4OP_CREATE, 1, "Create", 6, },
   72         { NFSV4OP_CREATE, 3, "Create", 6, },
   73         { NFSV4OP_REMOVE, 1, "Remove", 6, },
   74         { NFSV4OP_REMOVE, 1, "Remove", 6, },
   75         { NFSV4OP_SAVEFH, 5, "Rename", 6, },
   76         { NFSV4OP_SAVEFH, 4, "Link", 4, },
   77         { NFSV4OP_READDIR, 2, "Readdir", 7, },
   78         { NFSV4OP_READDIR, 2, "Readdir", 7, },
   79         { NFSV4OP_GETATTR, 1, "Getattr", 7, },
   80         { NFSV4OP_GETATTR, 1, "Getattr", 7, },
   81         { NFSV4OP_GETATTR, 1, "Getattr", 7, },
   82         { NFSV4OP_COMMIT, 2, "Commit", 6, },
   83         { NFSV4OP_LOOKUPP, 3, "Lookupp", 7, },
   84         { NFSV4OP_SETCLIENTID, 1, "SetClientID", 11, },
   85         { NFSV4OP_SETCLIENTIDCFRM, 1, "SetClientIDConfirm", 18, },
   86         { NFSV4OP_LOCK, 1, "Lock", 4, },
   87         { NFSV4OP_LOCKU, 1, "LockU", 5, },
   88         { NFSV4OP_OPEN, 2, "Open", 4, },
   89         { NFSV4OP_CLOSE, 1, "Close", 5, },
   90         { NFSV4OP_OPENCONFIRM, 1, "Openconfirm", 11, },
   91         { NFSV4OP_LOCKT, 1, "LockT", 5, },
   92         { NFSV4OP_OPENDOWNGRADE, 1, "Opendowngrade", 13, },
   93         { NFSV4OP_RENEW, 1, "Renew", 5, },
   94         { NFSV4OP_PUTROOTFH, 1, "Dirpath", 7, },
   95         { NFSV4OP_RELEASELCKOWN, 1, "Rellckown", 9, },
   96         { NFSV4OP_DELEGRETURN, 1, "Delegret", 8, },
   97         { NFSV4OP_DELEGRETURN, 3, "DelegRemove", 11, },
   98         { NFSV4OP_DELEGRETURN, 7, "DelegRename1", 12, },
   99         { NFSV4OP_DELEGRETURN, 9, "DelegRename2", 12, },
  100         { NFSV4OP_GETATTR, 1, "Getacl", 6, },
  101         { NFSV4OP_SETATTR, 1, "Setacl", 6, },
  102         { NFSV4OP_EXCHANGEID, 1, "ExchangeID", 10, },
  103         { NFSV4OP_CREATESESSION, 1, "CreateSession", 13, },
  104         { NFSV4OP_DESTROYSESSION, 1, "DestroySession", 14, },
  105         { NFSV4OP_DESTROYCLIENTID, 1, "DestroyClient", 13, },
  106         { NFSV4OP_FREESTATEID, 1, "FreeStateID", 11, },
  107         { NFSV4OP_LAYOUTGET, 1, "LayoutGet", 9, },
  108         { NFSV4OP_GETDEVINFO, 1, "GetDeviceInfo", 13, },
  109         { NFSV4OP_LAYOUTCOMMIT, 1, "LayoutCommit", 12, },
  110         { NFSV4OP_LAYOUTRETURN, 1, "LayoutReturn", 12, },
  111         { NFSV4OP_RECLAIMCOMPL, 1, "ReclaimComplete", 15, },
  112         { NFSV4OP_WRITE, 1, "WriteDS", 7, },
  113         { NFSV4OP_READ, 1, "ReadDS", 6, },
  114         { NFSV4OP_COMMIT, 1, "CommitDS", 8, },
  115 };
  116 
  117 /*
  118  * NFS RPCS that have large request message size.
  119  */
  120 static int nfs_bigrequest[NFSV41_NPROCS] = {
  121         0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  122         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  123         0, 0, 0, 0, 0, 0, 1, 0, 0
  124 };
  125 
  126 /*
  127  * Start building a request. Mostly just put the first file handle in
  128  * place.
  129  */
  130 APPLESTATIC void
  131 nfscl_reqstart(struct nfsrv_descript *nd, int procnum, struct nfsmount *nmp,
  132     u_int8_t *nfhp, int fhlen, u_int32_t **opcntpp, struct nfsclsession *sep)
  133 {
  134         struct mbuf *mb;
  135         u_int32_t *tl;
  136         int opcnt;
  137         nfsattrbit_t attrbits;
  138 
  139         /*
  140          * First, fill in some of the fields of nd.
  141          */
  142         nd->nd_slotseq = NULL;
  143         if (NFSHASNFSV4(nmp)) {
  144                 nd->nd_flag = ND_NFSV4 | ND_NFSCL;
  145                 if (NFSHASNFSV4N(nmp))
  146                         nd->nd_flag |= ND_NFSV41;
  147         } else if (NFSHASNFSV3(nmp))
  148                 nd->nd_flag = ND_NFSV3 | ND_NFSCL;
  149         else
  150                 nd->nd_flag = ND_NFSV2 | ND_NFSCL;
  151         nd->nd_procnum = procnum;
  152         nd->nd_repstat = 0;
  153 
  154         /*
  155          * Get the first mbuf for the request.
  156          */
  157         if (nfs_bigrequest[procnum])
  158                 NFSMCLGET(mb, M_WAITOK);
  159         else
  160                 NFSMGET(mb);
  161         mbuf_setlen(mb, 0);
  162         nd->nd_mreq = nd->nd_mb = mb;
  163         nd->nd_bpos = NFSMTOD(mb, caddr_t);
  164         
  165         /*
  166          * And fill the first file handle into the request.
  167          */
  168         if (nd->nd_flag & ND_NFSV4) {
  169                 opcnt = nfsv4_opmap[procnum].opcnt +
  170                     nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh;
  171                 if ((nd->nd_flag & ND_NFSV41) != 0) {
  172                         opcnt += nfsv4_opflag[nfsv4_opmap[procnum].op].needsseq;
  173                         if (procnum == NFSPROC_RENEW)
  174                                 /*
  175                                  * For the special case of Renew, just do a
  176                                  * Sequence Op.
  177                                  */
  178                                 opcnt = 1;
  179                         else if (procnum == NFSPROC_WRITEDS ||
  180                             procnum == NFSPROC_COMMITDS)
  181                                 /*
  182                                  * For the special case of a Writeor Commit to
  183                                  * a DS, the opcnt == 3, for Sequence, PutFH,
  184                                  * Write/Commit.
  185                                  */
  186                                 opcnt = 3;
  187                 }
  188                 /*
  189                  * What should the tag really be?
  190                  */
  191                 (void) nfsm_strtom(nd, nfsv4_opmap[procnum].tag,
  192                         nfsv4_opmap[procnum].taglen);
  193                 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
  194                 if ((nd->nd_flag & ND_NFSV41) != 0)
  195                         *tl++ = txdr_unsigned(NFSV41_MINORVERSION);
  196                 else
  197                         *tl++ = txdr_unsigned(NFSV4_MINORVERSION);
  198                 if (opcntpp != NULL)
  199                         *opcntpp = tl;
  200                 *tl = txdr_unsigned(opcnt);
  201                 if ((nd->nd_flag & ND_NFSV41) != 0 &&
  202                     nfsv4_opflag[nfsv4_opmap[procnum].op].needsseq > 0) {
  203                         if (nfsv4_opflag[nfsv4_opmap[procnum].op].loopbadsess >
  204                             0)
  205                                 nd->nd_flag |= ND_LOOPBADSESS;
  206                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
  207                         *tl = txdr_unsigned(NFSV4OP_SEQUENCE);
  208                         if (sep == NULL) {
  209                                 sep = nfsmnt_mdssession(nmp);
  210                                 nfsv4_setsequence(nmp, nd, sep,
  211                                     nfs_bigreply[procnum]);
  212                         } else
  213                                 nfsv4_setsequence(nmp, nd, sep,
  214                                     nfs_bigreply[procnum]);
  215                 }
  216                 if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh > 0) {
  217                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
  218                         *tl = txdr_unsigned(NFSV4OP_PUTFH);
  219                         (void) nfsm_fhtom(nd, nfhp, fhlen, 0);
  220                         if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh
  221                             == 2 && procnum != NFSPROC_WRITEDS &&
  222                             procnum != NFSPROC_COMMITDS) {
  223                                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
  224                                 *tl = txdr_unsigned(NFSV4OP_GETATTR);
  225                                 /*
  226                                  * For Lookup Ops, we want all the directory
  227                                  * attributes, so we can load the name cache.
  228                                  */
  229                                 if (procnum == NFSPROC_LOOKUP ||
  230                                     procnum == NFSPROC_LOOKUPP)
  231                                         NFSGETATTR_ATTRBIT(&attrbits);
  232                                 else {
  233                                         NFSWCCATTR_ATTRBIT(&attrbits);
  234                                         nd->nd_flag |= ND_V4WCCATTR;
  235                                 }
  236                                 (void) nfsrv_putattrbit(nd, &attrbits);
  237                         }
  238                 }
  239                 if (procnum != NFSPROC_RENEW ||
  240                     (nd->nd_flag & ND_NFSV41) == 0) {
  241                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
  242                         *tl = txdr_unsigned(nfsv4_opmap[procnum].op);
  243                 }
  244         } else {
  245                 (void) nfsm_fhtom(nd, nfhp, fhlen, 0);
  246         }
  247         if (procnum < NFSV41_NPROCS)
  248                 NFSINCRGLOBAL(nfsstatsv1.rpccnt[procnum]);
  249 }
  250 
  251 #ifndef APPLE
  252 /*
  253  * copies a uio scatter/gather list to an mbuf chain.
  254  * NOTE: can ony handle iovcnt == 1
  255  */
  256 APPLESTATIC void
  257 nfsm_uiombuf(struct nfsrv_descript *nd, struct uio *uiop, int siz)
  258 {
  259         char *uiocp;
  260         struct mbuf *mp, *mp2;
  261         int xfer, left, mlen;
  262         int uiosiz, clflg, rem;
  263         char *cp, *tcp;
  264 
  265         KASSERT(uiop->uio_iovcnt == 1, ("nfsm_uiotombuf: iovcnt != 1"));
  266 
  267         if (siz > ncl_mbuf_mlen)        /* or should it >= MCLBYTES ?? */
  268                 clflg = 1;
  269         else
  270                 clflg = 0;
  271         rem = NFSM_RNDUP(siz) - siz;
  272         mp = mp2 = nd->nd_mb;
  273         while (siz > 0) {
  274                 left = uiop->uio_iov->iov_len;
  275                 uiocp = uiop->uio_iov->iov_base;
  276                 if (left > siz)
  277                         left = siz;
  278                 uiosiz = left;
  279                 while (left > 0) {
  280                         mlen = M_TRAILINGSPACE(mp);
  281                         if (mlen == 0) {
  282                                 if (clflg)
  283                                         NFSMCLGET(mp, M_WAITOK);
  284                                 else
  285                                         NFSMGET(mp);
  286                                 mbuf_setlen(mp, 0);
  287                                 mbuf_setnext(mp2, mp);
  288                                 mp2 = mp;
  289                                 mlen = M_TRAILINGSPACE(mp);
  290                         }
  291                         xfer = (left > mlen) ? mlen : left;
  292 #ifdef notdef
  293                         /* Not Yet.. */
  294                         if (uiop->uio_iov->iov_op != NULL)
  295                                 (*(uiop->uio_iov->iov_op))
  296                                 (uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp),
  297                                     xfer);
  298                         else
  299 #endif
  300                         if (uiop->uio_segflg == UIO_SYSSPACE)
  301                             NFSBCOPY(uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp),
  302                                 xfer);
  303                         else
  304                             copyin(CAST_USER_ADDR_T(uiocp), NFSMTOD(mp, caddr_t)
  305                                 + mbuf_len(mp), xfer);
  306                         mbuf_setlen(mp, mbuf_len(mp) + xfer);
  307                         left -= xfer;
  308                         uiocp += xfer;
  309                         uiop->uio_offset += xfer;
  310                         uiop->uio_resid -= xfer;
  311                 }
  312                 tcp = (char *)uiop->uio_iov->iov_base;
  313                 tcp += uiosiz;
  314                 uiop->uio_iov->iov_base = (void *)tcp;
  315                 uiop->uio_iov->iov_len -= uiosiz;
  316                 siz -= uiosiz;
  317         }
  318         if (rem > 0) {
  319                 if (rem > M_TRAILINGSPACE(mp)) {
  320                         NFSMGET(mp);
  321                         mbuf_setlen(mp, 0);
  322                         mbuf_setnext(mp2, mp);
  323                 }
  324                 cp = NFSMTOD(mp, caddr_t) + mbuf_len(mp);
  325                 for (left = 0; left < rem; left++)
  326                         *cp++ = '\0';
  327                 mbuf_setlen(mp, mbuf_len(mp) + rem);
  328                 nd->nd_bpos = cp;
  329         } else
  330                 nd->nd_bpos = NFSMTOD(mp, caddr_t) + mbuf_len(mp);
  331         nd->nd_mb = mp;
  332 }
  333 #endif  /* !APPLE */
  334 
  335 /*
  336  * Load vnode attributes from the xdr file attributes.
  337  * Returns EBADRPC if they can't be parsed, 0 otherwise.
  338  */
  339 APPLESTATIC int
  340 nfsm_loadattr(struct nfsrv_descript *nd, struct nfsvattr *nap)
  341 {
  342         struct nfs_fattr *fp;
  343         int error = 0;
  344 
  345         if (nd->nd_flag & ND_NFSV4) {
  346                 error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL,
  347                     NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL);
  348         } else if (nd->nd_flag & ND_NFSV3) {
  349                 NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V3FATTR);
  350                 nap->na_type = nfsv34tov_type(fp->fa_type);
  351                 nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode);
  352                 nap->na_rdev = makedev(fxdr_unsigned(u_char, fp->fa3_rdev.specdata1),
  353                         fxdr_unsigned(u_char, fp->fa3_rdev.specdata2));
  354                 nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
  355                 nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid);
  356                 nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid);
  357                 nap->na_size = fxdr_hyper(&fp->fa3_size);
  358                 nap->na_blocksize = NFS_FABLKSIZE;
  359                 nap->na_bytes = fxdr_hyper(&fp->fa3_used);
  360                 nap->na_fileid = fxdr_hyper(&fp->fa3_fileid);
  361                 fxdr_nfsv3time(&fp->fa3_atime, &nap->na_atime);
  362                 fxdr_nfsv3time(&fp->fa3_ctime, &nap->na_ctime);
  363                 fxdr_nfsv3time(&fp->fa3_mtime, &nap->na_mtime);
  364                 nap->na_flags = 0;
  365                 nap->na_filerev = 0;
  366         } else {
  367                 NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V2FATTR);
  368                 nap->na_type = nfsv2tov_type(fp->fa_type);
  369                 nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode);
  370                 if (nap->na_type == VNON || nap->na_type == VREG)
  371                         nap->na_type = IFTOVT(nap->na_mode);
  372                 nap->na_rdev = fxdr_unsigned(dev_t, fp->fa2_rdev);
  373 
  374                 /*
  375                  * Really ugly NFSv2 kludge.
  376                  */
  377                 if (nap->na_type == VCHR && nap->na_rdev == ((dev_t)-1))
  378                         nap->na_type = VFIFO;
  379                 nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
  380                 nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid);
  381                 nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid);
  382                 nap->na_size = fxdr_unsigned(u_int32_t, fp->fa2_size);
  383                 nap->na_blocksize = fxdr_unsigned(int32_t, fp->fa2_blocksize);
  384                 nap->na_bytes =
  385                     (u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks) *
  386                     NFS_FABLKSIZE;
  387                 nap->na_fileid = fxdr_unsigned(uint64_t, fp->fa2_fileid);
  388                 fxdr_nfsv2time(&fp->fa2_atime, &nap->na_atime);
  389                 fxdr_nfsv2time(&fp->fa2_mtime, &nap->na_mtime);
  390                 nap->na_flags = 0;
  391                 nap->na_ctime.tv_sec = fxdr_unsigned(u_int32_t,
  392                     fp->fa2_ctime.nfsv2_sec);
  393                 nap->na_ctime.tv_nsec = 0;
  394                 nap->na_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec);
  395                 nap->na_filerev = 0;
  396         }
  397 nfsmout:
  398         return (error);
  399 }
  400 
  401 /*
  402  * This function finds the directory cookie that corresponds to the
  403  * logical byte offset given.
  404  */
  405 APPLESTATIC nfsuint64 *
  406 nfscl_getcookie(struct nfsnode *np, off_t off, int add)
  407 {
  408         struct nfsdmap *dp, *dp2;
  409         int pos;
  410 
  411         pos = off / NFS_DIRBLKSIZ;
  412         if (pos == 0) {
  413                 KASSERT(!add, ("nfs getcookie add at 0"));
  414                 return (&nfs_nullcookie);
  415         }
  416         pos--;
  417         dp = LIST_FIRST(&np->n_cookies);
  418         if (!dp) {
  419                 if (add) {
  420                         MALLOC(dp, struct nfsdmap *, sizeof (struct nfsdmap),
  421                                 M_NFSDIROFF, M_WAITOK);
  422                         dp->ndm_eocookie = 0;
  423                         LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list);
  424                 } else
  425                         return (NULL);
  426         }
  427         while (pos >= NFSNUMCOOKIES) {
  428                 pos -= NFSNUMCOOKIES;
  429                 if (LIST_NEXT(dp, ndm_list) != NULL) {
  430                         if (!add && dp->ndm_eocookie < NFSNUMCOOKIES &&
  431                                 pos >= dp->ndm_eocookie)
  432                                 return (NULL);
  433                         dp = LIST_NEXT(dp, ndm_list);
  434                 } else if (add) {
  435                         MALLOC(dp2, struct nfsdmap *, sizeof (struct nfsdmap),
  436                                 M_NFSDIROFF, M_WAITOK);
  437                         dp2->ndm_eocookie = 0;
  438                         LIST_INSERT_AFTER(dp, dp2, ndm_list);
  439                         dp = dp2;
  440                 } else
  441                         return (NULL);
  442         }
  443         if (pos >= dp->ndm_eocookie) {
  444                 if (add)
  445                         dp->ndm_eocookie = pos + 1;
  446                 else
  447                         return (NULL);
  448         }
  449         return (&dp->ndm_cookies[pos]);
  450 }
  451 
  452 /*
  453  * Gets a file handle out of an nfs reply sent to the client and returns
  454  * the file handle and the file's attributes.
  455  * For V4, it assumes that Getfh and Getattr Op's results are here.
  456  */
  457 APPLESTATIC int
  458 nfscl_mtofh(struct nfsrv_descript *nd, struct nfsfh **nfhpp,
  459     struct nfsvattr *nap, int *attrflagp)
  460 {
  461         u_int32_t *tl;
  462         int error = 0, flag = 1;
  463 
  464         *nfhpp = NULL;
  465         *attrflagp = 0;
  466         /*
  467          * First get the file handle and vnode.
  468          */
  469         if (nd->nd_flag & ND_NFSV3) {
  470                 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
  471                 flag = fxdr_unsigned(int, *tl);
  472         } else if (nd->nd_flag & ND_NFSV4) {
  473                 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
  474                 /* If the GetFH failed, clear flag. */
  475                 if (*++tl != 0) {
  476                         nd->nd_flag |= ND_NOMOREDATA;
  477                         flag = 0;
  478                         error = ENXIO;  /* Return ENXIO so *nfhpp isn't used. */
  479                 }
  480         }
  481         if (flag) {
  482                 error = nfsm_getfh(nd, nfhpp);
  483                 if (error)
  484                         return (error);
  485         }
  486 
  487         /*
  488          * Now, get the attributes.
  489          */
  490         if (flag != 0 && (nd->nd_flag & ND_NFSV4) != 0) {
  491                 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
  492                 if (*++tl != 0) {
  493                         nd->nd_flag |= ND_NOMOREDATA;
  494                         flag = 0;
  495                 }
  496         } else if (nd->nd_flag & ND_NFSV3) {
  497                 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
  498                 if (flag) {
  499                         flag = fxdr_unsigned(int, *tl);
  500                 } else if (fxdr_unsigned(int, *tl)) {
  501                         error = nfsm_advance(nd, NFSX_V3FATTR, -1);
  502                         if (error)
  503                                 return (error);
  504                 }
  505         }
  506         if (flag) {
  507                 error = nfsm_loadattr(nd, nap);
  508                 if (!error)
  509                         *attrflagp = 1;
  510         }
  511 nfsmout:
  512         return (error);
  513 }
  514 
  515 /*
  516  * Put a state Id in the mbuf list.
  517  */
  518 APPLESTATIC void
  519 nfsm_stateidtom(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp, int flag)
  520 {
  521         nfsv4stateid_t *st;
  522 
  523         NFSM_BUILD(st, nfsv4stateid_t *, NFSX_STATEID);
  524         if (flag == NFSSTATEID_PUTALLZERO) {
  525                 st->seqid = 0;
  526                 st->other[0] = 0;
  527                 st->other[1] = 0;
  528                 st->other[2] = 0;
  529         } else if (flag == NFSSTATEID_PUTALLONE) {
  530                 st->seqid = 0xffffffff;
  531                 st->other[0] = 0xffffffff;
  532                 st->other[1] = 0xffffffff;
  533                 st->other[2] = 0xffffffff;
  534         } else if (flag == NFSSTATEID_PUTSEQIDZERO) {
  535                 st->seqid = 0;
  536                 st->other[0] = stateidp->other[0];
  537                 st->other[1] = stateidp->other[1];
  538                 st->other[2] = stateidp->other[2];
  539         } else {
  540                 st->seqid = stateidp->seqid;
  541                 st->other[0] = stateidp->other[0];
  542                 st->other[1] = stateidp->other[1];
  543                 st->other[2] = stateidp->other[2];
  544         }
  545 }
  546 
  547 /*
  548  * Initialize the owner/delegation sleep lock.
  549  */
  550 APPLESTATIC void
  551 nfscl_lockinit(struct nfsv4lock *lckp)
  552 {
  553 
  554         lckp->nfslock_usecnt = 0;
  555         lckp->nfslock_lock = 0;
  556 }
  557 
  558 /*
  559  * Get an exclusive lock. (Not needed for OpenBSD4, since there is only one
  560  * thread for each posix process in the kernel.)
  561  */
  562 APPLESTATIC void
  563 nfscl_lockexcl(struct nfsv4lock *lckp, void *mutex)
  564 {
  565         int igotlock;
  566 
  567         do {
  568                 igotlock = nfsv4_lock(lckp, 1, NULL, mutex, NULL);
  569         } while (!igotlock);
  570 }
  571 
  572 /*
  573  * Release an exclusive lock.
  574  */
  575 APPLESTATIC void
  576 nfscl_lockunlock(struct nfsv4lock *lckp)
  577 {
  578 
  579         nfsv4_unlock(lckp, 0);
  580 }
  581 
  582 /*
  583  * Called to derefernce a lock on a stateid (delegation or open owner).
  584  */
  585 APPLESTATIC void
  586 nfscl_lockderef(struct nfsv4lock *lckp)
  587 {
  588 
  589         NFSLOCKCLSTATE();
  590         lckp->nfslock_usecnt--;
  591         if (lckp->nfslock_usecnt == 0 && (lckp->nfslock_lock & NFSV4LOCK_WANTED)) {
  592                 lckp->nfslock_lock &= ~NFSV4LOCK_WANTED;
  593                 wakeup((caddr_t)lckp);
  594         }
  595         NFSUNLOCKCLSTATE();
  596 }
  597 

Cache object: f6411bbba09478fcbe546f4e477addca


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