nfs_clcomsubs.c revision 244042
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: head/sys/fs/nfsclient/nfs_clcomsubs.c 244042 2012-12-08 22:52:39Z 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, }, 69191783Srmacklem { NFSV4OP_OPEN, 3, "Open", 4, }, 70191783Srmacklem { NFSV4OP_CREATE, 3, "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) 206244042Srmacklem nfsv4_setsequence(nd, NFSMNT_MDSSESSION(nmp), 207244042Srmacklem nfs_bigreply[procnum]); 208244042Srmacklem else 209244042Srmacklem nfsv4_setsequence(nd, sep, 210244042Srmacklem nfs_bigreply[procnum]); 211244042Srmacklem } 212191783Srmacklem if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh > 0) { 213244042Srmacklem NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 214191783Srmacklem *tl = txdr_unsigned(NFSV4OP_PUTFH); 215191783Srmacklem (void) nfsm_fhtom(nd, nfhp, fhlen, 0); 216244042Srmacklem if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh 217244042Srmacklem == 2 && procnum != NFSPROC_WRITEDS && 218244042Srmacklem procnum != NFSPROC_COMMITDS) { 219191783Srmacklem NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 220191783Srmacklem *tl = txdr_unsigned(NFSV4OP_GETATTR); 221191783Srmacklem NFSWCCATTR_ATTRBIT(&attrbits); 222191783Srmacklem (void) nfsrv_putattrbit(nd, &attrbits); 223191783Srmacklem nd->nd_flag |= ND_V4WCCATTR; 224191783Srmacklem } 225244042Srmacklem } 226244042Srmacklem if (procnum != NFSPROC_RENEW || 227244042Srmacklem (nd->nd_flag & ND_NFSV41) == 0) { 228191783Srmacklem NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 229244042Srmacklem *tl = txdr_unsigned(nfsv4_opmap[procnum].op); 230191783Srmacklem } 231191783Srmacklem } else { 232191783Srmacklem (void) nfsm_fhtom(nd, nfhp, fhlen, 0); 233191783Srmacklem } 234244042Srmacklem if (procnum < NFSV4_NPROCS) 235244042Srmacklem NFSINCRGLOBAL(newnfsstats.rpccnt[procnum]); 236191783Srmacklem} 237191783Srmacklem 238191783Srmacklem#ifndef APPLE 239191783Srmacklem/* 240191783Srmacklem * copies a uio scatter/gather list to an mbuf chain. 241191783Srmacklem * NOTE: can ony handle iovcnt == 1 242191783Srmacklem */ 243191783SrmacklemAPPLESTATIC void 244191783Srmacklemnfsm_uiombuf(struct nfsrv_descript *nd, struct uio *uiop, int siz) 245191783Srmacklem{ 246191783Srmacklem char *uiocp; 247191783Srmacklem struct mbuf *mp, *mp2; 248191783Srmacklem int xfer, left, mlen; 249191783Srmacklem int uiosiz, clflg, rem; 250191783Srmacklem char *cp, *tcp; 251191783Srmacklem 252209120Skib KASSERT(uiop->uio_iovcnt == 1, ("nfsm_uiotombuf: iovcnt != 1")); 253191783Srmacklem 254191783Srmacklem if (siz > ncl_mbuf_mlen) /* or should it >= MCLBYTES ?? */ 255191783Srmacklem clflg = 1; 256191783Srmacklem else 257191783Srmacklem clflg = 0; 258191783Srmacklem rem = NFSM_RNDUP(siz) - siz; 259191783Srmacklem mp = mp2 = nd->nd_mb; 260191783Srmacklem while (siz > 0) { 261191783Srmacklem left = uiop->uio_iov->iov_len; 262191783Srmacklem uiocp = uiop->uio_iov->iov_base; 263191783Srmacklem if (left > siz) 264191783Srmacklem left = siz; 265191783Srmacklem uiosiz = left; 266191783Srmacklem while (left > 0) { 267191783Srmacklem mlen = M_TRAILINGSPACE(mp); 268191783Srmacklem if (mlen == 0) { 269191783Srmacklem if (clflg) 270243882Sglebius NFSMCLGET(mp, M_WAITOK); 271191783Srmacklem else 272191783Srmacklem NFSMGET(mp); 273191783Srmacklem mbuf_setlen(mp, 0); 274191783Srmacklem mbuf_setnext(mp2, mp); 275191783Srmacklem mp2 = mp; 276191783Srmacklem mlen = M_TRAILINGSPACE(mp); 277191783Srmacklem } 278191783Srmacklem xfer = (left > mlen) ? mlen : left; 279191783Srmacklem#ifdef notdef 280191783Srmacklem /* Not Yet.. */ 281191783Srmacklem if (uiop->uio_iov->iov_op != NULL) 282191783Srmacklem (*(uiop->uio_iov->iov_op)) 283191783Srmacklem (uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp), 284191783Srmacklem xfer); 285191783Srmacklem else 286191783Srmacklem#endif 287191783Srmacklem if (uiop->uio_segflg == UIO_SYSSPACE) 288191783Srmacklem NFSBCOPY(uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp), 289191783Srmacklem xfer); 290191783Srmacklem else 291191783Srmacklem copyin(CAST_USER_ADDR_T(uiocp), NFSMTOD(mp, caddr_t) 292191783Srmacklem + mbuf_len(mp), xfer); 293191783Srmacklem mbuf_setlen(mp, mbuf_len(mp) + xfer); 294191783Srmacklem left -= xfer; 295191783Srmacklem uiocp += xfer; 296191783Srmacklem uiop->uio_offset += xfer; 297191783Srmacklem uiop->uio_resid -= xfer; 298191783Srmacklem } 299191783Srmacklem tcp = (char *)uiop->uio_iov->iov_base; 300191783Srmacklem tcp += uiosiz; 301191783Srmacklem uiop->uio_iov->iov_base = (void *)tcp; 302191783Srmacklem uiop->uio_iov->iov_len -= uiosiz; 303191783Srmacklem siz -= uiosiz; 304191783Srmacklem } 305191783Srmacklem if (rem > 0) { 306191783Srmacklem if (rem > M_TRAILINGSPACE(mp)) { 307191783Srmacklem NFSMGET(mp); 308191783Srmacklem mbuf_setlen(mp, 0); 309191783Srmacklem mbuf_setnext(mp2, mp); 310191783Srmacklem } 311191783Srmacklem cp = NFSMTOD(mp, caddr_t) + mbuf_len(mp); 312191783Srmacklem for (left = 0; left < rem; left++) 313191783Srmacklem *cp++ = '\0'; 314191783Srmacklem mbuf_setlen(mp, mbuf_len(mp) + rem); 315191783Srmacklem nd->nd_bpos = cp; 316191783Srmacklem } else 317191783Srmacklem nd->nd_bpos = NFSMTOD(mp, caddr_t) + mbuf_len(mp); 318191783Srmacklem nd->nd_mb = mp; 319191783Srmacklem} 320191783Srmacklem#endif /* !APPLE */ 321191783Srmacklem 322191783Srmacklem/* 323191783Srmacklem * Load vnode attributes from the xdr file attributes. 324191783Srmacklem * Returns EBADRPC if they can't be parsed, 0 otherwise. 325191783Srmacklem */ 326191783SrmacklemAPPLESTATIC int 327191783Srmacklemnfsm_loadattr(struct nfsrv_descript *nd, struct nfsvattr *nap) 328191783Srmacklem{ 329191783Srmacklem struct nfs_fattr *fp; 330191783Srmacklem int error = 0; 331191783Srmacklem 332191783Srmacklem if (nd->nd_flag & ND_NFSV4) { 333191783Srmacklem error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL, 334191783Srmacklem NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL); 335191783Srmacklem } else if (nd->nd_flag & ND_NFSV3) { 336191783Srmacklem NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V3FATTR); 337191783Srmacklem nap->na_type = nfsv34tov_type(fp->fa_type); 338191783Srmacklem nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode); 339191783Srmacklem nap->na_rdev = makedev(fxdr_unsigned(u_char, fp->fa3_rdev.specdata1), 340191783Srmacklem fxdr_unsigned(u_char, fp->fa3_rdev.specdata2)); 341191783Srmacklem nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink); 342191783Srmacklem nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid); 343191783Srmacklem nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid); 344191783Srmacklem nap->na_size = fxdr_hyper(&fp->fa3_size); 345191783Srmacklem nap->na_blocksize = NFS_FABLKSIZE; 346191783Srmacklem nap->na_bytes = fxdr_hyper(&fp->fa3_used); 347220152Szack nap->na_fileid = fxdr_hyper(&fp->fa3_fileid); 348191783Srmacklem fxdr_nfsv3time(&fp->fa3_atime, &nap->na_atime); 349191783Srmacklem fxdr_nfsv3time(&fp->fa3_ctime, &nap->na_ctime); 350191783Srmacklem fxdr_nfsv3time(&fp->fa3_mtime, &nap->na_mtime); 351191783Srmacklem nap->na_flags = 0; 352191783Srmacklem nap->na_filerev = 0; 353191783Srmacklem } else { 354191783Srmacklem NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V2FATTR); 355191783Srmacklem nap->na_type = nfsv2tov_type(fp->fa_type); 356191783Srmacklem nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode); 357191783Srmacklem if (nap->na_type == VNON || nap->na_type == VREG) 358191783Srmacklem nap->na_type = IFTOVT(nap->na_mode); 359191783Srmacklem nap->na_rdev = fxdr_unsigned(dev_t, fp->fa2_rdev); 360191783Srmacklem 361191783Srmacklem /* 362191783Srmacklem * Really ugly NFSv2 kludge. 363191783Srmacklem */ 364191783Srmacklem if (nap->na_type == VCHR && nap->na_rdev == ((dev_t)-1)) 365191783Srmacklem nap->na_type = VFIFO; 366191783Srmacklem nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink); 367191783Srmacklem nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid); 368191783Srmacklem nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid); 369191783Srmacklem nap->na_size = fxdr_unsigned(u_int32_t, fp->fa2_size); 370191783Srmacklem nap->na_blocksize = fxdr_unsigned(int32_t, fp->fa2_blocksize); 371191783Srmacklem nap->na_bytes = 372191783Srmacklem (u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks) * 373191783Srmacklem NFS_FABLKSIZE; 374220152Szack nap->na_fileid = fxdr_unsigned(uint64_t, fp->fa2_fileid); 375191783Srmacklem fxdr_nfsv2time(&fp->fa2_atime, &nap->na_atime); 376191783Srmacklem fxdr_nfsv2time(&fp->fa2_mtime, &nap->na_mtime); 377191783Srmacklem nap->na_flags = 0; 378191783Srmacklem nap->na_ctime.tv_sec = fxdr_unsigned(u_int32_t, 379191783Srmacklem fp->fa2_ctime.nfsv2_sec); 380191783Srmacklem nap->na_ctime.tv_nsec = 0; 381191783Srmacklem nap->na_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec); 382191783Srmacklem nap->na_filerev = 0; 383191783Srmacklem } 384191783Srmacklemnfsmout: 385191783Srmacklem return (error); 386191783Srmacklem} 387191783Srmacklem 388191783Srmacklem/* 389191783Srmacklem * This function finds the directory cookie that corresponds to the 390191783Srmacklem * logical byte offset given. 391191783Srmacklem */ 392191783SrmacklemAPPLESTATIC nfsuint64 * 393191783Srmacklemnfscl_getcookie(struct nfsnode *np, off_t off, int add) 394191783Srmacklem{ 395191783Srmacklem struct nfsdmap *dp, *dp2; 396191783Srmacklem int pos; 397191783Srmacklem 398191783Srmacklem pos = off / NFS_DIRBLKSIZ; 399191783Srmacklem if (pos == 0) { 400209120Skib KASSERT(!add, ("nfs getcookie add at 0")); 401191783Srmacklem return (&nfs_nullcookie); 402191783Srmacklem } 403191783Srmacklem pos--; 404191783Srmacklem dp = LIST_FIRST(&np->n_cookies); 405191783Srmacklem if (!dp) { 406191783Srmacklem if (add) { 407191783Srmacklem MALLOC(dp, struct nfsdmap *, sizeof (struct nfsdmap), 408191783Srmacklem M_NFSDIROFF, M_WAITOK); 409191783Srmacklem dp->ndm_eocookie = 0; 410191783Srmacklem LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list); 411191783Srmacklem } else 412191783Srmacklem return (NULL); 413191783Srmacklem } 414191783Srmacklem while (pos >= NFSNUMCOOKIES) { 415191783Srmacklem pos -= NFSNUMCOOKIES; 416191783Srmacklem if (LIST_NEXT(dp, ndm_list) != NULL) { 417191783Srmacklem if (!add && dp->ndm_eocookie < NFSNUMCOOKIES && 418191783Srmacklem pos >= dp->ndm_eocookie) 419191783Srmacklem return (NULL); 420191783Srmacklem dp = LIST_NEXT(dp, ndm_list); 421191783Srmacklem } else if (add) { 422191783Srmacklem MALLOC(dp2, struct nfsdmap *, sizeof (struct nfsdmap), 423191783Srmacklem M_NFSDIROFF, M_WAITOK); 424191783Srmacklem dp2->ndm_eocookie = 0; 425191783Srmacklem LIST_INSERT_AFTER(dp, dp2, ndm_list); 426191783Srmacklem dp = dp2; 427191783Srmacklem } else 428191783Srmacklem return (NULL); 429191783Srmacklem } 430191783Srmacklem if (pos >= dp->ndm_eocookie) { 431191783Srmacklem if (add) 432191783Srmacklem dp->ndm_eocookie = pos + 1; 433191783Srmacklem else 434191783Srmacklem return (NULL); 435191783Srmacklem } 436191783Srmacklem return (&dp->ndm_cookies[pos]); 437191783Srmacklem} 438191783Srmacklem 439191783Srmacklem/* 440191783Srmacklem * Gets a file handle out of an nfs reply sent to the client and returns 441191783Srmacklem * the file handle and the file's attributes. 442191783Srmacklem * For V4, it assumes that Getfh and Getattr Op's results are here. 443191783Srmacklem */ 444191783SrmacklemAPPLESTATIC int 445191783Srmacklemnfscl_mtofh(struct nfsrv_descript *nd, struct nfsfh **nfhpp, 446191783Srmacklem struct nfsvattr *nap, int *attrflagp) 447191783Srmacklem{ 448191783Srmacklem u_int32_t *tl; 449191783Srmacklem int error = 0, flag = 1; 450191783Srmacklem 451191783Srmacklem *nfhpp = NULL; 452191783Srmacklem *attrflagp = 0; 453191783Srmacklem /* 454191783Srmacklem * First get the file handle and vnode. 455191783Srmacklem */ 456191783Srmacklem if (nd->nd_flag & ND_NFSV3) { 457191783Srmacklem NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 458191783Srmacklem flag = fxdr_unsigned(int, *tl); 459191783Srmacklem } else if (nd->nd_flag & ND_NFSV4) { 460191783Srmacklem NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 461191783Srmacklem } 462191783Srmacklem if (flag) { 463191783Srmacklem error = nfsm_getfh(nd, nfhpp); 464191783Srmacklem if (error) 465191783Srmacklem return (error); 466191783Srmacklem } 467191783Srmacklem 468191783Srmacklem /* 469191783Srmacklem * Now, get the attributes. 470191783Srmacklem */ 471191783Srmacklem if (nd->nd_flag & ND_NFSV4) { 472191783Srmacklem NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 473191783Srmacklem } else if (nd->nd_flag & ND_NFSV3) { 474191783Srmacklem NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 475191783Srmacklem if (flag) { 476191783Srmacklem flag = fxdr_unsigned(int, *tl); 477191783Srmacklem } else if (fxdr_unsigned(int, *tl)) { 478191783Srmacklem error = nfsm_advance(nd, NFSX_V3FATTR, -1); 479191783Srmacklem if (error) 480191783Srmacklem return (error); 481191783Srmacklem } 482191783Srmacklem } 483191783Srmacklem if (flag) { 484191783Srmacklem error = nfsm_loadattr(nd, nap); 485191783Srmacklem if (!error) 486191783Srmacklem *attrflagp = 1; 487191783Srmacklem } 488191783Srmacklemnfsmout: 489191783Srmacklem return (error); 490191783Srmacklem} 491191783Srmacklem 492191783Srmacklem/* 493191783Srmacklem * Put a state Id in the mbuf list. 494191783Srmacklem */ 495191783SrmacklemAPPLESTATIC void 496191783Srmacklemnfsm_stateidtom(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp, int flag) 497191783Srmacklem{ 498191783Srmacklem nfsv4stateid_t *st; 499191783Srmacklem 500191783Srmacklem NFSM_BUILD(st, nfsv4stateid_t *, NFSX_STATEID); 501191783Srmacklem if (flag == NFSSTATEID_PUTALLZERO) { 502191783Srmacklem st->seqid = 0; 503191783Srmacklem st->other[0] = 0; 504191783Srmacklem st->other[1] = 0; 505191783Srmacklem st->other[2] = 0; 506191783Srmacklem } else if (flag == NFSSTATEID_PUTALLONE) { 507191783Srmacklem st->seqid = 0xffffffff; 508191783Srmacklem st->other[0] = 0xffffffff; 509191783Srmacklem st->other[1] = 0xffffffff; 510191783Srmacklem st->other[2] = 0xffffffff; 511244042Srmacklem } else if (flag == NFSSTATEID_PUTSEQIDZERO) { 512244042Srmacklem st->seqid = 0; 513244042Srmacklem st->other[0] = stateidp->other[0]; 514244042Srmacklem st->other[1] = stateidp->other[1]; 515244042Srmacklem st->other[2] = stateidp->other[2]; 516191783Srmacklem } else { 517191783Srmacklem st->seqid = stateidp->seqid; 518191783Srmacklem st->other[0] = stateidp->other[0]; 519191783Srmacklem st->other[1] = stateidp->other[1]; 520191783Srmacklem st->other[2] = stateidp->other[2]; 521191783Srmacklem } 522191783Srmacklem} 523191783Srmacklem 524191783Srmacklem/* 525191783Srmacklem * Initialize the owner/delegation sleep lock. 526191783Srmacklem */ 527191783SrmacklemAPPLESTATIC void 528191783Srmacklemnfscl_lockinit(struct nfsv4lock *lckp) 529191783Srmacklem{ 530191783Srmacklem 531191783Srmacklem lckp->nfslock_usecnt = 0; 532191783Srmacklem lckp->nfslock_lock = 0; 533191783Srmacklem} 534191783Srmacklem 535191783Srmacklem/* 536191783Srmacklem * Get an exclusive lock. (Not needed for OpenBSD4, since there is only one 537191783Srmacklem * thread for each posix process in the kernel.) 538191783Srmacklem */ 539191783SrmacklemAPPLESTATIC void 540191783Srmacklemnfscl_lockexcl(struct nfsv4lock *lckp, void *mutex) 541191783Srmacklem{ 542191783Srmacklem int igotlock; 543191783Srmacklem 544191783Srmacklem do { 545222389Srmacklem igotlock = nfsv4_lock(lckp, 1, NULL, mutex, NULL); 546191783Srmacklem } while (!igotlock); 547191783Srmacklem} 548191783Srmacklem 549191783Srmacklem/* 550191783Srmacklem * Release an exclusive lock. 551191783Srmacklem */ 552191783SrmacklemAPPLESTATIC void 553191783Srmacklemnfscl_lockunlock(struct nfsv4lock *lckp) 554191783Srmacklem{ 555191783Srmacklem 556191783Srmacklem nfsv4_unlock(lckp, 0); 557191783Srmacklem} 558191783Srmacklem 559191783Srmacklem/* 560191783Srmacklem * Called to derefernce a lock on a stateid (delegation or open owner). 561191783Srmacklem */ 562191783SrmacklemAPPLESTATIC void 563191783Srmacklemnfscl_lockderef(struct nfsv4lock *lckp) 564191783Srmacklem{ 565191783Srmacklem 566191783Srmacklem NFSLOCKCLSTATE(); 567191783Srmacklem lckp->nfslock_usecnt--; 568191783Srmacklem if (lckp->nfslock_usecnt == 0 && (lckp->nfslock_lock & NFSV4LOCK_WANTED)) { 569191783Srmacklem lckp->nfslock_lock &= ~NFSV4LOCK_WANTED; 570191783Srmacklem wakeup((caddr_t)lckp); 571191783Srmacklem } 572191783Srmacklem NFSUNLOCKCLSTATE(); 573191783Srmacklem} 574191783Srmacklem 575