19ec7b004SRick Macklem /*- 29ec7b004SRick Macklem * Copyright (c) 1989, 1993 39ec7b004SRick Macklem * The Regents of the University of California. All rights reserved. 49ec7b004SRick Macklem * 59ec7b004SRick Macklem * This code is derived from software contributed to Berkeley by 69ec7b004SRick Macklem * Rick Macklem at The University of Guelph. 79ec7b004SRick Macklem * 89ec7b004SRick Macklem * Redistribution and use in source and binary forms, with or without 99ec7b004SRick Macklem * modification, are permitted provided that the following conditions 109ec7b004SRick Macklem * are met: 119ec7b004SRick Macklem * 1. Redistributions of source code must retain the above copyright 129ec7b004SRick Macklem * notice, this list of conditions and the following disclaimer. 139ec7b004SRick Macklem * 2. Redistributions in binary form must reproduce the above copyright 149ec7b004SRick Macklem * notice, this list of conditions and the following disclaimer in the 159ec7b004SRick Macklem * documentation and/or other materials provided with the distribution. 169ec7b004SRick Macklem * 4. Neither the name of the University nor the names of its contributors 179ec7b004SRick Macklem * may be used to endorse or promote products derived from this software 189ec7b004SRick Macklem * without specific prior written permission. 199ec7b004SRick Macklem * 209ec7b004SRick Macklem * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 219ec7b004SRick Macklem * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 229ec7b004SRick Macklem * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 239ec7b004SRick Macklem * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 249ec7b004SRick Macklem * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 259ec7b004SRick Macklem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 269ec7b004SRick Macklem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 279ec7b004SRick Macklem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 289ec7b004SRick Macklem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 299ec7b004SRick Macklem * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 309ec7b004SRick Macklem * SUCH DAMAGE. 319ec7b004SRick Macklem * 329ec7b004SRick Macklem */ 339ec7b004SRick Macklem 349ec7b004SRick Macklem #include <sys/cdefs.h> 359ec7b004SRick Macklem __FBSDID("$FreeBSD$"); 369ec7b004SRick Macklem 379ec7b004SRick Macklem /* 389ec7b004SRick Macklem * These functions support the macros and help fiddle mbuf chains for 399ec7b004SRick Macklem * the nfs op functions. They do things like create the rpc header and 409ec7b004SRick Macklem * copy data between mbuf chains and uio lists. 419ec7b004SRick Macklem */ 429ec7b004SRick Macklem #ifndef APPLEKEXT 439ec7b004SRick Macklem #include <fs/nfs/nfsport.h> 449ec7b004SRick Macklem 459ec7b004SRick Macklem extern struct nfsstats newnfsstats; 469ec7b004SRick Macklem extern struct nfsv4_opflag nfsv4_opflag[NFSV4OP_NOPS]; 479ec7b004SRick Macklem extern int ncl_mbuf_mlen; 489ec7b004SRick Macklem extern enum vtype newnv2tov_type[8]; 499ec7b004SRick Macklem extern enum vtype nv34tov_type[8]; 509ec7b004SRick Macklem NFSCLSTATEMUTEX; 519ec7b004SRick Macklem #endif /* !APPLEKEXT */ 529ec7b004SRick Macklem 539ec7b004SRick Macklem static nfsuint64 nfs_nullcookie = {{ 0, 0 }}; 549ec7b004SRick Macklem static struct { 559ec7b004SRick Macklem int op; 569ec7b004SRick Macklem int opcnt; 579ec7b004SRick Macklem const u_char *tag; 589ec7b004SRick Macklem int taglen; 599ec7b004SRick Macklem } nfsv4_opmap[NFS_NPROCS] = { 609ec7b004SRick Macklem { 0, 1, "Null", 4 }, 619ec7b004SRick Macklem { NFSV4OP_GETATTR, 1, "Getattr", 7, }, 629ec7b004SRick Macklem { NFSV4OP_SETATTR, 2, "Setattr", 7, }, 639ec7b004SRick Macklem { NFSV4OP_LOOKUP, 3, "Lookup", 6, }, 649ec7b004SRick Macklem { NFSV4OP_ACCESS, 2, "Access", 6, }, 659ec7b004SRick Macklem { NFSV4OP_READLINK, 2, "Readlink", 8, }, 669ec7b004SRick Macklem { NFSV4OP_READ, 1, "Read", 4, }, 679ec7b004SRick Macklem { NFSV4OP_WRITE, 2, "Write", 5, }, 689ec7b004SRick Macklem { NFSV4OP_OPEN, 3, "Open", 4, }, 699ec7b004SRick Macklem { NFSV4OP_CREATE, 3, "Create", 6, }, 709ec7b004SRick Macklem { NFSV4OP_CREATE, 1, "Create", 6, }, 719ec7b004SRick Macklem { NFSV4OP_CREATE, 3, "Create", 6, }, 729ec7b004SRick Macklem { NFSV4OP_REMOVE, 1, "Remove", 6, }, 739ec7b004SRick Macklem { NFSV4OP_REMOVE, 1, "Remove", 6, }, 749ec7b004SRick Macklem { NFSV4OP_SAVEFH, 5, "Rename", 6, }, 759ec7b004SRick Macklem { NFSV4OP_SAVEFH, 4, "Link", 4, }, 769ec7b004SRick Macklem { NFSV4OP_READDIR, 2, "Readdir", 7, }, 779ec7b004SRick Macklem { NFSV4OP_READDIR, 2, "Readdir", 7, }, 789ec7b004SRick Macklem { NFSV4OP_GETATTR, 1, "Getattr", 7, }, 799ec7b004SRick Macklem { NFSV4OP_GETATTR, 1, "Getattr", 7, }, 809ec7b004SRick Macklem { NFSV4OP_GETATTR, 1, "Getattr", 7, }, 819ec7b004SRick Macklem { NFSV4OP_COMMIT, 2, "Commit", 6, }, 829ec7b004SRick Macklem { NFSV4OP_LOOKUPP, 3, "Lookupp", 7, }, 839ec7b004SRick Macklem { NFSV4OP_SETCLIENTID, 1, "SetClientID", 11, }, 849ec7b004SRick Macklem { NFSV4OP_SETCLIENTIDCFRM, 1, "SetClientIDConfirm", 18, }, 859ec7b004SRick Macklem { NFSV4OP_LOCK, 1, "Lock", 4, }, 869ec7b004SRick Macklem { NFSV4OP_LOCKU, 1, "LockU", 5, }, 879ec7b004SRick Macklem { NFSV4OP_OPEN, 2, "Open", 4, }, 889ec7b004SRick Macklem { NFSV4OP_CLOSE, 1, "Close", 5, }, 899ec7b004SRick Macklem { NFSV4OP_OPENCONFIRM, 1, "Openconfirm", 11, }, 909ec7b004SRick Macklem { NFSV4OP_LOCKT, 1, "LockT", 5, }, 919ec7b004SRick Macklem { NFSV4OP_OPENDOWNGRADE, 1, "Opendowngrade", 13, }, 929ec7b004SRick Macklem { NFSV4OP_RENEW, 1, "Renew", 5, }, 939ec7b004SRick Macklem { NFSV4OP_PUTROOTFH, 1, "Dirpath", 7, }, 949ec7b004SRick Macklem { NFSV4OP_RELEASELCKOWN, 1, "Rellckown", 9, }, 959ec7b004SRick Macklem { NFSV4OP_DELEGRETURN, 1, "Delegret", 8, }, 969ec7b004SRick Macklem { NFSV4OP_DELEGRETURN, 3, "DelegRemove", 11, }, 979ec7b004SRick Macklem { NFSV4OP_DELEGRETURN, 7, "DelegRename1", 12, }, 989ec7b004SRick Macklem { NFSV4OP_DELEGRETURN, 9, "DelegRename2", 12, }, 999ec7b004SRick Macklem { NFSV4OP_GETATTR, 1, "Getacl", 6, }, 1009ec7b004SRick Macklem { NFSV4OP_SETATTR, 1, "Setacl", 6, }, 1019ec7b004SRick Macklem }; 1029ec7b004SRick Macklem 1039ec7b004SRick Macklem 1049ec7b004SRick Macklem /* 1059ec7b004SRick Macklem * NFS RPCS that have large request message size. 1069ec7b004SRick Macklem */ 1079ec7b004SRick Macklem static int nfs_bigrequest[NFS_NPROCS] = { 1089ec7b004SRick Macklem 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1099ec7b004SRick Macklem 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1109ec7b004SRick Macklem }; 1119ec7b004SRick Macklem 1129ec7b004SRick Macklem /* 1139ec7b004SRick Macklem * Start building a request. Mostly just put the first file handle in 1149ec7b004SRick Macklem * place. 1159ec7b004SRick Macklem */ 1169ec7b004SRick Macklem APPLESTATIC void 1179ec7b004SRick Macklem nfscl_reqstart(struct nfsrv_descript *nd, int procnum, struct nfsmount *nmp, 1189ec7b004SRick Macklem u_int8_t *nfhp, int fhlen, u_int32_t **opcntpp) 1199ec7b004SRick Macklem { 1209ec7b004SRick Macklem struct mbuf *mb; 1219ec7b004SRick Macklem u_int32_t *tl; 1229ec7b004SRick Macklem int opcnt; 1239ec7b004SRick Macklem nfsattrbit_t attrbits; 1249ec7b004SRick Macklem 1259ec7b004SRick Macklem /* 1269ec7b004SRick Macklem * First, fill in some of the fields of nd. 1279ec7b004SRick Macklem */ 1289ec7b004SRick Macklem if (NFSHASNFSV4(nmp)) 1299ec7b004SRick Macklem nd->nd_flag = ND_NFSV4; 1309ec7b004SRick Macklem else if (NFSHASNFSV3(nmp)) 1319ec7b004SRick Macklem nd->nd_flag = ND_NFSV3; 1329ec7b004SRick Macklem else 1339ec7b004SRick Macklem nd->nd_flag = ND_NFSV2; 1349ec7b004SRick Macklem nd->nd_procnum = procnum; 1359ec7b004SRick Macklem nd->nd_repstat = 0; 1369ec7b004SRick Macklem 1379ec7b004SRick Macklem /* 1389ec7b004SRick Macklem * Get the first mbuf for the request. 1399ec7b004SRick Macklem */ 1409ec7b004SRick Macklem if (nfs_bigrequest[procnum]) 1419ec7b004SRick Macklem NFSMCLGET(mb, M_WAIT); 1429ec7b004SRick Macklem else 1439ec7b004SRick Macklem NFSMGET(mb); 1449ec7b004SRick Macklem mbuf_setlen(mb, 0); 1459ec7b004SRick Macklem nd->nd_mreq = nd->nd_mb = mb; 1469ec7b004SRick Macklem nd->nd_bpos = NFSMTOD(mb, caddr_t); 1479ec7b004SRick Macklem 1489ec7b004SRick Macklem /* 1499ec7b004SRick Macklem * And fill the first file handle into the request. 1509ec7b004SRick Macklem */ 1519ec7b004SRick Macklem if (nd->nd_flag & ND_NFSV4) { 1529ec7b004SRick Macklem opcnt = nfsv4_opmap[procnum].opcnt + 1539ec7b004SRick Macklem nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh; 1549ec7b004SRick Macklem /* 1559ec7b004SRick Macklem * What should the tag really be? 1569ec7b004SRick Macklem */ 1579ec7b004SRick Macklem (void) nfsm_strtom(nd, nfsv4_opmap[procnum].tag, 1589ec7b004SRick Macklem nfsv4_opmap[procnum].taglen); 1599ec7b004SRick Macklem NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 1609ec7b004SRick Macklem *tl++ = txdr_unsigned(NFSV4_MINORVERSION); 1619ec7b004SRick Macklem if (opcntpp != NULL) 1629ec7b004SRick Macklem *opcntpp = tl; 1639ec7b004SRick Macklem *tl++ = txdr_unsigned(opcnt); 1649ec7b004SRick Macklem if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh > 0) { 1659ec7b004SRick Macklem *tl = txdr_unsigned(NFSV4OP_PUTFH); 1669ec7b004SRick Macklem (void) nfsm_fhtom(nd, nfhp, fhlen, 0); 1679ec7b004SRick Macklem if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh==2){ 1689ec7b004SRick Macklem NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 1699ec7b004SRick Macklem *tl = txdr_unsigned(NFSV4OP_GETATTR); 1709ec7b004SRick Macklem NFSWCCATTR_ATTRBIT(&attrbits); 1719ec7b004SRick Macklem (void) nfsrv_putattrbit(nd, &attrbits); 1729ec7b004SRick Macklem nd->nd_flag |= ND_V4WCCATTR; 1739ec7b004SRick Macklem } 1749ec7b004SRick Macklem NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 1759ec7b004SRick Macklem } 1769ec7b004SRick Macklem *tl = txdr_unsigned(nfsv4_opmap[procnum].op); 1779ec7b004SRick Macklem } else { 1789ec7b004SRick Macklem (void) nfsm_fhtom(nd, nfhp, fhlen, 0); 1799ec7b004SRick Macklem } 1809ec7b004SRick Macklem NFSINCRGLOBAL(newnfsstats.rpccnt[procnum]); 1819ec7b004SRick Macklem } 1829ec7b004SRick Macklem 1839ec7b004SRick Macklem #ifndef APPLE 1849ec7b004SRick Macklem /* 1859ec7b004SRick Macklem * copies a uio scatter/gather list to an mbuf chain. 1869ec7b004SRick Macklem * NOTE: can ony handle iovcnt == 1 1879ec7b004SRick Macklem */ 1889ec7b004SRick Macklem APPLESTATIC void 1899ec7b004SRick Macklem nfsm_uiombuf(struct nfsrv_descript *nd, struct uio *uiop, int siz) 1909ec7b004SRick Macklem { 1919ec7b004SRick Macklem char *uiocp; 1929ec7b004SRick Macklem struct mbuf *mp, *mp2; 1939ec7b004SRick Macklem int xfer, left, mlen; 1949ec7b004SRick Macklem int uiosiz, clflg, rem; 1959ec7b004SRick Macklem char *cp, *tcp; 1969ec7b004SRick Macklem 1979ec7b004SRick Macklem #ifdef DIAGNOSTIC 1989ec7b004SRick Macklem if (uiop->uio_iovcnt != 1) 1999ec7b004SRick Macklem panic("nfsm_uiotombuf: iovcnt != 1"); 2009ec7b004SRick Macklem #endif 2019ec7b004SRick Macklem 2029ec7b004SRick Macklem if (siz > ncl_mbuf_mlen) /* or should it >= MCLBYTES ?? */ 2039ec7b004SRick Macklem clflg = 1; 2049ec7b004SRick Macklem else 2059ec7b004SRick Macklem clflg = 0; 2069ec7b004SRick Macklem rem = NFSM_RNDUP(siz) - siz; 2079ec7b004SRick Macklem mp = mp2 = nd->nd_mb; 2089ec7b004SRick Macklem while (siz > 0) { 2099ec7b004SRick Macklem left = uiop->uio_iov->iov_len; 2109ec7b004SRick Macklem uiocp = uiop->uio_iov->iov_base; 2119ec7b004SRick Macklem if (left > siz) 2129ec7b004SRick Macklem left = siz; 2139ec7b004SRick Macklem uiosiz = left; 2149ec7b004SRick Macklem while (left > 0) { 2159ec7b004SRick Macklem mlen = M_TRAILINGSPACE(mp); 2169ec7b004SRick Macklem if (mlen == 0) { 2179ec7b004SRick Macklem if (clflg) 2189ec7b004SRick Macklem NFSMCLGET(mp, M_WAIT); 2199ec7b004SRick Macklem else 2209ec7b004SRick Macklem NFSMGET(mp); 2219ec7b004SRick Macklem mbuf_setlen(mp, 0); 2229ec7b004SRick Macklem mbuf_setnext(mp2, mp); 2239ec7b004SRick Macklem mp2 = mp; 2249ec7b004SRick Macklem mlen = M_TRAILINGSPACE(mp); 2259ec7b004SRick Macklem } 2269ec7b004SRick Macklem xfer = (left > mlen) ? mlen : left; 2279ec7b004SRick Macklem #ifdef notdef 2289ec7b004SRick Macklem /* Not Yet.. */ 2299ec7b004SRick Macklem if (uiop->uio_iov->iov_op != NULL) 2309ec7b004SRick Macklem (*(uiop->uio_iov->iov_op)) 2319ec7b004SRick Macklem (uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp), 2329ec7b004SRick Macklem xfer); 2339ec7b004SRick Macklem else 2349ec7b004SRick Macklem #endif 2359ec7b004SRick Macklem if (uiop->uio_segflg == UIO_SYSSPACE) 2369ec7b004SRick Macklem NFSBCOPY(uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp), 2379ec7b004SRick Macklem xfer); 2389ec7b004SRick Macklem else 2399ec7b004SRick Macklem copyin(CAST_USER_ADDR_T(uiocp), NFSMTOD(mp, caddr_t) 2409ec7b004SRick Macklem + mbuf_len(mp), xfer); 2419ec7b004SRick Macklem mbuf_setlen(mp, mbuf_len(mp) + xfer); 2429ec7b004SRick Macklem left -= xfer; 2439ec7b004SRick Macklem uiocp += xfer; 2449ec7b004SRick Macklem uiop->uio_offset += xfer; 2459ec7b004SRick Macklem uiop->uio_resid -= xfer; 2469ec7b004SRick Macklem } 2479ec7b004SRick Macklem tcp = (char *)uiop->uio_iov->iov_base; 2489ec7b004SRick Macklem tcp += uiosiz; 2499ec7b004SRick Macklem uiop->uio_iov->iov_base = (void *)tcp; 2509ec7b004SRick Macklem uiop->uio_iov->iov_len -= uiosiz; 2519ec7b004SRick Macklem siz -= uiosiz; 2529ec7b004SRick Macklem } 2539ec7b004SRick Macklem if (rem > 0) { 2549ec7b004SRick Macklem if (rem > M_TRAILINGSPACE(mp)) { 2559ec7b004SRick Macklem NFSMGET(mp); 2569ec7b004SRick Macklem mbuf_setlen(mp, 0); 2579ec7b004SRick Macklem mbuf_setnext(mp2, mp); 2589ec7b004SRick Macklem } 2599ec7b004SRick Macklem cp = NFSMTOD(mp, caddr_t) + mbuf_len(mp); 2609ec7b004SRick Macklem for (left = 0; left < rem; left++) 2619ec7b004SRick Macklem *cp++ = '\0'; 2629ec7b004SRick Macklem mbuf_setlen(mp, mbuf_len(mp) + rem); 2639ec7b004SRick Macklem nd->nd_bpos = cp; 2649ec7b004SRick Macklem } else 2659ec7b004SRick Macklem nd->nd_bpos = NFSMTOD(mp, caddr_t) + mbuf_len(mp); 2669ec7b004SRick Macklem nd->nd_mb = mp; 2679ec7b004SRick Macklem } 2689ec7b004SRick Macklem #endif /* !APPLE */ 2699ec7b004SRick Macklem 2709ec7b004SRick Macklem /* 2719ec7b004SRick Macklem * Load vnode attributes from the xdr file attributes. 2729ec7b004SRick Macklem * Returns EBADRPC if they can't be parsed, 0 otherwise. 2739ec7b004SRick Macklem */ 2749ec7b004SRick Macklem APPLESTATIC int 2759ec7b004SRick Macklem nfsm_loadattr(struct nfsrv_descript *nd, struct nfsvattr *nap) 2769ec7b004SRick Macklem { 2779ec7b004SRick Macklem struct nfs_fattr *fp; 2789ec7b004SRick Macklem int error = 0; 2799ec7b004SRick Macklem 2809ec7b004SRick Macklem if (nd->nd_flag & ND_NFSV4) { 2819ec7b004SRick Macklem error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL, 2829ec7b004SRick Macklem NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL); 2839ec7b004SRick Macklem } else if (nd->nd_flag & ND_NFSV3) { 2849ec7b004SRick Macklem NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V3FATTR); 2859ec7b004SRick Macklem nap->na_type = nfsv34tov_type(fp->fa_type); 2869ec7b004SRick Macklem nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode); 2879ec7b004SRick Macklem nap->na_rdev = makedev(fxdr_unsigned(u_char, fp->fa3_rdev.specdata1), 2889ec7b004SRick Macklem fxdr_unsigned(u_char, fp->fa3_rdev.specdata2)); 2899ec7b004SRick Macklem nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink); 2909ec7b004SRick Macklem nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid); 2919ec7b004SRick Macklem nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid); 2929ec7b004SRick Macklem nap->na_size = fxdr_hyper(&fp->fa3_size); 2939ec7b004SRick Macklem nap->na_blocksize = NFS_FABLKSIZE; 2949ec7b004SRick Macklem nap->na_bytes = fxdr_hyper(&fp->fa3_used); 2959ec7b004SRick Macklem nap->na_fileid = fxdr_unsigned(int32_t, 2969ec7b004SRick Macklem fp->fa3_fileid.nfsuquad[1]); 2979ec7b004SRick Macklem fxdr_nfsv3time(&fp->fa3_atime, &nap->na_atime); 2989ec7b004SRick Macklem fxdr_nfsv3time(&fp->fa3_ctime, &nap->na_ctime); 2999ec7b004SRick Macklem fxdr_nfsv3time(&fp->fa3_mtime, &nap->na_mtime); 3009ec7b004SRick Macklem nap->na_flags = 0; 3019ec7b004SRick Macklem nap->na_filerev = 0; 3029ec7b004SRick Macklem } else { 3039ec7b004SRick Macklem NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V2FATTR); 3049ec7b004SRick Macklem nap->na_type = nfsv2tov_type(fp->fa_type); 3059ec7b004SRick Macklem nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode); 3069ec7b004SRick Macklem if (nap->na_type == VNON || nap->na_type == VREG) 3079ec7b004SRick Macklem nap->na_type = IFTOVT(nap->na_mode); 3089ec7b004SRick Macklem nap->na_rdev = fxdr_unsigned(dev_t, fp->fa2_rdev); 3099ec7b004SRick Macklem 3109ec7b004SRick Macklem /* 3119ec7b004SRick Macklem * Really ugly NFSv2 kludge. 3129ec7b004SRick Macklem */ 3139ec7b004SRick Macklem if (nap->na_type == VCHR && nap->na_rdev == ((dev_t)-1)) 3149ec7b004SRick Macklem nap->na_type = VFIFO; 3159ec7b004SRick Macklem nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink); 3169ec7b004SRick Macklem nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid); 3179ec7b004SRick Macklem nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid); 3189ec7b004SRick Macklem nap->na_size = fxdr_unsigned(u_int32_t, fp->fa2_size); 3199ec7b004SRick Macklem nap->na_blocksize = fxdr_unsigned(int32_t, fp->fa2_blocksize); 3209ec7b004SRick Macklem nap->na_bytes = 3219ec7b004SRick Macklem (u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks) * 3229ec7b004SRick Macklem NFS_FABLKSIZE; 3239ec7b004SRick Macklem nap->na_fileid = fxdr_unsigned(int32_t, fp->fa2_fileid); 3249ec7b004SRick Macklem fxdr_nfsv2time(&fp->fa2_atime, &nap->na_atime); 3259ec7b004SRick Macklem fxdr_nfsv2time(&fp->fa2_mtime, &nap->na_mtime); 3269ec7b004SRick Macklem nap->na_flags = 0; 3279ec7b004SRick Macklem nap->na_ctime.tv_sec = fxdr_unsigned(u_int32_t, 3289ec7b004SRick Macklem fp->fa2_ctime.nfsv2_sec); 3299ec7b004SRick Macklem nap->na_ctime.tv_nsec = 0; 3309ec7b004SRick Macklem nap->na_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec); 3319ec7b004SRick Macklem nap->na_filerev = 0; 3329ec7b004SRick Macklem } 3339ec7b004SRick Macklem nfsmout: 3349ec7b004SRick Macklem return (error); 3359ec7b004SRick Macklem } 3369ec7b004SRick Macklem 3379ec7b004SRick Macklem /* 3389ec7b004SRick Macklem * This function finds the directory cookie that corresponds to the 3399ec7b004SRick Macklem * logical byte offset given. 3409ec7b004SRick Macklem */ 3419ec7b004SRick Macklem APPLESTATIC nfsuint64 * 3429ec7b004SRick Macklem nfscl_getcookie(struct nfsnode *np, off_t off, int add) 3439ec7b004SRick Macklem { 3449ec7b004SRick Macklem struct nfsdmap *dp, *dp2; 3459ec7b004SRick Macklem int pos; 3469ec7b004SRick Macklem 3479ec7b004SRick Macklem pos = off / NFS_DIRBLKSIZ; 3489ec7b004SRick Macklem if (pos == 0) { 3499ec7b004SRick Macklem #ifdef DIAGNOSTIC 3509ec7b004SRick Macklem if (add) 3519ec7b004SRick Macklem panic("nfs getcookie add at 0"); 3529ec7b004SRick Macklem #endif 3539ec7b004SRick Macklem return (&nfs_nullcookie); 3549ec7b004SRick Macklem } 3559ec7b004SRick Macklem pos--; 3569ec7b004SRick Macklem dp = LIST_FIRST(&np->n_cookies); 3579ec7b004SRick Macklem if (!dp) { 3589ec7b004SRick Macklem if (add) { 3599ec7b004SRick Macklem MALLOC(dp, struct nfsdmap *, sizeof (struct nfsdmap), 3609ec7b004SRick Macklem M_NFSDIROFF, M_WAITOK); 3619ec7b004SRick Macklem dp->ndm_eocookie = 0; 3629ec7b004SRick Macklem LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list); 3639ec7b004SRick Macklem } else 3649ec7b004SRick Macklem return (NULL); 3659ec7b004SRick Macklem } 3669ec7b004SRick Macklem while (pos >= NFSNUMCOOKIES) { 3679ec7b004SRick Macklem pos -= NFSNUMCOOKIES; 3689ec7b004SRick Macklem if (LIST_NEXT(dp, ndm_list) != NULL) { 3699ec7b004SRick Macklem if (!add && dp->ndm_eocookie < NFSNUMCOOKIES && 3709ec7b004SRick Macklem pos >= dp->ndm_eocookie) 3719ec7b004SRick Macklem return (NULL); 3729ec7b004SRick Macklem dp = LIST_NEXT(dp, ndm_list); 3739ec7b004SRick Macklem } else if (add) { 3749ec7b004SRick Macklem MALLOC(dp2, struct nfsdmap *, sizeof (struct nfsdmap), 3759ec7b004SRick Macklem M_NFSDIROFF, M_WAITOK); 3769ec7b004SRick Macklem dp2->ndm_eocookie = 0; 3779ec7b004SRick Macklem LIST_INSERT_AFTER(dp, dp2, ndm_list); 3789ec7b004SRick Macklem dp = dp2; 3799ec7b004SRick Macklem } else 3809ec7b004SRick Macklem return (NULL); 3819ec7b004SRick Macklem } 3829ec7b004SRick Macklem if (pos >= dp->ndm_eocookie) { 3839ec7b004SRick Macklem if (add) 3849ec7b004SRick Macklem dp->ndm_eocookie = pos + 1; 3859ec7b004SRick Macklem else 3869ec7b004SRick Macklem return (NULL); 3879ec7b004SRick Macklem } 3889ec7b004SRick Macklem return (&dp->ndm_cookies[pos]); 3899ec7b004SRick Macklem } 3909ec7b004SRick Macklem 3919ec7b004SRick Macklem /* 3929ec7b004SRick Macklem * Gets a file handle out of an nfs reply sent to the client and returns 3939ec7b004SRick Macklem * the file handle and the file's attributes. 3949ec7b004SRick Macklem * For V4, it assumes that Getfh and Getattr Op's results are here. 3959ec7b004SRick Macklem */ 3969ec7b004SRick Macklem APPLESTATIC int 3979ec7b004SRick Macklem nfscl_mtofh(struct nfsrv_descript *nd, struct nfsfh **nfhpp, 3989ec7b004SRick Macklem struct nfsvattr *nap, int *attrflagp) 3999ec7b004SRick Macklem { 4009ec7b004SRick Macklem u_int32_t *tl; 4019ec7b004SRick Macklem int error = 0, flag = 1; 4029ec7b004SRick Macklem 4039ec7b004SRick Macklem *nfhpp = NULL; 4049ec7b004SRick Macklem *attrflagp = 0; 4059ec7b004SRick Macklem /* 4069ec7b004SRick Macklem * First get the file handle and vnode. 4079ec7b004SRick Macklem */ 4089ec7b004SRick Macklem if (nd->nd_flag & ND_NFSV3) { 4099ec7b004SRick Macklem NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 4109ec7b004SRick Macklem flag = fxdr_unsigned(int, *tl); 4119ec7b004SRick Macklem } else if (nd->nd_flag & ND_NFSV4) { 4129ec7b004SRick Macklem NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 4139ec7b004SRick Macklem } 4149ec7b004SRick Macklem if (flag) { 4159ec7b004SRick Macklem error = nfsm_getfh(nd, nfhpp); 4169ec7b004SRick Macklem if (error) 4179ec7b004SRick Macklem return (error); 4189ec7b004SRick Macklem } 4199ec7b004SRick Macklem 4209ec7b004SRick Macklem /* 4219ec7b004SRick Macklem * Now, get the attributes. 4229ec7b004SRick Macklem */ 4239ec7b004SRick Macklem if (nd->nd_flag & ND_NFSV4) { 4249ec7b004SRick Macklem NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 4259ec7b004SRick Macklem } else if (nd->nd_flag & ND_NFSV3) { 4269ec7b004SRick Macklem NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 4279ec7b004SRick Macklem if (flag) { 4289ec7b004SRick Macklem flag = fxdr_unsigned(int, *tl); 4299ec7b004SRick Macklem } else if (fxdr_unsigned(int, *tl)) { 4309ec7b004SRick Macklem error = nfsm_advance(nd, NFSX_V3FATTR, -1); 4319ec7b004SRick Macklem if (error) 4329ec7b004SRick Macklem return (error); 4339ec7b004SRick Macklem } 4349ec7b004SRick Macklem } 4359ec7b004SRick Macklem if (flag) { 4369ec7b004SRick Macklem error = nfsm_loadattr(nd, nap); 4379ec7b004SRick Macklem if (!error) 4389ec7b004SRick Macklem *attrflagp = 1; 4399ec7b004SRick Macklem } 4409ec7b004SRick Macklem nfsmout: 4419ec7b004SRick Macklem return (error); 4429ec7b004SRick Macklem } 4439ec7b004SRick Macklem 4449ec7b004SRick Macklem /* 4459ec7b004SRick Macklem * Put a state Id in the mbuf list. 4469ec7b004SRick Macklem */ 4479ec7b004SRick Macklem APPLESTATIC void 4489ec7b004SRick Macklem nfsm_stateidtom(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp, int flag) 4499ec7b004SRick Macklem { 4509ec7b004SRick Macklem nfsv4stateid_t *st; 4519ec7b004SRick Macklem 4529ec7b004SRick Macklem NFSM_BUILD(st, nfsv4stateid_t *, NFSX_STATEID); 4539ec7b004SRick Macklem if (flag == NFSSTATEID_PUTALLZERO) { 4549ec7b004SRick Macklem st->seqid = 0; 4559ec7b004SRick Macklem st->other[0] = 0; 4569ec7b004SRick Macklem st->other[1] = 0; 4579ec7b004SRick Macklem st->other[2] = 0; 4589ec7b004SRick Macklem } else if (flag == NFSSTATEID_PUTALLONE) { 4599ec7b004SRick Macklem st->seqid = 0xffffffff; 4609ec7b004SRick Macklem st->other[0] = 0xffffffff; 4619ec7b004SRick Macklem st->other[1] = 0xffffffff; 4629ec7b004SRick Macklem st->other[2] = 0xffffffff; 4639ec7b004SRick Macklem } else { 4649ec7b004SRick Macklem st->seqid = stateidp->seqid; 4659ec7b004SRick Macklem st->other[0] = stateidp->other[0]; 4669ec7b004SRick Macklem st->other[1] = stateidp->other[1]; 4679ec7b004SRick Macklem st->other[2] = stateidp->other[2]; 4689ec7b004SRick Macklem } 4699ec7b004SRick Macklem } 4709ec7b004SRick Macklem 4719ec7b004SRick Macklem /* 4729ec7b004SRick Macklem * Initialize the owner/delegation sleep lock. 4739ec7b004SRick Macklem */ 4749ec7b004SRick Macklem APPLESTATIC void 4759ec7b004SRick Macklem nfscl_lockinit(struct nfsv4lock *lckp) 4769ec7b004SRick Macklem { 4779ec7b004SRick Macklem 4789ec7b004SRick Macklem lckp->nfslock_usecnt = 0; 4799ec7b004SRick Macklem lckp->nfslock_lock = 0; 4809ec7b004SRick Macklem } 4819ec7b004SRick Macklem 4829ec7b004SRick Macklem /* 4839ec7b004SRick Macklem * Get an exclusive lock. (Not needed for OpenBSD4, since there is only one 4849ec7b004SRick Macklem * thread for each posix process in the kernel.) 4859ec7b004SRick Macklem */ 4869ec7b004SRick Macklem APPLESTATIC void 4879ec7b004SRick Macklem nfscl_lockexcl(struct nfsv4lock *lckp, void *mutex) 4889ec7b004SRick Macklem { 4899ec7b004SRick Macklem int igotlock; 4909ec7b004SRick Macklem 4919ec7b004SRick Macklem do { 4929ec7b004SRick Macklem igotlock = nfsv4_lock(lckp, 1, NULL, mutex); 4939ec7b004SRick Macklem } while (!igotlock); 4949ec7b004SRick Macklem } 4959ec7b004SRick Macklem 4969ec7b004SRick Macklem /* 4979ec7b004SRick Macklem * Release an exclusive lock. 4989ec7b004SRick Macklem */ 4999ec7b004SRick Macklem APPLESTATIC void 5009ec7b004SRick Macklem nfscl_lockunlock(struct nfsv4lock *lckp) 5019ec7b004SRick Macklem { 5029ec7b004SRick Macklem 5039ec7b004SRick Macklem nfsv4_unlock(lckp, 0); 5049ec7b004SRick Macklem } 5059ec7b004SRick Macklem 5069ec7b004SRick Macklem /* 5079ec7b004SRick Macklem * Called to derefernce a lock on a stateid (delegation or open owner). 5089ec7b004SRick Macklem */ 5099ec7b004SRick Macklem APPLESTATIC void 5109ec7b004SRick Macklem nfscl_lockderef(struct nfsv4lock *lckp) 5119ec7b004SRick Macklem { 5129ec7b004SRick Macklem 5139ec7b004SRick Macklem NFSLOCKCLSTATE(); 5149ec7b004SRick Macklem lckp->nfslock_usecnt--; 5159ec7b004SRick Macklem if (lckp->nfslock_usecnt == 0 && (lckp->nfslock_lock & NFSV4LOCK_WANTED)) { 5169ec7b004SRick Macklem lckp->nfslock_lock &= ~NFSV4LOCK_WANTED; 5179ec7b004SRick Macklem wakeup((caddr_t)lckp); 5189ec7b004SRick Macklem } 5199ec7b004SRick Macklem NFSUNLOCKCLSTATE(); 5209ec7b004SRick Macklem } 5219ec7b004SRick Macklem 522