Home | History | Annotate | Line # | Download | only in client
nfs_clcomsubs.c revision 1.1.1.1.10.3
      1  1.1.1.1.10.2       tls /*	$NetBSD: nfs_clcomsubs.c,v 1.1.1.1.10.3 2017/12/03 11:38:42 jdolecek Exp $	*/
      2  1.1.1.1.10.2       tls /*-
      3  1.1.1.1.10.2       tls  * Copyright (c) 1989, 1993
      4  1.1.1.1.10.2       tls  *	The Regents of the University of California.  All rights reserved.
      5  1.1.1.1.10.2       tls  *
      6  1.1.1.1.10.2       tls  * This code is derived from software contributed to Berkeley by
      7  1.1.1.1.10.2       tls  * Rick Macklem at The University of Guelph.
      8  1.1.1.1.10.2       tls  *
      9  1.1.1.1.10.2       tls  * Redistribution and use in source and binary forms, with or without
     10  1.1.1.1.10.2       tls  * modification, are permitted provided that the following conditions
     11  1.1.1.1.10.2       tls  * are met:
     12  1.1.1.1.10.2       tls  * 1. Redistributions of source code must retain the above copyright
     13  1.1.1.1.10.2       tls  *    notice, this list of conditions and the following disclaimer.
     14  1.1.1.1.10.2       tls  * 2. Redistributions in binary form must reproduce the above copyright
     15  1.1.1.1.10.2       tls  *    notice, this list of conditions and the following disclaimer in the
     16  1.1.1.1.10.2       tls  *    documentation and/or other materials provided with the distribution.
     17  1.1.1.1.10.2       tls  * 4. Neither the name of the University nor the names of its contributors
     18  1.1.1.1.10.2       tls  *    may be used to endorse or promote products derived from this software
     19  1.1.1.1.10.2       tls  *    without specific prior written permission.
     20  1.1.1.1.10.2       tls  *
     21  1.1.1.1.10.2       tls  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     22  1.1.1.1.10.2       tls  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23  1.1.1.1.10.2       tls  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24  1.1.1.1.10.2       tls  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     25  1.1.1.1.10.2       tls  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26  1.1.1.1.10.2       tls  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27  1.1.1.1.10.2       tls  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28  1.1.1.1.10.2       tls  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29  1.1.1.1.10.2       tls  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30  1.1.1.1.10.2       tls  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31  1.1.1.1.10.2       tls  * SUCH DAMAGE.
     32  1.1.1.1.10.2       tls  *
     33  1.1.1.1.10.2       tls  */
     34  1.1.1.1.10.2       tls 
     35  1.1.1.1.10.2       tls #include <sys/cdefs.h>
     36  1.1.1.1.10.3  jdolecek /* __FBSDID("FreeBSD: head/sys/fs/nfsclient/nfs_clcomsubs.c 304026 2016-08-12 22:44:59Z rmacklem "); */
     37  1.1.1.1.10.2       tls __RCSID("$NetBSD: nfs_clcomsubs.c,v 1.1.1.1.10.3 2017/12/03 11:38:42 jdolecek Exp $");
     38  1.1.1.1.10.2       tls 
     39  1.1.1.1.10.2       tls /*
     40  1.1.1.1.10.2       tls  * These functions support the macros and help fiddle mbuf chains for
     41  1.1.1.1.10.2       tls  * the nfs op functions. They do things like create the rpc header and
     42  1.1.1.1.10.2       tls  * copy data between mbuf chains and uio lists.
     43  1.1.1.1.10.2       tls  */
     44  1.1.1.1.10.2       tls #ifndef APPLEKEXT
     45  1.1.1.1.10.3  jdolecek #include <fs/nfs/common/nfsport.h>
     46  1.1.1.1.10.2       tls 
     47  1.1.1.1.10.3  jdolecek extern struct nfsstatsv1 nfsstatsv1;
     48  1.1.1.1.10.2       tls extern struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS];
     49  1.1.1.1.10.2       tls extern int ncl_mbuf_mlen;
     50  1.1.1.1.10.2       tls extern enum vtype newnv2tov_type[8];
     51  1.1.1.1.10.2       tls extern enum vtype nv34tov_type[8];
     52  1.1.1.1.10.2       tls extern int	nfs_bigreply[NFSV41_NPROCS];
     53  1.1.1.1.10.2       tls NFSCLSTATEMUTEX;
     54  1.1.1.1.10.2       tls #endif	/* !APPLEKEXT */
     55  1.1.1.1.10.2       tls 
     56  1.1.1.1.10.2       tls static nfsuint64 nfs_nullcookie = {{ 0, 0 }};
     57  1.1.1.1.10.2       tls static struct {
     58  1.1.1.1.10.2       tls 	int	op;
     59  1.1.1.1.10.2       tls 	int	opcnt;
     60  1.1.1.1.10.2       tls 	const u_char *tag;
     61  1.1.1.1.10.2       tls 	int	taglen;
     62  1.1.1.1.10.2       tls } nfsv4_opmap[NFSV41_NPROCS] = {
     63  1.1.1.1.10.2       tls 	{ 0, 1, "Null", 4 },
     64  1.1.1.1.10.2       tls 	{ NFSV4OP_GETATTR, 1, "Getattr", 7, },
     65  1.1.1.1.10.2       tls 	{ NFSV4OP_SETATTR, 2, "Setattr", 7, },
     66  1.1.1.1.10.2       tls 	{ NFSV4OP_LOOKUP, 3, "Lookup", 6, },
     67  1.1.1.1.10.2       tls 	{ NFSV4OP_ACCESS, 2, "Access", 6, },
     68  1.1.1.1.10.2       tls 	{ NFSV4OP_READLINK, 2, "Readlink", 8, },
     69  1.1.1.1.10.2       tls 	{ NFSV4OP_READ, 1, "Read", 4, },
     70  1.1.1.1.10.2       tls 	{ NFSV4OP_WRITE, 2, "Write", 5, },
     71  1.1.1.1.10.3  jdolecek 	{ NFSV4OP_OPEN, 5, "Open", 4, },
     72  1.1.1.1.10.3  jdolecek 	{ NFSV4OP_CREATE, 5, "Create", 6, },
     73  1.1.1.1.10.2       tls 	{ NFSV4OP_CREATE, 1, "Create", 6, },
     74  1.1.1.1.10.2       tls 	{ NFSV4OP_CREATE, 3, "Create", 6, },
     75  1.1.1.1.10.2       tls 	{ NFSV4OP_REMOVE, 1, "Remove", 6, },
     76  1.1.1.1.10.2       tls 	{ NFSV4OP_REMOVE, 1, "Remove", 6, },
     77  1.1.1.1.10.2       tls 	{ NFSV4OP_SAVEFH, 5, "Rename", 6, },
     78  1.1.1.1.10.2       tls 	{ NFSV4OP_SAVEFH, 4, "Link", 4, },
     79  1.1.1.1.10.2       tls 	{ NFSV4OP_READDIR, 2, "Readdir", 7, },
     80  1.1.1.1.10.2       tls 	{ NFSV4OP_READDIR, 2, "Readdir", 7, },
     81  1.1.1.1.10.2       tls 	{ NFSV4OP_GETATTR, 1, "Getattr", 7, },
     82  1.1.1.1.10.2       tls 	{ NFSV4OP_GETATTR, 1, "Getattr", 7, },
     83  1.1.1.1.10.2       tls 	{ NFSV4OP_GETATTR, 1, "Getattr", 7, },
     84  1.1.1.1.10.2       tls 	{ NFSV4OP_COMMIT, 2, "Commit", 6, },
     85  1.1.1.1.10.2       tls 	{ NFSV4OP_LOOKUPP, 3, "Lookupp", 7, },
     86  1.1.1.1.10.2       tls 	{ NFSV4OP_SETCLIENTID, 1, "SetClientID", 11, },
     87  1.1.1.1.10.2       tls 	{ NFSV4OP_SETCLIENTIDCFRM, 1, "SetClientIDConfirm", 18, },
     88  1.1.1.1.10.2       tls 	{ NFSV4OP_LOCK, 1, "Lock", 4, },
     89  1.1.1.1.10.2       tls 	{ NFSV4OP_LOCKU, 1, "LockU", 5, },
     90  1.1.1.1.10.2       tls 	{ NFSV4OP_OPEN, 2, "Open", 4, },
     91  1.1.1.1.10.2       tls 	{ NFSV4OP_CLOSE, 1, "Close", 5, },
     92  1.1.1.1.10.2       tls 	{ NFSV4OP_OPENCONFIRM, 1, "Openconfirm", 11, },
     93  1.1.1.1.10.2       tls 	{ NFSV4OP_LOCKT, 1, "LockT", 5, },
     94  1.1.1.1.10.2       tls 	{ NFSV4OP_OPENDOWNGRADE, 1, "Opendowngrade", 13, },
     95  1.1.1.1.10.2       tls 	{ NFSV4OP_RENEW, 1, "Renew", 5, },
     96  1.1.1.1.10.2       tls 	{ NFSV4OP_PUTROOTFH, 1, "Dirpath", 7, },
     97  1.1.1.1.10.2       tls 	{ NFSV4OP_RELEASELCKOWN, 1, "Rellckown", 9, },
     98  1.1.1.1.10.2       tls 	{ NFSV4OP_DELEGRETURN, 1, "Delegret", 8, },
     99  1.1.1.1.10.2       tls 	{ NFSV4OP_DELEGRETURN, 3, "DelegRemove", 11, },
    100  1.1.1.1.10.2       tls 	{ NFSV4OP_DELEGRETURN, 7, "DelegRename1", 12, },
    101  1.1.1.1.10.2       tls 	{ NFSV4OP_DELEGRETURN, 9, "DelegRename2", 12, },
    102  1.1.1.1.10.2       tls 	{ NFSV4OP_GETATTR, 1, "Getacl", 6, },
    103  1.1.1.1.10.2       tls 	{ NFSV4OP_SETATTR, 1, "Setacl", 6, },
    104  1.1.1.1.10.2       tls 	{ NFSV4OP_EXCHANGEID, 1, "ExchangeID", 10, },
    105  1.1.1.1.10.2       tls 	{ NFSV4OP_CREATESESSION, 1, "CreateSession", 13, },
    106  1.1.1.1.10.2       tls 	{ NFSV4OP_DESTROYSESSION, 1, "DestroySession", 14, },
    107  1.1.1.1.10.2       tls 	{ NFSV4OP_DESTROYCLIENTID, 1, "DestroyClient", 13, },
    108  1.1.1.1.10.2       tls 	{ NFSV4OP_FREESTATEID, 1, "FreeStateID", 11, },
    109  1.1.1.1.10.2       tls 	{ NFSV4OP_LAYOUTGET, 1, "LayoutGet", 9, },
    110  1.1.1.1.10.2       tls 	{ NFSV4OP_GETDEVINFO, 1, "GetDeviceInfo", 13, },
    111  1.1.1.1.10.2       tls 	{ NFSV4OP_LAYOUTCOMMIT, 1, "LayoutCommit", 12, },
    112  1.1.1.1.10.2       tls 	{ NFSV4OP_LAYOUTRETURN, 1, "LayoutReturn", 12, },
    113  1.1.1.1.10.2       tls 	{ NFSV4OP_RECLAIMCOMPL, 1, "ReclaimComplete", 15, },
    114  1.1.1.1.10.2       tls 	{ NFSV4OP_WRITE, 1, "WriteDS", 7, },
    115  1.1.1.1.10.2       tls 	{ NFSV4OP_READ, 1, "ReadDS", 6, },
    116  1.1.1.1.10.2       tls 	{ NFSV4OP_COMMIT, 1, "CommitDS", 8, },
    117  1.1.1.1.10.2       tls };
    118  1.1.1.1.10.2       tls 
    119  1.1.1.1.10.2       tls /*
    120  1.1.1.1.10.2       tls  * NFS RPCS that have large request message size.
    121  1.1.1.1.10.2       tls  */
    122  1.1.1.1.10.2       tls static int nfs_bigrequest[NFSV41_NPROCS] = {
    123  1.1.1.1.10.2       tls 	0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    124  1.1.1.1.10.2       tls 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    125  1.1.1.1.10.2       tls 	0, 0, 0, 0, 0, 0, 1, 0, 0
    126  1.1.1.1.10.2       tls };
    127  1.1.1.1.10.2       tls 
    128  1.1.1.1.10.2       tls /*
    129  1.1.1.1.10.2       tls  * Start building a request. Mostly just put the first file handle in
    130  1.1.1.1.10.2       tls  * place.
    131  1.1.1.1.10.2       tls  */
    132  1.1.1.1.10.2       tls APPLESTATIC void
    133  1.1.1.1.10.2       tls nfscl_reqstart(struct nfsrv_descript *nd, int procnum, struct nfsmount *nmp,
    134  1.1.1.1.10.2       tls     u_int8_t *nfhp, int fhlen, u_int32_t **opcntpp, struct nfsclsession *sep)
    135  1.1.1.1.10.2       tls {
    136  1.1.1.1.10.2       tls 	struct mbuf *mb;
    137  1.1.1.1.10.2       tls 	u_int32_t *tl;
    138  1.1.1.1.10.2       tls 	int opcnt;
    139  1.1.1.1.10.2       tls 	nfsattrbit_t attrbits;
    140  1.1.1.1.10.2       tls 
    141  1.1.1.1.10.2       tls 	/*
    142  1.1.1.1.10.2       tls 	 * First, fill in some of the fields of nd.
    143  1.1.1.1.10.2       tls 	 */
    144  1.1.1.1.10.2       tls 	nd->nd_slotseq = NULL;
    145  1.1.1.1.10.2       tls 	if (NFSHASNFSV4(nmp)) {
    146  1.1.1.1.10.2       tls 		nd->nd_flag = ND_NFSV4 | ND_NFSCL;
    147  1.1.1.1.10.2       tls 		if (NFSHASNFSV4N(nmp))
    148  1.1.1.1.10.2       tls 			nd->nd_flag |= ND_NFSV41;
    149  1.1.1.1.10.2       tls 	} else if (NFSHASNFSV3(nmp))
    150  1.1.1.1.10.2       tls 		nd->nd_flag = ND_NFSV3 | ND_NFSCL;
    151  1.1.1.1.10.2       tls 	else
    152  1.1.1.1.10.2       tls 		nd->nd_flag = ND_NFSV2 | ND_NFSCL;
    153  1.1.1.1.10.2       tls 	nd->nd_procnum = procnum;
    154  1.1.1.1.10.2       tls 	nd->nd_repstat = 0;
    155  1.1.1.1.10.2       tls 
    156  1.1.1.1.10.2       tls 	/*
    157  1.1.1.1.10.2       tls 	 * Get the first mbuf for the request.
    158  1.1.1.1.10.2       tls 	 */
    159  1.1.1.1.10.2       tls 	if (nfs_bigrequest[procnum])
    160  1.1.1.1.10.2       tls 		NFSMCLGET(mb, M_WAITOK);
    161  1.1.1.1.10.2       tls 	else
    162  1.1.1.1.10.2       tls 		NFSMGET(mb);
    163  1.1.1.1.10.2       tls 	mbuf_setlen(mb, 0);
    164  1.1.1.1.10.2       tls 	nd->nd_mreq = nd->nd_mb = mb;
    165  1.1.1.1.10.2       tls 	nd->nd_bpos = NFSMTOD(mb, caddr_t);
    166  1.1.1.1.10.2       tls 
    167  1.1.1.1.10.2       tls 	/*
    168  1.1.1.1.10.2       tls 	 * And fill the first file handle into the request.
    169  1.1.1.1.10.2       tls 	 */
    170  1.1.1.1.10.2       tls 	if (nd->nd_flag & ND_NFSV4) {
    171  1.1.1.1.10.2       tls 		opcnt = nfsv4_opmap[procnum].opcnt +
    172  1.1.1.1.10.2       tls 		    nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh;
    173  1.1.1.1.10.2       tls 		if ((nd->nd_flag & ND_NFSV41) != 0) {
    174  1.1.1.1.10.2       tls 			opcnt += nfsv4_opflag[nfsv4_opmap[procnum].op].needsseq;
    175  1.1.1.1.10.2       tls 			if (procnum == NFSPROC_RENEW)
    176  1.1.1.1.10.2       tls 				/*
    177  1.1.1.1.10.2       tls 				 * For the special case of Renew, just do a
    178  1.1.1.1.10.2       tls 				 * Sequence Op.
    179  1.1.1.1.10.2       tls 				 */
    180  1.1.1.1.10.2       tls 				opcnt = 1;
    181  1.1.1.1.10.2       tls 			else if (procnum == NFSPROC_WRITEDS ||
    182  1.1.1.1.10.2       tls 			    procnum == NFSPROC_COMMITDS)
    183  1.1.1.1.10.2       tls 				/*
    184  1.1.1.1.10.2       tls 				 * For the special case of a Writeor Commit to
    185  1.1.1.1.10.2       tls 				 * a DS, the opcnt == 3, for Sequence, PutFH,
    186  1.1.1.1.10.2       tls 				 * Write/Commit.
    187  1.1.1.1.10.2       tls 				 */
    188  1.1.1.1.10.2       tls 				opcnt = 3;
    189  1.1.1.1.10.2       tls 		}
    190  1.1.1.1.10.2       tls 		/*
    191  1.1.1.1.10.2       tls 		 * What should the tag really be?
    192  1.1.1.1.10.2       tls 		 */
    193  1.1.1.1.10.2       tls 		(void) nfsm_strtom(nd, nfsv4_opmap[procnum].tag,
    194  1.1.1.1.10.2       tls 			nfsv4_opmap[procnum].taglen);
    195  1.1.1.1.10.2       tls 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
    196  1.1.1.1.10.2       tls 		if ((nd->nd_flag & ND_NFSV41) != 0)
    197  1.1.1.1.10.2       tls 			*tl++ = txdr_unsigned(NFSV41_MINORVERSION);
    198  1.1.1.1.10.2       tls 		else
    199  1.1.1.1.10.2       tls 			*tl++ = txdr_unsigned(NFSV4_MINORVERSION);
    200  1.1.1.1.10.2       tls 		if (opcntpp != NULL)
    201  1.1.1.1.10.2       tls 			*opcntpp = tl;
    202  1.1.1.1.10.2       tls 		*tl = txdr_unsigned(opcnt);
    203  1.1.1.1.10.2       tls 		if ((nd->nd_flag & ND_NFSV41) != 0 &&
    204  1.1.1.1.10.2       tls 		    nfsv4_opflag[nfsv4_opmap[procnum].op].needsseq > 0) {
    205  1.1.1.1.10.2       tls 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
    206  1.1.1.1.10.2       tls 			*tl = txdr_unsigned(NFSV4OP_SEQUENCE);
    207  1.1.1.1.10.2       tls 			if (sep == NULL)
    208  1.1.1.1.10.3  jdolecek 				nfsv4_setsequence(nmp, nd,
    209  1.1.1.1.10.3  jdolecek 				    NFSMNT_MDSSESSION(nmp),
    210  1.1.1.1.10.2       tls 				    nfs_bigreply[procnum]);
    211  1.1.1.1.10.2       tls 			else
    212  1.1.1.1.10.3  jdolecek 				nfsv4_setsequence(nmp, nd, sep,
    213  1.1.1.1.10.2       tls 				    nfs_bigreply[procnum]);
    214  1.1.1.1.10.2       tls 		}
    215  1.1.1.1.10.2       tls 		if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh > 0) {
    216  1.1.1.1.10.2       tls 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
    217  1.1.1.1.10.2       tls 			*tl = txdr_unsigned(NFSV4OP_PUTFH);
    218  1.1.1.1.10.2       tls 			(void) nfsm_fhtom(nd, nfhp, fhlen, 0);
    219  1.1.1.1.10.2       tls 			if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh
    220  1.1.1.1.10.2       tls 			    == 2 && procnum != NFSPROC_WRITEDS &&
    221  1.1.1.1.10.2       tls 			    procnum != NFSPROC_COMMITDS) {
    222  1.1.1.1.10.2       tls 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
    223  1.1.1.1.10.2       tls 				*tl = txdr_unsigned(NFSV4OP_GETATTR);
    224  1.1.1.1.10.3  jdolecek 				/*
    225  1.1.1.1.10.3  jdolecek 				 * For Lookup Ops, we want all the directory
    226  1.1.1.1.10.3  jdolecek 				 * attributes, so we can load the name cache.
    227  1.1.1.1.10.3  jdolecek 				 */
    228  1.1.1.1.10.3  jdolecek 				if (procnum == NFSPROC_LOOKUP ||
    229  1.1.1.1.10.3  jdolecek 				    procnum == NFSPROC_LOOKUPP)
    230  1.1.1.1.10.3  jdolecek 					NFSGETATTR_ATTRBIT(&attrbits);
    231  1.1.1.1.10.3  jdolecek 				else {
    232  1.1.1.1.10.3  jdolecek 					NFSWCCATTR_ATTRBIT(&attrbits);
    233  1.1.1.1.10.3  jdolecek 					nd->nd_flag |= ND_V4WCCATTR;
    234  1.1.1.1.10.3  jdolecek 				}
    235  1.1.1.1.10.2       tls 				(void) nfsrv_putattrbit(nd, &attrbits);
    236  1.1.1.1.10.2       tls 			}
    237  1.1.1.1.10.2       tls 		}
    238  1.1.1.1.10.2       tls 		if (procnum != NFSPROC_RENEW ||
    239  1.1.1.1.10.2       tls 		    (nd->nd_flag & ND_NFSV41) == 0) {
    240  1.1.1.1.10.2       tls 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
    241  1.1.1.1.10.2       tls 			*tl = txdr_unsigned(nfsv4_opmap[procnum].op);
    242  1.1.1.1.10.2       tls 		}
    243  1.1.1.1.10.2       tls 	} else {
    244  1.1.1.1.10.2       tls 		(void) nfsm_fhtom(nd, nfhp, fhlen, 0);
    245  1.1.1.1.10.2       tls 	}
    246  1.1.1.1.10.3  jdolecek 	if (procnum < NFSV41_NPROCS)
    247  1.1.1.1.10.3  jdolecek 		NFSINCRGLOBAL(nfsstatsv1.rpccnt[procnum]);
    248  1.1.1.1.10.2       tls }
    249  1.1.1.1.10.2       tls 
    250  1.1.1.1.10.2       tls #ifndef APPLE
    251  1.1.1.1.10.2       tls /*
    252  1.1.1.1.10.2       tls  * copies a uio scatter/gather list to an mbuf chain.
    253  1.1.1.1.10.2       tls  * NOTE: can ony handle iovcnt == 1
    254  1.1.1.1.10.2       tls  */
    255  1.1.1.1.10.2       tls APPLESTATIC void
    256  1.1.1.1.10.2       tls nfsm_uiombuf(struct nfsrv_descript *nd, struct uio *uiop, int siz)
    257  1.1.1.1.10.2       tls {
    258  1.1.1.1.10.2       tls 	char *uiocp;
    259  1.1.1.1.10.2       tls 	struct mbuf *mp, *mp2;
    260  1.1.1.1.10.2       tls 	int xfer, left, mlen;
    261  1.1.1.1.10.2       tls 	int uiosiz, clflg, rem;
    262  1.1.1.1.10.2       tls 	char *cp, *tcp;
    263  1.1.1.1.10.2       tls 
    264  1.1.1.1.10.2       tls 	KASSERT(uiop->uio_iovcnt == 1, ("nfsm_uiotombuf: iovcnt != 1"));
    265  1.1.1.1.10.2       tls 
    266  1.1.1.1.10.2       tls 	if (siz > ncl_mbuf_mlen)	/* or should it >= MCLBYTES ?? */
    267  1.1.1.1.10.2       tls 		clflg = 1;
    268  1.1.1.1.10.2       tls 	else
    269  1.1.1.1.10.2       tls 		clflg = 0;
    270  1.1.1.1.10.2       tls 	rem = NFSM_RNDUP(siz) - siz;
    271  1.1.1.1.10.2       tls 	mp = mp2 = nd->nd_mb;
    272  1.1.1.1.10.2       tls 	while (siz > 0) {
    273  1.1.1.1.10.2       tls 		left = uiop->uio_iov->iov_len;
    274  1.1.1.1.10.2       tls 		uiocp = uiop->uio_iov->iov_base;
    275  1.1.1.1.10.2       tls 		if (left > siz)
    276  1.1.1.1.10.2       tls 			left = siz;
    277  1.1.1.1.10.2       tls 		uiosiz = left;
    278  1.1.1.1.10.2       tls 		while (left > 0) {
    279  1.1.1.1.10.2       tls 			mlen = M_TRAILINGSPACE(mp);
    280  1.1.1.1.10.2       tls 			if (mlen == 0) {
    281  1.1.1.1.10.2       tls 				if (clflg)
    282  1.1.1.1.10.2       tls 					NFSMCLGET(mp, M_WAITOK);
    283  1.1.1.1.10.2       tls 				else
    284  1.1.1.1.10.2       tls 					NFSMGET(mp);
    285  1.1.1.1.10.2       tls 				mbuf_setlen(mp, 0);
    286  1.1.1.1.10.2       tls 				mbuf_setnext(mp2, mp);
    287  1.1.1.1.10.2       tls 				mp2 = mp;
    288  1.1.1.1.10.2       tls 				mlen = M_TRAILINGSPACE(mp);
    289  1.1.1.1.10.2       tls 			}
    290  1.1.1.1.10.2       tls 			xfer = (left > mlen) ? mlen : left;
    291  1.1.1.1.10.2       tls #ifdef notdef
    292  1.1.1.1.10.2       tls 			/* Not Yet.. */
    293  1.1.1.1.10.2       tls 			if (uiop->uio_iov->iov_op != NULL)
    294  1.1.1.1.10.2       tls 				(*(uiop->uio_iov->iov_op))
    295  1.1.1.1.10.2       tls 				(uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp),
    296  1.1.1.1.10.2       tls 				    xfer);
    297  1.1.1.1.10.2       tls 			else
    298  1.1.1.1.10.2       tls #endif
    299  1.1.1.1.10.2       tls 			if (uiop->uio_segflg == UIO_SYSSPACE)
    300  1.1.1.1.10.2       tls 			    NFSBCOPY(uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp),
    301  1.1.1.1.10.2       tls 				xfer);
    302  1.1.1.1.10.2       tls 			else
    303  1.1.1.1.10.2       tls 			    copyin(CAST_USER_ADDR_T(uiocp), NFSMTOD(mp, caddr_t)
    304  1.1.1.1.10.2       tls 				+ mbuf_len(mp), xfer);
    305  1.1.1.1.10.2       tls 			mbuf_setlen(mp, mbuf_len(mp) + xfer);
    306  1.1.1.1.10.2       tls 			left -= xfer;
    307  1.1.1.1.10.2       tls 			uiocp += xfer;
    308  1.1.1.1.10.2       tls 			uiop->uio_offset += xfer;
    309  1.1.1.1.10.2       tls 			uiop->uio_resid -= xfer;
    310  1.1.1.1.10.2       tls 		}
    311  1.1.1.1.10.2       tls 		tcp = (char *)uiop->uio_iov->iov_base;
    312  1.1.1.1.10.2       tls 		tcp += uiosiz;
    313  1.1.1.1.10.2       tls 		uiop->uio_iov->iov_base = (void *)tcp;
    314  1.1.1.1.10.2       tls 		uiop->uio_iov->iov_len -= uiosiz;
    315  1.1.1.1.10.2       tls 		siz -= uiosiz;
    316  1.1.1.1.10.2       tls 	}
    317  1.1.1.1.10.2       tls 	if (rem > 0) {
    318  1.1.1.1.10.2       tls 		if (rem > M_TRAILINGSPACE(mp)) {
    319  1.1.1.1.10.2       tls 			NFSMGET(mp);
    320  1.1.1.1.10.2       tls 			mbuf_setlen(mp, 0);
    321  1.1.1.1.10.2       tls 			mbuf_setnext(mp2, mp);
    322  1.1.1.1.10.2       tls 		}
    323  1.1.1.1.10.2       tls 		cp = NFSMTOD(mp, caddr_t) + mbuf_len(mp);
    324  1.1.1.1.10.2       tls 		for (left = 0; left < rem; left++)
    325  1.1.1.1.10.2       tls 			*cp++ = '\0';
    326  1.1.1.1.10.2       tls 		mbuf_setlen(mp, mbuf_len(mp) + rem);
    327  1.1.1.1.10.2       tls 		nd->nd_bpos = cp;
    328  1.1.1.1.10.2       tls 	} else
    329  1.1.1.1.10.2       tls 		nd->nd_bpos = NFSMTOD(mp, caddr_t) + mbuf_len(mp);
    330  1.1.1.1.10.2       tls 	nd->nd_mb = mp;
    331  1.1.1.1.10.2       tls }
    332  1.1.1.1.10.2       tls #endif	/* !APPLE */
    333  1.1.1.1.10.2       tls 
    334  1.1.1.1.10.2       tls /*
    335  1.1.1.1.10.2       tls  * Load vnode attributes from the xdr file attributes.
    336  1.1.1.1.10.2       tls  * Returns EBADRPC if they can't be parsed, 0 otherwise.
    337  1.1.1.1.10.2       tls  */
    338  1.1.1.1.10.2       tls APPLESTATIC int
    339  1.1.1.1.10.2       tls nfsm_loadattr(struct nfsrv_descript *nd, struct nfsvattr *nap)
    340  1.1.1.1.10.2       tls {
    341  1.1.1.1.10.2       tls 	struct nfs_fattr *fp;
    342  1.1.1.1.10.2       tls 	int error = 0;
    343  1.1.1.1.10.2       tls 
    344  1.1.1.1.10.2       tls 	if (nd->nd_flag & ND_NFSV4) {
    345  1.1.1.1.10.2       tls 		error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL,
    346  1.1.1.1.10.2       tls 		    NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL);
    347  1.1.1.1.10.2       tls 	} else if (nd->nd_flag & ND_NFSV3) {
    348  1.1.1.1.10.2       tls 		NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V3FATTR);
    349  1.1.1.1.10.2       tls 		nap->na_type = nfsv34tov_type(fp->fa_type);
    350  1.1.1.1.10.2       tls 		nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode);
    351  1.1.1.1.10.2       tls 		nap->na_rdev = makedev(fxdr_unsigned(u_char, fp->fa3_rdev.specdata1),
    352  1.1.1.1.10.2       tls 			fxdr_unsigned(u_char, fp->fa3_rdev.specdata2));
    353  1.1.1.1.10.2       tls 		nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
    354  1.1.1.1.10.2       tls 		nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid);
    355  1.1.1.1.10.2       tls 		nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid);
    356  1.1.1.1.10.2       tls 		nap->na_size = fxdr_hyper(&fp->fa3_size);
    357  1.1.1.1.10.2       tls 		nap->na_blocksize = NFS_FABLKSIZE;
    358  1.1.1.1.10.2       tls 		nap->na_bytes = fxdr_hyper(&fp->fa3_used);
    359  1.1.1.1.10.2       tls 		nap->na_fileid = fxdr_hyper(&fp->fa3_fileid);
    360  1.1.1.1.10.2       tls 		fxdr_nfsv3time(&fp->fa3_atime, &nap->na_atime);
    361  1.1.1.1.10.2       tls 		fxdr_nfsv3time(&fp->fa3_ctime, &nap->na_ctime);
    362  1.1.1.1.10.2       tls 		fxdr_nfsv3time(&fp->fa3_mtime, &nap->na_mtime);
    363  1.1.1.1.10.2       tls 		nap->na_flags = 0;
    364  1.1.1.1.10.2       tls 		nap->na_filerev = 0;
    365  1.1.1.1.10.2       tls 	} else {
    366  1.1.1.1.10.2       tls 		NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V2FATTR);
    367  1.1.1.1.10.2       tls 		nap->na_type = nfsv2tov_type(fp->fa_type);
    368  1.1.1.1.10.2       tls 		nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode);
    369  1.1.1.1.10.2       tls 		if (nap->na_type == VNON || nap->na_type == VREG)
    370  1.1.1.1.10.2       tls 			nap->na_type = IFTOVT(nap->na_mode);
    371  1.1.1.1.10.2       tls 		nap->na_rdev = fxdr_unsigned(dev_t, fp->fa2_rdev);
    372  1.1.1.1.10.2       tls 
    373  1.1.1.1.10.2       tls 		/*
    374  1.1.1.1.10.2       tls 		 * Really ugly NFSv2 kludge.
    375  1.1.1.1.10.2       tls 		 */
    376  1.1.1.1.10.2       tls 		if (nap->na_type == VCHR && nap->na_rdev == ((dev_t)-1))
    377  1.1.1.1.10.2       tls 			nap->na_type = VFIFO;
    378  1.1.1.1.10.2       tls 		nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
    379  1.1.1.1.10.2       tls 		nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid);
    380  1.1.1.1.10.2       tls 		nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid);
    381  1.1.1.1.10.2       tls 		nap->na_size = fxdr_unsigned(u_int32_t, fp->fa2_size);
    382  1.1.1.1.10.2       tls 		nap->na_blocksize = fxdr_unsigned(int32_t, fp->fa2_blocksize);
    383  1.1.1.1.10.2       tls 		nap->na_bytes =
    384  1.1.1.1.10.2       tls 		    (u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks) *
    385  1.1.1.1.10.2       tls 		    NFS_FABLKSIZE;
    386  1.1.1.1.10.2       tls 		nap->na_fileid = fxdr_unsigned(uint64_t, fp->fa2_fileid);
    387  1.1.1.1.10.2       tls 		fxdr_nfsv2time(&fp->fa2_atime, &nap->na_atime);
    388  1.1.1.1.10.2       tls 		fxdr_nfsv2time(&fp->fa2_mtime, &nap->na_mtime);
    389  1.1.1.1.10.2       tls 		nap->na_flags = 0;
    390  1.1.1.1.10.2       tls 		nap->na_ctime.tv_sec = fxdr_unsigned(u_int32_t,
    391  1.1.1.1.10.2       tls 		    fp->fa2_ctime.nfsv2_sec);
    392  1.1.1.1.10.2       tls 		nap->na_ctime.tv_nsec = 0;
    393  1.1.1.1.10.2       tls 		nap->na_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec);
    394  1.1.1.1.10.2       tls 		nap->na_filerev = 0;
    395  1.1.1.1.10.2       tls 	}
    396  1.1.1.1.10.2       tls nfsmout:
    397  1.1.1.1.10.2       tls 	return (error);
    398  1.1.1.1.10.2       tls }
    399  1.1.1.1.10.2       tls 
    400  1.1.1.1.10.2       tls /*
    401  1.1.1.1.10.2       tls  * This function finds the directory cookie that corresponds to the
    402  1.1.1.1.10.2       tls  * logical byte offset given.
    403  1.1.1.1.10.2       tls  */
    404  1.1.1.1.10.2       tls APPLESTATIC nfsuint64 *
    405  1.1.1.1.10.2       tls nfscl_getcookie(struct nfsnode *np, off_t off, int add)
    406  1.1.1.1.10.2       tls {
    407  1.1.1.1.10.2       tls 	struct nfsdmap *dp, *dp2;
    408  1.1.1.1.10.2       tls 	int pos;
    409  1.1.1.1.10.2       tls 
    410  1.1.1.1.10.2       tls 	pos = off / NFS_DIRBLKSIZ;
    411  1.1.1.1.10.2       tls 	if (pos == 0) {
    412  1.1.1.1.10.2       tls 		KASSERT(!add, ("nfs getcookie add at 0"));
    413  1.1.1.1.10.2       tls 		return (&nfs_nullcookie);
    414  1.1.1.1.10.2       tls 	}
    415  1.1.1.1.10.2       tls 	pos--;
    416  1.1.1.1.10.2       tls 	dp = LIST_FIRST(&np->n_cookies);
    417  1.1.1.1.10.2       tls 	if (!dp) {
    418  1.1.1.1.10.2       tls 		if (add) {
    419  1.1.1.1.10.2       tls 			MALLOC(dp, struct nfsdmap *, sizeof (struct nfsdmap),
    420  1.1.1.1.10.2       tls 				M_NFSDIROFF, M_WAITOK);
    421  1.1.1.1.10.2       tls 			dp->ndm_eocookie = 0;
    422  1.1.1.1.10.2       tls 			LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list);
    423  1.1.1.1.10.2       tls 		} else
    424  1.1.1.1.10.2       tls 			return (NULL);
    425  1.1.1.1.10.2       tls 	}
    426  1.1.1.1.10.2       tls 	while (pos >= NFSNUMCOOKIES) {
    427  1.1.1.1.10.2       tls 		pos -= NFSNUMCOOKIES;
    428  1.1.1.1.10.2       tls 		if (LIST_NEXT(dp, ndm_list) != NULL) {
    429  1.1.1.1.10.2       tls 			if (!add && dp->ndm_eocookie < NFSNUMCOOKIES &&
    430  1.1.1.1.10.2       tls 				pos >= dp->ndm_eocookie)
    431  1.1.1.1.10.2       tls 				return (NULL);
    432  1.1.1.1.10.2       tls 			dp = LIST_NEXT(dp, ndm_list);
    433  1.1.1.1.10.2       tls 		} else if (add) {
    434  1.1.1.1.10.2       tls 			MALLOC(dp2, struct nfsdmap *, sizeof (struct nfsdmap),
    435  1.1.1.1.10.2       tls 				M_NFSDIROFF, M_WAITOK);
    436  1.1.1.1.10.2       tls 			dp2->ndm_eocookie = 0;
    437  1.1.1.1.10.2       tls 			LIST_INSERT_AFTER(dp, dp2, ndm_list);
    438  1.1.1.1.10.2       tls 			dp = dp2;
    439  1.1.1.1.10.2       tls 		} else
    440  1.1.1.1.10.2       tls 			return (NULL);
    441  1.1.1.1.10.2       tls 	}
    442  1.1.1.1.10.2       tls 	if (pos >= dp->ndm_eocookie) {
    443  1.1.1.1.10.2       tls 		if (add)
    444  1.1.1.1.10.2       tls 			dp->ndm_eocookie = pos + 1;
    445  1.1.1.1.10.2       tls 		else
    446  1.1.1.1.10.2       tls 			return (NULL);
    447  1.1.1.1.10.2       tls 	}
    448  1.1.1.1.10.2       tls 	return (&dp->ndm_cookies[pos]);
    449  1.1.1.1.10.2       tls }
    450  1.1.1.1.10.2       tls 
    451  1.1.1.1.10.2       tls /*
    452  1.1.1.1.10.2       tls  * Gets a file handle out of an nfs reply sent to the client and returns
    453  1.1.1.1.10.2       tls  * the file handle and the file's attributes.
    454  1.1.1.1.10.2       tls  * For V4, it assumes that Getfh and Getattr Op's results are here.
    455  1.1.1.1.10.2       tls  */
    456  1.1.1.1.10.2       tls APPLESTATIC int
    457  1.1.1.1.10.2       tls nfscl_mtofh(struct nfsrv_descript *nd, struct nfsfh **nfhpp,
    458  1.1.1.1.10.2       tls     struct nfsvattr *nap, int *attrflagp)
    459  1.1.1.1.10.2       tls {
    460  1.1.1.1.10.2       tls 	u_int32_t *tl;
    461  1.1.1.1.10.2       tls 	int error = 0, flag = 1;
    462  1.1.1.1.10.2       tls 
    463  1.1.1.1.10.2       tls 	*nfhpp = NULL;
    464  1.1.1.1.10.2       tls 	*attrflagp = 0;
    465  1.1.1.1.10.2       tls 	/*
    466  1.1.1.1.10.2       tls 	 * First get the file handle and vnode.
    467  1.1.1.1.10.2       tls 	 */
    468  1.1.1.1.10.2       tls 	if (nd->nd_flag & ND_NFSV3) {
    469  1.1.1.1.10.2       tls 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
    470  1.1.1.1.10.2       tls 		flag = fxdr_unsigned(int, *tl);
    471  1.1.1.1.10.2       tls 	} else if (nd->nd_flag & ND_NFSV4) {
    472  1.1.1.1.10.2       tls 		NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
    473  1.1.1.1.10.2       tls 	}
    474  1.1.1.1.10.2       tls 	if (flag) {
    475  1.1.1.1.10.2       tls 		error = nfsm_getfh(nd, nfhpp);
    476  1.1.1.1.10.2       tls 		if (error)
    477  1.1.1.1.10.2       tls 			return (error);
    478  1.1.1.1.10.2       tls 	}
    479  1.1.1.1.10.2       tls 
    480  1.1.1.1.10.2       tls 	/*
    481  1.1.1.1.10.2       tls 	 * Now, get the attributes.
    482  1.1.1.1.10.2       tls 	 */
    483  1.1.1.1.10.2       tls 	if (nd->nd_flag & ND_NFSV4) {
    484  1.1.1.1.10.2       tls 		NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
    485  1.1.1.1.10.2       tls 	} else if (nd->nd_flag & ND_NFSV3) {
    486  1.1.1.1.10.2       tls 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
    487  1.1.1.1.10.2       tls 		if (flag) {
    488  1.1.1.1.10.2       tls 			flag = fxdr_unsigned(int, *tl);
    489  1.1.1.1.10.2       tls 		} else if (fxdr_unsigned(int, *tl)) {
    490  1.1.1.1.10.2       tls 			error = nfsm_advance(nd, NFSX_V3FATTR, -1);
    491  1.1.1.1.10.2       tls 			if (error)
    492  1.1.1.1.10.2       tls 				return (error);
    493  1.1.1.1.10.2       tls 		}
    494  1.1.1.1.10.2       tls 	}
    495  1.1.1.1.10.2       tls 	if (flag) {
    496  1.1.1.1.10.2       tls 		error = nfsm_loadattr(nd, nap);
    497  1.1.1.1.10.2       tls 		if (!error)
    498  1.1.1.1.10.2       tls 			*attrflagp = 1;
    499  1.1.1.1.10.2       tls 	}
    500  1.1.1.1.10.2       tls nfsmout:
    501  1.1.1.1.10.2       tls 	return (error);
    502  1.1.1.1.10.2       tls }
    503  1.1.1.1.10.2       tls 
    504  1.1.1.1.10.2       tls /*
    505  1.1.1.1.10.2       tls  * Put a state Id in the mbuf list.
    506  1.1.1.1.10.2       tls  */
    507  1.1.1.1.10.2       tls APPLESTATIC void
    508  1.1.1.1.10.2       tls nfsm_stateidtom(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp, int flag)
    509  1.1.1.1.10.2       tls {
    510  1.1.1.1.10.2       tls 	nfsv4stateid_t *st;
    511  1.1.1.1.10.2       tls 
    512  1.1.1.1.10.2       tls 	NFSM_BUILD(st, nfsv4stateid_t *, NFSX_STATEID);
    513  1.1.1.1.10.2       tls 	if (flag == NFSSTATEID_PUTALLZERO) {
    514  1.1.1.1.10.2       tls 		st->seqid = 0;
    515  1.1.1.1.10.2       tls 		st->other[0] = 0;
    516  1.1.1.1.10.2       tls 		st->other[1] = 0;
    517  1.1.1.1.10.2       tls 		st->other[2] = 0;
    518  1.1.1.1.10.2       tls 	} else if (flag == NFSSTATEID_PUTALLONE) {
    519  1.1.1.1.10.2       tls 		st->seqid = 0xffffffff;
    520  1.1.1.1.10.2       tls 		st->other[0] = 0xffffffff;
    521  1.1.1.1.10.2       tls 		st->other[1] = 0xffffffff;
    522  1.1.1.1.10.2       tls 		st->other[2] = 0xffffffff;
    523  1.1.1.1.10.2       tls 	} else if (flag == NFSSTATEID_PUTSEQIDZERO) {
    524  1.1.1.1.10.2       tls 		st->seqid = 0;
    525  1.1.1.1.10.2       tls 		st->other[0] = stateidp->other[0];
    526  1.1.1.1.10.2       tls 		st->other[1] = stateidp->other[1];
    527  1.1.1.1.10.2       tls 		st->other[2] = stateidp->other[2];
    528  1.1.1.1.10.2       tls 	} else {
    529  1.1.1.1.10.2       tls 		st->seqid = stateidp->seqid;
    530  1.1.1.1.10.2       tls 		st->other[0] = stateidp->other[0];
    531  1.1.1.1.10.2       tls 		st->other[1] = stateidp->other[1];
    532  1.1.1.1.10.2       tls 		st->other[2] = stateidp->other[2];
    533  1.1.1.1.10.2       tls 	}
    534  1.1.1.1.10.2       tls }
    535  1.1.1.1.10.2       tls 
    536  1.1.1.1.10.2       tls /*
    537  1.1.1.1.10.2       tls  * Initialize the owner/delegation sleep lock.
    538  1.1.1.1.10.2       tls  */
    539  1.1.1.1.10.2       tls APPLESTATIC void
    540  1.1.1.1.10.2       tls nfscl_lockinit(struct nfsv4lock *lckp)
    541  1.1.1.1.10.2       tls {
    542  1.1.1.1.10.2       tls 
    543  1.1.1.1.10.2       tls 	lckp->nfslock_usecnt = 0;
    544  1.1.1.1.10.2       tls 	lckp->nfslock_lock = 0;
    545  1.1.1.1.10.2       tls }
    546  1.1.1.1.10.2       tls 
    547  1.1.1.1.10.2       tls /*
    548  1.1.1.1.10.2       tls  * Get an exclusive lock. (Not needed for OpenBSD4, since there is only one
    549  1.1.1.1.10.2       tls  * thread for each posix process in the kernel.)
    550  1.1.1.1.10.2       tls  */
    551  1.1.1.1.10.2       tls APPLESTATIC void
    552  1.1.1.1.10.2       tls nfscl_lockexcl(struct nfsv4lock *lckp, void *mutex)
    553  1.1.1.1.10.2       tls {
    554  1.1.1.1.10.2       tls 	int igotlock;
    555  1.1.1.1.10.2       tls 
    556  1.1.1.1.10.2       tls 	do {
    557  1.1.1.1.10.2       tls 		igotlock = nfsv4_lock(lckp, 1, NULL, mutex, NULL);
    558  1.1.1.1.10.2       tls 	} while (!igotlock);
    559  1.1.1.1.10.2       tls }
    560  1.1.1.1.10.2       tls 
    561  1.1.1.1.10.2       tls /*
    562  1.1.1.1.10.2       tls  * Release an exclusive lock.
    563  1.1.1.1.10.2       tls  */
    564  1.1.1.1.10.2       tls APPLESTATIC void
    565  1.1.1.1.10.2       tls nfscl_lockunlock(struct nfsv4lock *lckp)
    566  1.1.1.1.10.2       tls {
    567  1.1.1.1.10.2       tls 
    568  1.1.1.1.10.2       tls 	nfsv4_unlock(lckp, 0);
    569  1.1.1.1.10.2       tls }
    570  1.1.1.1.10.2       tls 
    571  1.1.1.1.10.2       tls /*
    572  1.1.1.1.10.2       tls  * Called to derefernce a lock on a stateid (delegation or open owner).
    573  1.1.1.1.10.2       tls  */
    574  1.1.1.1.10.2       tls APPLESTATIC void
    575  1.1.1.1.10.2       tls nfscl_lockderef(struct nfsv4lock *lckp)
    576  1.1.1.1.10.2       tls {
    577  1.1.1.1.10.2       tls 
    578  1.1.1.1.10.2       tls 	NFSLOCKCLSTATE();
    579  1.1.1.1.10.2       tls 	lckp->nfslock_usecnt--;
    580  1.1.1.1.10.2       tls 	if (lckp->nfslock_usecnt == 0 && (lckp->nfslock_lock & NFSV4LOCK_WANTED)) {
    581  1.1.1.1.10.2       tls 		lckp->nfslock_lock &= ~NFSV4LOCK_WANTED;
    582  1.1.1.1.10.2       tls 		wakeup((caddr_t)lckp);
    583  1.1.1.1.10.2       tls 	}
    584  1.1.1.1.10.2       tls 	NFSUNLOCKCLSTATE();
    585  1.1.1.1.10.2       tls }
    586  1.1.1.1.10.2       tls 
    587