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