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/10.2/sys/fs/nfsclient/nfs_clcomsubs.c 265469 2014-05-06 21:54:52Z 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 nfsstats newnfsstats;
   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                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
  204                         *tl = txdr_unsigned(NFSV4OP_SEQUENCE);
  205                         if (sep == NULL)
  206                                 nfsv4_setsequence(nmp, nd,
  207                                     NFSMNT_MDSSESSION(nmp),
  208                                     nfs_bigreply[procnum]);
  209                         else
  210                                 nfsv4_setsequence(nmp, nd, sep,
  211                                     nfs_bigreply[procnum]);
  212                 }
  213                 if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh > 0) {
  214                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
  215                         *tl = txdr_unsigned(NFSV4OP_PUTFH);
  216                         (void) nfsm_fhtom(nd, nfhp, fhlen, 0);
  217                         if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh
  218                             == 2 && procnum != NFSPROC_WRITEDS &&
  219                             procnum != NFSPROC_COMMITDS) {
  220                                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
  221                                 *tl = txdr_unsigned(NFSV4OP_GETATTR);
  222                                 /*
  223                                  * For Lookup Ops, we want all the directory
  224                                  * attributes, so we can load the name cache.
  225                                  */
  226                                 if (procnum == NFSPROC_LOOKUP ||
  227                                     procnum == NFSPROC_LOOKUPP)
  228                                         NFSGETATTR_ATTRBIT(&attrbits);
  229                                 else {
  230                                         NFSWCCATTR_ATTRBIT(&attrbits);
  231                                         nd->nd_flag |= ND_V4WCCATTR;
  232                                 }
  233                                 (void) nfsrv_putattrbit(nd, &attrbits);
  234                         }
  235                 }
  236                 if (procnum != NFSPROC_RENEW ||
  237                     (nd->nd_flag & ND_NFSV41) == 0) {
  238                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
  239                         *tl = txdr_unsigned(nfsv4_opmap[procnum].op);
  240                 }
  241         } else {
  242                 (void) nfsm_fhtom(nd, nfhp, fhlen, 0);
  243         }
  244         if (procnum < NFSV4_NPROCS)
  245                 NFSINCRGLOBAL(newnfsstats.rpccnt[procnum]);
  246 }
  247 
  248 #ifndef APPLE
  249 /*
  250  * copies a uio scatter/gather list to an mbuf chain.
  251  * NOTE: can ony handle iovcnt == 1
  252  */
  253 APPLESTATIC void
  254 nfsm_uiombuf(struct nfsrv_descript *nd, struct uio *uiop, int siz)
  255 {
  256         char *uiocp;
  257         struct mbuf *mp, *mp2;
  258         int xfer, left, mlen;
  259         int uiosiz, clflg, rem;
  260         char *cp, *tcp;
  261 
  262         KASSERT(uiop->uio_iovcnt == 1, ("nfsm_uiotombuf: iovcnt != 1"));
  263 
  264         if (siz > ncl_mbuf_mlen)        /* or should it >= MCLBYTES ?? */
  265                 clflg = 1;
  266         else
  267                 clflg = 0;
  268         rem = NFSM_RNDUP(siz) - siz;
  269         mp = mp2 = nd->nd_mb;
  270         while (siz > 0) {
  271                 left = uiop->uio_iov->iov_len;
  272                 uiocp = uiop->uio_iov->iov_base;
  273                 if (left > siz)
  274                         left = siz;
  275                 uiosiz = left;
  276                 while (left > 0) {
  277                         mlen = M_TRAILINGSPACE(mp);
  278                         if (mlen == 0) {
  279                                 if (clflg)
  280                                         NFSMCLGET(mp, M_WAITOK);
  281                                 else
  282                                         NFSMGET(mp);
  283                                 mbuf_setlen(mp, 0);
  284                                 mbuf_setnext(mp2, mp);
  285                                 mp2 = mp;
  286                                 mlen = M_TRAILINGSPACE(mp);
  287                         }
  288                         xfer = (left > mlen) ? mlen : left;
  289 #ifdef notdef
  290                         /* Not Yet.. */
  291                         if (uiop->uio_iov->iov_op != NULL)
  292                                 (*(uiop->uio_iov->iov_op))
  293                                 (uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp),
  294                                     xfer);
  295                         else
  296 #endif
  297                         if (uiop->uio_segflg == UIO_SYSSPACE)
  298                             NFSBCOPY(uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp),
  299                                 xfer);
  300                         else
  301                             copyin(CAST_USER_ADDR_T(uiocp), NFSMTOD(mp, caddr_t)
  302                                 + mbuf_len(mp), xfer);
  303                         mbuf_setlen(mp, mbuf_len(mp) + xfer);
  304                         left -= xfer;
  305                         uiocp += xfer;
  306                         uiop->uio_offset += xfer;
  307                         uiop->uio_resid -= xfer;
  308                 }
  309                 tcp = (char *)uiop->uio_iov->iov_base;
  310                 tcp += uiosiz;
  311                 uiop->uio_iov->iov_base = (void *)tcp;
  312                 uiop->uio_iov->iov_len -= uiosiz;
  313                 siz -= uiosiz;
  314         }
  315         if (rem > 0) {
  316                 if (rem > M_TRAILINGSPACE(mp)) {
  317                         NFSMGET(mp);
  318                         mbuf_setlen(mp, 0);
  319                         mbuf_setnext(mp2, mp);
  320                 }
  321                 cp = NFSMTOD(mp, caddr_t) + mbuf_len(mp);
  322                 for (left = 0; left < rem; left++)
  323                         *cp++ = '\0';
  324                 mbuf_setlen(mp, mbuf_len(mp) + rem);
  325                 nd->nd_bpos = cp;
  326         } else
  327                 nd->nd_bpos = NFSMTOD(mp, caddr_t) + mbuf_len(mp);
  328         nd->nd_mb = mp;
  329 }
  330 #endif  /* !APPLE */
  331 
  332 /*
  333  * Load vnode attributes from the xdr file attributes.
  334  * Returns EBADRPC if they can't be parsed, 0 otherwise.
  335  */
  336 APPLESTATIC int
  337 nfsm_loadattr(struct nfsrv_descript *nd, struct nfsvattr *nap)
  338 {
  339         struct nfs_fattr *fp;
  340         int error = 0;
  341 
  342         if (nd->nd_flag & ND_NFSV4) {
  343                 error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL,
  344                     NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL);
  345         } else if (nd->nd_flag & ND_NFSV3) {
  346                 NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V3FATTR);
  347                 nap->na_type = nfsv34tov_type(fp->fa_type);
  348                 nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode);
  349                 nap->na_rdev = makedev(fxdr_unsigned(u_char, fp->fa3_rdev.specdata1),
  350                         fxdr_unsigned(u_char, fp->fa3_rdev.specdata2));
  351                 nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
  352                 nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid);
  353                 nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid);
  354                 nap->na_size = fxdr_hyper(&fp->fa3_size);
  355                 nap->na_blocksize = NFS_FABLKSIZE;
  356                 nap->na_bytes = fxdr_hyper(&fp->fa3_used);
  357                 nap->na_fileid = fxdr_hyper(&fp->fa3_fileid);
  358                 fxdr_nfsv3time(&fp->fa3_atime, &nap->na_atime);
  359                 fxdr_nfsv3time(&fp->fa3_ctime, &nap->na_ctime);
  360                 fxdr_nfsv3time(&fp->fa3_mtime, &nap->na_mtime);
  361                 nap->na_flags = 0;
  362                 nap->na_filerev = 0;
  363         } else {
  364                 NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V2FATTR);
  365                 nap->na_type = nfsv2tov_type(fp->fa_type);
  366                 nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode);
  367                 if (nap->na_type == VNON || nap->na_type == VREG)
  368                         nap->na_type = IFTOVT(nap->na_mode);
  369                 nap->na_rdev = fxdr_unsigned(dev_t, fp->fa2_rdev);
  370 
  371                 /*
  372                  * Really ugly NFSv2 kludge.
  373                  */
  374                 if (nap->na_type == VCHR && nap->na_rdev == ((dev_t)-1))
  375                         nap->na_type = VFIFO;
  376                 nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
  377                 nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid);
  378                 nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid);
  379                 nap->na_size = fxdr_unsigned(u_int32_t, fp->fa2_size);
  380                 nap->na_blocksize = fxdr_unsigned(int32_t, fp->fa2_blocksize);
  381                 nap->na_bytes =
  382                     (u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks) *
  383                     NFS_FABLKSIZE;
  384                 nap->na_fileid = fxdr_unsigned(uint64_t, fp->fa2_fileid);
  385                 fxdr_nfsv2time(&fp->fa2_atime, &nap->na_atime);
  386                 fxdr_nfsv2time(&fp->fa2_mtime, &nap->na_mtime);
  387                 nap->na_flags = 0;
  388                 nap->na_ctime.tv_sec = fxdr_unsigned(u_int32_t,
  389                     fp->fa2_ctime.nfsv2_sec);
  390                 nap->na_ctime.tv_nsec = 0;
  391                 nap->na_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec);
  392                 nap->na_filerev = 0;
  393         }
  394 nfsmout:
  395         return (error);
  396 }
  397 
  398 /*
  399  * This function finds the directory cookie that corresponds to the
  400  * logical byte offset given.
  401  */
  402 APPLESTATIC nfsuint64 *
  403 nfscl_getcookie(struct nfsnode *np, off_t off, int add)
  404 {
  405         struct nfsdmap *dp, *dp2;
  406         int pos;
  407 
  408         pos = off / NFS_DIRBLKSIZ;
  409         if (pos == 0) {
  410                 KASSERT(!add, ("nfs getcookie add at 0"));
  411                 return (&nfs_nullcookie);
  412         }
  413         pos--;
  414         dp = LIST_FIRST(&np->n_cookies);
  415         if (!dp) {
  416                 if (add) {
  417                         MALLOC(dp, struct nfsdmap *, sizeof (struct nfsdmap),
  418                                 M_NFSDIROFF, M_WAITOK);
  419                         dp->ndm_eocookie = 0;
  420                         LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list);
  421                 } else
  422                         return (NULL);
  423         }
  424         while (pos >= NFSNUMCOOKIES) {
  425                 pos -= NFSNUMCOOKIES;
  426                 if (LIST_NEXT(dp, ndm_list) != NULL) {
  427                         if (!add && dp->ndm_eocookie < NFSNUMCOOKIES &&
  428                                 pos >= dp->ndm_eocookie)
  429                                 return (NULL);
  430                         dp = LIST_NEXT(dp, ndm_list);
  431                 } else if (add) {
  432                         MALLOC(dp2, struct nfsdmap *, sizeof (struct nfsdmap),
  433                                 M_NFSDIROFF, M_WAITOK);
  434                         dp2->ndm_eocookie = 0;
  435                         LIST_INSERT_AFTER(dp, dp2, ndm_list);
  436                         dp = dp2;
  437                 } else
  438                         return (NULL);
  439         }
  440         if (pos >= dp->ndm_eocookie) {
  441                 if (add)
  442                         dp->ndm_eocookie = pos + 1;
  443                 else
  444                         return (NULL);
  445         }
  446         return (&dp->ndm_cookies[pos]);
  447 }
  448 
  449 /*
  450  * Gets a file handle out of an nfs reply sent to the client and returns
  451  * the file handle and the file's attributes.
  452  * For V4, it assumes that Getfh and Getattr Op's results are here.
  453  */
  454 APPLESTATIC int
  455 nfscl_mtofh(struct nfsrv_descript *nd, struct nfsfh **nfhpp,
  456     struct nfsvattr *nap, int *attrflagp)
  457 {
  458         u_int32_t *tl;
  459         int error = 0, flag = 1;
  460 
  461         *nfhpp = NULL;
  462         *attrflagp = 0;
  463         /*
  464          * First get the file handle and vnode.
  465          */
  466         if (nd->nd_flag & ND_NFSV3) {
  467                 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
  468                 flag = fxdr_unsigned(int, *tl);
  469         } else if (nd->nd_flag & ND_NFSV4) {
  470                 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
  471         }
  472         if (flag) {
  473                 error = nfsm_getfh(nd, nfhpp);
  474                 if (error)
  475                         return (error);
  476         }
  477 
  478         /*
  479          * Now, get the attributes.
  480          */
  481         if (nd->nd_flag & ND_NFSV4) {
  482                 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
  483         } else if (nd->nd_flag & ND_NFSV3) {
  484                 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
  485                 if (flag) {
  486                         flag = fxdr_unsigned(int, *tl);
  487                 } else if (fxdr_unsigned(int, *tl)) {
  488                         error = nfsm_advance(nd, NFSX_V3FATTR, -1);
  489                         if (error)
  490                                 return (error);
  491                 }
  492         }
  493         if (flag) {
  494                 error = nfsm_loadattr(nd, nap);
  495                 if (!error)
  496                         *attrflagp = 1;
  497         }
  498 nfsmout:
  499         return (error);
  500 }
  501 
  502 /*
  503  * Put a state Id in the mbuf list.
  504  */
  505 APPLESTATIC void
  506 nfsm_stateidtom(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp, int flag)
  507 {
  508         nfsv4stateid_t *st;
  509 
  510         NFSM_BUILD(st, nfsv4stateid_t *, NFSX_STATEID);
  511         if (flag == NFSSTATEID_PUTALLZERO) {
  512                 st->seqid = 0;
  513                 st->other[0] = 0;
  514                 st->other[1] = 0;
  515                 st->other[2] = 0;
  516         } else if (flag == NFSSTATEID_PUTALLONE) {
  517                 st->seqid = 0xffffffff;
  518                 st->other[0] = 0xffffffff;
  519                 st->other[1] = 0xffffffff;
  520                 st->other[2] = 0xffffffff;
  521         } else if (flag == NFSSTATEID_PUTSEQIDZERO) {
  522                 st->seqid = 0;
  523                 st->other[0] = stateidp->other[0];
  524                 st->other[1] = stateidp->other[1];
  525                 st->other[2] = stateidp->other[2];
  526         } else {
  527                 st->seqid = stateidp->seqid;
  528                 st->other[0] = stateidp->other[0];
  529                 st->other[1] = stateidp->other[1];
  530                 st->other[2] = stateidp->other[2];
  531         }
  532 }
  533 
  534 /*
  535  * Initialize the owner/delegation sleep lock.
  536  */
  537 APPLESTATIC void
  538 nfscl_lockinit(struct nfsv4lock *lckp)
  539 {
  540 
  541         lckp->nfslock_usecnt = 0;
  542         lckp->nfslock_lock = 0;
  543 }
  544 
  545 /*
  546  * Get an exclusive lock. (Not needed for OpenBSD4, since there is only one
  547  * thread for each posix process in the kernel.)
  548  */
  549 APPLESTATIC void
  550 nfscl_lockexcl(struct nfsv4lock *lckp, void *mutex)
  551 {
  552         int igotlock;
  553 
  554         do {
  555                 igotlock = nfsv4_lock(lckp, 1, NULL, mutex, NULL);
  556         } while (!igotlock);
  557 }
  558 
  559 /*
  560  * Release an exclusive lock.
  561  */
  562 APPLESTATIC void
  563 nfscl_lockunlock(struct nfsv4lock *lckp)
  564 {
  565 
  566         nfsv4_unlock(lckp, 0);
  567 }
  568 
  569 /*
  570  * Called to derefernce a lock on a stateid (delegation or open owner).
  571  */
  572 APPLESTATIC void
  573 nfscl_lockderef(struct nfsv4lock *lckp)
  574 {
  575 
  576         NFSLOCKCLSTATE();
  577         lckp->nfslock_usecnt--;
  578         if (lckp->nfslock_usecnt == 0 && (lckp->nfslock_lock & NFSV4LOCK_WANTED)) {
  579                 lckp->nfslock_lock &= ~NFSV4LOCK_WANTED;
  580                 wakeup((caddr_t)lckp);
  581         }
  582         NFSUNLOCKCLSTATE();
  583 }
  584 

Cache object: 942e45d128950da329df83f6bbbd4bb1


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