2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
38 * These functions support the macros and help fiddle mbuf chains for
39 * the nfs op functions. They do things like create the rpc header and
40 * copy data between mbuf chains and uio lists.
43 #include <fs/nfs/nfsport.h>
45 extern struct nfsstatsv1 nfsstatsv1;
46 extern struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS];
47 extern int ncl_mbuf_mlen;
48 extern enum vtype newnv2tov_type[8];
49 extern enum vtype nv34tov_type[8];
50 extern int nfs_bigreply[NFSV41_NPROCS];
52 #endif /* !APPLEKEXT */
54 static nfsuint64 nfs_nullcookie = {{ 0, 0 }};
60 } nfsv4_opmap[NFSV41_NPROCS] = {
62 { NFSV4OP_GETATTR, 1, "Getattr", 7, },
63 { NFSV4OP_SETATTR, 2, "Setattr", 7, },
64 { NFSV4OP_LOOKUP, 3, "Lookup", 6, },
65 { NFSV4OP_ACCESS, 2, "Access", 6, },
66 { NFSV4OP_READLINK, 2, "Readlink", 8, },
67 { NFSV4OP_READ, 1, "Read", 4, },
68 { NFSV4OP_WRITE, 2, "Write", 5, },
69 { NFSV4OP_OPEN, 5, "Open", 4, },
70 { NFSV4OP_CREATE, 5, "Create", 6, },
71 { NFSV4OP_CREATE, 1, "Create", 6, },
72 { NFSV4OP_CREATE, 3, "Create", 6, },
73 { NFSV4OP_REMOVE, 1, "Remove", 6, },
74 { NFSV4OP_REMOVE, 1, "Remove", 6, },
75 { NFSV4OP_SAVEFH, 5, "Rename", 6, },
76 { NFSV4OP_SAVEFH, 4, "Link", 4, },
77 { NFSV4OP_READDIR, 2, "Readdir", 7, },
78 { NFSV4OP_READDIR, 2, "Readdir", 7, },
79 { NFSV4OP_GETATTR, 1, "Getattr", 7, },
80 { NFSV4OP_GETATTR, 1, "Getattr", 7, },
81 { NFSV4OP_GETATTR, 1, "Getattr", 7, },
82 { NFSV4OP_COMMIT, 2, "Commit", 6, },
83 { NFSV4OP_LOOKUPP, 3, "Lookupp", 7, },
84 { NFSV4OP_SETCLIENTID, 1, "SetClientID", 11, },
85 { NFSV4OP_SETCLIENTIDCFRM, 1, "SetClientIDConfirm", 18, },
86 { NFSV4OP_LOCK, 1, "Lock", 4, },
87 { NFSV4OP_LOCKU, 1, "LockU", 5, },
88 { NFSV4OP_OPEN, 2, "Open", 4, },
89 { NFSV4OP_CLOSE, 1, "Close", 5, },
90 { NFSV4OP_OPENCONFIRM, 1, "Openconfirm", 11, },
91 { NFSV4OP_LOCKT, 1, "LockT", 5, },
92 { NFSV4OP_OPENDOWNGRADE, 1, "Opendowngrade", 13, },
93 { NFSV4OP_RENEW, 1, "Renew", 5, },
94 { NFSV4OP_PUTROOTFH, 1, "Dirpath", 7, },
95 { NFSV4OP_RELEASELCKOWN, 1, "Rellckown", 9, },
96 { NFSV4OP_DELEGRETURN, 1, "Delegret", 8, },
97 { NFSV4OP_DELEGRETURN, 3, "DelegRemove", 11, },
98 { NFSV4OP_DELEGRETURN, 7, "DelegRename1", 12, },
99 { NFSV4OP_DELEGRETURN, 9, "DelegRename2", 12, },
100 { NFSV4OP_GETATTR, 1, "Getacl", 6, },
101 { NFSV4OP_SETATTR, 1, "Setacl", 6, },
102 { NFSV4OP_EXCHANGEID, 1, "ExchangeID", 10, },
103 { NFSV4OP_CREATESESSION, 1, "CreateSession", 13, },
104 { NFSV4OP_DESTROYSESSION, 1, "DestroySession", 14, },
105 { NFSV4OP_DESTROYCLIENTID, 1, "DestroyClient", 13, },
106 { NFSV4OP_FREESTATEID, 1, "FreeStateID", 11, },
107 { NFSV4OP_LAYOUTGET, 1, "LayoutGet", 9, },
108 { NFSV4OP_GETDEVINFO, 1, "GetDeviceInfo", 13, },
109 { NFSV4OP_LAYOUTCOMMIT, 1, "LayoutCommit", 12, },
110 { NFSV4OP_LAYOUTRETURN, 1, "LayoutReturn", 12, },
111 { NFSV4OP_RECLAIMCOMPL, 1, "ReclaimComplete", 15, },
112 { NFSV4OP_WRITE, 1, "WriteDS", 7, },
113 { NFSV4OP_READ, 1, "ReadDS", 6, },
114 { NFSV4OP_COMMIT, 1, "CommitDS", 8, },
115 { NFSV4OP_OPEN, 3, "OpenLayoutGet", 13, },
116 { NFSV4OP_OPEN, 8, "CreateLayGet", 12, },
120 * NFS RPCS that have large request message size.
122 static int nfs_bigrequest[NFSV41_NPROCS] = {
123 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
124 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
125 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0
129 * Start building a request. Mostly just put the first file handle in
133 nfscl_reqstart(struct nfsrv_descript *nd, int procnum, struct nfsmount *nmp,
134 u_int8_t *nfhp, int fhlen, u_int32_t **opcntpp, struct nfsclsession *sep,
135 int vers, int minorvers)
140 nfsattrbit_t attrbits;
143 * First, fill in some of the fields of nd.
145 nd->nd_slotseq = NULL;
146 if (vers == NFS_VER4) {
147 nd->nd_flag = ND_NFSV4 | ND_NFSCL;
148 if (minorvers == NFSV41_MINORVERSION)
149 nd->nd_flag |= ND_NFSV41;
150 } else if (vers == NFS_VER3)
151 nd->nd_flag = ND_NFSV3 | ND_NFSCL;
153 if (NFSHASNFSV4(nmp)) {
154 nd->nd_flag = ND_NFSV4 | ND_NFSCL;
155 if (NFSHASNFSV4N(nmp))
156 nd->nd_flag |= ND_NFSV41;
157 } else if (NFSHASNFSV3(nmp))
158 nd->nd_flag = ND_NFSV3 | ND_NFSCL;
160 nd->nd_flag = ND_NFSV2 | ND_NFSCL;
162 nd->nd_procnum = procnum;
166 * Get the first mbuf for the request.
168 if (nfs_bigrequest[procnum])
169 NFSMCLGET(mb, M_WAITOK);
173 nd->nd_mreq = nd->nd_mb = mb;
174 nd->nd_bpos = NFSMTOD(mb, caddr_t);
177 * And fill the first file handle into the request.
179 if (nd->nd_flag & ND_NFSV4) {
180 opcnt = nfsv4_opmap[procnum].opcnt +
181 nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh;
182 if ((nd->nd_flag & ND_NFSV41) != 0) {
183 opcnt += nfsv4_opflag[nfsv4_opmap[procnum].op].needsseq;
184 if (procnum == NFSPROC_RENEW)
186 * For the special case of Renew, just do a
190 else if (procnum == NFSPROC_WRITEDS ||
191 procnum == NFSPROC_COMMITDS)
193 * For the special case of a Writeor Commit to
194 * a DS, the opcnt == 3, for Sequence, PutFH,
200 * What should the tag really be?
202 (void) nfsm_strtom(nd, nfsv4_opmap[procnum].tag,
203 nfsv4_opmap[procnum].taglen);
204 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
205 if ((nd->nd_flag & ND_NFSV41) != 0)
206 *tl++ = txdr_unsigned(NFSV41_MINORVERSION);
208 *tl++ = txdr_unsigned(NFSV4_MINORVERSION);
211 *tl = txdr_unsigned(opcnt);
212 if ((nd->nd_flag & ND_NFSV41) != 0 &&
213 nfsv4_opflag[nfsv4_opmap[procnum].op].needsseq > 0) {
214 if (nfsv4_opflag[nfsv4_opmap[procnum].op].loopbadsess >
216 nd->nd_flag |= ND_LOOPBADSESS;
217 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
218 *tl = txdr_unsigned(NFSV4OP_SEQUENCE);
220 sep = nfsmnt_mdssession(nmp);
221 nfsv4_setsequence(nmp, nd, sep,
222 nfs_bigreply[procnum]);
224 nfsv4_setsequence(nmp, nd, sep,
225 nfs_bigreply[procnum]);
227 if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh > 0) {
228 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
229 *tl = txdr_unsigned(NFSV4OP_PUTFH);
230 (void) nfsm_fhtom(nd, nfhp, fhlen, 0);
231 if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh
232 == 2 && procnum != NFSPROC_WRITEDS &&
233 procnum != NFSPROC_COMMITDS) {
234 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
235 *tl = txdr_unsigned(NFSV4OP_GETATTR);
237 * For Lookup Ops, we want all the directory
238 * attributes, so we can load the name cache.
240 if (procnum == NFSPROC_LOOKUP ||
241 procnum == NFSPROC_LOOKUPP)
242 NFSGETATTR_ATTRBIT(&attrbits);
244 NFSWCCATTR_ATTRBIT(&attrbits);
245 nd->nd_flag |= ND_V4WCCATTR;
247 (void) nfsrv_putattrbit(nd, &attrbits);
250 if (procnum != NFSPROC_RENEW ||
251 (nd->nd_flag & ND_NFSV41) == 0) {
252 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
253 *tl = txdr_unsigned(nfsv4_opmap[procnum].op);
256 (void) nfsm_fhtom(nd, nfhp, fhlen, 0);
258 if (procnum < NFSV41_NPROCS)
259 NFSINCRGLOBAL(nfsstatsv1.rpccnt[procnum]);
263 * copies a uio scatter/gather list to an mbuf chain.
264 * NOTE: can ony handle iovcnt == 1
267 nfsm_uiombuf(struct nfsrv_descript *nd, struct uio *uiop, int siz)
270 struct mbuf *mp, *mp2;
271 int xfer, left, mlen;
272 int uiosiz, clflg, rem;
275 KASSERT(uiop->uio_iovcnt == 1, ("nfsm_uiotombuf: iovcnt != 1"));
277 if (siz > ncl_mbuf_mlen) /* or should it >= MCLBYTES ?? */
281 rem = NFSM_RNDUP(siz) - siz;
282 mp = mp2 = nd->nd_mb;
284 left = uiop->uio_iov->iov_len;
285 uiocp = uiop->uio_iov->iov_base;
290 mlen = M_TRAILINGSPACE(mp);
293 NFSMCLGET(mp, M_WAITOK);
297 mbuf_setnext(mp2, mp);
299 mlen = M_TRAILINGSPACE(mp);
301 xfer = (left > mlen) ? mlen : left;
304 if (uiop->uio_iov->iov_op != NULL)
305 (*(uiop->uio_iov->iov_op))
306 (uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp),
310 if (uiop->uio_segflg == UIO_SYSSPACE)
311 NFSBCOPY(uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp),
314 copyin(CAST_USER_ADDR_T(uiocp), NFSMTOD(mp, caddr_t)
315 + mbuf_len(mp), xfer);
316 mbuf_setlen(mp, mbuf_len(mp) + xfer);
319 uiop->uio_offset += xfer;
320 uiop->uio_resid -= xfer;
322 tcp = (char *)uiop->uio_iov->iov_base;
324 uiop->uio_iov->iov_base = (void *)tcp;
325 uiop->uio_iov->iov_len -= uiosiz;
329 if (rem > M_TRAILINGSPACE(mp)) {
332 mbuf_setnext(mp2, mp);
334 cp = NFSMTOD(mp, caddr_t) + mbuf_len(mp);
335 for (left = 0; left < rem; left++)
337 mbuf_setlen(mp, mbuf_len(mp) + rem);
340 nd->nd_bpos = NFSMTOD(mp, caddr_t) + mbuf_len(mp);
345 * copies a uio scatter/gather list to an mbuf chain.
346 * This version returns the mbuf list and does not use "nd".
347 * NOTE: can ony handle iovcnt == 1
350 nfsm_uiombuflist(struct uio *uiop, int siz, struct mbuf **mbp, char **cpp)
353 struct mbuf *mp, *mp2, *firstmp;
354 int xfer, left, mlen;
355 int uiosiz, clflg, rem;
358 KASSERT(uiop->uio_iovcnt == 1, ("nfsm_uiotombuf: iovcnt != 1"));
360 if (siz > ncl_mbuf_mlen) /* or should it >= MCLBYTES ?? */
364 rem = NFSM_RNDUP(siz) - siz;
366 NFSMCLGET(mp, M_WAITOK);
372 left = uiop->uio_iov->iov_len;
373 uiocp = uiop->uio_iov->iov_base;
378 mlen = M_TRAILINGSPACE(mp);
381 NFSMCLGET(mp, M_WAITOK);
385 mbuf_setnext(mp2, mp);
387 mlen = M_TRAILINGSPACE(mp);
389 xfer = (left > mlen) ? mlen : left;
390 if (uiop->uio_segflg == UIO_SYSSPACE)
391 NFSBCOPY(uiocp, NFSMTOD(mp, caddr_t) +
394 copyin(uiocp, NFSMTOD(mp, caddr_t) +
396 mbuf_setlen(mp, mbuf_len(mp) + xfer);
399 uiop->uio_offset += xfer;
400 uiop->uio_resid -= xfer;
402 tcp = (char *)uiop->uio_iov->iov_base;
404 uiop->uio_iov->iov_base = (void *)tcp;
405 uiop->uio_iov->iov_len -= uiosiz;
409 *cpp = NFSMTOD(mp, caddr_t) + mbuf_len(mp);
416 * Load vnode attributes from the xdr file attributes.
417 * Returns EBADRPC if they can't be parsed, 0 otherwise.
420 nfsm_loadattr(struct nfsrv_descript *nd, struct nfsvattr *nap)
422 struct nfs_fattr *fp;
425 if (nd->nd_flag & ND_NFSV4) {
426 error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL,
427 NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL);
428 } else if (nd->nd_flag & ND_NFSV3) {
429 NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V3FATTR);
430 nap->na_type = nfsv34tov_type(fp->fa_type);
431 nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode);
432 nap->na_rdev = makedev(fxdr_unsigned(u_char, fp->fa3_rdev.specdata1),
433 fxdr_unsigned(u_char, fp->fa3_rdev.specdata2));
434 nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
435 nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid);
436 nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid);
437 nap->na_size = fxdr_hyper(&fp->fa3_size);
438 nap->na_blocksize = NFS_FABLKSIZE;
439 nap->na_bytes = fxdr_hyper(&fp->fa3_used);
440 nap->na_fileid = fxdr_hyper(&fp->fa3_fileid);
441 fxdr_nfsv3time(&fp->fa3_atime, &nap->na_atime);
442 fxdr_nfsv3time(&fp->fa3_ctime, &nap->na_ctime);
443 fxdr_nfsv3time(&fp->fa3_mtime, &nap->na_mtime);
447 NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V2FATTR);
448 nap->na_type = nfsv2tov_type(fp->fa_type);
449 nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode);
450 if (nap->na_type == VNON || nap->na_type == VREG)
451 nap->na_type = IFTOVT(nap->na_mode);
452 nap->na_rdev = fxdr_unsigned(dev_t, fp->fa2_rdev);
455 * Really ugly NFSv2 kludge.
457 if (nap->na_type == VCHR && nap->na_rdev == ((dev_t)-1))
458 nap->na_type = VFIFO;
459 nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
460 nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid);
461 nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid);
462 nap->na_size = fxdr_unsigned(u_int32_t, fp->fa2_size);
463 nap->na_blocksize = fxdr_unsigned(int32_t, fp->fa2_blocksize);
465 (u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks) *
467 nap->na_fileid = fxdr_unsigned(uint64_t, fp->fa2_fileid);
468 fxdr_nfsv2time(&fp->fa2_atime, &nap->na_atime);
469 fxdr_nfsv2time(&fp->fa2_mtime, &nap->na_mtime);
471 nap->na_ctime.tv_sec = fxdr_unsigned(u_int32_t,
472 fp->fa2_ctime.nfsv2_sec);
473 nap->na_ctime.tv_nsec = 0;
474 nap->na_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec);
482 * This function finds the directory cookie that corresponds to the
483 * logical byte offset given.
485 APPLESTATIC nfsuint64 *
486 nfscl_getcookie(struct nfsnode *np, off_t off, int add)
488 struct nfsdmap *dp, *dp2;
491 pos = off / NFS_DIRBLKSIZ;
493 KASSERT(!add, ("nfs getcookie add at 0"));
494 return (&nfs_nullcookie);
497 dp = LIST_FIRST(&np->n_cookies);
500 MALLOC(dp, struct nfsdmap *, sizeof (struct nfsdmap),
501 M_NFSDIROFF, M_WAITOK);
502 dp->ndm_eocookie = 0;
503 LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list);
507 while (pos >= NFSNUMCOOKIES) {
508 pos -= NFSNUMCOOKIES;
509 if (LIST_NEXT(dp, ndm_list) != NULL) {
510 if (!add && dp->ndm_eocookie < NFSNUMCOOKIES &&
511 pos >= dp->ndm_eocookie)
513 dp = LIST_NEXT(dp, ndm_list);
515 MALLOC(dp2, struct nfsdmap *, sizeof (struct nfsdmap),
516 M_NFSDIROFF, M_WAITOK);
517 dp2->ndm_eocookie = 0;
518 LIST_INSERT_AFTER(dp, dp2, ndm_list);
523 if (pos >= dp->ndm_eocookie) {
525 dp->ndm_eocookie = pos + 1;
529 return (&dp->ndm_cookies[pos]);
533 * Gets a file handle out of an nfs reply sent to the client and returns
534 * the file handle and the file's attributes.
535 * For V4, it assumes that Getfh and Getattr Op's results are here.
538 nfscl_mtofh(struct nfsrv_descript *nd, struct nfsfh **nfhpp,
539 struct nfsvattr *nap, int *attrflagp)
542 int error = 0, flag = 1;
547 * First get the file handle and vnode.
549 if (nd->nd_flag & ND_NFSV3) {
550 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
551 flag = fxdr_unsigned(int, *tl);
552 } else if (nd->nd_flag & ND_NFSV4) {
553 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
554 /* If the GetFH failed, clear flag. */
556 nd->nd_flag |= ND_NOMOREDATA;
558 error = ENXIO; /* Return ENXIO so *nfhpp isn't used. */
562 error = nfsm_getfh(nd, nfhpp);
568 * Now, get the attributes.
570 if (flag != 0 && (nd->nd_flag & ND_NFSV4) != 0) {
571 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
573 nd->nd_flag |= ND_NOMOREDATA;
576 } else if (nd->nd_flag & ND_NFSV3) {
577 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
579 flag = fxdr_unsigned(int, *tl);
580 } else if (fxdr_unsigned(int, *tl)) {
581 error = nfsm_advance(nd, NFSX_V3FATTR, -1);
587 error = nfsm_loadattr(nd, nap);
596 * Put a state Id in the mbuf list.
599 nfsm_stateidtom(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp, int flag)
603 NFSM_BUILD(st, nfsv4stateid_t *, NFSX_STATEID);
604 if (flag == NFSSTATEID_PUTALLZERO) {
609 } else if (flag == NFSSTATEID_PUTALLONE) {
610 st->seqid = 0xffffffff;
611 st->other[0] = 0xffffffff;
612 st->other[1] = 0xffffffff;
613 st->other[2] = 0xffffffff;
614 } else if (flag == NFSSTATEID_PUTSEQIDZERO) {
616 st->other[0] = stateidp->other[0];
617 st->other[1] = stateidp->other[1];
618 st->other[2] = stateidp->other[2];
620 st->seqid = stateidp->seqid;
621 st->other[0] = stateidp->other[0];
622 st->other[1] = stateidp->other[1];
623 st->other[2] = stateidp->other[2];
628 * Initialize the owner/delegation sleep lock.
631 nfscl_lockinit(struct nfsv4lock *lckp)
634 lckp->nfslock_usecnt = 0;
635 lckp->nfslock_lock = 0;
639 * Get an exclusive lock. (Not needed for OpenBSD4, since there is only one
640 * thread for each posix process in the kernel.)
643 nfscl_lockexcl(struct nfsv4lock *lckp, void *mutex)
648 igotlock = nfsv4_lock(lckp, 1, NULL, mutex, NULL);
653 * Release an exclusive lock.
656 nfscl_lockunlock(struct nfsv4lock *lckp)
659 nfsv4_unlock(lckp, 0);
663 * Called to derefernce a lock on a stateid (delegation or open owner).
666 nfscl_lockderef(struct nfsv4lock *lckp)
670 lckp->nfslock_usecnt--;
671 if (lckp->nfslock_usecnt == 0 && (lckp->nfslock_lock & NFSV4LOCK_WANTED)) {
672 lckp->nfslock_lock &= ~NFSV4LOCK_WANTED;
673 wakeup((caddr_t)lckp);