1 /*- 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Rick Macklem at The University of Guelph. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 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 * 4. 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. 19 * 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 30 * SUCH DAMAGE. 31 * 32 */ 33 34 #include <sys/cdefs.h> 35 __FBSDID("$FreeBSD$"); 36 37 /* 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. 41 */ 42 #ifndef APPLEKEXT 43 #include <fs/nfs/nfsport.h> 44 45 extern struct nfsstats newnfsstats; 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]; 51 NFSCLSTATEMUTEX; 52 #endif /* !APPLEKEXT */ 53 54 static nfsuint64 nfs_nullcookie = {{ 0, 0 }}; 55 static struct { 56 int op; 57 int opcnt; 58 const u_char *tag; 59 int taglen; 60 } nfsv4_opmap[NFSV41_NPROCS] = { 61 { 0, 1, "Null", 4 }, 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, 3, "Open", 4, }, 70 { NFSV4OP_CREATE, 3, "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 }; 116 117 /* 118 * NFS RPCS that have large request message size. 119 */ 120 static int nfs_bigrequest[NFSV41_NPROCS] = { 121 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123 0, 0, 0, 0, 0, 0, 1, 0, 0 124 }; 125 126 /* 127 * Start building a request. Mostly just put the first file handle in 128 * place. 129 */ 130 APPLESTATIC void 131 nfscl_reqstart(struct nfsrv_descript *nd, int procnum, struct nfsmount *nmp, 132 u_int8_t *nfhp, int fhlen, u_int32_t **opcntpp, struct nfsclsession *sep) 133 { 134 struct mbuf *mb; 135 u_int32_t *tl; 136 int opcnt; 137 nfsattrbit_t attrbits; 138 139 /* 140 * First, fill in some of the fields of nd. 141 */ 142 nd->nd_slotseq = NULL; 143 if (NFSHASNFSV4(nmp)) { 144 nd->nd_flag = ND_NFSV4 | ND_NFSCL; 145 if (NFSHASNFSV4N(nmp)) 146 nd->nd_flag |= ND_NFSV41; 147 } else if (NFSHASNFSV3(nmp)) 148 nd->nd_flag = ND_NFSV3 | ND_NFSCL; 149 else 150 nd->nd_flag = ND_NFSV2 | ND_NFSCL; 151 nd->nd_procnum = procnum; 152 nd->nd_repstat = 0; 153 154 /* 155 * Get the first mbuf for the request. 156 */ 157 if (nfs_bigrequest[procnum]) 158 NFSMCLGET(mb, M_WAITOK); 159 else 160 NFSMGET(mb); 161 mbuf_setlen(mb, 0); 162 nd->nd_mreq = nd->nd_mb = mb; 163 nd->nd_bpos = NFSMTOD(mb, caddr_t); 164 165 /* 166 * And fill the first file handle into the request. 167 */ 168 if (nd->nd_flag & ND_NFSV4) { 169 opcnt = nfsv4_opmap[procnum].opcnt + 170 nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh; 171 if ((nd->nd_flag & ND_NFSV41) != 0) { 172 opcnt += nfsv4_opflag[nfsv4_opmap[procnum].op].needsseq; 173 if (procnum == NFSPROC_RENEW) 174 /* 175 * For the special case of Renew, just do a 176 * Sequence Op. 177 */ 178 opcnt = 1; 179 else if (procnum == NFSPROC_WRITEDS || 180 procnum == NFSPROC_COMMITDS) 181 /* 182 * For the special case of a Writeor Commit to 183 * a DS, the opcnt == 3, for Sequence, PutFH, 184 * Write/Commit. 185 */ 186 opcnt = 3; 187 } 188 /* 189 * What should the tag really be? 190 */ 191 (void) nfsm_strtom(nd, nfsv4_opmap[procnum].tag, 192 nfsv4_opmap[procnum].taglen); 193 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 194 if ((nd->nd_flag & ND_NFSV41) != 0) 195 *tl++ = txdr_unsigned(NFSV41_MINORVERSION); 196 else 197 *tl++ = txdr_unsigned(NFSV4_MINORVERSION); 198 if (opcntpp != NULL) 199 *opcntpp = tl; 200 *tl = txdr_unsigned(opcnt); 201 if ((nd->nd_flag & ND_NFSV41) != 0 && 202 nfsv4_opflag[nfsv4_opmap[procnum].op].needsseq > 0) { 203 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 204 *tl = txdr_unsigned(NFSV4OP_SEQUENCE); 205 if (sep == NULL) 206 nfsv4_setsequence(nd, NFSMNT_MDSSESSION(nmp), 207 nfs_bigreply[procnum]); 208 else 209 nfsv4_setsequence(nd, sep, 210 nfs_bigreply[procnum]); 211 } 212 if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh > 0) { 213 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 214 *tl = txdr_unsigned(NFSV4OP_PUTFH); 215 (void) nfsm_fhtom(nd, nfhp, fhlen, 0); 216 if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh 217 == 2 && procnum != NFSPROC_WRITEDS && 218 procnum != NFSPROC_COMMITDS) { 219 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 220 *tl = txdr_unsigned(NFSV4OP_GETATTR); 221 NFSWCCATTR_ATTRBIT(&attrbits); 222 (void) nfsrv_putattrbit(nd, &attrbits); 223 nd->nd_flag |= ND_V4WCCATTR; 224 } 225 } 226 if (procnum != NFSPROC_RENEW || 227 (nd->nd_flag & ND_NFSV41) == 0) { 228 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 229 *tl = txdr_unsigned(nfsv4_opmap[procnum].op); 230 } 231 } else { 232 (void) nfsm_fhtom(nd, nfhp, fhlen, 0); 233 } 234 if (procnum < NFSV4_NPROCS) 235 NFSINCRGLOBAL(newnfsstats.rpccnt[procnum]); 236 } 237 238 #ifndef APPLE 239 /* 240 * copies a uio scatter/gather list to an mbuf chain. 241 * NOTE: can ony handle iovcnt == 1 242 */ 243 APPLESTATIC void 244 nfsm_uiombuf(struct nfsrv_descript *nd, struct uio *uiop, int siz) 245 { 246 char *uiocp; 247 struct mbuf *mp, *mp2; 248 int xfer, left, mlen; 249 int uiosiz, clflg, rem; 250 char *cp, *tcp; 251 252 KASSERT(uiop->uio_iovcnt == 1, ("nfsm_uiotombuf: iovcnt != 1")); 253 254 if (siz > ncl_mbuf_mlen) /* or should it >= MCLBYTES ?? */ 255 clflg = 1; 256 else 257 clflg = 0; 258 rem = NFSM_RNDUP(siz) - siz; 259 mp = mp2 = nd->nd_mb; 260 while (siz > 0) { 261 left = uiop->uio_iov->iov_len; 262 uiocp = uiop->uio_iov->iov_base; 263 if (left > siz) 264 left = siz; 265 uiosiz = left; 266 while (left > 0) { 267 mlen = M_TRAILINGSPACE(mp); 268 if (mlen == 0) { 269 if (clflg) 270 NFSMCLGET(mp, M_WAITOK); 271 else 272 NFSMGET(mp); 273 mbuf_setlen(mp, 0); 274 mbuf_setnext(mp2, mp); 275 mp2 = mp; 276 mlen = M_TRAILINGSPACE(mp); 277 } 278 xfer = (left > mlen) ? mlen : left; 279 #ifdef notdef 280 /* Not Yet.. */ 281 if (uiop->uio_iov->iov_op != NULL) 282 (*(uiop->uio_iov->iov_op)) 283 (uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp), 284 xfer); 285 else 286 #endif 287 if (uiop->uio_segflg == UIO_SYSSPACE) 288 NFSBCOPY(uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp), 289 xfer); 290 else 291 copyin(CAST_USER_ADDR_T(uiocp), NFSMTOD(mp, caddr_t) 292 + mbuf_len(mp), xfer); 293 mbuf_setlen(mp, mbuf_len(mp) + xfer); 294 left -= xfer; 295 uiocp += xfer; 296 uiop->uio_offset += xfer; 297 uiop->uio_resid -= xfer; 298 } 299 tcp = (char *)uiop->uio_iov->iov_base; 300 tcp += uiosiz; 301 uiop->uio_iov->iov_base = (void *)tcp; 302 uiop->uio_iov->iov_len -= uiosiz; 303 siz -= uiosiz; 304 } 305 if (rem > 0) { 306 if (rem > M_TRAILINGSPACE(mp)) { 307 NFSMGET(mp); 308 mbuf_setlen(mp, 0); 309 mbuf_setnext(mp2, mp); 310 } 311 cp = NFSMTOD(mp, caddr_t) + mbuf_len(mp); 312 for (left = 0; left < rem; left++) 313 *cp++ = '\0'; 314 mbuf_setlen(mp, mbuf_len(mp) + rem); 315 nd->nd_bpos = cp; 316 } else 317 nd->nd_bpos = NFSMTOD(mp, caddr_t) + mbuf_len(mp); 318 nd->nd_mb = mp; 319 } 320 #endif /* !APPLE */ 321 322 /* 323 * Load vnode attributes from the xdr file attributes. 324 * Returns EBADRPC if they can't be parsed, 0 otherwise. 325 */ 326 APPLESTATIC int 327 nfsm_loadattr(struct nfsrv_descript *nd, struct nfsvattr *nap) 328 { 329 struct nfs_fattr *fp; 330 int error = 0; 331 332 if (nd->nd_flag & ND_NFSV4) { 333 error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL, 334 NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL); 335 } else if (nd->nd_flag & ND_NFSV3) { 336 NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V3FATTR); 337 nap->na_type = nfsv34tov_type(fp->fa_type); 338 nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode); 339 nap->na_rdev = makedev(fxdr_unsigned(u_char, fp->fa3_rdev.specdata1), 340 fxdr_unsigned(u_char, fp->fa3_rdev.specdata2)); 341 nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink); 342 nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid); 343 nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid); 344 nap->na_size = fxdr_hyper(&fp->fa3_size); 345 nap->na_blocksize = NFS_FABLKSIZE; 346 nap->na_bytes = fxdr_hyper(&fp->fa3_used); 347 nap->na_fileid = fxdr_hyper(&fp->fa3_fileid); 348 fxdr_nfsv3time(&fp->fa3_atime, &nap->na_atime); 349 fxdr_nfsv3time(&fp->fa3_ctime, &nap->na_ctime); 350 fxdr_nfsv3time(&fp->fa3_mtime, &nap->na_mtime); 351 nap->na_flags = 0; 352 nap->na_filerev = 0; 353 } else { 354 NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V2FATTR); 355 nap->na_type = nfsv2tov_type(fp->fa_type); 356 nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode); 357 if (nap->na_type == VNON || nap->na_type == VREG) 358 nap->na_type = IFTOVT(nap->na_mode); 359 nap->na_rdev = fxdr_unsigned(dev_t, fp->fa2_rdev); 360 361 /* 362 * Really ugly NFSv2 kludge. 363 */ 364 if (nap->na_type == VCHR && nap->na_rdev == ((dev_t)-1)) 365 nap->na_type = VFIFO; 366 nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink); 367 nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid); 368 nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid); 369 nap->na_size = fxdr_unsigned(u_int32_t, fp->fa2_size); 370 nap->na_blocksize = fxdr_unsigned(int32_t, fp->fa2_blocksize); 371 nap->na_bytes = 372 (u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks) * 373 NFS_FABLKSIZE; 374 nap->na_fileid = fxdr_unsigned(uint64_t, fp->fa2_fileid); 375 fxdr_nfsv2time(&fp->fa2_atime, &nap->na_atime); 376 fxdr_nfsv2time(&fp->fa2_mtime, &nap->na_mtime); 377 nap->na_flags = 0; 378 nap->na_ctime.tv_sec = fxdr_unsigned(u_int32_t, 379 fp->fa2_ctime.nfsv2_sec); 380 nap->na_ctime.tv_nsec = 0; 381 nap->na_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec); 382 nap->na_filerev = 0; 383 } 384 nfsmout: 385 return (error); 386 } 387 388 /* 389 * This function finds the directory cookie that corresponds to the 390 * logical byte offset given. 391 */ 392 APPLESTATIC nfsuint64 * 393 nfscl_getcookie(struct nfsnode *np, off_t off, int add) 394 { 395 struct nfsdmap *dp, *dp2; 396 int pos; 397 398 pos = off / NFS_DIRBLKSIZ; 399 if (pos == 0) { 400 KASSERT(!add, ("nfs getcookie add at 0")); 401 return (&nfs_nullcookie); 402 } 403 pos--; 404 dp = LIST_FIRST(&np->n_cookies); 405 if (!dp) { 406 if (add) { 407 MALLOC(dp, struct nfsdmap *, sizeof (struct nfsdmap), 408 M_NFSDIROFF, M_WAITOK); 409 dp->ndm_eocookie = 0; 410 LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list); 411 } else 412 return (NULL); 413 } 414 while (pos >= NFSNUMCOOKIES) { 415 pos -= NFSNUMCOOKIES; 416 if (LIST_NEXT(dp, ndm_list) != NULL) { 417 if (!add && dp->ndm_eocookie < NFSNUMCOOKIES && 418 pos >= dp->ndm_eocookie) 419 return (NULL); 420 dp = LIST_NEXT(dp, ndm_list); 421 } else if (add) { 422 MALLOC(dp2, struct nfsdmap *, sizeof (struct nfsdmap), 423 M_NFSDIROFF, M_WAITOK); 424 dp2->ndm_eocookie = 0; 425 LIST_INSERT_AFTER(dp, dp2, ndm_list); 426 dp = dp2; 427 } else 428 return (NULL); 429 } 430 if (pos >= dp->ndm_eocookie) { 431 if (add) 432 dp->ndm_eocookie = pos + 1; 433 else 434 return (NULL); 435 } 436 return (&dp->ndm_cookies[pos]); 437 } 438 439 /* 440 * Gets a file handle out of an nfs reply sent to the client and returns 441 * the file handle and the file's attributes. 442 * For V4, it assumes that Getfh and Getattr Op's results are here. 443 */ 444 APPLESTATIC int 445 nfscl_mtofh(struct nfsrv_descript *nd, struct nfsfh **nfhpp, 446 struct nfsvattr *nap, int *attrflagp) 447 { 448 u_int32_t *tl; 449 int error = 0, flag = 1; 450 451 *nfhpp = NULL; 452 *attrflagp = 0; 453 /* 454 * First get the file handle and vnode. 455 */ 456 if (nd->nd_flag & ND_NFSV3) { 457 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 458 flag = fxdr_unsigned(int, *tl); 459 } else if (nd->nd_flag & ND_NFSV4) { 460 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 461 } 462 if (flag) { 463 error = nfsm_getfh(nd, nfhpp); 464 if (error) 465 return (error); 466 } 467 468 /* 469 * Now, get the attributes. 470 */ 471 if (nd->nd_flag & ND_NFSV4) { 472 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 473 } else if (nd->nd_flag & ND_NFSV3) { 474 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 475 if (flag) { 476 flag = fxdr_unsigned(int, *tl); 477 } else if (fxdr_unsigned(int, *tl)) { 478 error = nfsm_advance(nd, NFSX_V3FATTR, -1); 479 if (error) 480 return (error); 481 } 482 } 483 if (flag) { 484 error = nfsm_loadattr(nd, nap); 485 if (!error) 486 *attrflagp = 1; 487 } 488 nfsmout: 489 return (error); 490 } 491 492 /* 493 * Put a state Id in the mbuf list. 494 */ 495 APPLESTATIC void 496 nfsm_stateidtom(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp, int flag) 497 { 498 nfsv4stateid_t *st; 499 500 NFSM_BUILD(st, nfsv4stateid_t *, NFSX_STATEID); 501 if (flag == NFSSTATEID_PUTALLZERO) { 502 st->seqid = 0; 503 st->other[0] = 0; 504 st->other[1] = 0; 505 st->other[2] = 0; 506 } else if (flag == NFSSTATEID_PUTALLONE) { 507 st->seqid = 0xffffffff; 508 st->other[0] = 0xffffffff; 509 st->other[1] = 0xffffffff; 510 st->other[2] = 0xffffffff; 511 } else if (flag == NFSSTATEID_PUTSEQIDZERO) { 512 st->seqid = 0; 513 st->other[0] = stateidp->other[0]; 514 st->other[1] = stateidp->other[1]; 515 st->other[2] = stateidp->other[2]; 516 } else { 517 st->seqid = stateidp->seqid; 518 st->other[0] = stateidp->other[0]; 519 st->other[1] = stateidp->other[1]; 520 st->other[2] = stateidp->other[2]; 521 } 522 } 523 524 /* 525 * Initialize the owner/delegation sleep lock. 526 */ 527 APPLESTATIC void 528 nfscl_lockinit(struct nfsv4lock *lckp) 529 { 530 531 lckp->nfslock_usecnt = 0; 532 lckp->nfslock_lock = 0; 533 } 534 535 /* 536 * Get an exclusive lock. (Not needed for OpenBSD4, since there is only one 537 * thread for each posix process in the kernel.) 538 */ 539 APPLESTATIC void 540 nfscl_lockexcl(struct nfsv4lock *lckp, void *mutex) 541 { 542 int igotlock; 543 544 do { 545 igotlock = nfsv4_lock(lckp, 1, NULL, mutex, NULL); 546 } while (!igotlock); 547 } 548 549 /* 550 * Release an exclusive lock. 551 */ 552 APPLESTATIC void 553 nfscl_lockunlock(struct nfsv4lock *lckp) 554 { 555 556 nfsv4_unlock(lckp, 0); 557 } 558 559 /* 560 * Called to derefernce a lock on a stateid (delegation or open owner). 561 */ 562 APPLESTATIC void 563 nfscl_lockderef(struct nfsv4lock *lckp) 564 { 565 566 NFSLOCKCLSTATE(); 567 lckp->nfslock_usecnt--; 568 if (lckp->nfslock_usecnt == 0 && (lckp->nfslock_lock & NFSV4LOCK_WANTED)) { 569 lckp->nfslock_lock &= ~NFSV4LOCK_WANTED; 570 wakeup((caddr_t)lckp); 571 } 572 NFSUNLOCKCLSTATE(); 573 } 574 575