xref: /freebsd/sys/fs/nfsclient/nfs_clcomsubs.c (revision 9ec7b004d0edbf800e5b875353109a36b997b0a3)
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