2 * SPDX-License-Identifier: BSD-3-Clause
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Rick Macklem at The University of Guelph.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
40 * These functions support the macros and help fiddle mbuf chains for
41 * the nfs op functions. They do things like create the rpc header and
42 * copy data between mbuf chains and uio lists.
45 #include <fs/nfs/nfsport.h>
47 extern struct nfsstatsv1 nfsstatsv1;
48 extern struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS];
49 extern int ncl_mbuf_mlen;
50 extern enum vtype newnv2tov_type[8];
51 extern enum vtype nv34tov_type[8];
52 extern int nfs_bigreply[NFSV41_NPROCS];
54 #endif /* !APPLEKEXT */
56 static nfsuint64 nfs_nullcookie = {{ 0, 0 }};
62 } nfsv4_opmap[NFSV41_NPROCS] = {
64 { NFSV4OP_GETATTR, 1, "Getattr", 7, },
65 { NFSV4OP_SETATTR, 2, "Setattr", 7, },
66 { NFSV4OP_LOOKUP, 3, "Lookup", 6, },
67 { NFSV4OP_ACCESS, 2, "Access", 6, },
68 { NFSV4OP_READLINK, 2, "Readlink", 8, },
69 { NFSV4OP_READ, 1, "Read", 4, },
70 { NFSV4OP_WRITE, 2, "Write", 5, },
71 { NFSV4OP_OPEN, 5, "Open", 4, },
72 { NFSV4OP_CREATE, 5, "Create", 6, },
73 { NFSV4OP_CREATE, 1, "Create", 6, },
74 { NFSV4OP_CREATE, 3, "Create", 6, },
75 { NFSV4OP_REMOVE, 1, "Remove", 6, },
76 { NFSV4OP_REMOVE, 1, "Remove", 6, },
77 { NFSV4OP_SAVEFH, 5, "Rename", 6, },
78 { NFSV4OP_SAVEFH, 4, "Link", 4, },
79 { NFSV4OP_READDIR, 2, "Readdir", 7, },
80 { NFSV4OP_READDIR, 2, "Readdir", 7, },
81 { NFSV4OP_GETATTR, 1, "Getattr", 7, },
82 { NFSV4OP_GETATTR, 1, "Getattr", 7, },
83 { NFSV4OP_GETATTR, 1, "Getattr", 7, },
84 { NFSV4OP_COMMIT, 2, "Commit", 6, },
85 { NFSV4OP_LOOKUPP, 3, "Lookupp", 7, },
86 { NFSV4OP_SETCLIENTID, 1, "SetClientID", 11, },
87 { NFSV4OP_SETCLIENTIDCFRM, 1, "SetClientIDConfirm", 18, },
88 { NFSV4OP_LOCK, 1, "Lock", 4, },
89 { NFSV4OP_LOCKU, 1, "LockU", 5, },
90 { NFSV4OP_OPEN, 2, "Open", 4, },
91 { NFSV4OP_CLOSE, 1, "Close", 5, },
92 { NFSV4OP_OPENCONFIRM, 1, "Openconfirm", 11, },
93 { NFSV4OP_LOCKT, 1, "LockT", 5, },
94 { NFSV4OP_OPENDOWNGRADE, 1, "Opendowngrade", 13, },
95 { NFSV4OP_RENEW, 1, "Renew", 5, },
96 { NFSV4OP_PUTROOTFH, 1, "Dirpath", 7, },
97 { NFSV4OP_RELEASELCKOWN, 1, "Rellckown", 9, },
98 { NFSV4OP_DELEGRETURN, 1, "Delegret", 8, },
99 { NFSV4OP_DELEGRETURN, 3, "DelegRemove", 11, },
100 { NFSV4OP_DELEGRETURN, 7, "DelegRename1", 12, },
101 { NFSV4OP_DELEGRETURN, 9, "DelegRename2", 12, },
102 { NFSV4OP_GETATTR, 1, "Getacl", 6, },
103 { NFSV4OP_SETATTR, 1, "Setacl", 6, },
104 { NFSV4OP_EXCHANGEID, 1, "ExchangeID", 10, },
105 { NFSV4OP_CREATESESSION, 1, "CreateSession", 13, },
106 { NFSV4OP_DESTROYSESSION, 1, "DestroySession", 14, },
107 { NFSV4OP_DESTROYCLIENTID, 1, "DestroyClient", 13, },
108 { NFSV4OP_FREESTATEID, 1, "FreeStateID", 11, },
109 { NFSV4OP_LAYOUTGET, 1, "LayoutGet", 9, },
110 { NFSV4OP_GETDEVINFO, 1, "GetDeviceInfo", 13, },
111 { NFSV4OP_LAYOUTCOMMIT, 1, "LayoutCommit", 12, },
112 { NFSV4OP_LAYOUTRETURN, 1, "LayoutReturn", 12, },
113 { NFSV4OP_RECLAIMCOMPL, 1, "ReclaimComplete", 15, },
114 { NFSV4OP_WRITE, 1, "WriteDS", 7, },
115 { NFSV4OP_READ, 1, "ReadDS", 6, },
116 { NFSV4OP_COMMIT, 1, "CommitDS", 8, },
117 { NFSV4OP_OPEN, 3, "OpenLayoutGet", 13, },
118 { NFSV4OP_OPEN, 8, "CreateLayGet", 12, },
122 * NFS RPCS that have large request message size.
124 static int nfs_bigrequest[NFSV41_NPROCS] = {
125 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
126 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
127 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0
131 * Start building a request. Mostly just put the first file handle in
135 nfscl_reqstart(struct nfsrv_descript *nd, int procnum, struct nfsmount *nmp,
136 u_int8_t *nfhp, int fhlen, u_int32_t **opcntpp, struct nfsclsession *sep,
137 int vers, int minorvers)
142 nfsattrbit_t attrbits;
145 * First, fill in some of the fields of nd.
147 nd->nd_slotseq = NULL;
148 if (vers == NFS_VER4) {
149 nd->nd_flag = ND_NFSV4 | ND_NFSCL;
150 if (minorvers == NFSV41_MINORVERSION)
151 nd->nd_flag |= ND_NFSV41;
152 } else if (vers == NFS_VER3)
153 nd->nd_flag = ND_NFSV3 | ND_NFSCL;
155 if (NFSHASNFSV4(nmp)) {
156 nd->nd_flag = ND_NFSV4 | ND_NFSCL;
157 if (NFSHASNFSV4N(nmp))
158 nd->nd_flag |= ND_NFSV41;
159 } else if (NFSHASNFSV3(nmp))
160 nd->nd_flag = ND_NFSV3 | ND_NFSCL;
162 nd->nd_flag = ND_NFSV2 | ND_NFSCL;
164 nd->nd_procnum = procnum;
168 * Get the first mbuf for the request.
170 if (nfs_bigrequest[procnum])
171 NFSMCLGET(mb, M_WAITOK);
175 nd->nd_mreq = nd->nd_mb = mb;
176 nd->nd_bpos = NFSMTOD(mb, caddr_t);
179 * And fill the first file handle into the request.
181 if (nd->nd_flag & ND_NFSV4) {
182 opcnt = nfsv4_opmap[procnum].opcnt +
183 nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh;
184 if ((nd->nd_flag & ND_NFSV41) != 0) {
185 opcnt += nfsv4_opflag[nfsv4_opmap[procnum].op].needsseq;
186 if (procnum == NFSPROC_RENEW)
188 * For the special case of Renew, just do a
192 else if (procnum == NFSPROC_WRITEDS ||
193 procnum == NFSPROC_COMMITDS)
195 * For the special case of a Writeor Commit to
196 * a DS, the opcnt == 3, for Sequence, PutFH,
202 * What should the tag really be?
204 (void) nfsm_strtom(nd, nfsv4_opmap[procnum].tag,
205 nfsv4_opmap[procnum].taglen);
206 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
207 if ((nd->nd_flag & ND_NFSV41) != 0)
208 *tl++ = txdr_unsigned(NFSV41_MINORVERSION);
210 *tl++ = txdr_unsigned(NFSV4_MINORVERSION);
213 *tl = txdr_unsigned(opcnt);
214 if ((nd->nd_flag & ND_NFSV41) != 0 &&
215 nfsv4_opflag[nfsv4_opmap[procnum].op].needsseq > 0) {
216 if (nfsv4_opflag[nfsv4_opmap[procnum].op].loopbadsess >
218 nd->nd_flag |= ND_LOOPBADSESS;
219 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
220 *tl = txdr_unsigned(NFSV4OP_SEQUENCE);
222 sep = nfsmnt_mdssession(nmp);
223 nfsv4_setsequence(nmp, nd, sep,
224 nfs_bigreply[procnum]);
226 nfsv4_setsequence(nmp, nd, sep,
227 nfs_bigreply[procnum]);
229 if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh > 0) {
230 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
231 *tl = txdr_unsigned(NFSV4OP_PUTFH);
232 (void) nfsm_fhtom(nd, nfhp, fhlen, 0);
233 if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh
234 == 2 && procnum != NFSPROC_WRITEDS &&
235 procnum != NFSPROC_COMMITDS) {
236 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
237 *tl = txdr_unsigned(NFSV4OP_GETATTR);
239 * For Lookup Ops, we want all the directory
240 * attributes, so we can load the name cache.
242 if (procnum == NFSPROC_LOOKUP ||
243 procnum == NFSPROC_LOOKUPP)
244 NFSGETATTR_ATTRBIT(&attrbits);
246 NFSWCCATTR_ATTRBIT(&attrbits);
247 nd->nd_flag |= ND_V4WCCATTR;
249 (void) nfsrv_putattrbit(nd, &attrbits);
252 if (procnum != NFSPROC_RENEW ||
253 (nd->nd_flag & ND_NFSV41) == 0) {
254 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
255 *tl = txdr_unsigned(nfsv4_opmap[procnum].op);
258 (void) nfsm_fhtom(nd, nfhp, fhlen, 0);
260 if (procnum < NFSV41_NPROCS)
261 NFSINCRGLOBAL(nfsstatsv1.rpccnt[procnum]);
265 * copies a uio scatter/gather list to an mbuf chain.
266 * NOTE: can ony handle iovcnt == 1
269 nfsm_uiombuf(struct nfsrv_descript *nd, struct uio *uiop, int siz)
272 struct mbuf *mp, *mp2;
273 int xfer, left, mlen;
274 int uiosiz, clflg, rem;
277 KASSERT(uiop->uio_iovcnt == 1, ("nfsm_uiotombuf: iovcnt != 1"));
279 if (siz > ncl_mbuf_mlen) /* or should it >= MCLBYTES ?? */
283 rem = NFSM_RNDUP(siz) - siz;
284 mp = mp2 = nd->nd_mb;
286 left = uiop->uio_iov->iov_len;
287 uiocp = uiop->uio_iov->iov_base;
292 mlen = M_TRAILINGSPACE(mp);
295 NFSMCLGET(mp, M_WAITOK);
299 mbuf_setnext(mp2, mp);
301 mlen = M_TRAILINGSPACE(mp);
303 xfer = (left > mlen) ? mlen : left;
306 if (uiop->uio_iov->iov_op != NULL)
307 (*(uiop->uio_iov->iov_op))
308 (uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp),
312 if (uiop->uio_segflg == UIO_SYSSPACE)
313 NFSBCOPY(uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp),
316 copyin(CAST_USER_ADDR_T(uiocp), NFSMTOD(mp, caddr_t)
317 + mbuf_len(mp), xfer);
318 mbuf_setlen(mp, mbuf_len(mp) + xfer);
321 uiop->uio_offset += xfer;
322 uiop->uio_resid -= xfer;
324 tcp = (char *)uiop->uio_iov->iov_base;
326 uiop->uio_iov->iov_base = (void *)tcp;
327 uiop->uio_iov->iov_len -= uiosiz;
331 if (rem > M_TRAILINGSPACE(mp)) {
334 mbuf_setnext(mp2, mp);
336 cp = NFSMTOD(mp, caddr_t) + mbuf_len(mp);
337 for (left = 0; left < rem; left++)
339 mbuf_setlen(mp, mbuf_len(mp) + rem);
342 nd->nd_bpos = NFSMTOD(mp, caddr_t) + mbuf_len(mp);
347 * copies a uio scatter/gather list to an mbuf chain.
348 * This version returns the mbuf list and does not use "nd".
349 * NOTE: can ony handle iovcnt == 1
352 nfsm_uiombuflist(struct uio *uiop, int siz, struct mbuf **mbp, char **cpp)
355 struct mbuf *mp, *mp2, *firstmp;
356 int xfer, left, mlen;
357 int uiosiz, clflg, rem;
360 KASSERT(uiop->uio_iovcnt == 1, ("nfsm_uiotombuf: iovcnt != 1"));
362 if (siz > ncl_mbuf_mlen) /* or should it >= MCLBYTES ?? */
366 rem = NFSM_RNDUP(siz) - siz;
368 NFSMCLGET(mp, M_WAITOK);
374 left = uiop->uio_iov->iov_len;
375 uiocp = uiop->uio_iov->iov_base;
380 mlen = M_TRAILINGSPACE(mp);
383 NFSMCLGET(mp, M_WAITOK);
387 mbuf_setnext(mp2, mp);
389 mlen = M_TRAILINGSPACE(mp);
391 xfer = (left > mlen) ? mlen : left;
392 if (uiop->uio_segflg == UIO_SYSSPACE)
393 NFSBCOPY(uiocp, NFSMTOD(mp, caddr_t) +
396 copyin(uiocp, NFSMTOD(mp, caddr_t) +
398 mbuf_setlen(mp, mbuf_len(mp) + xfer);
401 uiop->uio_offset += xfer;
402 uiop->uio_resid -= xfer;
404 tcp = (char *)uiop->uio_iov->iov_base;
406 uiop->uio_iov->iov_base = (void *)tcp;
407 uiop->uio_iov->iov_len -= uiosiz;
411 *cpp = NFSMTOD(mp, caddr_t) + mbuf_len(mp);
418 * Load vnode attributes from the xdr file attributes.
419 * Returns EBADRPC if they can't be parsed, 0 otherwise.
422 nfsm_loadattr(struct nfsrv_descript *nd, struct nfsvattr *nap)
424 struct nfs_fattr *fp;
427 if (nd->nd_flag & ND_NFSV4) {
428 error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL,
429 NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL);
430 } else if (nd->nd_flag & ND_NFSV3) {
431 NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V3FATTR);
432 nap->na_type = nfsv34tov_type(fp->fa_type);
433 nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode);
434 nap->na_rdev = makedev(fxdr_unsigned(u_char, fp->fa3_rdev.specdata1),
435 fxdr_unsigned(u_char, fp->fa3_rdev.specdata2));
436 nap->na_nlink = fxdr_unsigned(uint32_t, fp->fa_nlink);
437 nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid);
438 nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid);
439 nap->na_size = fxdr_hyper(&fp->fa3_size);
440 nap->na_blocksize = NFS_FABLKSIZE;
441 nap->na_bytes = fxdr_hyper(&fp->fa3_used);
442 nap->na_fileid = fxdr_hyper(&fp->fa3_fileid);
443 fxdr_nfsv3time(&fp->fa3_atime, &nap->na_atime);
444 fxdr_nfsv3time(&fp->fa3_ctime, &nap->na_ctime);
445 fxdr_nfsv3time(&fp->fa3_mtime, &nap->na_mtime);
449 NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V2FATTR);
450 nap->na_type = nfsv2tov_type(fp->fa_type);
451 nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode);
452 if (nap->na_type == VNON || nap->na_type == VREG)
453 nap->na_type = IFTOVT(nap->na_mode);
454 nap->na_rdev = fxdr_unsigned(dev_t, fp->fa2_rdev);
457 * Really ugly NFSv2 kludge.
459 if (nap->na_type == VCHR && nap->na_rdev == ((dev_t)-1))
460 nap->na_type = VFIFO;
461 nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
462 nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid);
463 nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid);
464 nap->na_size = fxdr_unsigned(u_int32_t, fp->fa2_size);
465 nap->na_blocksize = fxdr_unsigned(int32_t, fp->fa2_blocksize);
467 (u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks) *
469 nap->na_fileid = fxdr_unsigned(uint64_t, fp->fa2_fileid);
470 fxdr_nfsv2time(&fp->fa2_atime, &nap->na_atime);
471 fxdr_nfsv2time(&fp->fa2_mtime, &nap->na_mtime);
473 nap->na_ctime.tv_sec = fxdr_unsigned(u_int32_t,
474 fp->fa2_ctime.nfsv2_sec);
475 nap->na_ctime.tv_nsec = 0;
476 nap->na_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec);
484 * This function finds the directory cookie that corresponds to the
485 * logical byte offset given.
487 APPLESTATIC nfsuint64 *
488 nfscl_getcookie(struct nfsnode *np, off_t off, int add)
490 struct nfsdmap *dp, *dp2;
493 pos = off / NFS_DIRBLKSIZ;
495 KASSERT(!add, ("nfs getcookie add at 0"));
496 return (&nfs_nullcookie);
499 dp = LIST_FIRST(&np->n_cookies);
502 dp = malloc(sizeof (struct nfsdmap),
503 M_NFSDIROFF, M_WAITOK);
504 dp->ndm_eocookie = 0;
505 LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list);
509 while (pos >= NFSNUMCOOKIES) {
510 pos -= NFSNUMCOOKIES;
511 if (LIST_NEXT(dp, ndm_list) != NULL) {
512 if (!add && dp->ndm_eocookie < NFSNUMCOOKIES &&
513 pos >= dp->ndm_eocookie)
515 dp = LIST_NEXT(dp, ndm_list);
517 dp2 = malloc(sizeof (struct nfsdmap),
518 M_NFSDIROFF, M_WAITOK);
519 dp2->ndm_eocookie = 0;
520 LIST_INSERT_AFTER(dp, dp2, ndm_list);
525 if (pos >= dp->ndm_eocookie) {
527 dp->ndm_eocookie = pos + 1;
531 return (&dp->ndm_cookies[pos]);
535 * Gets a file handle out of an nfs reply sent to the client and returns
536 * the file handle and the file's attributes.
537 * For V4, it assumes that Getfh and Getattr Op's results are here.
540 nfscl_mtofh(struct nfsrv_descript *nd, struct nfsfh **nfhpp,
541 struct nfsvattr *nap, int *attrflagp)
544 int error = 0, flag = 1;
549 * First get the file handle and vnode.
551 if (nd->nd_flag & ND_NFSV3) {
552 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
553 flag = fxdr_unsigned(int, *tl);
554 } else if (nd->nd_flag & ND_NFSV4) {
555 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
556 /* If the GetFH failed, clear flag. */
558 nd->nd_flag |= ND_NOMOREDATA;
560 error = ENXIO; /* Return ENXIO so *nfhpp isn't used. */
564 error = nfsm_getfh(nd, nfhpp);
570 * Now, get the attributes.
572 if (flag != 0 && (nd->nd_flag & ND_NFSV4) != 0) {
573 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
575 nd->nd_flag |= ND_NOMOREDATA;
578 } else if (nd->nd_flag & ND_NFSV3) {
579 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
581 flag = fxdr_unsigned(int, *tl);
582 } else if (fxdr_unsigned(int, *tl)) {
583 error = nfsm_advance(nd, NFSX_V3FATTR, -1);
589 error = nfsm_loadattr(nd, nap);
598 * Put a state Id in the mbuf list.
601 nfsm_stateidtom(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp, int flag)
605 NFSM_BUILD(st, nfsv4stateid_t *, NFSX_STATEID);
606 if (flag == NFSSTATEID_PUTALLZERO) {
611 } else if (flag == NFSSTATEID_PUTALLONE) {
612 st->seqid = 0xffffffff;
613 st->other[0] = 0xffffffff;
614 st->other[1] = 0xffffffff;
615 st->other[2] = 0xffffffff;
616 } else if (flag == NFSSTATEID_PUTSEQIDZERO) {
618 st->other[0] = stateidp->other[0];
619 st->other[1] = stateidp->other[1];
620 st->other[2] = stateidp->other[2];
622 st->seqid = stateidp->seqid;
623 st->other[0] = stateidp->other[0];
624 st->other[1] = stateidp->other[1];
625 st->other[2] = stateidp->other[2];
630 * Initialize the owner/delegation sleep lock.
633 nfscl_lockinit(struct nfsv4lock *lckp)
636 lckp->nfslock_usecnt = 0;
637 lckp->nfslock_lock = 0;
641 * Get an exclusive lock. (Not needed for OpenBSD4, since there is only one
642 * thread for each posix process in the kernel.)
645 nfscl_lockexcl(struct nfsv4lock *lckp, void *mutex)
650 igotlock = nfsv4_lock(lckp, 1, NULL, mutex, NULL);
655 * Release an exclusive lock.
658 nfscl_lockunlock(struct nfsv4lock *lckp)
661 nfsv4_unlock(lckp, 0);
665 * Called to derefernce a lock on a stateid (delegation or open owner).
668 nfscl_lockderef(struct nfsv4lock *lckp)
672 lckp->nfslock_usecnt--;
673 if (lckp->nfslock_usecnt == 0 && (lckp->nfslock_lock & NFSV4LOCK_WANTED)) {
674 lckp->nfslock_lock &= ~NFSV4LOCK_WANTED;
675 wakeup((caddr_t)lckp);