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(nmp, nd, 207 NFSMNT_MDSSESSION(nmp), 208 nfs_bigreply[procnum]); 209 else 210 nfsv4_setsequence(nmp, nd, sep, 211 nfs_bigreply[procnum]); 212 } 213 if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh > 0) { 214 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 215 *tl = txdr_unsigned(NFSV4OP_PUTFH); 216 (void) nfsm_fhtom(nd, nfhp, fhlen, 0); 217 if (nfsv4_opflag[nfsv4_opmap[procnum].op].needscfh 218 == 2 && procnum != NFSPROC_WRITEDS && 219 procnum != NFSPROC_COMMITDS) { 220 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 221 *tl = txdr_unsigned(NFSV4OP_GETATTR); 222 NFSWCCATTR_ATTRBIT(&attrbits); 223 (void) nfsrv_putattrbit(nd, &attrbits); 224 nd->nd_flag |= ND_V4WCCATTR; 225 } 226 } 227 if (procnum != NFSPROC_RENEW || 228 (nd->nd_flag & ND_NFSV41) == 0) { 229 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 230 *tl = txdr_unsigned(nfsv4_opmap[procnum].op); 231 } 232 } else { 233 (void) nfsm_fhtom(nd, nfhp, fhlen, 0); 234 } 235 if (procnum < NFSV4_NPROCS) 236 NFSINCRGLOBAL(newnfsstats.rpccnt[procnum]); 237 } 238 239 #ifndef APPLE 240 /* 241 * copies a uio scatter/gather list to an mbuf chain. 242 * NOTE: can ony handle iovcnt == 1 243 */ 244 APPLESTATIC void 245 nfsm_uiombuf(struct nfsrv_descript *nd, struct uio *uiop, int siz) 246 { 247 char *uiocp; 248 struct mbuf *mp, *mp2; 249 int xfer, left, mlen; 250 int uiosiz, clflg, rem; 251 char *cp, *tcp; 252 253 KASSERT(uiop->uio_iovcnt == 1, ("nfsm_uiotombuf: iovcnt != 1")); 254 255 if (siz > ncl_mbuf_mlen) /* or should it >= MCLBYTES ?? */ 256 clflg = 1; 257 else 258 clflg = 0; 259 rem = NFSM_RNDUP(siz) - siz; 260 mp = mp2 = nd->nd_mb; 261 while (siz > 0) { 262 left = uiop->uio_iov->iov_len; 263 uiocp = uiop->uio_iov->iov_base; 264 if (left > siz) 265 left = siz; 266 uiosiz = left; 267 while (left > 0) { 268 mlen = M_TRAILINGSPACE(mp); 269 if (mlen == 0) { 270 if (clflg) 271 NFSMCLGET(mp, M_WAITOK); 272 else 273 NFSMGET(mp); 274 mbuf_setlen(mp, 0); 275 mbuf_setnext(mp2, mp); 276 mp2 = mp; 277 mlen = M_TRAILINGSPACE(mp); 278 } 279 xfer = (left > mlen) ? mlen : left; 280 #ifdef notdef 281 /* Not Yet.. */ 282 if (uiop->uio_iov->iov_op != NULL) 283 (*(uiop->uio_iov->iov_op)) 284 (uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp), 285 xfer); 286 else 287 #endif 288 if (uiop->uio_segflg == UIO_SYSSPACE) 289 NFSBCOPY(uiocp, NFSMTOD(mp, caddr_t) + mbuf_len(mp), 290 xfer); 291 else 292 copyin(CAST_USER_ADDR_T(uiocp), NFSMTOD(mp, caddr_t) 293 + mbuf_len(mp), xfer); 294 mbuf_setlen(mp, mbuf_len(mp) + xfer); 295 left -= xfer; 296 uiocp += xfer; 297 uiop->uio_offset += xfer; 298 uiop->uio_resid -= xfer; 299 } 300 tcp = (char *)uiop->uio_iov->iov_base; 301 tcp += uiosiz; 302 uiop->uio_iov->iov_base = (void *)tcp; 303 uiop->uio_iov->iov_len -= uiosiz; 304 siz -= uiosiz; 305 } 306 if (rem > 0) { 307 if (rem > M_TRAILINGSPACE(mp)) { 308 NFSMGET(mp); 309 mbuf_setlen(mp, 0); 310 mbuf_setnext(mp2, mp); 311 } 312 cp = NFSMTOD(mp, caddr_t) + mbuf_len(mp); 313 for (left = 0; left < rem; left++) 314 *cp++ = '\0'; 315 mbuf_setlen(mp, mbuf_len(mp) + rem); 316 nd->nd_bpos = cp; 317 } else 318 nd->nd_bpos = NFSMTOD(mp, caddr_t) + mbuf_len(mp); 319 nd->nd_mb = mp; 320 } 321 #endif /* !APPLE */ 322 323 /* 324 * Load vnode attributes from the xdr file attributes. 325 * Returns EBADRPC if they can't be parsed, 0 otherwise. 326 */ 327 APPLESTATIC int 328 nfsm_loadattr(struct nfsrv_descript *nd, struct nfsvattr *nap) 329 { 330 struct nfs_fattr *fp; 331 int error = 0; 332 333 if (nd->nd_flag & ND_NFSV4) { 334 error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL, 335 NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL); 336 } else if (nd->nd_flag & ND_NFSV3) { 337 NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V3FATTR); 338 nap->na_type = nfsv34tov_type(fp->fa_type); 339 nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode); 340 nap->na_rdev = makedev(fxdr_unsigned(u_char, fp->fa3_rdev.specdata1), 341 fxdr_unsigned(u_char, fp->fa3_rdev.specdata2)); 342 nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink); 343 nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid); 344 nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid); 345 nap->na_size = fxdr_hyper(&fp->fa3_size); 346 nap->na_blocksize = NFS_FABLKSIZE; 347 nap->na_bytes = fxdr_hyper(&fp->fa3_used); 348 nap->na_fileid = fxdr_hyper(&fp->fa3_fileid); 349 fxdr_nfsv3time(&fp->fa3_atime, &nap->na_atime); 350 fxdr_nfsv3time(&fp->fa3_ctime, &nap->na_ctime); 351 fxdr_nfsv3time(&fp->fa3_mtime, &nap->na_mtime); 352 nap->na_flags = 0; 353 nap->na_filerev = 0; 354 } else { 355 NFSM_DISSECT(fp, struct nfs_fattr *, NFSX_V2FATTR); 356 nap->na_type = nfsv2tov_type(fp->fa_type); 357 nap->na_mode = fxdr_unsigned(u_short, fp->fa_mode); 358 if (nap->na_type == VNON || nap->na_type == VREG) 359 nap->na_type = IFTOVT(nap->na_mode); 360 nap->na_rdev = fxdr_unsigned(dev_t, fp->fa2_rdev); 361 362 /* 363 * Really ugly NFSv2 kludge. 364 */ 365 if (nap->na_type == VCHR && nap->na_rdev == ((dev_t)-1)) 366 nap->na_type = VFIFO; 367 nap->na_nlink = fxdr_unsigned(u_short, fp->fa_nlink); 368 nap->na_uid = fxdr_unsigned(uid_t, fp->fa_uid); 369 nap->na_gid = fxdr_unsigned(gid_t, fp->fa_gid); 370 nap->na_size = fxdr_unsigned(u_int32_t, fp->fa2_size); 371 nap->na_blocksize = fxdr_unsigned(int32_t, fp->fa2_blocksize); 372 nap->na_bytes = 373 (u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks) * 374 NFS_FABLKSIZE; 375 nap->na_fileid = fxdr_unsigned(uint64_t, fp->fa2_fileid); 376 fxdr_nfsv2time(&fp->fa2_atime, &nap->na_atime); 377 fxdr_nfsv2time(&fp->fa2_mtime, &nap->na_mtime); 378 nap->na_flags = 0; 379 nap->na_ctime.tv_sec = fxdr_unsigned(u_int32_t, 380 fp->fa2_ctime.nfsv2_sec); 381 nap->na_ctime.tv_nsec = 0; 382 nap->na_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec); 383 nap->na_filerev = 0; 384 } 385 nfsmout: 386 return (error); 387 } 388 389 /* 390 * This function finds the directory cookie that corresponds to the 391 * logical byte offset given. 392 */ 393 APPLESTATIC nfsuint64 * 394 nfscl_getcookie(struct nfsnode *np, off_t off, int add) 395 { 396 struct nfsdmap *dp, *dp2; 397 int pos; 398 399 pos = off / NFS_DIRBLKSIZ; 400 if (pos == 0) { 401 KASSERT(!add, ("nfs getcookie add at 0")); 402 return (&nfs_nullcookie); 403 } 404 pos--; 405 dp = LIST_FIRST(&np->n_cookies); 406 if (!dp) { 407 if (add) { 408 MALLOC(dp, struct nfsdmap *, sizeof (struct nfsdmap), 409 M_NFSDIROFF, M_WAITOK); 410 dp->ndm_eocookie = 0; 411 LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list); 412 } else 413 return (NULL); 414 } 415 while (pos >= NFSNUMCOOKIES) { 416 pos -= NFSNUMCOOKIES; 417 if (LIST_NEXT(dp, ndm_list) != NULL) { 418 if (!add && dp->ndm_eocookie < NFSNUMCOOKIES && 419 pos >= dp->ndm_eocookie) 420 return (NULL); 421 dp = LIST_NEXT(dp, ndm_list); 422 } else if (add) { 423 MALLOC(dp2, struct nfsdmap *, sizeof (struct nfsdmap), 424 M_NFSDIROFF, M_WAITOK); 425 dp2->ndm_eocookie = 0; 426 LIST_INSERT_AFTER(dp, dp2, ndm_list); 427 dp = dp2; 428 } else 429 return (NULL); 430 } 431 if (pos >= dp->ndm_eocookie) { 432 if (add) 433 dp->ndm_eocookie = pos + 1; 434 else 435 return (NULL); 436 } 437 return (&dp->ndm_cookies[pos]); 438 } 439 440 /* 441 * Gets a file handle out of an nfs reply sent to the client and returns 442 * the file handle and the file's attributes. 443 * For V4, it assumes that Getfh and Getattr Op's results are here. 444 */ 445 APPLESTATIC int 446 nfscl_mtofh(struct nfsrv_descript *nd, struct nfsfh **nfhpp, 447 struct nfsvattr *nap, int *attrflagp) 448 { 449 u_int32_t *tl; 450 int error = 0, flag = 1; 451 452 *nfhpp = NULL; 453 *attrflagp = 0; 454 /* 455 * First get the file handle and vnode. 456 */ 457 if (nd->nd_flag & ND_NFSV3) { 458 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 459 flag = fxdr_unsigned(int, *tl); 460 } else if (nd->nd_flag & ND_NFSV4) { 461 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 462 } 463 if (flag) { 464 error = nfsm_getfh(nd, nfhpp); 465 if (error) 466 return (error); 467 } 468 469 /* 470 * Now, get the attributes. 471 */ 472 if (nd->nd_flag & ND_NFSV4) { 473 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 474 } else if (nd->nd_flag & ND_NFSV3) { 475 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 476 if (flag) { 477 flag = fxdr_unsigned(int, *tl); 478 } else if (fxdr_unsigned(int, *tl)) { 479 error = nfsm_advance(nd, NFSX_V3FATTR, -1); 480 if (error) 481 return (error); 482 } 483 } 484 if (flag) { 485 error = nfsm_loadattr(nd, nap); 486 if (!error) 487 *attrflagp = 1; 488 } 489 nfsmout: 490 return (error); 491 } 492 493 /* 494 * Put a state Id in the mbuf list. 495 */ 496 APPLESTATIC void 497 nfsm_stateidtom(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp, int flag) 498 { 499 nfsv4stateid_t *st; 500 501 NFSM_BUILD(st, nfsv4stateid_t *, NFSX_STATEID); 502 if (flag == NFSSTATEID_PUTALLZERO) { 503 st->seqid = 0; 504 st->other[0] = 0; 505 st->other[1] = 0; 506 st->other[2] = 0; 507 } else if (flag == NFSSTATEID_PUTALLONE) { 508 st->seqid = 0xffffffff; 509 st->other[0] = 0xffffffff; 510 st->other[1] = 0xffffffff; 511 st->other[2] = 0xffffffff; 512 } else if (flag == NFSSTATEID_PUTSEQIDZERO) { 513 st->seqid = 0; 514 st->other[0] = stateidp->other[0]; 515 st->other[1] = stateidp->other[1]; 516 st->other[2] = stateidp->other[2]; 517 } else { 518 st->seqid = stateidp->seqid; 519 st->other[0] = stateidp->other[0]; 520 st->other[1] = stateidp->other[1]; 521 st->other[2] = stateidp->other[2]; 522 } 523 } 524 525 /* 526 * Initialize the owner/delegation sleep lock. 527 */ 528 APPLESTATIC void 529 nfscl_lockinit(struct nfsv4lock *lckp) 530 { 531 532 lckp->nfslock_usecnt = 0; 533 lckp->nfslock_lock = 0; 534 } 535 536 /* 537 * Get an exclusive lock. (Not needed for OpenBSD4, since there is only one 538 * thread for each posix process in the kernel.) 539 */ 540 APPLESTATIC void 541 nfscl_lockexcl(struct nfsv4lock *lckp, void *mutex) 542 { 543 int igotlock; 544 545 do { 546 igotlock = nfsv4_lock(lckp, 1, NULL, mutex, NULL); 547 } while (!igotlock); 548 } 549 550 /* 551 * Release an exclusive lock. 552 */ 553 APPLESTATIC void 554 nfscl_lockunlock(struct nfsv4lock *lckp) 555 { 556 557 nfsv4_unlock(lckp, 0); 558 } 559 560 /* 561 * Called to derefernce a lock on a stateid (delegation or open owner). 562 */ 563 APPLESTATIC void 564 nfscl_lockderef(struct nfsv4lock *lckp) 565 { 566 567 NFSLOCKCLSTATE(); 568 lckp->nfslock_usecnt--; 569 if (lckp->nfslock_usecnt == 0 && (lckp->nfslock_lock & NFSV4LOCK_WANTED)) { 570 lckp->nfslock_lock &= ~NFSV4LOCK_WANTED; 571 wakeup((caddr_t)lckp); 572 } 573 NFSUNLOCKCLSTATE(); 574 } 575 576