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