1191783Srmacklem/*- 2191783Srmacklem * Copyright (c) 1989, 1993 3191783Srmacklem * The Regents of the University of California. All rights reserved. 4191783Srmacklem * 5191783Srmacklem * This code is derived from software contributed to Berkeley by 6191783Srmacklem * Rick Macklem at The University of Guelph. 7191783Srmacklem * 8191783Srmacklem * Redistribution and use in source and binary forms, with or without 9191783Srmacklem * modification, are permitted provided that the following conditions 10191783Srmacklem * are met: 11191783Srmacklem * 1. Redistributions of source code must retain the above copyright 12191783Srmacklem * notice, this list of conditions and the following disclaimer. 13191783Srmacklem * 2. Redistributions in binary form must reproduce the above copyright 14191783Srmacklem * notice, this list of conditions and the following disclaimer in the 15191783Srmacklem * documentation and/or other materials provided with the distribution. 16191783Srmacklem * 4. Neither the name of the University nor the names of its contributors 17191783Srmacklem * may be used to endorse or promote products derived from this software 18191783Srmacklem * without specific prior written permission. 19191783Srmacklem * 20191783Srmacklem * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21191783Srmacklem * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22191783Srmacklem * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23191783Srmacklem * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24191783Srmacklem * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25191783Srmacklem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26191783Srmacklem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27191783Srmacklem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28191783Srmacklem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29191783Srmacklem * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30191783Srmacklem * SUCH DAMAGE. 31191783Srmacklem * 32191783Srmacklem */ 33191783Srmacklem 34191783Srmacklem#include <sys/cdefs.h> 35191783Srmacklem__FBSDID("$FreeBSD: releng/10.2/sys/fs/nfsclient/nfs_clcomsubs.c 265469 2014-05-06 21:54:52Z rmacklem $"); 36191783Srmacklem 37191783Srmacklem/* 38191783Srmacklem * These functions support the macros and help fiddle mbuf chains for 39191783Srmacklem * the nfs op functions. They do things like create the rpc header and 40191783Srmacklem * copy data between mbuf chains and uio lists. 41191783Srmacklem */ 42191783Srmacklem#ifndef APPLEKEXT 43191783Srmacklem#include <fs/nfs/nfsport.h> 44191783Srmacklem 45191783Srmacklemextern struct nfsstats newnfsstats; 46244042Srmacklemextern struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS]; 47191783Srmacklemextern int ncl_mbuf_mlen; 48191783Srmacklemextern enum vtype newnv2tov_type[8]; 49191783Srmacklemextern enum vtype nv34tov_type[8]; 50244042Srmacklemextern int nfs_bigreply[NFSV41_NPROCS]; 51191783SrmacklemNFSCLSTATEMUTEX; 52191783Srmacklem#endif /* !APPLEKEXT */ 53191783Srmacklem 54191783Srmacklemstatic nfsuint64 nfs_nullcookie = {{ 0, 0 }}; 55191783Srmacklemstatic struct { 56191783Srmacklem int op; 57191783Srmacklem int opcnt; 58191783Srmacklem const u_char *tag; 59191783Srmacklem int taglen; 60244042Srmacklem} nfsv4_opmap[NFSV41_NPROCS] = { 61191783Srmacklem { 0, 1, "Null", 4 }, 62191783Srmacklem { NFSV4OP_GETATTR, 1, "Getattr", 7, }, 63191783Srmacklem { NFSV4OP_SETATTR, 2, "Setattr", 7, }, 64191783Srmacklem { NFSV4OP_LOOKUP, 3, "Lookup", 6, }, 65191783Srmacklem { NFSV4OP_ACCESS, 2, "Access", 6, }, 66191783Srmacklem { NFSV4OP_READLINK, 2, "Readlink", 8, }, 67191783Srmacklem { NFSV4OP_READ, 1, "Read", 4, }, 68191783Srmacklem { NFSV4OP_WRITE, 2, "Write", 5, }, 69265466Srmacklem { NFSV4OP_OPEN, 5, "Open", 4, }, 70265469Srmacklem { NFSV4OP_CREATE, 5, "Create", 6, }, 71191783Srmacklem { NFSV4OP_CREATE, 1, "Create", 6, }, 72191783Srmacklem { NFSV4OP_CREATE, 3, "Create", 6, }, 73191783Srmacklem { NFSV4OP_REMOVE, 1, "Remove", 6, }, 74191783Srmacklem { NFSV4OP_REMOVE, 1, "Remove", 6, }, 75191783Srmacklem { NFSV4OP_SAVEFH, 5, "Rename", 6, }, 76191783Srmacklem { NFSV4OP_SAVEFH, 4, "Link", 4, }, 77191783Srmacklem { NFSV4OP_READDIR, 2, "Readdir", 7, }, 78191783Srmacklem { NFSV4OP_READDIR, 2, "Readdir", 7, }, 79191783Srmacklem { NFSV4OP_GETATTR, 1, "Getattr", 7, }, 80191783Srmacklem { NFSV4OP_GETATTR, 1, "Getattr", 7, }, 81191783Srmacklem { NFSV4OP_GETATTR, 1, "Getattr", 7, }, 82191783Srmacklem { NFSV4OP_COMMIT, 2, "Commit", 6, }, 83191783Srmacklem { NFSV4OP_LOOKUPP, 3, "Lookupp", 7, }, 84191783Srmacklem { NFSV4OP_SETCLIENTID, 1, "SetClientID", 11, }, 85191783Srmacklem { NFSV4OP_SETCLIENTIDCFRM, 1, "SetClientIDConfirm", 18, }, 86191783Srmacklem { NFSV4OP_LOCK, 1, "Lock", 4, }, 87191783Srmacklem { NFSV4OP_LOCKU, 1, "LockU", 5, }, 88191783Srmacklem { NFSV4OP_OPEN, 2, "Open", 4, }, 89191783Srmacklem { NFSV4OP_CLOSE, 1, "Close", 5, }, 90191783Srmacklem { NFSV4OP_OPENCONFIRM, 1, "Openconfirm", 11, }, 91191783Srmacklem { NFSV4OP_LOCKT, 1, "LockT", 5, }, 92191783Srmacklem { NFSV4OP_OPENDOWNGRADE, 1, "Opendowngrade", 13, }, 93191783Srmacklem { NFSV4OP_RENEW, 1, "Renew", 5, }, 94191783Srmacklem { NFSV4OP_PUTROOTFH, 1, "Dirpath", 7, }, 95191783Srmacklem { NFSV4OP_RELEASELCKOWN, 1, "Rellckown", 9, }, 96191783Srmacklem { NFSV4OP_DELEGRETURN, 1, "Delegret", 8, }, 97191783Srmacklem { NFSV4OP_DELEGRETURN, 3, "DelegRemove", 11, }, 98191783Srmacklem { NFSV4OP_DELEGRETURN, 7, "DelegRename1", 12, }, 99191783Srmacklem { NFSV4OP_DELEGRETURN, 9, "DelegRename2", 12, }, 100191783Srmacklem { NFSV4OP_GETATTR, 1, "Getacl", 6, }, 101191783Srmacklem { NFSV4OP_SETATTR, 1, "Setacl", 6, }, 102244042Srmacklem { NFSV4OP_EXCHANGEID, 1, "ExchangeID", 10, }, 103244042Srmacklem { NFSV4OP_CREATESESSION, 1, "CreateSession", 13, }, 104244042Srmacklem { NFSV4OP_DESTROYSESSION, 1, "DestroySession", 14, }, 105244042Srmacklem { NFSV4OP_DESTROYCLIENTID, 1, "DestroyClient", 13, }, 106244042Srmacklem { NFSV4OP_FREESTATEID, 1, "FreeStateID", 11, }, 107244042Srmacklem { NFSV4OP_LAYOUTGET, 1, "LayoutGet", 9, }, 108244042Srmacklem { NFSV4OP_GETDEVINFO, 1, "GetDeviceInfo", 13, }, 109244042Srmacklem { NFSV4OP_LAYOUTCOMMIT, 1, "LayoutCommit", 12, }, 110244042Srmacklem { NFSV4OP_LAYOUTRETURN, 1, "LayoutReturn", 12, }, 111244042Srmacklem { NFSV4OP_RECLAIMCOMPL, 1, "ReclaimComplete", 15, }, 112244042Srmacklem { NFSV4OP_WRITE, 1, "WriteDS", 7, }, 113244042Srmacklem { NFSV4OP_READ, 1, "ReadDS", 6, }, 114244042Srmacklem { NFSV4OP_COMMIT, 1, "CommitDS", 8, }, 115191783Srmacklem}; 116191783Srmacklem 117191783Srmacklem/* 118191783Srmacklem * NFS RPCS that have large request message size. 119191783Srmacklem */ 120244042Srmacklemstatic int nfs_bigrequest[NFSV41_NPROCS] = { 121191783Srmacklem 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122244042Srmacklem 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123244042Srmacklem 0, 0, 0, 0, 0, 0, 1, 0, 0 124191783Srmacklem}; 125191783Srmacklem 126191783Srmacklem/* 127191783Srmacklem * Start building a request. Mostly just put the first file handle in 128191783Srmacklem * place. 129191783Srmacklem */ 130191783SrmacklemAPPLESTATIC void 131191783Srmacklemnfscl_reqstart(struct nfsrv_descript *nd, int procnum, struct nfsmount *nmp, 132244042Srmacklem u_int8_t *nfhp, int fhlen, u_int32_t **opcntpp, struct nfsclsession *sep) 133191783Srmacklem{ 134191783Srmacklem struct mbuf *mb; 135191783Srmacklem u_int32_t *tl; 136191783Srmacklem int opcnt; 137191783Srmacklem nfsattrbit_t attrbits; 138191783Srmacklem 139191783Srmacklem /* 140191783Srmacklem * First, fill in some of the fields of nd. 141191783Srmacklem */ 142244042Srmacklem nd->nd_slotseq = NULL; 143244042Srmacklem if (NFSHASNFSV4(nmp)) { 144240720Srmacklem nd->nd_flag = ND_NFSV4 | ND_NFSCL; 145244042Srmacklem if (NFSHASNFSV4N(nmp)) 146244042Srmacklem nd->nd_flag |= ND_NFSV41; 147244042Srmacklem } else if (NFSHASNFSV3(nmp)) 148240720Srmacklem nd->nd_flag = ND_NFSV3 | ND_NFSCL; 149191783Srmacklem else 150240720Srmacklem nd->nd_flag = ND_NFSV2 | ND_NFSCL; 151191783Srmacklem nd->nd_procnum = procnum; 152191783Srmacklem nd->nd_repstat = 0; 153191783Srmacklem 154191783Srmacklem /* 155191783Srmacklem * Get the first mbuf for the request. 156191783Srmacklem */ 157191783Srmacklem if (nfs_bigrequest[procnum]) 158243882Sglebius NFSMCLGET(mb, M_WAITOK); 159191783Srmacklem else 160191783Srmacklem NFSMGET(mb); 161191783Srmacklem mbuf_setlen(mb, 0); 162191783Srmacklem nd->nd_mreq = nd->nd_mb = mb; 163191783Srmacklem nd->nd_bpos = NFSMTOD(mb, caddr_t); 164191783Srmacklem 165191783Srmacklem /* 166191783Srmacklem * And fill the first file handle into the request. 167191783Srmacklem */ 168191783Srmacklem if (nd->nd_flag & ND_NFSV4) { 169191783Srmacklem opcnt = nfsv4_opmap[procnum].opcnt + 170191783Srmacklem nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh; 171244042Srmacklem if ((nd->nd_flag & ND_NFSV41) != 0) { 172244042Srmacklem opcnt += nfsv4_opflag[nfsv4_opmap[procnum].op].needsseq; 173244042Srmacklem if (procnum == NFSPROC_RENEW) 174244042Srmacklem /* 175244042Srmacklem * For the special case of Renew, just do a 176244042Srmacklem * Sequence Op. 177244042Srmacklem */ 178244042Srmacklem opcnt = 1; 179244042Srmacklem else if (procnum == NFSPROC_WRITEDS || 180244042Srmacklem procnum == NFSPROC_COMMITDS) 181244042Srmacklem /* 182244042Srmacklem * For the special case of a Writeor Commit to 183244042Srmacklem * a DS, the opcnt == 3, for Sequence, PutFH, 184244042Srmacklem * Write/Commit. 185244042Srmacklem */ 186244042Srmacklem opcnt = 3; 187244042Srmacklem } 188191783Srmacklem /* 189191783Srmacklem * What should the tag really be? 190191783Srmacklem */ 191191783Srmacklem (void) nfsm_strtom(nd, nfsv4_opmap[procnum].tag, 192191783Srmacklem nfsv4_opmap[procnum].taglen); 193244042Srmacklem NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 194244042Srmacklem if ((nd->nd_flag & ND_NFSV41) != 0) 195244042Srmacklem *tl++ = txdr_unsigned(NFSV41_MINORVERSION); 196244042Srmacklem else 197244042Srmacklem *tl++ = txdr_unsigned(NFSV4_MINORVERSION); 198191783Srmacklem if (opcntpp != NULL) 199191783Srmacklem *opcntpp = tl; 200244042Srmacklem *tl = txdr_unsigned(opcnt); 201244042Srmacklem if ((nd->nd_flag & ND_NFSV41) != 0 && 202244042Srmacklem nfsv4_opflag[nfsv4_opmap[procnum].op].needsseq > 0) { 203244042Srmacklem NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 204244042Srmacklem *tl = txdr_unsigned(NFSV4OP_SEQUENCE); 205244042Srmacklem if (sep == NULL) 206259238Srmacklem nfsv4_setsequence(nmp, nd, 207259238Srmacklem NFSMNT_MDSSESSION(nmp), 208244042Srmacklem nfs_bigreply[procnum]); 209244042Srmacklem else 210259238Srmacklem nfsv4_setsequence(nmp, nd, sep, 211244042Srmacklem nfs_bigreply[procnum]); 212244042Srmacklem } 213191783Srmacklem if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh > 0) { 214244042Srmacklem NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 215191783Srmacklem *tl = txdr_unsigned(NFSV4OP_PUTFH); 216191783Srmacklem (void) nfsm_fhtom(nd, nfhp, fhlen, 0); 217244042Srmacklem if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh 218244042Srmacklem == 2 && procnum != NFSPROC_WRITEDS && 219244042Srmacklem procnum != NFSPROC_COMMITDS) { 220191783Srmacklem NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 221191783Srmacklem *tl = txdr_unsigned(NFSV4OP_GETATTR); 222265434Srmacklem /* 223265434Srmacklem * For Lookup Ops, we want all the directory 224265434Srmacklem * attributes, so we can load the name cache. 225265434Srmacklem */ 226265434Srmacklem if (procnum == NFSPROC_LOOKUP || 227265434Srmacklem procnum == NFSPROC_LOOKUPP) 228265434Srmacklem NFSGETATTR_ATTRBIT(&attrbits); 229265434Srmacklem else { 230265434Srmacklem NFSWCCATTR_ATTRBIT(&attrbits); 231265434Srmacklem nd->nd_flag |= ND_V4WCCATTR; 232265434Srmacklem } 233191783Srmacklem (void) nfsrv_putattrbit(nd, &attrbits); 234191783Srmacklem } 235244042Srmacklem } 236244042Srmacklem if (procnum != NFSPROC_RENEW || 237244042Srmacklem (nd->nd_flag & ND_NFSV41) == 0) { 238191783Srmacklem NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 239244042Srmacklem *tl = txdr_unsigned(nfsv4_opmap[procnum].op); 240191783Srmacklem } 241191783Srmacklem } else { 242191783Srmacklem (void) nfsm_fhtom(nd, nfhp, fhlen, 0); 243191783Srmacklem } 244244042Srmacklem if (procnum < NFSV4_NPROCS) 245244042Srmacklem NFSINCRGLOBAL(newnfsstats.rpccnt[procnum]); 246191783Srmacklem} 247191783Srmacklem 248191783Srmacklem#ifndef APPLE 249191783Srmacklem/* 250191783Srmacklem * copies a uio scatter/gather list to an mbuf chain. 251191783Srmacklem * NOTE: can ony handle iovcnt == 1 252191783Srmacklem */ 253191783SrmacklemAPPLESTATIC void 254191783Srmacklemnfsm_uiombuf(struct nfsrv_descript *nd, struct uio *uiop, int siz) 255191783Srmacklem{ 256191783Srmacklem char *uiocp; 257191783Srmacklem struct mbuf *mp, *mp2; 258191783Srmacklem int xfer, left, mlen; 259191783Srmacklem int uiosiz, clflg, rem; 260191783Srmacklem char *cp, *tcp; 261191783Srmacklem 262209120Skib KASSERT(uiop->uio_iovcnt == 1, ("nfsm_uiotombuf: iovcnt != 1")); 263191783Srmacklem 264191783Srmacklem if (siz > ncl_mbuf_mlen) /* or should it >= MCLBYTES ?? */ 265191783Srmacklem clflg = 1; 266191783Srmacklem else 267191783Srmacklem clflg = 0; 268191783Srmacklem rem = NFSM_RNDUP(siz) - siz; 269191783Srmacklem mp = mp2 = nd->nd_mb; 270191783Srmacklem while (siz > 0) { 271191783Srmacklem left = uiop->uio_iov->iov_len; 272191783Srmacklem uiocp = uiop->uio_iov->iov_base; 273191783Srmacklem if (left > siz) 274191783Srmacklem left = siz; 275191783Srmacklem uiosiz = left; 276191783Srmacklem while (left > 0) { 277191783Srmacklem mlen = M_TRAILINGSPACE(mp); 278191783Srmacklem if (mlen == 0) { 279191783Srmacklem if (clflg) 280243882Sglebius NFSMCLGET(mp, M_WAITOK); 281191783Srmacklem else 282191783Srmacklem NFSMGET(mp); 283191783Srmacklem mbuf_setlen(mp, 0); 284191783Srmacklem mbuf_setnext(mp2, mp); 285191783Srmacklem mp2 = mp; 286191783Srmacklem mlen = M_TRAILINGSPACE(mp); 287191783Srmacklem } 288191783Srmacklem xfer = (left > mlen) ? mlen : left; 289191783Srmacklem#ifdef notdef 290191783Srmacklem /* Not Yet.. */ 291191783Srmacklem if (uiop->uio_iov->iov_op != NULL) 292191783Srmacklem (*(uiop->uio_iov->iov_op)) 293191783Srmacklem (uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp), 294191783Srmacklem xfer); 295191783Srmacklem else 296191783Srmacklem#endif 297191783Srmacklem if (uiop->uio_segflg == UIO_SYSSPACE) 298191783Srmacklem NFSBCOPY(uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp), 299191783Srmacklem xfer); 300191783Srmacklem else 301191783Srmacklem copyin(CAST_USER_ADDR_T(uiocp), NFSMTOD(mp, caddr_t) 302191783Srmacklem + mbuf_len(mp), xfer); 303191783Srmacklem mbuf_setlen(mp, mbuf_len(mp) + xfer); 304191783Srmacklem left -= xfer; 305191783Srmacklem uiocp += xfer; 306191783Srmacklem uiop->uio_offset += xfer; 307191783Srmacklem uiop->uio_resid -= xfer; 308191783Srmacklem } 309191783Srmacklem tcp = (char *)uiop->uio_iov->iov_base; 310191783Srmacklem tcp += uiosiz; 311191783Srmacklem uiop->uio_iov->iov_base = (void *)tcp; 312191783Srmacklem uiop->uio_iov->iov_len -= uiosiz; 313191783Srmacklem siz -= uiosiz; 314191783Srmacklem } 315191783Srmacklem if (rem > 0) { 316191783Srmacklem if (rem > M_TRAILINGSPACE(mp)) { 317191783Srmacklem NFSMGET(mp); 318191783Srmacklem mbuf_setlen(mp, 0); 319191783Srmacklem mbuf_setnext(mp2, mp); 320191783Srmacklem } 321191783Srmacklem cp = NFSMTOD(mp, caddr_t) + mbuf_len(mp); 322191783Srmacklem for (left = 0; left < rem; left++) 323191783Srmacklem *cp++ = '\0'; 324191783Srmacklem mbuf_setlen(mp, mbuf_len(mp) + rem); 325191783Srmacklem nd->nd_bpos = cp; 326191783Srmacklem } else 327191783Srmacklem nd->nd_bpos = NFSMTOD(mp, caddr_t) + mbuf_len(mp); 328191783Srmacklem nd->nd_mb = mp; 329191783Srmacklem} 330191783Srmacklem#endif /* !APPLE */ 331191783Srmacklem 332191783Srmacklem/* 333191783Srmacklem * Load vnode attributes from the xdr file attributes. 334191783Srmacklem * Returns EBADRPC if they can't be parsed, 0 otherwise. 335191783Srmacklem */ 336191783SrmacklemAPPLESTATIC int 337191783Srmacklemnfsm_loadattr(struct nfsrv_descript *nd, struct nfsvattr *nap) 338191783Srmacklem{ 339191783Srmacklem struct nfs_fattr *fp; 340191783Srmacklem int error = 0; 341191783Srmacklem 342191783Srmacklem if (nd->nd_flag & ND_NFSV4) { 343191783Srmacklem error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL, 344191783Srmacklem NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL); 345191783Srmacklem } else if (nd->nd_flag & ND_NFSV3) { 346191783Srmacklem NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V3FATTR); 347191783Srmacklem nap->na_type = nfsv34tov_type(fp->fa_type); 348191783Srmacklem nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode); 349191783Srmacklem nap->na_rdev = makedev(fxdr_unsigned(u_char, fp->fa3_rdev.specdata1), 350191783Srmacklem fxdr_unsigned(u_char, fp->fa3_rdev.specdata2)); 351191783Srmacklem nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink); 352191783Srmacklem nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid); 353191783Srmacklem nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid); 354191783Srmacklem nap->na_size = fxdr_hyper(&fp->fa3_size); 355191783Srmacklem nap->na_blocksize = NFS_FABLKSIZE; 356191783Srmacklem nap->na_bytes = fxdr_hyper(&fp->fa3_used); 357220152Szack nap->na_fileid = fxdr_hyper(&fp->fa3_fileid); 358191783Srmacklem fxdr_nfsv3time(&fp->fa3_atime, &nap->na_atime); 359191783Srmacklem fxdr_nfsv3time(&fp->fa3_ctime, &nap->na_ctime); 360191783Srmacklem fxdr_nfsv3time(&fp->fa3_mtime, &nap->na_mtime); 361191783Srmacklem nap->na_flags = 0; 362191783Srmacklem nap->na_filerev = 0; 363191783Srmacklem } else { 364191783Srmacklem NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V2FATTR); 365191783Srmacklem nap->na_type = nfsv2tov_type(fp->fa_type); 366191783Srmacklem nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode); 367191783Srmacklem if (nap->na_type == VNON || nap->na_type == VREG) 368191783Srmacklem nap->na_type = IFTOVT(nap->na_mode); 369191783Srmacklem nap->na_rdev = fxdr_unsigned(dev_t, fp->fa2_rdev); 370191783Srmacklem 371191783Srmacklem /* 372191783Srmacklem * Really ugly NFSv2 kludge. 373191783Srmacklem */ 374191783Srmacklem if (nap->na_type == VCHR && nap->na_rdev == ((dev_t)-1)) 375191783Srmacklem nap->na_type = VFIFO; 376191783Srmacklem nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink); 377191783Srmacklem nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid); 378191783Srmacklem nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid); 379191783Srmacklem nap->na_size = fxdr_unsigned(u_int32_t, fp->fa2_size); 380191783Srmacklem nap->na_blocksize = fxdr_unsigned(int32_t, fp->fa2_blocksize); 381191783Srmacklem nap->na_bytes = 382191783Srmacklem (u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks) * 383191783Srmacklem NFS_FABLKSIZE; 384220152Szack nap->na_fileid = fxdr_unsigned(uint64_t, fp->fa2_fileid); 385191783Srmacklem fxdr_nfsv2time(&fp->fa2_atime, &nap->na_atime); 386191783Srmacklem fxdr_nfsv2time(&fp->fa2_mtime, &nap->na_mtime); 387191783Srmacklem nap->na_flags = 0; 388191783Srmacklem nap->na_ctime.tv_sec = fxdr_unsigned(u_int32_t, 389191783Srmacklem fp->fa2_ctime.nfsv2_sec); 390191783Srmacklem nap->na_ctime.tv_nsec = 0; 391191783Srmacklem nap->na_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec); 392191783Srmacklem nap->na_filerev = 0; 393191783Srmacklem } 394191783Srmacklemnfsmout: 395191783Srmacklem return (error); 396191783Srmacklem} 397191783Srmacklem 398191783Srmacklem/* 399191783Srmacklem * This function finds the directory cookie that corresponds to the 400191783Srmacklem * logical byte offset given. 401191783Srmacklem */ 402191783SrmacklemAPPLESTATIC nfsuint64 * 403191783Srmacklemnfscl_getcookie(struct nfsnode *np, off_t off, int add) 404191783Srmacklem{ 405191783Srmacklem struct nfsdmap *dp, *dp2; 406191783Srmacklem int pos; 407191783Srmacklem 408191783Srmacklem pos = off / NFS_DIRBLKSIZ; 409191783Srmacklem if (pos == 0) { 410209120Skib KASSERT(!add, ("nfs getcookie add at 0")); 411191783Srmacklem return (&nfs_nullcookie); 412191783Srmacklem } 413191783Srmacklem pos--; 414191783Srmacklem dp = LIST_FIRST(&np->n_cookies); 415191783Srmacklem if (!dp) { 416191783Srmacklem if (add) { 417191783Srmacklem MALLOC(dp, struct nfsdmap *, sizeof (struct nfsdmap), 418191783Srmacklem M_NFSDIROFF, M_WAITOK); 419191783Srmacklem dp->ndm_eocookie = 0; 420191783Srmacklem LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list); 421191783Srmacklem } else 422191783Srmacklem return (NULL); 423191783Srmacklem } 424191783Srmacklem while (pos >= NFSNUMCOOKIES) { 425191783Srmacklem pos -= NFSNUMCOOKIES; 426191783Srmacklem if (LIST_NEXT(dp, ndm_list) != NULL) { 427191783Srmacklem if (!add && dp->ndm_eocookie < NFSNUMCOOKIES && 428191783Srmacklem pos >= dp->ndm_eocookie) 429191783Srmacklem return (NULL); 430191783Srmacklem dp = LIST_NEXT(dp, ndm_list); 431191783Srmacklem } else if (add) { 432191783Srmacklem MALLOC(dp2, struct nfsdmap *, sizeof (struct nfsdmap), 433191783Srmacklem M_NFSDIROFF, M_WAITOK); 434191783Srmacklem dp2->ndm_eocookie = 0; 435191783Srmacklem LIST_INSERT_AFTER(dp, dp2, ndm_list); 436191783Srmacklem dp = dp2; 437191783Srmacklem } else 438191783Srmacklem return (NULL); 439191783Srmacklem } 440191783Srmacklem if (pos >= dp->ndm_eocookie) { 441191783Srmacklem if (add) 442191783Srmacklem dp->ndm_eocookie = pos + 1; 443191783Srmacklem else 444191783Srmacklem return (NULL); 445191783Srmacklem } 446191783Srmacklem return (&dp->ndm_cookies[pos]); 447191783Srmacklem} 448191783Srmacklem 449191783Srmacklem/* 450191783Srmacklem * Gets a file handle out of an nfs reply sent to the client and returns 451191783Srmacklem * the file handle and the file's attributes. 452191783Srmacklem * For V4, it assumes that Getfh and Getattr Op's results are here. 453191783Srmacklem */ 454191783SrmacklemAPPLESTATIC int 455191783Srmacklemnfscl_mtofh(struct nfsrv_descript *nd, struct nfsfh **nfhpp, 456191783Srmacklem struct nfsvattr *nap, int *attrflagp) 457191783Srmacklem{ 458191783Srmacklem u_int32_t *tl; 459191783Srmacklem int error = 0, flag = 1; 460191783Srmacklem 461191783Srmacklem *nfhpp = NULL; 462191783Srmacklem *attrflagp = 0; 463191783Srmacklem /* 464191783Srmacklem * First get the file handle and vnode. 465191783Srmacklem */ 466191783Srmacklem if (nd->nd_flag & ND_NFSV3) { 467191783Srmacklem NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 468191783Srmacklem flag = fxdr_unsigned(int, *tl); 469191783Srmacklem } else if (nd->nd_flag & ND_NFSV4) { 470191783Srmacklem NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 471191783Srmacklem } 472191783Srmacklem if (flag) { 473191783Srmacklem error = nfsm_getfh(nd, nfhpp); 474191783Srmacklem if (error) 475191783Srmacklem return (error); 476191783Srmacklem } 477191783Srmacklem 478191783Srmacklem /* 479191783Srmacklem * Now, get the attributes. 480191783Srmacklem */ 481191783Srmacklem if (nd->nd_flag & ND_NFSV4) { 482191783Srmacklem NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 483191783Srmacklem } else if (nd->nd_flag & ND_NFSV3) { 484191783Srmacklem NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 485191783Srmacklem if (flag) { 486191783Srmacklem flag = fxdr_unsigned(int, *tl); 487191783Srmacklem } else if (fxdr_unsigned(int, *tl)) { 488191783Srmacklem error = nfsm_advance(nd, NFSX_V3FATTR, -1); 489191783Srmacklem if (error) 490191783Srmacklem return (error); 491191783Srmacklem } 492191783Srmacklem } 493191783Srmacklem if (flag) { 494191783Srmacklem error = nfsm_loadattr(nd, nap); 495191783Srmacklem if (!error) 496191783Srmacklem *attrflagp = 1; 497191783Srmacklem } 498191783Srmacklemnfsmout: 499191783Srmacklem return (error); 500191783Srmacklem} 501191783Srmacklem 502191783Srmacklem/* 503191783Srmacklem * Put a state Id in the mbuf list. 504191783Srmacklem */ 505191783SrmacklemAPPLESTATIC void 506191783Srmacklemnfsm_stateidtom(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp, int flag) 507191783Srmacklem{ 508191783Srmacklem nfsv4stateid_t *st; 509191783Srmacklem 510191783Srmacklem NFSM_BUILD(st, nfsv4stateid_t *, NFSX_STATEID); 511191783Srmacklem if (flag == NFSSTATEID_PUTALLZERO) { 512191783Srmacklem st->seqid = 0; 513191783Srmacklem st->other[0] = 0; 514191783Srmacklem st->other[1] = 0; 515191783Srmacklem st->other[2] = 0; 516191783Srmacklem } else if (flag == NFSSTATEID_PUTALLONE) { 517191783Srmacklem st->seqid = 0xffffffff; 518191783Srmacklem st->other[0] = 0xffffffff; 519191783Srmacklem st->other[1] = 0xffffffff; 520191783Srmacklem st->other[2] = 0xffffffff; 521244042Srmacklem } else if (flag == NFSSTATEID_PUTSEQIDZERO) { 522244042Srmacklem st->seqid = 0; 523244042Srmacklem st->other[0] = stateidp->other[0]; 524244042Srmacklem st->other[1] = stateidp->other[1]; 525244042Srmacklem st->other[2] = stateidp->other[2]; 526191783Srmacklem } else { 527191783Srmacklem st->seqid = stateidp->seqid; 528191783Srmacklem st->other[0] = stateidp->other[0]; 529191783Srmacklem st->other[1] = stateidp->other[1]; 530191783Srmacklem st->other[2] = stateidp->other[2]; 531191783Srmacklem } 532191783Srmacklem} 533191783Srmacklem 534191783Srmacklem/* 535191783Srmacklem * Initialize the owner/delegation sleep lock. 536191783Srmacklem */ 537191783SrmacklemAPPLESTATIC void 538191783Srmacklemnfscl_lockinit(struct nfsv4lock *lckp) 539191783Srmacklem{ 540191783Srmacklem 541191783Srmacklem lckp->nfslock_usecnt = 0; 542191783Srmacklem lckp->nfslock_lock = 0; 543191783Srmacklem} 544191783Srmacklem 545191783Srmacklem/* 546191783Srmacklem * Get an exclusive lock. (Not needed for OpenBSD4, since there is only one 547191783Srmacklem * thread for each posix process in the kernel.) 548191783Srmacklem */ 549191783SrmacklemAPPLESTATIC void 550191783Srmacklemnfscl_lockexcl(struct nfsv4lock *lckp, void *mutex) 551191783Srmacklem{ 552191783Srmacklem int igotlock; 553191783Srmacklem 554191783Srmacklem do { 555222389Srmacklem igotlock = nfsv4_lock(lckp, 1, NULL, mutex, NULL); 556191783Srmacklem } while (!igotlock); 557191783Srmacklem} 558191783Srmacklem 559191783Srmacklem/* 560191783Srmacklem * Release an exclusive lock. 561191783Srmacklem */ 562191783SrmacklemAPPLESTATIC void 563191783Srmacklemnfscl_lockunlock(struct nfsv4lock *lckp) 564191783Srmacklem{ 565191783Srmacklem 566191783Srmacklem nfsv4_unlock(lckp, 0); 567191783Srmacklem} 568191783Srmacklem 569191783Srmacklem/* 570191783Srmacklem * Called to derefernce a lock on a stateid (delegation or open owner). 571191783Srmacklem */ 572191783SrmacklemAPPLESTATIC void 573191783Srmacklemnfscl_lockderef(struct nfsv4lock *lckp) 574191783Srmacklem{ 575191783Srmacklem 576191783Srmacklem NFSLOCKCLSTATE(); 577191783Srmacklem lckp->nfslock_usecnt--; 578191783Srmacklem if (lckp->nfslock_usecnt == 0 && (lckp->nfslock_lock & NFSV4LOCK_WANTED)) { 579191783Srmacklem lckp->nfslock_lock &= ~NFSV4LOCK_WANTED; 580191783Srmacklem wakeup((caddr_t)lckp); 581191783Srmacklem } 582191783Srmacklem NFSUNLOCKCLSTATE(); 583191783Srmacklem} 584191783Srmacklem 585