1 /*- 2 * Copyright (c) 2009 Rick Macklem, University of Guelph 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #ifndef APPLEKEXT 32 #include <fs/nfs/nfsport.h> 33 34 struct nfsrv_stablefirst nfsrv_stablefirst; 35 int nfsrv_issuedelegs = 0; 36 int nfsrv_dolocallocks = 0; 37 struct nfsv4lock nfsv4rootfs_lock; 38 39 extern int newnfs_numnfsd; 40 extern struct nfsstats newnfsstats; 41 extern int nfsrv_lease; 42 extern struct timeval nfsboottime; 43 extern u_int32_t newnfs_true, newnfs_false; 44 NFSV4ROOTLOCKMUTEX; 45 NFSSTATESPINLOCK; 46 47 /* 48 * Hash lists for nfs V4. 49 * (Some would put them in the .h file, but I don't like declaring storage 50 * in a .h) 51 */ 52 struct nfsclienthashhead nfsclienthash[NFSCLIENTHASHSIZE]; 53 struct nfslockhashhead nfslockhash[NFSLOCKHASHSIZE]; 54 #endif /* !APPLEKEXT */ 55 56 static u_int32_t nfsrv_openpluslock = 0, nfsrv_delegatecnt = 0; 57 static time_t nfsrvboottime; 58 static int nfsrv_writedelegifpos = 1; 59 static int nfsrv_returnoldstateid = 0, nfsrv_clients = 0; 60 static int nfsrv_clienthighwater = NFSRV_CLIENTHIGHWATER; 61 static int nfsrv_nogsscallback = 0; 62 63 /* local functions */ 64 static void nfsrv_dumpaclient(struct nfsclient *clp, 65 struct nfsd_dumpclients *dumpp); 66 static void nfsrv_freeopenowner(struct nfsstate *stp, int cansleep, 67 NFSPROC_T *p); 68 static int nfsrv_freeopen(struct nfsstate *stp, vnode_t vp, int cansleep, 69 NFSPROC_T *p); 70 static void nfsrv_freelockowner(struct nfsstate *stp, vnode_t vp, int cansleep, 71 NFSPROC_T *p); 72 static void nfsrv_freeallnfslocks(struct nfsstate *stp, vnode_t vp, 73 int cansleep, NFSPROC_T *p); 74 static void nfsrv_freenfslock(struct nfslock *lop); 75 static void nfsrv_freenfslockfile(struct nfslockfile *lfp); 76 static void nfsrv_freedeleg(struct nfsstate *); 77 static int nfsrv_getstate(struct nfsclient *clp, nfsv4stateid_t *stateidp, 78 u_int32_t flags, struct nfsstate **stpp); 79 static void nfsrv_getowner(struct nfsstatehead *hp, struct nfsstate *new_stp, 80 struct nfsstate **stpp); 81 static int nfsrv_getlockfh(vnode_t vp, u_short flags, 82 struct nfslockfile **new_lfpp, fhandle_t *nfhp, NFSPROC_T *p); 83 static int nfsrv_getlockfile(u_short flags, struct nfslockfile **new_lfpp, 84 struct nfslockfile **lfpp, fhandle_t *nfhp, int lockit); 85 static void nfsrv_insertlock(struct nfslock *new_lop, 86 struct nfslock *insert_lop, struct nfsstate *stp, struct nfslockfile *lfp); 87 static void nfsrv_updatelock(struct nfsstate *stp, struct nfslock **new_lopp, 88 struct nfslock **other_lopp, struct nfslockfile *lfp); 89 static int nfsrv_getipnumber(u_char *cp); 90 static int nfsrv_checkrestart(nfsquad_t clientid, u_int32_t flags, 91 nfsv4stateid_t *stateidp, int specialid); 92 static int nfsrv_checkgrace(u_int32_t flags); 93 static int nfsrv_docallback(struct nfsclient *clp, int procnum, 94 nfsv4stateid_t *stateidp, int trunc, fhandle_t *fhp, 95 struct nfsvattr *nap, nfsattrbit_t *attrbitp, NFSPROC_T *p); 96 static u_int32_t nfsrv_nextclientindex(void); 97 static u_int32_t nfsrv_nextstateindex(struct nfsclient *clp); 98 static void nfsrv_markstable(struct nfsclient *clp); 99 static int nfsrv_checkstable(struct nfsclient *clp); 100 static int nfsrv_clientconflict(struct nfsclient *clp, int *haslockp, struct 101 vnode *vp, NFSPROC_T *p); 102 static int nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, 103 NFSPROC_T *p, vnode_t vp); 104 static int nfsrv_cleandeleg(vnode_t vp, struct nfslockfile *lfp, 105 struct nfsclient *clp, int *haslockp, NFSPROC_T *p); 106 static int nfsrv_notsamecredname(struct nfsrv_descript *nd, 107 struct nfsclient *clp); 108 static time_t nfsrv_leaseexpiry(void); 109 static void nfsrv_delaydelegtimeout(struct nfsstate *stp); 110 static int nfsrv_checkseqid(struct nfsrv_descript *nd, u_int32_t seqid, 111 struct nfsstate *stp, struct nfsrvcache *op); 112 static int nfsrv_nootherstate(struct nfsstate *stp); 113 static int nfsrv_locallock(vnode_t vp, struct nfslockfile *lfp, int flags, 114 uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p); 115 static void nfsrv_localunlock(vnode_t vp, struct nfslockfile *lfp, 116 uint64_t init_first, uint64_t init_end, NFSPROC_T *p); 117 static int nfsrv_dolocal(vnode_t vp, struct nfslockfile *lfp, int flags, 118 int oldflags, uint64_t first, uint64_t end, struct nfslockconflict *cfp, 119 NFSPROC_T *p); 120 static void nfsrv_locallock_rollback(vnode_t vp, struct nfslockfile *lfp, 121 NFSPROC_T *p); 122 static void nfsrv_locallock_commit(struct nfslockfile *lfp, int flags, 123 uint64_t first, uint64_t end); 124 static void nfsrv_locklf(struct nfslockfile *lfp); 125 static void nfsrv_unlocklf(struct nfslockfile *lfp); 126 127 /* 128 * Scan the client list for a match and either return the current one, 129 * create a new entry or return an error. 130 * If returning a non-error, the clp structure must either be linked into 131 * the client list or free'd. 132 */ 133 APPLESTATIC int 134 nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp, 135 nfsquad_t *clientidp, nfsquad_t *confirmp, NFSPROC_T *p) 136 { 137 struct nfsclient *clp = NULL, *new_clp = *new_clpp; 138 int i; 139 struct nfsstate *stp, *tstp; 140 struct sockaddr_in *sad, *rad; 141 int zapit = 0, gotit, hasstate = 0, igotlock; 142 static u_int64_t confirm_index = 0; 143 144 /* 145 * Check for state resource limit exceeded. 146 */ 147 if (nfsrv_openpluslock > NFSRV_V4STATELIMIT) 148 return (NFSERR_RESOURCE); 149 150 if ((nd->nd_flag & ND_GSS) && nfsrv_nogsscallback) 151 /* 152 * Don't do callbacks for AUTH_GSS. 153 * (Since these aren't yet debugged, they might cause the 154 * server to crap out, if they get past the Init call to 155 * the client.) 156 */ 157 new_clp->lc_program = 0; 158 159 /* Lock out other nfsd threads */ 160 NFSLOCKV4ROOTMUTEX(); 161 nfsv4_relref(&nfsv4rootfs_lock); 162 do { 163 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 164 NFSV4ROOTLOCKMUTEXPTR); 165 } while (!igotlock); 166 NFSUNLOCKV4ROOTMUTEX(); 167 NFSLOCKSTATE(); /* to avoid a race with */ 168 NFSUNLOCKSTATE(); /* nfsrv_servertimer() */ 169 170 /* 171 * Search for a match in the client list. 172 */ 173 gotit = i = 0; 174 while (i < NFSCLIENTHASHSIZE && !gotit) { 175 LIST_FOREACH(clp, &nfsclienthash[i], lc_hash) { 176 if (new_clp->lc_idlen == clp->lc_idlen && 177 !NFSBCMP(new_clp->lc_id, clp->lc_id, clp->lc_idlen)) { 178 gotit = 1; 179 break; 180 } 181 } 182 i++; 183 } 184 if (!gotit || 185 (clp->lc_flags & (LCL_NEEDSCONFIRM | LCL_ADMINREVOKED))) { 186 /* 187 * Get rid of the old one. 188 */ 189 if (i != NFSCLIENTHASHSIZE) { 190 LIST_REMOVE(clp, lc_hash); 191 nfsrv_cleanclient(clp, p); 192 nfsrv_freedeleglist(&clp->lc_deleg); 193 nfsrv_freedeleglist(&clp->lc_olddeleg); 194 zapit = 1; 195 } 196 /* 197 * Add it after assigning a client id to it. 198 */ 199 new_clp->lc_flags |= LCL_NEEDSCONFIRM; 200 confirmp->qval = new_clp->lc_confirm.qval = ++confirm_index; 201 clientidp->lval[0] = new_clp->lc_clientid.lval[0] = 202 (u_int32_t)nfsrvboottime; 203 clientidp->lval[1] = new_clp->lc_clientid.lval[1] = 204 nfsrv_nextclientindex(); 205 new_clp->lc_stateindex = 0; 206 new_clp->lc_statemaxindex = 0; 207 new_clp->lc_cbref = 0; 208 new_clp->lc_expiry = nfsrv_leaseexpiry(); 209 LIST_INIT(&new_clp->lc_open); 210 LIST_INIT(&new_clp->lc_deleg); 211 LIST_INIT(&new_clp->lc_olddeleg); 212 for (i = 0; i < NFSSTATEHASHSIZE; i++) 213 LIST_INIT(&new_clp->lc_stateid[i]); 214 LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp, 215 lc_hash); 216 newnfsstats.srvclients++; 217 nfsrv_openpluslock++; 218 nfsrv_clients++; 219 NFSLOCKV4ROOTMUTEX(); 220 nfsv4_unlock(&nfsv4rootfs_lock, 1); 221 NFSUNLOCKV4ROOTMUTEX(); 222 if (zapit) 223 nfsrv_zapclient(clp, p); 224 *new_clpp = NULL; 225 return (0); 226 } 227 228 /* 229 * Now, handle the cases where the id is already issued. 230 */ 231 if (nfsrv_notsamecredname(nd, clp)) { 232 /* 233 * Check to see if there is expired state that should go away. 234 */ 235 if (clp->lc_expiry < NFSD_MONOSEC && 236 (!LIST_EMPTY(&clp->lc_open) || !LIST_EMPTY(&clp->lc_deleg))) { 237 nfsrv_cleanclient(clp, p); 238 nfsrv_freedeleglist(&clp->lc_deleg); 239 } 240 241 /* 242 * If there is outstanding state, then reply NFSERR_CLIDINUSE per 243 * RFC3530 Sec. 8.1.2 last para. 244 */ 245 if (!LIST_EMPTY(&clp->lc_deleg)) { 246 hasstate = 1; 247 } else if (LIST_EMPTY(&clp->lc_open)) { 248 hasstate = 0; 249 } else { 250 hasstate = 0; 251 /* Look for an Open on the OpenOwner */ 252 LIST_FOREACH(stp, &clp->lc_open, ls_list) { 253 if (!LIST_EMPTY(&stp->ls_open)) { 254 hasstate = 1; 255 break; 256 } 257 } 258 } 259 if (hasstate) { 260 /* 261 * If the uid doesn't match, return NFSERR_CLIDINUSE after 262 * filling out the correct ipaddr and portnum. 263 */ 264 sad = NFSSOCKADDR(new_clp->lc_req.nr_nam, struct sockaddr_in *); 265 rad = NFSSOCKADDR(clp->lc_req.nr_nam, struct sockaddr_in *); 266 sad->sin_addr.s_addr = rad->sin_addr.s_addr; 267 sad->sin_port = rad->sin_port; 268 NFSLOCKV4ROOTMUTEX(); 269 nfsv4_unlock(&nfsv4rootfs_lock, 1); 270 NFSUNLOCKV4ROOTMUTEX(); 271 return (NFSERR_CLIDINUSE); 272 } 273 } 274 275 if (NFSBCMP(new_clp->lc_verf, clp->lc_verf, NFSX_VERF)) { 276 /* 277 * If the verifier has changed, the client has rebooted 278 * and a new client id is issued. The old state info 279 * can be thrown away once the SETCLIENTID_CONFIRM occurs. 280 */ 281 LIST_REMOVE(clp, lc_hash); 282 new_clp->lc_flags |= LCL_NEEDSCONFIRM; 283 confirmp->qval = new_clp->lc_confirm.qval = ++confirm_index; 284 clientidp->lval[0] = new_clp->lc_clientid.lval[0] = 285 nfsrvboottime; 286 clientidp->lval[1] = new_clp->lc_clientid.lval[1] = 287 nfsrv_nextclientindex(); 288 new_clp->lc_stateindex = 0; 289 new_clp->lc_statemaxindex = 0; 290 new_clp->lc_cbref = 0; 291 new_clp->lc_expiry = nfsrv_leaseexpiry(); 292 293 /* 294 * Save the state until confirmed. 295 */ 296 LIST_NEWHEAD(&new_clp->lc_open, &clp->lc_open, ls_list); 297 LIST_FOREACH(tstp, &new_clp->lc_open, ls_list) 298 tstp->ls_clp = new_clp; 299 LIST_NEWHEAD(&new_clp->lc_deleg, &clp->lc_deleg, ls_list); 300 LIST_FOREACH(tstp, &new_clp->lc_deleg, ls_list) 301 tstp->ls_clp = new_clp; 302 LIST_NEWHEAD(&new_clp->lc_olddeleg, &clp->lc_olddeleg, 303 ls_list); 304 LIST_FOREACH(tstp, &new_clp->lc_olddeleg, ls_list) 305 tstp->ls_clp = new_clp; 306 for (i = 0; i < NFSSTATEHASHSIZE; i++) { 307 LIST_NEWHEAD(&new_clp->lc_stateid[i], 308 &clp->lc_stateid[i], ls_hash); 309 LIST_FOREACH(tstp, &new_clp->lc_stateid[i], ls_list) 310 tstp->ls_clp = new_clp; 311 } 312 LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp, 313 lc_hash); 314 newnfsstats.srvclients++; 315 nfsrv_openpluslock++; 316 nfsrv_clients++; 317 NFSLOCKV4ROOTMUTEX(); 318 nfsv4_unlock(&nfsv4rootfs_lock, 1); 319 NFSUNLOCKV4ROOTMUTEX(); 320 321 /* 322 * Must wait until any outstanding callback on the old clp 323 * completes. 324 */ 325 while (clp->lc_cbref) { 326 clp->lc_flags |= LCL_WAKEUPWANTED; 327 (void) tsleep((caddr_t)clp, PZERO - 1, 328 "nfsd clp", 10 * hz); 329 } 330 nfsrv_zapclient(clp, p); 331 *new_clpp = NULL; 332 return (0); 333 } 334 /* 335 * id and verifier match, so update the net address info 336 * and get rid of any existing callback authentication 337 * handle, so a new one will be acquired. 338 */ 339 LIST_REMOVE(clp, lc_hash); 340 new_clp->lc_flags |= (LCL_NEEDSCONFIRM | LCL_DONTCLEAN); 341 new_clp->lc_expiry = nfsrv_leaseexpiry(); 342 confirmp->qval = new_clp->lc_confirm.qval = ++confirm_index; 343 clientidp->lval[0] = new_clp->lc_clientid.lval[0] = 344 clp->lc_clientid.lval[0]; 345 clientidp->lval[1] = new_clp->lc_clientid.lval[1] = 346 clp->lc_clientid.lval[1]; 347 new_clp->lc_delegtime = clp->lc_delegtime; 348 new_clp->lc_stateindex = clp->lc_stateindex; 349 new_clp->lc_statemaxindex = clp->lc_statemaxindex; 350 new_clp->lc_cbref = 0; 351 LIST_NEWHEAD(&new_clp->lc_open, &clp->lc_open, ls_list); 352 LIST_FOREACH(tstp, &new_clp->lc_open, ls_list) 353 tstp->ls_clp = new_clp; 354 LIST_NEWHEAD(&new_clp->lc_deleg, &clp->lc_deleg, ls_list); 355 LIST_FOREACH(tstp, &new_clp->lc_deleg, ls_list) 356 tstp->ls_clp = new_clp; 357 LIST_NEWHEAD(&new_clp->lc_olddeleg, &clp->lc_olddeleg, ls_list); 358 LIST_FOREACH(tstp, &new_clp->lc_olddeleg, ls_list) 359 tstp->ls_clp = new_clp; 360 for (i = 0; i < NFSSTATEHASHSIZE; i++) { 361 LIST_NEWHEAD(&new_clp->lc_stateid[i], &clp->lc_stateid[i], 362 ls_hash); 363 LIST_FOREACH(tstp, &new_clp->lc_stateid[i], ls_list) 364 tstp->ls_clp = new_clp; 365 } 366 LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp, 367 lc_hash); 368 newnfsstats.srvclients++; 369 nfsrv_openpluslock++; 370 nfsrv_clients++; 371 NFSLOCKV4ROOTMUTEX(); 372 nfsv4_unlock(&nfsv4rootfs_lock, 1); 373 NFSUNLOCKV4ROOTMUTEX(); 374 375 /* 376 * Must wait until any outstanding callback on the old clp 377 * completes. 378 */ 379 while (clp->lc_cbref) { 380 clp->lc_flags |= LCL_WAKEUPWANTED; 381 (void) tsleep((caddr_t)clp, PZERO - 1, "nfsd clp", 10 * hz); 382 } 383 nfsrv_zapclient(clp, p); 384 *new_clpp = NULL; 385 return (0); 386 } 387 388 /* 389 * Check to see if the client id exists and optionally confirm it. 390 */ 391 APPLESTATIC int 392 nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp, 393 nfsquad_t confirm, struct nfsrv_descript *nd, NFSPROC_T *p) 394 { 395 struct nfsclient *clp; 396 struct nfsstate *stp; 397 int i; 398 struct nfsclienthashhead *hp; 399 int error = 0, igotlock, doneok; 400 401 if (clpp) 402 *clpp = NULL; 403 if (nfsrvboottime != clientid.lval[0]) 404 return (NFSERR_STALECLIENTID); 405 406 /* 407 * If called with opflags == CLOPS_RENEW, the State Lock is 408 * already held. Otherwise, we need to get either that or, 409 * for the case of Confirm, lock out the nfsd threads. 410 */ 411 if (opflags & CLOPS_CONFIRM) { 412 NFSLOCKV4ROOTMUTEX(); 413 nfsv4_relref(&nfsv4rootfs_lock); 414 do { 415 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 416 NFSV4ROOTLOCKMUTEXPTR); 417 } while (!igotlock); 418 NFSUNLOCKV4ROOTMUTEX(); 419 NFSLOCKSTATE(); /* to avoid a race with */ 420 NFSUNLOCKSTATE(); /* nfsrv_servertimer() */ 421 } else if (opflags != CLOPS_RENEW) { 422 NFSLOCKSTATE(); 423 } 424 425 hp = NFSCLIENTHASH(clientid); 426 LIST_FOREACH(clp, hp, lc_hash) { 427 if (clp->lc_clientid.lval[1] == clientid.lval[1]) 428 break; 429 } 430 if (clp == LIST_END(hp)) { 431 if (opflags & CLOPS_CONFIRM) 432 error = NFSERR_STALECLIENTID; 433 else 434 error = NFSERR_EXPIRED; 435 } else if (clp->lc_flags & LCL_ADMINREVOKED) { 436 /* 437 * If marked admin revoked, just return the error. 438 */ 439 error = NFSERR_ADMINREVOKED; 440 } 441 if (error) { 442 if (opflags & CLOPS_CONFIRM) { 443 NFSLOCKV4ROOTMUTEX(); 444 nfsv4_unlock(&nfsv4rootfs_lock, 1); 445 NFSUNLOCKV4ROOTMUTEX(); 446 } else if (opflags != CLOPS_RENEW) { 447 NFSUNLOCKSTATE(); 448 } 449 return (error); 450 } 451 452 /* 453 * Perform any operations specified by the opflags. 454 */ 455 if (opflags & CLOPS_CONFIRM) { 456 if (clp->lc_confirm.qval != confirm.qval) 457 error = NFSERR_STALECLIENTID; 458 else if (nfsrv_notsamecredname(nd, clp)) 459 error = NFSERR_CLIDINUSE; 460 461 if (!error) { 462 if ((clp->lc_flags & (LCL_NEEDSCONFIRM | LCL_DONTCLEAN)) == 463 LCL_NEEDSCONFIRM) { 464 /* 465 * Hang onto the delegations (as old delegations) 466 * for an Open with CLAIM_DELEGATE_PREV unless in 467 * grace, but get rid of the rest of the state. 468 */ 469 nfsrv_cleanclient(clp, p); 470 nfsrv_freedeleglist(&clp->lc_olddeleg); 471 if (nfsrv_checkgrace(0)) { 472 /* In grace, so just delete delegations */ 473 nfsrv_freedeleglist(&clp->lc_deleg); 474 } else { 475 LIST_FOREACH(stp, &clp->lc_deleg, ls_list) 476 stp->ls_flags |= NFSLCK_OLDDELEG; 477 clp->lc_delegtime = NFSD_MONOSEC + 478 nfsrv_lease + NFSRV_LEASEDELTA; 479 LIST_NEWHEAD(&clp->lc_olddeleg, &clp->lc_deleg, 480 ls_list); 481 } 482 } 483 clp->lc_flags &= ~(LCL_NEEDSCONFIRM | LCL_DONTCLEAN); 484 if (clp->lc_program) 485 clp->lc_flags |= LCL_NEEDSCBNULL; 486 } 487 } else if (clp->lc_flags & LCL_NEEDSCONFIRM) { 488 error = NFSERR_EXPIRED; 489 } 490 491 /* 492 * If called by the Renew Op, we must check the principal. 493 */ 494 if (!error && (opflags & CLOPS_RENEWOP)) { 495 if (nfsrv_notsamecredname(nd, clp)) { 496 doneok = 0; 497 for (i = 0; i < NFSSTATEHASHSIZE && doneok == 0; i++) { 498 LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) { 499 if ((stp->ls_flags & NFSLCK_OPEN) && 500 stp->ls_uid == nd->nd_cred->cr_uid) { 501 doneok = 1; 502 break; 503 } 504 } 505 } 506 if (!doneok) 507 error = NFSERR_ACCES; 508 } 509 if (!error && (clp->lc_flags & LCL_CBDOWN)) 510 error = NFSERR_CBPATHDOWN; 511 } 512 if ((!error || error == NFSERR_CBPATHDOWN) && 513 (opflags & CLOPS_RENEW)) { 514 clp->lc_expiry = nfsrv_leaseexpiry(); 515 } 516 if (opflags & CLOPS_CONFIRM) { 517 NFSLOCKV4ROOTMUTEX(); 518 nfsv4_unlock(&nfsv4rootfs_lock, 1); 519 NFSUNLOCKV4ROOTMUTEX(); 520 } else if (opflags != CLOPS_RENEW) { 521 NFSUNLOCKSTATE(); 522 } 523 if (clpp) 524 *clpp = clp; 525 return (error); 526 } 527 528 /* 529 * Called from the new nfssvc syscall to admin revoke a clientid. 530 * Returns 0 for success, error otherwise. 531 */ 532 APPLESTATIC int 533 nfsrv_adminrevoke(struct nfsd_clid *revokep, NFSPROC_T *p) 534 { 535 struct nfsclient *clp = NULL; 536 int i; 537 int gotit, igotlock; 538 539 /* 540 * First, lock out the nfsd so that state won't change while the 541 * revocation record is being written to the stable storage restart 542 * file. 543 */ 544 NFSLOCKV4ROOTMUTEX(); 545 do { 546 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 547 NFSV4ROOTLOCKMUTEXPTR); 548 } while (!igotlock); 549 NFSUNLOCKV4ROOTMUTEX(); 550 NFSLOCKSTATE(); /* to avoid a race with */ 551 NFSUNLOCKSTATE(); /* nfsrv_servertimer() */ 552 553 /* 554 * Search for a match in the client list. 555 */ 556 gotit = i = 0; 557 while (i < NFSCLIENTHASHSIZE && !gotit) { 558 LIST_FOREACH(clp, &nfsclienthash[i], lc_hash) { 559 if (revokep->nclid_idlen == clp->lc_idlen && 560 !NFSBCMP(revokep->nclid_id, clp->lc_id, clp->lc_idlen)) { 561 gotit = 1; 562 break; 563 } 564 } 565 i++; 566 } 567 if (!gotit) { 568 NFSLOCKV4ROOTMUTEX(); 569 nfsv4_unlock(&nfsv4rootfs_lock, 0); 570 NFSUNLOCKV4ROOTMUTEX(); 571 return (EPERM); 572 } 573 574 /* 575 * Now, write out the revocation record 576 */ 577 nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p); 578 579 /* 580 * and clear out the state, marking the clientid revoked. 581 */ 582 clp->lc_flags &= ~LCL_CALLBACKSON; 583 clp->lc_flags |= LCL_ADMINREVOKED; 584 nfsrv_cleanclient(clp, p); 585 nfsrv_freedeleglist(&clp->lc_deleg); 586 nfsrv_freedeleglist(&clp->lc_olddeleg); 587 NFSLOCKV4ROOTMUTEX(); 588 nfsv4_unlock(&nfsv4rootfs_lock, 0); 589 NFSUNLOCKV4ROOTMUTEX(); 590 return (0); 591 } 592 593 /* 594 * Dump out stats for all clients. Called from nfssvc(2), that is used 595 * newnfsstats. 596 */ 597 APPLESTATIC void 598 nfsrv_dumpclients(struct nfsd_dumpclients *dumpp, int maxcnt) 599 { 600 struct nfsclient *clp; 601 int i = 0, cnt = 0; 602 603 /* 604 * First, get a reference on the nfsv4rootfs_lock so that an 605 * exclusive lock cannot be acquired while dumping the clients. 606 */ 607 NFSLOCKV4ROOTMUTEX(); 608 nfsv4_getref(&nfsv4rootfs_lock, NULL, NFSV4ROOTLOCKMUTEXPTR); 609 NFSUNLOCKV4ROOTMUTEX(); 610 NFSLOCKSTATE(); 611 /* 612 * Rattle through the client lists until done. 613 */ 614 while (i < NFSCLIENTHASHSIZE && cnt < maxcnt) { 615 clp = LIST_FIRST(&nfsclienthash[i]); 616 while (clp != LIST_END(&nfsclienthash[i]) && cnt < maxcnt) { 617 nfsrv_dumpaclient(clp, &dumpp[cnt]); 618 cnt++; 619 clp = LIST_NEXT(clp, lc_hash); 620 } 621 i++; 622 } 623 if (cnt < maxcnt) 624 dumpp[cnt].ndcl_clid.nclid_idlen = 0; 625 NFSUNLOCKSTATE(); 626 NFSLOCKV4ROOTMUTEX(); 627 nfsv4_relref(&nfsv4rootfs_lock); 628 NFSUNLOCKV4ROOTMUTEX(); 629 } 630 631 /* 632 * Dump stats for a client. Must be called with the NFSSTATELOCK and spl'd. 633 */ 634 static void 635 nfsrv_dumpaclient(struct nfsclient *clp, struct nfsd_dumpclients *dumpp) 636 { 637 struct nfsstate *stp, *openstp, *lckownstp; 638 struct nfslock *lop; 639 struct sockaddr *sad; 640 struct sockaddr_in *rad; 641 struct sockaddr_in6 *rad6; 642 643 dumpp->ndcl_nopenowners = dumpp->ndcl_nlockowners = 0; 644 dumpp->ndcl_nopens = dumpp->ndcl_nlocks = 0; 645 dumpp->ndcl_ndelegs = dumpp->ndcl_nolddelegs = 0; 646 dumpp->ndcl_flags = clp->lc_flags; 647 dumpp->ndcl_clid.nclid_idlen = clp->lc_idlen; 648 NFSBCOPY(clp->lc_id, dumpp->ndcl_clid.nclid_id, clp->lc_idlen); 649 sad = NFSSOCKADDR(clp->lc_req.nr_nam, struct sockaddr *); 650 dumpp->ndcl_addrfam = sad->sa_family; 651 if (sad->sa_family == AF_INET) { 652 rad = (struct sockaddr_in *)sad; 653 dumpp->ndcl_cbaddr.sin_addr = rad->sin_addr; 654 } else { 655 rad6 = (struct sockaddr_in6 *)sad; 656 dumpp->ndcl_cbaddr.sin6_addr = rad6->sin6_addr; 657 } 658 659 /* 660 * Now, scan the state lists and total up the opens and locks. 661 */ 662 LIST_FOREACH(stp, &clp->lc_open, ls_list) { 663 dumpp->ndcl_nopenowners++; 664 LIST_FOREACH(openstp, &stp->ls_open, ls_list) { 665 dumpp->ndcl_nopens++; 666 LIST_FOREACH(lckownstp, &openstp->ls_open, ls_list) { 667 dumpp->ndcl_nlockowners++; 668 LIST_FOREACH(lop, &lckownstp->ls_lock, lo_lckowner) { 669 dumpp->ndcl_nlocks++; 670 } 671 } 672 } 673 } 674 675 /* 676 * and the delegation lists. 677 */ 678 LIST_FOREACH(stp, &clp->lc_deleg, ls_list) { 679 dumpp->ndcl_ndelegs++; 680 } 681 LIST_FOREACH(stp, &clp->lc_olddeleg, ls_list) { 682 dumpp->ndcl_nolddelegs++; 683 } 684 } 685 686 /* 687 * Dump out lock stats for a file. 688 */ 689 APPLESTATIC void 690 nfsrv_dumplocks(vnode_t vp, struct nfsd_dumplocks *ldumpp, int maxcnt, 691 NFSPROC_T *p) 692 { 693 struct nfsstate *stp; 694 struct nfslock *lop; 695 int cnt = 0; 696 struct nfslockfile *lfp; 697 struct sockaddr *sad; 698 struct sockaddr_in *rad; 699 struct sockaddr_in6 *rad6; 700 int ret; 701 fhandle_t nfh; 702 703 ret = nfsrv_getlockfh(vp, 0, NULL, &nfh, p); 704 /* 705 * First, get a reference on the nfsv4rootfs_lock so that an 706 * exclusive lock on it cannot be acquired while dumping the locks. 707 */ 708 NFSLOCKV4ROOTMUTEX(); 709 nfsv4_getref(&nfsv4rootfs_lock, NULL, NFSV4ROOTLOCKMUTEXPTR); 710 NFSUNLOCKV4ROOTMUTEX(); 711 NFSLOCKSTATE(); 712 if (!ret) 713 ret = nfsrv_getlockfile(0, NULL, &lfp, &nfh, 0); 714 if (ret) { 715 ldumpp[0].ndlck_clid.nclid_idlen = 0; 716 NFSUNLOCKSTATE(); 717 NFSLOCKV4ROOTMUTEX(); 718 nfsv4_relref(&nfsv4rootfs_lock); 719 NFSUNLOCKV4ROOTMUTEX(); 720 return; 721 } 722 723 /* 724 * For each open share on file, dump it out. 725 */ 726 stp = LIST_FIRST(&lfp->lf_open); 727 while (stp != LIST_END(&lfp->lf_open) && cnt < maxcnt) { 728 ldumpp[cnt].ndlck_flags = stp->ls_flags; 729 ldumpp[cnt].ndlck_stateid.seqid = stp->ls_stateid.seqid; 730 ldumpp[cnt].ndlck_stateid.other[0] = stp->ls_stateid.other[0]; 731 ldumpp[cnt].ndlck_stateid.other[1] = stp->ls_stateid.other[1]; 732 ldumpp[cnt].ndlck_stateid.other[2] = stp->ls_stateid.other[2]; 733 ldumpp[cnt].ndlck_owner.nclid_idlen = 734 stp->ls_openowner->ls_ownerlen; 735 NFSBCOPY(stp->ls_openowner->ls_owner, 736 ldumpp[cnt].ndlck_owner.nclid_id, 737 stp->ls_openowner->ls_ownerlen); 738 ldumpp[cnt].ndlck_clid.nclid_idlen = stp->ls_clp->lc_idlen; 739 NFSBCOPY(stp->ls_clp->lc_id, ldumpp[cnt].ndlck_clid.nclid_id, 740 stp->ls_clp->lc_idlen); 741 sad=NFSSOCKADDR(stp->ls_clp->lc_req.nr_nam, struct sockaddr *); 742 ldumpp[cnt].ndlck_addrfam = sad->sa_family; 743 if (sad->sa_family == AF_INET) { 744 rad = (struct sockaddr_in *)sad; 745 ldumpp[cnt].ndlck_cbaddr.sin_addr = rad->sin_addr; 746 } else { 747 rad6 = (struct sockaddr_in6 *)sad; 748 ldumpp[cnt].ndlck_cbaddr.sin6_addr = rad6->sin6_addr; 749 } 750 stp = LIST_NEXT(stp, ls_file); 751 cnt++; 752 } 753 754 /* 755 * and all locks. 756 */ 757 lop = LIST_FIRST(&lfp->lf_lock); 758 while (lop != LIST_END(&lfp->lf_lock) && cnt < maxcnt) { 759 stp = lop->lo_stp; 760 ldumpp[cnt].ndlck_flags = lop->lo_flags; 761 ldumpp[cnt].ndlck_first = lop->lo_first; 762 ldumpp[cnt].ndlck_end = lop->lo_end; 763 ldumpp[cnt].ndlck_stateid.seqid = stp->ls_stateid.seqid; 764 ldumpp[cnt].ndlck_stateid.other[0] = stp->ls_stateid.other[0]; 765 ldumpp[cnt].ndlck_stateid.other[1] = stp->ls_stateid.other[1]; 766 ldumpp[cnt].ndlck_stateid.other[2] = stp->ls_stateid.other[2]; 767 ldumpp[cnt].ndlck_owner.nclid_idlen = stp->ls_ownerlen; 768 NFSBCOPY(stp->ls_owner, ldumpp[cnt].ndlck_owner.nclid_id, 769 stp->ls_ownerlen); 770 ldumpp[cnt].ndlck_clid.nclid_idlen = stp->ls_clp->lc_idlen; 771 NFSBCOPY(stp->ls_clp->lc_id, ldumpp[cnt].ndlck_clid.nclid_id, 772 stp->ls_clp->lc_idlen); 773 sad=NFSSOCKADDR(stp->ls_clp->lc_req.nr_nam, struct sockaddr *); 774 ldumpp[cnt].ndlck_addrfam = sad->sa_family; 775 if (sad->sa_family == AF_INET) { 776 rad = (struct sockaddr_in *)sad; 777 ldumpp[cnt].ndlck_cbaddr.sin_addr = rad->sin_addr; 778 } else { 779 rad6 = (struct sockaddr_in6 *)sad; 780 ldumpp[cnt].ndlck_cbaddr.sin6_addr = rad6->sin6_addr; 781 } 782 lop = LIST_NEXT(lop, lo_lckfile); 783 cnt++; 784 } 785 786 /* 787 * and the delegations. 788 */ 789 stp = LIST_FIRST(&lfp->lf_deleg); 790 while (stp != LIST_END(&lfp->lf_deleg) && cnt < maxcnt) { 791 ldumpp[cnt].ndlck_flags = stp->ls_flags; 792 ldumpp[cnt].ndlck_stateid.seqid = stp->ls_stateid.seqid; 793 ldumpp[cnt].ndlck_stateid.other[0] = stp->ls_stateid.other[0]; 794 ldumpp[cnt].ndlck_stateid.other[1] = stp->ls_stateid.other[1]; 795 ldumpp[cnt].ndlck_stateid.other[2] = stp->ls_stateid.other[2]; 796 ldumpp[cnt].ndlck_owner.nclid_idlen = 0; 797 ldumpp[cnt].ndlck_clid.nclid_idlen = stp->ls_clp->lc_idlen; 798 NFSBCOPY(stp->ls_clp->lc_id, ldumpp[cnt].ndlck_clid.nclid_id, 799 stp->ls_clp->lc_idlen); 800 sad=NFSSOCKADDR(stp->ls_clp->lc_req.nr_nam, struct sockaddr *); 801 ldumpp[cnt].ndlck_addrfam = sad->sa_family; 802 if (sad->sa_family == AF_INET) { 803 rad = (struct sockaddr_in *)sad; 804 ldumpp[cnt].ndlck_cbaddr.sin_addr = rad->sin_addr; 805 } else { 806 rad6 = (struct sockaddr_in6 *)sad; 807 ldumpp[cnt].ndlck_cbaddr.sin6_addr = rad6->sin6_addr; 808 } 809 stp = LIST_NEXT(stp, ls_file); 810 cnt++; 811 } 812 813 /* 814 * If list isn't full, mark end of list by setting the client name 815 * to zero length. 816 */ 817 if (cnt < maxcnt) 818 ldumpp[cnt].ndlck_clid.nclid_idlen = 0; 819 NFSUNLOCKSTATE(); 820 NFSLOCKV4ROOTMUTEX(); 821 nfsv4_relref(&nfsv4rootfs_lock); 822 NFSUNLOCKV4ROOTMUTEX(); 823 } 824 825 /* 826 * Server timer routine. It can scan any linked list, so long 827 * as it holds the spin lock and there is no exclusive lock on 828 * nfsv4rootfs_lock. 829 * Must be called by a kernel thread and not a timer interrupt, 830 * so that it only runs when the nfsd threads are sleeping on a 831 * uniprocessor and uses the State spin lock for an SMP system. 832 * (For OpenBSD, a kthread is ok. For FreeBSD, I think it is ok 833 * to do this from a callout, since the spin locks work. For 834 * Darwin, I'm not sure what will work correctly yet.) 835 * Should be called once per second. 836 */ 837 APPLESTATIC void 838 nfsrv_servertimer(void) 839 { 840 struct nfsclient *clp, *nclp; 841 struct nfsstate *stp, *nstp; 842 int i; 843 844 /* 845 * Make sure nfsboottime is set. This is used by V3 as well 846 * as V4. Note that nfsboottime is not nfsrvboottime, which is 847 * only used by the V4 server for leases. 848 */ 849 if (nfsboottime.tv_sec == 0) 850 NFSSETBOOTTIME(nfsboottime); 851 852 /* 853 * If server hasn't started yet, just return. 854 */ 855 NFSLOCKSTATE(); 856 if (nfsrv_stablefirst.nsf_eograce == 0) { 857 NFSUNLOCKSTATE(); 858 return; 859 } 860 if (!(nfsrv_stablefirst.nsf_flags & NFSNSF_UPDATEDONE)) { 861 if (!(nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) && 862 NFSD_MONOSEC > nfsrv_stablefirst.nsf_eograce) 863 nfsrv_stablefirst.nsf_flags |= 864 (NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK); 865 NFSUNLOCKSTATE(); 866 return; 867 } 868 869 /* 870 * Return now if an nfsd thread has the exclusive lock on 871 * nfsv4rootfs_lock. The dirty trick here is that we have 872 * the spin lock already and the nfsd threads do a: 873 * NFSLOCKSTATE, NFSUNLOCKSTATE after getting the exclusive 874 * lock, so they won't race with code after this check. 875 */ 876 if (nfsv4rootfs_lock.nfslock_lock & NFSV4LOCK_LOCK) { 877 NFSUNLOCKSTATE(); 878 return; 879 } 880 881 /* 882 * For each client... 883 */ 884 for (i = 0; i < NFSCLIENTHASHSIZE; i++) { 885 clp = LIST_FIRST(&nfsclienthash[i]); 886 while (clp != LIST_END(&nfsclienthash[i])) { 887 nclp = LIST_NEXT(clp, lc_hash); 888 if (!(clp->lc_flags & LCL_EXPIREIT)) { 889 if (((clp->lc_expiry + NFSRV_STALELEASE) < NFSD_MONOSEC 890 && ((LIST_EMPTY(&clp->lc_deleg) 891 && LIST_EMPTY(&clp->lc_open)) || 892 nfsrv_clients > nfsrv_clienthighwater)) || 893 (clp->lc_expiry + NFSRV_MOULDYLEASE) < NFSD_MONOSEC || 894 (clp->lc_expiry < NFSD_MONOSEC && 895 (nfsrv_openpluslock * 10 / 9) > NFSRV_V4STATELIMIT)) { 896 /* 897 * Lease has expired several nfsrv_lease times ago: 898 * PLUS 899 * - no state is associated with it 900 * OR 901 * - above high water mark for number of clients 902 * (nfsrv_clienthighwater should be large enough 903 * that this only occurs when clients fail to 904 * use the same nfs_client_id4.id. Maybe somewhat 905 * higher that the maximum number of clients that 906 * will mount this server?) 907 * OR 908 * Lease has expired a very long time ago 909 * OR 910 * Lease has expired PLUS the number of opens + locks 911 * has exceeded 90% of capacity 912 * 913 * --> Mark for expiry. The actual expiry will be done 914 * by an nfsd sometime soon. 915 */ 916 clp->lc_flags |= LCL_EXPIREIT; 917 nfsrv_stablefirst.nsf_flags |= 918 (NFSNSF_NEEDLOCK | NFSNSF_EXPIREDCLIENT); 919 } else { 920 /* 921 * If there are no opens, increment no open tick cnt 922 * If time exceeds NFSNOOPEN, mark it to be thrown away 923 * otherwise, if there is an open, reset no open time 924 * Hopefully, this will avoid excessive re-creation 925 * of open owners and subsequent open confirms. 926 */ 927 stp = LIST_FIRST(&clp->lc_open); 928 while (stp != LIST_END(&clp->lc_open)) { 929 nstp = LIST_NEXT(stp, ls_list); 930 if (LIST_EMPTY(&stp->ls_open)) { 931 stp->ls_noopens++; 932 if (stp->ls_noopens > NFSNOOPEN || 933 (nfsrv_openpluslock * 2) > 934 NFSRV_V4STATELIMIT) 935 nfsrv_stablefirst.nsf_flags |= 936 NFSNSF_NOOPENS; 937 } else { 938 stp->ls_noopens = 0; 939 } 940 stp = nstp; 941 } 942 } 943 } 944 clp = nclp; 945 } 946 } 947 NFSUNLOCKSTATE(); 948 } 949 950 /* 951 * The following set of functions free up the various data structures. 952 */ 953 /* 954 * Clear out all open/lock state related to this nfsclient. 955 * Caller must hold an exclusive lock on nfsv4rootfs_lock, so that 956 * there are no other active nfsd threads. 957 */ 958 APPLESTATIC void 959 nfsrv_cleanclient(struct nfsclient *clp, NFSPROC_T *p) 960 { 961 struct nfsstate *stp, *nstp; 962 963 LIST_FOREACH_SAFE(stp, &clp->lc_open, ls_list, nstp) 964 nfsrv_freeopenowner(stp, 1, p); 965 } 966 967 /* 968 * Free a client that has been cleaned. It should also already have been 969 * removed from the lists. 970 * (Just to be safe w.r.t. newnfs_disconnect(), call this function when 971 * softclock interrupts are enabled.) 972 */ 973 APPLESTATIC void 974 nfsrv_zapclient(struct nfsclient *clp, NFSPROC_T *p) 975 { 976 977 #ifdef notyet 978 if ((clp->lc_flags & (LCL_GSS | LCL_CALLBACKSON)) == 979 (LCL_GSS | LCL_CALLBACKSON) && 980 (clp->lc_hand.nfsh_flag & NFSG_COMPLETE) && 981 clp->lc_handlelen > 0) { 982 clp->lc_hand.nfsh_flag &= ~NFSG_COMPLETE; 983 clp->lc_hand.nfsh_flag |= NFSG_DESTROYED; 984 (void) nfsrv_docallback(clp, NFSV4PROC_CBNULL, 985 NULL, 0, NULL, NULL, NULL, p); 986 } 987 #endif 988 newnfs_disconnect(&clp->lc_req); 989 NFSSOCKADDRFREE(clp->lc_req.nr_nam); 990 NFSFREEMUTEX(&clp->lc_req.nr_mtx); 991 free((caddr_t)clp, M_NFSDCLIENT); 992 NFSLOCKSTATE(); 993 newnfsstats.srvclients--; 994 nfsrv_openpluslock--; 995 nfsrv_clients--; 996 NFSUNLOCKSTATE(); 997 } 998 999 /* 1000 * Free a list of delegation state structures. 1001 * (This function will also free all nfslockfile structures that no 1002 * longer have associated state.) 1003 */ 1004 APPLESTATIC void 1005 nfsrv_freedeleglist(struct nfsstatehead *sthp) 1006 { 1007 struct nfsstate *stp, *nstp; 1008 1009 LIST_FOREACH_SAFE(stp, sthp, ls_list, nstp) { 1010 nfsrv_freedeleg(stp); 1011 } 1012 LIST_INIT(sthp); 1013 } 1014 1015 /* 1016 * Free up a delegation. 1017 */ 1018 static void 1019 nfsrv_freedeleg(struct nfsstate *stp) 1020 { 1021 struct nfslockfile *lfp; 1022 1023 LIST_REMOVE(stp, ls_hash); 1024 LIST_REMOVE(stp, ls_list); 1025 LIST_REMOVE(stp, ls_file); 1026 lfp = stp->ls_lfp; 1027 if (LIST_EMPTY(&lfp->lf_open) && 1028 LIST_EMPTY(&lfp->lf_lock) && LIST_EMPTY(&lfp->lf_deleg) && 1029 LIST_EMPTY(&lfp->lf_locallock) && LIST_EMPTY(&lfp->lf_rollback) && 1030 lfp->lf_usecount == 0 && 1031 nfsv4_testlock(&lfp->lf_locallock_lck) == 0) 1032 nfsrv_freenfslockfile(lfp); 1033 FREE((caddr_t)stp, M_NFSDSTATE); 1034 newnfsstats.srvdelegates--; 1035 nfsrv_openpluslock--; 1036 nfsrv_delegatecnt--; 1037 } 1038 1039 /* 1040 * This function frees an open owner and all associated opens. 1041 */ 1042 static void 1043 nfsrv_freeopenowner(struct nfsstate *stp, int cansleep, NFSPROC_T *p) 1044 { 1045 struct nfsstate *nstp, *tstp; 1046 1047 LIST_REMOVE(stp, ls_list); 1048 /* 1049 * Now, free all associated opens. 1050 */ 1051 nstp = LIST_FIRST(&stp->ls_open); 1052 while (nstp != LIST_END(&stp->ls_open)) { 1053 tstp = nstp; 1054 nstp = LIST_NEXT(nstp, ls_list); 1055 (void) nfsrv_freeopen(tstp, NULL, cansleep, p); 1056 } 1057 if (stp->ls_op) 1058 nfsrvd_derefcache(stp->ls_op); 1059 FREE((caddr_t)stp, M_NFSDSTATE); 1060 newnfsstats.srvopenowners--; 1061 nfsrv_openpluslock--; 1062 } 1063 1064 /* 1065 * This function frees an open (nfsstate open structure) with all associated 1066 * lock_owners and locks. It also frees the nfslockfile structure iff there 1067 * are no other opens on the file. 1068 * Returns 1 if it free'd the nfslockfile, 0 otherwise. 1069 */ 1070 static int 1071 nfsrv_freeopen(struct nfsstate *stp, vnode_t vp, int cansleep, NFSPROC_T *p) 1072 { 1073 struct nfsstate *nstp, *tstp; 1074 struct nfslockfile *lfp; 1075 int ret; 1076 1077 LIST_REMOVE(stp, ls_hash); 1078 LIST_REMOVE(stp, ls_list); 1079 LIST_REMOVE(stp, ls_file); 1080 1081 lfp = stp->ls_lfp; 1082 /* 1083 * Now, free all lockowners associated with this open. 1084 */ 1085 LIST_FOREACH_SAFE(tstp, &stp->ls_open, ls_list, nstp) 1086 nfsrv_freelockowner(tstp, vp, cansleep, p); 1087 1088 /* 1089 * The nfslockfile is freed here if there are no locks 1090 * associated with the open. 1091 * If there are locks associated with the open, the 1092 * nfslockfile structure can be freed via nfsrv_freelockowner(). 1093 * (That is why the call must be here instead of after the loop.) 1094 */ 1095 if (lfp != NULL && LIST_EMPTY(&lfp->lf_open) && 1096 LIST_EMPTY(&lfp->lf_deleg) && LIST_EMPTY(&lfp->lf_lock) && 1097 LIST_EMPTY(&lfp->lf_locallock) && LIST_EMPTY(&lfp->lf_rollback) && 1098 lfp->lf_usecount == 0 && 1099 (cansleep != 0 || nfsv4_testlock(&lfp->lf_locallock_lck) == 0)) { 1100 nfsrv_freenfslockfile(lfp); 1101 ret = 1; 1102 } else 1103 ret = 0; 1104 FREE((caddr_t)stp, M_NFSDSTATE); 1105 newnfsstats.srvopens--; 1106 nfsrv_openpluslock--; 1107 return (ret); 1108 } 1109 1110 /* 1111 * Frees a lockowner and all associated locks. 1112 */ 1113 static void 1114 nfsrv_freelockowner(struct nfsstate *stp, vnode_t vp, int cansleep, 1115 NFSPROC_T *p) 1116 { 1117 1118 LIST_REMOVE(stp, ls_hash); 1119 LIST_REMOVE(stp, ls_list); 1120 nfsrv_freeallnfslocks(stp, vp, cansleep, p); 1121 if (stp->ls_op) 1122 nfsrvd_derefcache(stp->ls_op); 1123 FREE((caddr_t)stp, M_NFSDSTATE); 1124 newnfsstats.srvlockowners--; 1125 nfsrv_openpluslock--; 1126 } 1127 1128 /* 1129 * Free all the nfs locks on a lockowner. 1130 */ 1131 static void 1132 nfsrv_freeallnfslocks(struct nfsstate *stp, vnode_t vp, int cansleep, 1133 NFSPROC_T *p) 1134 { 1135 struct nfslock *lop, *nlop; 1136 struct nfsrollback *rlp, *nrlp; 1137 struct nfslockfile *lfp = NULL; 1138 int gottvp = 0; 1139 vnode_t tvp = NULL; 1140 1141 lop = LIST_FIRST(&stp->ls_lock); 1142 while (lop != LIST_END(&stp->ls_lock)) { 1143 nlop = LIST_NEXT(lop, lo_lckowner); 1144 /* 1145 * Since all locks should be for the same file, lfp should 1146 * not change. 1147 */ 1148 if (lfp == NULL) 1149 lfp = lop->lo_lfp; 1150 else if (lfp != lop->lo_lfp) 1151 panic("allnfslocks"); 1152 /* 1153 * If vp is NULL and cansleep != 0, a vnode must be acquired 1154 * from the file handle. This only occurs when called from 1155 * nfsrv_cleanclient(). 1156 */ 1157 if (gottvp == 0) { 1158 if (nfsrv_dolocallocks == 0) 1159 tvp = NULL; 1160 else if (vp == NULL && cansleep != 0) 1161 tvp = nfsvno_getvp(&lfp->lf_fh); 1162 else 1163 tvp = vp; 1164 gottvp = 1; 1165 } 1166 1167 if (tvp != NULL) { 1168 if (cansleep == 0) 1169 panic("allnfs2"); 1170 nfsrv_localunlock(tvp, lfp, lop->lo_first, 1171 lop->lo_end, p); 1172 LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, 1173 nrlp) 1174 free(rlp, M_NFSDROLLBACK); 1175 LIST_INIT(&lfp->lf_rollback); 1176 } 1177 nfsrv_freenfslock(lop); 1178 lop = nlop; 1179 } 1180 if (vp == NULL && tvp != NULL) 1181 vput(tvp); 1182 } 1183 1184 /* 1185 * Free an nfslock structure. 1186 */ 1187 static void 1188 nfsrv_freenfslock(struct nfslock *lop) 1189 { 1190 1191 if (lop->lo_lckfile.le_prev != NULL) { 1192 LIST_REMOVE(lop, lo_lckfile); 1193 newnfsstats.srvlocks--; 1194 nfsrv_openpluslock--; 1195 } 1196 LIST_REMOVE(lop, lo_lckowner); 1197 FREE((caddr_t)lop, M_NFSDLOCK); 1198 } 1199 1200 /* 1201 * This function frees an nfslockfile structure. 1202 */ 1203 static void 1204 nfsrv_freenfslockfile(struct nfslockfile *lfp) 1205 { 1206 1207 LIST_REMOVE(lfp, lf_hash); 1208 FREE((caddr_t)lfp, M_NFSDLOCKFILE); 1209 } 1210 1211 /* 1212 * This function looks up an nfsstate structure via stateid. 1213 */ 1214 static int 1215 nfsrv_getstate(struct nfsclient *clp, nfsv4stateid_t *stateidp, __unused u_int32_t flags, 1216 struct nfsstate **stpp) 1217 { 1218 struct nfsstate *stp; 1219 struct nfsstatehead *hp; 1220 1221 *stpp = NULL; 1222 hp = NFSSTATEHASH(clp, *stateidp); 1223 LIST_FOREACH(stp, hp, ls_hash) { 1224 if (!NFSBCMP(stp->ls_stateid.other, stateidp->other, 1225 NFSX_STATEIDOTHER)) 1226 break; 1227 } 1228 1229 /* 1230 * If no state id in list, return NFSERR_BADSTATEID. 1231 */ 1232 if (stp == LIST_END(hp)) 1233 return (NFSERR_BADSTATEID); 1234 *stpp = stp; 1235 return (0); 1236 } 1237 1238 /* 1239 * This function gets an nfsstate structure via owner string. 1240 */ 1241 static void 1242 nfsrv_getowner(struct nfsstatehead *hp, struct nfsstate *new_stp, 1243 struct nfsstate **stpp) 1244 { 1245 struct nfsstate *stp; 1246 1247 *stpp = NULL; 1248 LIST_FOREACH(stp, hp, ls_list) { 1249 if (new_stp->ls_ownerlen == stp->ls_ownerlen && 1250 !NFSBCMP(new_stp->ls_owner,stp->ls_owner,stp->ls_ownerlen)) { 1251 *stpp = stp; 1252 return; 1253 } 1254 } 1255 } 1256 1257 /* 1258 * Lock control function called to update lock status. 1259 * Returns 0 upon success, -1 if there is no lock and the flags indicate 1260 * that one isn't to be created and an NFSERR_xxx for other errors. 1261 * The structures new_stp and new_lop are passed in as pointers that should 1262 * be set to NULL if the structure is used and shouldn't be free'd. 1263 * For the NFSLCK_TEST and NFSLCK_CHECK cases, the structures are 1264 * never used and can safely be allocated on the stack. For all other 1265 * cases, *new_stpp and *new_lopp should be malloc'd before the call, 1266 * in case they are used. 1267 */ 1268 APPLESTATIC int 1269 nfsrv_lockctrl(vnode_t vp, struct nfsstate **new_stpp, 1270 struct nfslock **new_lopp, struct nfslockconflict *cfp, 1271 nfsquad_t clientid, nfsv4stateid_t *stateidp, 1272 __unused struct nfsexstuff *exp, 1273 struct nfsrv_descript *nd, NFSPROC_T *p) 1274 { 1275 struct nfslock *lop; 1276 struct nfsstate *new_stp = *new_stpp; 1277 struct nfslock *new_lop = *new_lopp; 1278 struct nfsstate *tstp, *mystp, *nstp; 1279 int specialid = 0; 1280 struct nfslockfile *lfp; 1281 struct nfslock *other_lop = NULL; 1282 struct nfsstate *stp, *lckstp = NULL; 1283 struct nfsclient *clp = NULL; 1284 u_int32_t bits; 1285 int error = 0, haslock = 0, ret, reterr; 1286 int getlckret, delegation = 0, filestruct_locked; 1287 fhandle_t nfh; 1288 uint64_t first, end; 1289 uint32_t lock_flags; 1290 1291 if (new_stp->ls_flags & (NFSLCK_CHECK | NFSLCK_SETATTR)) { 1292 /* 1293 * Note the special cases of "all 1s" or "all 0s" stateids and 1294 * let reads with all 1s go ahead. 1295 */ 1296 if (new_stp->ls_stateid.seqid == 0x0 && 1297 new_stp->ls_stateid.other[0] == 0x0 && 1298 new_stp->ls_stateid.other[1] == 0x0 && 1299 new_stp->ls_stateid.other[2] == 0x0) 1300 specialid = 1; 1301 else if (new_stp->ls_stateid.seqid == 0xffffffff && 1302 new_stp->ls_stateid.other[0] == 0xffffffff && 1303 new_stp->ls_stateid.other[1] == 0xffffffff && 1304 new_stp->ls_stateid.other[2] == 0xffffffff) 1305 specialid = 2; 1306 } 1307 1308 /* 1309 * Check for restart conditions (client and server). 1310 */ 1311 error = nfsrv_checkrestart(clientid, new_stp->ls_flags, 1312 &new_stp->ls_stateid, specialid); 1313 if (error) 1314 return (error); 1315 1316 /* 1317 * Check for state resource limit exceeded. 1318 */ 1319 if ((new_stp->ls_flags & NFSLCK_LOCK) && 1320 nfsrv_openpluslock > NFSRV_V4STATELIMIT) 1321 return (NFSERR_RESOURCE); 1322 1323 /* 1324 * For the lock case, get another nfslock structure, 1325 * just in case we need it. 1326 * Malloc now, before we start sifting through the linked lists, 1327 * in case we have to wait for memory. 1328 */ 1329 tryagain: 1330 if (new_stp->ls_flags & NFSLCK_LOCK) 1331 MALLOC(other_lop, struct nfslock *, sizeof (struct nfslock), 1332 M_NFSDLOCK, M_WAITOK); 1333 filestruct_locked = 0; 1334 reterr = 0; 1335 lfp = NULL; 1336 1337 /* 1338 * Get the lockfile structure for CFH now, so we can do a sanity 1339 * check against the stateid, before incrementing the seqid#, since 1340 * we want to return NFSERR_BADSTATEID on failure and the seqid# 1341 * shouldn't be incremented for this case. 1342 * If nfsrv_getlockfile() returns -1, it means "not found", which 1343 * will be handled later. 1344 * If we are doing Lock/LockU and local locking is enabled, sleep 1345 * lock the nfslockfile structure. 1346 */ 1347 getlckret = nfsrv_getlockfh(vp, new_stp->ls_flags, NULL, &nfh, p); 1348 NFSLOCKSTATE(); 1349 if (getlckret == 0) { 1350 if ((new_stp->ls_flags & (NFSLCK_LOCK | NFSLCK_UNLOCK)) != 0 && 1351 nfsrv_dolocallocks != 0 && nd->nd_repstat == 0) { 1352 getlckret = nfsrv_getlockfile(new_stp->ls_flags, NULL, 1353 &lfp, &nfh, 1); 1354 if (getlckret == 0) 1355 filestruct_locked = 1; 1356 } else 1357 getlckret = nfsrv_getlockfile(new_stp->ls_flags, NULL, 1358 &lfp, &nfh, 0); 1359 } 1360 if (getlckret != 0 && getlckret != -1) 1361 reterr = getlckret; 1362 1363 if (filestruct_locked != 0) { 1364 LIST_INIT(&lfp->lf_rollback); 1365 if ((new_stp->ls_flags & NFSLCK_LOCK)) { 1366 /* 1367 * For local locking, do the advisory locking now, so 1368 * that any conflict can be detected. A failure later 1369 * can be rolled back locally. If an error is returned, 1370 * struct nfslockfile has been unlocked and any local 1371 * locking rolled back. 1372 */ 1373 NFSUNLOCKSTATE(); 1374 reterr = nfsrv_locallock(vp, lfp, 1375 (new_lop->lo_flags & (NFSLCK_READ | NFSLCK_WRITE)), 1376 new_lop->lo_first, new_lop->lo_end, cfp, p); 1377 NFSLOCKSTATE(); 1378 } 1379 } 1380 1381 if (specialid == 0) { 1382 if (new_stp->ls_flags & NFSLCK_TEST) { 1383 /* 1384 * RFC 3530 does not list LockT as an op that renews a 1385 * lease, but the concensus seems to be that it is ok 1386 * for a server to do so. 1387 */ 1388 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, 1389 (nfsquad_t)((u_quad_t)0), NULL, p); 1390 1391 /* 1392 * Since NFSERR_EXPIRED, NFSERR_ADMINREVOKED are not valid 1393 * error returns for LockT, just go ahead and test for a lock, 1394 * since there are no locks for this client, but other locks 1395 * can conflict. (ie. same client will always be false) 1396 */ 1397 if (error == NFSERR_EXPIRED || error == NFSERR_ADMINREVOKED) 1398 error = 0; 1399 lckstp = new_stp; 1400 } else { 1401 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, 1402 (nfsquad_t)((u_quad_t)0), NULL, p); 1403 if (error == 0) 1404 /* 1405 * Look up the stateid 1406 */ 1407 error = nfsrv_getstate(clp, &new_stp->ls_stateid, 1408 new_stp->ls_flags, &stp); 1409 /* 1410 * do some sanity checks for an unconfirmed open or a 1411 * stateid that refers to the wrong file, for an open stateid 1412 */ 1413 if (error == 0 && (stp->ls_flags & NFSLCK_OPEN) && 1414 ((stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM) || 1415 (getlckret == 0 && stp->ls_lfp != lfp))) 1416 error = NFSERR_BADSTATEID; 1417 if (error == 0 && 1418 (stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) && 1419 getlckret == 0 && stp->ls_lfp != lfp) 1420 error = NFSERR_BADSTATEID; 1421 1422 /* 1423 * If the lockowner stateid doesn't refer to the same file, 1424 * I believe that is considered ok, since some clients will 1425 * only create a single lockowner and use that for all locks 1426 * on all files. 1427 * For now, log it as a diagnostic, instead of considering it 1428 * a BadStateid. 1429 */ 1430 if (error == 0 && (stp->ls_flags & 1431 (NFSLCK_OPEN | NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) == 0 && 1432 getlckret == 0 && stp->ls_lfp != lfp) { 1433 #ifdef DIAGNOSTIC 1434 printf("Got a lock statid for different file open\n"); 1435 #endif 1436 /* 1437 error = NFSERR_BADSTATEID; 1438 */ 1439 } 1440 1441 if (error == 0) { 1442 if (new_stp->ls_flags & NFSLCK_OPENTOLOCK) { 1443 /* 1444 * If haslock set, we've already checked the seqid. 1445 */ 1446 if (!haslock) { 1447 if (stp->ls_flags & NFSLCK_OPEN) 1448 error = nfsrv_checkseqid(nd, new_stp->ls_seq, 1449 stp->ls_openowner, new_stp->ls_op); 1450 else 1451 error = NFSERR_BADSTATEID; 1452 } 1453 if (!error) 1454 nfsrv_getowner(&stp->ls_open, new_stp, &lckstp); 1455 if (lckstp) 1456 /* 1457 * I believe this should be an error, but it 1458 * isn't obvious what NFSERR_xxx would be 1459 * appropriate, so I'll use NFSERR_INVAL for now. 1460 */ 1461 error = NFSERR_INVAL; 1462 else 1463 lckstp = new_stp; 1464 } else if (new_stp->ls_flags&(NFSLCK_LOCK|NFSLCK_UNLOCK)) { 1465 /* 1466 * If haslock set, ditto above. 1467 */ 1468 if (!haslock) { 1469 if (stp->ls_flags & NFSLCK_OPEN) 1470 error = NFSERR_BADSTATEID; 1471 else 1472 error = nfsrv_checkseqid(nd, new_stp->ls_seq, 1473 stp, new_stp->ls_op); 1474 } 1475 lckstp = stp; 1476 } else { 1477 lckstp = stp; 1478 } 1479 } 1480 /* 1481 * If the seqid part of the stateid isn't the same, return 1482 * NFSERR_OLDSTATEID for cases other than I/O Ops. 1483 * For I/O Ops, only return NFSERR_OLDSTATEID if 1484 * nfsrv_returnoldstateid is set. (The concensus on the email 1485 * list was that most clients would prefer to not receive 1486 * NFSERR_OLDSTATEID for I/O Ops, but the RFC suggests that that 1487 * is what will happen, so I use the nfsrv_returnoldstateid to 1488 * allow for either server configuration.) 1489 */ 1490 if (!error && stp->ls_stateid.seqid!=new_stp->ls_stateid.seqid && 1491 (!(new_stp->ls_flags & NFSLCK_CHECK) || 1492 nfsrv_returnoldstateid)) 1493 error = NFSERR_OLDSTATEID; 1494 } 1495 } 1496 1497 /* 1498 * Now we can check for grace. 1499 */ 1500 if (!error) 1501 error = nfsrv_checkgrace(new_stp->ls_flags); 1502 if ((new_stp->ls_flags & NFSLCK_RECLAIM) && !error && 1503 nfsrv_checkstable(clp)) 1504 error = NFSERR_NOGRACE; 1505 /* 1506 * If we successfully Reclaimed state, note that. 1507 */ 1508 if ((new_stp->ls_flags & NFSLCK_RECLAIM) && !error) 1509 nfsrv_markstable(clp); 1510 1511 /* 1512 * At this point, either error == NFSERR_BADSTATEID or the 1513 * seqid# has been updated, so we can return any error. 1514 * If error == 0, there may be an error in: 1515 * nd_repstat - Set by the calling function. 1516 * reterr - Set above, if getting the nfslockfile structure 1517 * or acquiring the local lock failed. 1518 * (If both of these are set, nd_repstat should probably be 1519 * returned, since that error was detected before this 1520 * function call.) 1521 */ 1522 if (error != 0 || nd->nd_repstat != 0 || reterr != 0) { 1523 if (error == 0) { 1524 if (nd->nd_repstat != 0) 1525 error = nd->nd_repstat; 1526 else 1527 error = reterr; 1528 } 1529 if (filestruct_locked != 0) { 1530 /* Roll back local locks. */ 1531 NFSUNLOCKSTATE(); 1532 nfsrv_locallock_rollback(vp, lfp, p); 1533 NFSLOCKSTATE(); 1534 nfsrv_unlocklf(lfp); 1535 } 1536 NFSUNLOCKSTATE(); 1537 if (other_lop) 1538 FREE((caddr_t)other_lop, M_NFSDLOCK); 1539 if (haslock) { 1540 NFSLOCKV4ROOTMUTEX(); 1541 nfsv4_unlock(&nfsv4rootfs_lock, 1); 1542 NFSUNLOCKV4ROOTMUTEX(); 1543 } 1544 return (error); 1545 } 1546 1547 /* 1548 * Check the nfsrv_getlockfile return. 1549 * Returned -1 if no structure found. 1550 */ 1551 if (getlckret == -1) { 1552 error = NFSERR_EXPIRED; 1553 /* 1554 * Called from lockt, so no lock is OK. 1555 */ 1556 if (new_stp->ls_flags & NFSLCK_TEST) { 1557 error = 0; 1558 } else if (new_stp->ls_flags & 1559 (NFSLCK_CHECK | NFSLCK_SETATTR)) { 1560 /* 1561 * Called to check for a lock, OK if the stateid is all 1562 * 1s or all 0s, but there should be an nfsstate 1563 * otherwise. 1564 * (ie. If there is no open, I'll assume no share 1565 * deny bits.) 1566 */ 1567 if (specialid) 1568 error = 0; 1569 else 1570 error = NFSERR_BADSTATEID; 1571 } 1572 NFSUNLOCKSTATE(); 1573 if (haslock) { 1574 NFSLOCKV4ROOTMUTEX(); 1575 nfsv4_unlock(&nfsv4rootfs_lock, 1); 1576 NFSUNLOCKV4ROOTMUTEX(); 1577 } 1578 /* 1579 * Called to lock or unlock, so the lock has gone away. 1580 */ 1581 return (error); 1582 } 1583 1584 /* 1585 * For NFSLCK_CHECK and NFSLCK_LOCK, test for a share conflict. 1586 * For NFSLCK_CHECK, allow a read if write access is granted, 1587 * but check for a deny. For NFSLCK_LOCK, require correct access, 1588 * which implies a conflicting deny can't exist. 1589 */ 1590 if (new_stp->ls_flags & (NFSLCK_CHECK | NFSLCK_LOCK)) { 1591 /* 1592 * Four kinds of state id: 1593 * - specialid (all 0s or all 1s), only for NFSLCK_CHECK 1594 * - stateid for an open 1595 * - stateid for a delegation 1596 * - stateid for a lock owner 1597 */ 1598 if (!specialid) { 1599 if (stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) { 1600 delegation = 1; 1601 mystp = stp; 1602 nfsrv_delaydelegtimeout(stp); 1603 } else if (stp->ls_flags & NFSLCK_OPEN) { 1604 mystp = stp; 1605 } else { 1606 mystp = stp->ls_openstp; 1607 } 1608 /* 1609 * If locking or checking, require correct access 1610 * bit set. 1611 */ 1612 if (((new_stp->ls_flags & NFSLCK_LOCK) && 1613 !((new_lop->lo_flags >> NFSLCK_LOCKSHIFT) & 1614 mystp->ls_flags & NFSLCK_ACCESSBITS)) || 1615 ((new_stp->ls_flags & (NFSLCK_CHECK|NFSLCK_READACCESS)) == 1616 (NFSLCK_CHECK | NFSLCK_READACCESS) && 1617 !(mystp->ls_flags & NFSLCK_READACCESS)) || 1618 ((new_stp->ls_flags & (NFSLCK_CHECK|NFSLCK_WRITEACCESS)) == 1619 (NFSLCK_CHECK | NFSLCK_WRITEACCESS) && 1620 !(mystp->ls_flags & NFSLCK_WRITEACCESS))) { 1621 if (filestruct_locked != 0) { 1622 /* Roll back local locks. */ 1623 NFSUNLOCKSTATE(); 1624 nfsrv_locallock_rollback(vp, lfp, p); 1625 NFSLOCKSTATE(); 1626 nfsrv_unlocklf(lfp); 1627 } 1628 NFSUNLOCKSTATE(); 1629 if (other_lop) 1630 FREE((caddr_t)other_lop, M_NFSDLOCK); 1631 if (haslock) { 1632 NFSLOCKV4ROOTMUTEX(); 1633 nfsv4_unlock(&nfsv4rootfs_lock, 1); 1634 NFSUNLOCKV4ROOTMUTEX(); 1635 } 1636 return (NFSERR_OPENMODE); 1637 } 1638 } else 1639 mystp = NULL; 1640 if ((new_stp->ls_flags & NFSLCK_CHECK) && !delegation) { 1641 /* 1642 * Check for a conflicting deny bit. 1643 */ 1644 LIST_FOREACH(tstp, &lfp->lf_open, ls_file) { 1645 if (tstp != mystp) { 1646 bits = tstp->ls_flags; 1647 bits >>= NFSLCK_SHIFT; 1648 if (new_stp->ls_flags & bits & NFSLCK_ACCESSBITS) { 1649 ret = nfsrv_clientconflict(tstp->ls_clp, &haslock, 1650 vp, p); 1651 if (ret) { 1652 /* 1653 * nfsrv_clientconflict unlocks state 1654 * when it returns non-zero. 1655 */ 1656 lckstp = NULL; 1657 goto tryagain; 1658 } 1659 NFSUNLOCKSTATE(); 1660 if (haslock) { 1661 NFSLOCKV4ROOTMUTEX(); 1662 nfsv4_unlock(&nfsv4rootfs_lock, 1); 1663 NFSUNLOCKV4ROOTMUTEX(); 1664 } 1665 return (NFSERR_OPENMODE); 1666 } 1667 } 1668 } 1669 1670 /* We're outta here */ 1671 NFSUNLOCKSTATE(); 1672 if (haslock) { 1673 NFSLOCKV4ROOTMUTEX(); 1674 nfsv4_unlock(&nfsv4rootfs_lock, 1); 1675 NFSUNLOCKV4ROOTMUTEX(); 1676 } 1677 return (0); 1678 } 1679 } 1680 1681 /* 1682 * For setattr, just get rid of all the Delegations for other clients. 1683 */ 1684 if (new_stp->ls_flags & NFSLCK_SETATTR) { 1685 ret = nfsrv_cleandeleg(vp, lfp, clp, &haslock, p); 1686 if (ret) { 1687 /* 1688 * nfsrv_cleandeleg() unlocks state when it 1689 * returns non-zero. 1690 */ 1691 if (ret == -1) { 1692 lckstp = NULL; 1693 goto tryagain; 1694 } 1695 return (ret); 1696 } 1697 if (!(new_stp->ls_flags & NFSLCK_CHECK) || 1698 (LIST_EMPTY(&lfp->lf_open) && LIST_EMPTY(&lfp->lf_lock) && 1699 LIST_EMPTY(&lfp->lf_deleg))) { 1700 NFSUNLOCKSTATE(); 1701 if (haslock) { 1702 NFSLOCKV4ROOTMUTEX(); 1703 nfsv4_unlock(&nfsv4rootfs_lock, 1); 1704 NFSUNLOCKV4ROOTMUTEX(); 1705 } 1706 return (0); 1707 } 1708 } 1709 1710 /* 1711 * Check for a conflicting delegation. If one is found, call 1712 * nfsrv_delegconflict() to handle it. If the v4root lock hasn't 1713 * been set yet, it will get the lock. Otherwise, it will recall 1714 * the delegation. Then, we try try again... 1715 * I currently believe the conflict algorithm to be: 1716 * For Lock Ops (Lock/LockT/LockU) 1717 * - there is a conflict iff a different client has a write delegation 1718 * For Reading (Read Op) 1719 * - there is a conflict iff a different client has a write delegation 1720 * (the specialids are always a different client) 1721 * For Writing (Write/Setattr of size) 1722 * - there is a conflict if a different client has any delegation 1723 * - there is a conflict if the same client has a read delegation 1724 * (I don't understand why this isn't allowed, but that seems to be 1725 * the current concensus?) 1726 */ 1727 tstp = LIST_FIRST(&lfp->lf_deleg); 1728 while (tstp != LIST_END(&lfp->lf_deleg)) { 1729 nstp = LIST_NEXT(tstp, ls_file); 1730 if ((((new_stp->ls_flags&(NFSLCK_LOCK|NFSLCK_UNLOCK|NFSLCK_TEST))|| 1731 ((new_stp->ls_flags & NFSLCK_CHECK) && 1732 (new_lop->lo_flags & NFSLCK_READ))) && 1733 clp != tstp->ls_clp && 1734 (tstp->ls_flags & NFSLCK_DELEGWRITE)) || 1735 ((new_stp->ls_flags & NFSLCK_CHECK) && 1736 (new_lop->lo_flags & NFSLCK_WRITE) && 1737 (clp != tstp->ls_clp || 1738 (tstp->ls_flags & NFSLCK_DELEGREAD)))) { 1739 if (filestruct_locked != 0) { 1740 /* Roll back local locks. */ 1741 NFSUNLOCKSTATE(); 1742 nfsrv_locallock_rollback(vp, lfp, p); 1743 NFSLOCKSTATE(); 1744 nfsrv_unlocklf(lfp); 1745 } 1746 ret = nfsrv_delegconflict(tstp, &haslock, p, vp); 1747 if (ret) { 1748 /* 1749 * nfsrv_delegconflict unlocks state when it 1750 * returns non-zero, which it always does. 1751 */ 1752 if (other_lop) { 1753 FREE((caddr_t)other_lop, M_NFSDLOCK); 1754 other_lop = NULL; 1755 } 1756 if (ret == -1) { 1757 lckstp = NULL; 1758 goto tryagain; 1759 } 1760 return (ret); 1761 } 1762 /* Never gets here. */ 1763 } 1764 tstp = nstp; 1765 } 1766 1767 /* 1768 * Handle the unlock case by calling nfsrv_updatelock(). 1769 * (Should I have done some access checking above for unlock? For now, 1770 * just let it happen.) 1771 */ 1772 if (new_stp->ls_flags & NFSLCK_UNLOCK) { 1773 first = new_lop->lo_first; 1774 end = new_lop->lo_end; 1775 nfsrv_updatelock(stp, new_lopp, &other_lop, lfp); 1776 stateidp->seqid = ++(stp->ls_stateid.seqid); 1777 stateidp->other[0] = stp->ls_stateid.other[0]; 1778 stateidp->other[1] = stp->ls_stateid.other[1]; 1779 stateidp->other[2] = stp->ls_stateid.other[2]; 1780 if (filestruct_locked != 0) { 1781 NFSUNLOCKSTATE(); 1782 /* Update the local locks. */ 1783 nfsrv_localunlock(vp, lfp, first, end, p); 1784 NFSLOCKSTATE(); 1785 nfsrv_unlocklf(lfp); 1786 } 1787 NFSUNLOCKSTATE(); 1788 if (haslock) { 1789 NFSLOCKV4ROOTMUTEX(); 1790 nfsv4_unlock(&nfsv4rootfs_lock, 1); 1791 NFSUNLOCKV4ROOTMUTEX(); 1792 } 1793 return (0); 1794 } 1795 1796 /* 1797 * Search for a conflicting lock. A lock conflicts if: 1798 * - the lock range overlaps and 1799 * - at least one lock is a write lock and 1800 * - it is not owned by the same lock owner 1801 */ 1802 if (!delegation) { 1803 LIST_FOREACH(lop, &lfp->lf_lock, lo_lckfile) { 1804 if (new_lop->lo_end > lop->lo_first && 1805 new_lop->lo_first < lop->lo_end && 1806 (new_lop->lo_flags == NFSLCK_WRITE || 1807 lop->lo_flags == NFSLCK_WRITE) && 1808 lckstp != lop->lo_stp && 1809 (clp != lop->lo_stp->ls_clp || 1810 lckstp->ls_ownerlen != lop->lo_stp->ls_ownerlen || 1811 NFSBCMP(lckstp->ls_owner, lop->lo_stp->ls_owner, 1812 lckstp->ls_ownerlen))) { 1813 if (other_lop) { 1814 FREE((caddr_t)other_lop, M_NFSDLOCK); 1815 other_lop = NULL; 1816 } 1817 ret = nfsrv_clientconflict(lop->lo_stp->ls_clp,&haslock,vp,p); 1818 if (ret) { 1819 if (filestruct_locked != 0) { 1820 /* Roll back local locks. */ 1821 nfsrv_locallock_rollback(vp, lfp, p); 1822 NFSLOCKSTATE(); 1823 nfsrv_unlocklf(lfp); 1824 NFSUNLOCKSTATE(); 1825 } 1826 /* 1827 * nfsrv_clientconflict() unlocks state when it 1828 * returns non-zero. 1829 */ 1830 lckstp = NULL; 1831 goto tryagain; 1832 } 1833 /* 1834 * Found a conflicting lock, so record the conflict and 1835 * return the error. 1836 */ 1837 if (cfp) { 1838 cfp->cl_clientid.lval[0]=lop->lo_stp->ls_stateid.other[0]; 1839 cfp->cl_clientid.lval[1]=lop->lo_stp->ls_stateid.other[1]; 1840 cfp->cl_first = lop->lo_first; 1841 cfp->cl_end = lop->lo_end; 1842 cfp->cl_flags = lop->lo_flags; 1843 cfp->cl_ownerlen = lop->lo_stp->ls_ownerlen; 1844 NFSBCOPY(lop->lo_stp->ls_owner, cfp->cl_owner, 1845 cfp->cl_ownerlen); 1846 } 1847 if (new_stp->ls_flags & NFSLCK_RECLAIM) 1848 error = NFSERR_RECLAIMCONFLICT; 1849 else if (new_stp->ls_flags & NFSLCK_CHECK) 1850 error = NFSERR_LOCKED; 1851 else 1852 error = NFSERR_DENIED; 1853 if (filestruct_locked != 0) { 1854 /* Roll back local locks. */ 1855 NFSUNLOCKSTATE(); 1856 nfsrv_locallock_rollback(vp, lfp, p); 1857 NFSLOCKSTATE(); 1858 nfsrv_unlocklf(lfp); 1859 } 1860 NFSUNLOCKSTATE(); 1861 if (haslock) { 1862 NFSLOCKV4ROOTMUTEX(); 1863 nfsv4_unlock(&nfsv4rootfs_lock, 1); 1864 NFSUNLOCKV4ROOTMUTEX(); 1865 } 1866 return (error); 1867 } 1868 } 1869 } 1870 1871 /* 1872 * We only get here if there was no lock that conflicted. 1873 */ 1874 if (new_stp->ls_flags & (NFSLCK_TEST | NFSLCK_CHECK)) { 1875 NFSUNLOCKSTATE(); 1876 if (haslock) { 1877 NFSLOCKV4ROOTMUTEX(); 1878 nfsv4_unlock(&nfsv4rootfs_lock, 1); 1879 NFSUNLOCKV4ROOTMUTEX(); 1880 } 1881 return (0); 1882 } 1883 1884 /* 1885 * We only get here when we are creating or modifying a lock. 1886 * There are two variants: 1887 * - exist_lock_owner where lock_owner exists 1888 * - open_to_lock_owner with new lock_owner 1889 */ 1890 first = new_lop->lo_first; 1891 end = new_lop->lo_end; 1892 lock_flags = new_lop->lo_flags; 1893 if (!(new_stp->ls_flags & NFSLCK_OPENTOLOCK)) { 1894 nfsrv_updatelock(lckstp, new_lopp, &other_lop, lfp); 1895 stateidp->seqid = ++(lckstp->ls_stateid.seqid); 1896 stateidp->other[0] = lckstp->ls_stateid.other[0]; 1897 stateidp->other[1] = lckstp->ls_stateid.other[1]; 1898 stateidp->other[2] = lckstp->ls_stateid.other[2]; 1899 } else { 1900 /* 1901 * The new open_to_lock_owner case. 1902 * Link the new nfsstate into the lists. 1903 */ 1904 new_stp->ls_seq = new_stp->ls_opentolockseq; 1905 nfsrvd_refcache(new_stp->ls_op); 1906 stateidp->seqid = new_stp->ls_stateid.seqid = 0; 1907 stateidp->other[0] = new_stp->ls_stateid.other[0] = 1908 clp->lc_clientid.lval[0]; 1909 stateidp->other[1] = new_stp->ls_stateid.other[1] = 1910 clp->lc_clientid.lval[1]; 1911 stateidp->other[2] = new_stp->ls_stateid.other[2] = 1912 nfsrv_nextstateindex(clp); 1913 new_stp->ls_clp = clp; 1914 LIST_INIT(&new_stp->ls_lock); 1915 new_stp->ls_openstp = stp; 1916 new_stp->ls_lfp = lfp; 1917 nfsrv_insertlock(new_lop, (struct nfslock *)new_stp, new_stp, 1918 lfp); 1919 LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_stp->ls_stateid), 1920 new_stp, ls_hash); 1921 LIST_INSERT_HEAD(&stp->ls_open, new_stp, ls_list); 1922 *new_lopp = NULL; 1923 *new_stpp = NULL; 1924 newnfsstats.srvlockowners++; 1925 nfsrv_openpluslock++; 1926 } 1927 if (filestruct_locked != 0) { 1928 NFSUNLOCKSTATE(); 1929 nfsrv_locallock_commit(lfp, lock_flags, first, end); 1930 NFSLOCKSTATE(); 1931 nfsrv_unlocklf(lfp); 1932 } 1933 NFSUNLOCKSTATE(); 1934 if (haslock) { 1935 NFSLOCKV4ROOTMUTEX(); 1936 nfsv4_unlock(&nfsv4rootfs_lock, 1); 1937 NFSUNLOCKV4ROOTMUTEX(); 1938 } 1939 if (other_lop) 1940 FREE((caddr_t)other_lop, M_NFSDLOCK); 1941 return (0); 1942 } 1943 1944 /* 1945 * Check for state errors for Open. 1946 * repstat is passed back out as an error if more critical errors 1947 * are not detected. 1948 */ 1949 APPLESTATIC int 1950 nfsrv_opencheck(nfsquad_t clientid, nfsv4stateid_t *stateidp, 1951 struct nfsstate *new_stp, vnode_t vp, struct nfsrv_descript *nd, 1952 NFSPROC_T *p, int repstat) 1953 { 1954 struct nfsstate *stp, *nstp; 1955 struct nfsclient *clp; 1956 struct nfsstate *ownerstp; 1957 struct nfslockfile *lfp, *new_lfp; 1958 int error, haslock = 0, ret, readonly = 0, getfhret = 0; 1959 1960 if ((new_stp->ls_flags & NFSLCK_SHAREBITS) == NFSLCK_READACCESS) 1961 readonly = 1; 1962 /* 1963 * Check for restart conditions (client and server). 1964 */ 1965 error = nfsrv_checkrestart(clientid, new_stp->ls_flags, 1966 &new_stp->ls_stateid, 0); 1967 if (error) 1968 return (error); 1969 1970 /* 1971 * Check for state resource limit exceeded. 1972 * Technically this should be SMP protected, but the worst 1973 * case error is "out by one or two" on the count when it 1974 * returns NFSERR_RESOURCE and the limit is just a rather 1975 * arbitrary high water mark, so no harm is done. 1976 */ 1977 if (nfsrv_openpluslock > NFSRV_V4STATELIMIT) 1978 return (NFSERR_RESOURCE); 1979 1980 tryagain: 1981 MALLOC(new_lfp, struct nfslockfile *, sizeof (struct nfslockfile), 1982 M_NFSDLOCKFILE, M_WAITOK); 1983 if (vp) 1984 getfhret = nfsrv_getlockfh(vp, new_stp->ls_flags, &new_lfp, 1985 NULL, p); 1986 NFSLOCKSTATE(); 1987 /* 1988 * Get the nfsclient structure. 1989 */ 1990 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, 1991 (nfsquad_t)((u_quad_t)0), NULL, p); 1992 1993 /* 1994 * Look up the open owner. See if it needs confirmation and 1995 * check the seq#, as required. 1996 */ 1997 if (!error) 1998 nfsrv_getowner(&clp->lc_open, new_stp, &ownerstp); 1999 2000 if (!error && ownerstp) { 2001 error = nfsrv_checkseqid(nd, new_stp->ls_seq, ownerstp, 2002 new_stp->ls_op); 2003 /* 2004 * If the OpenOwner hasn't been confirmed, assume the 2005 * old one was a replay and this one is ok. 2006 * See: RFC3530 Sec. 14.2.18. 2007 */ 2008 if (error == NFSERR_BADSEQID && 2009 (ownerstp->ls_flags & NFSLCK_NEEDSCONFIRM)) 2010 error = 0; 2011 } 2012 2013 /* 2014 * Check for grace. 2015 */ 2016 if (!error) 2017 error = nfsrv_checkgrace(new_stp->ls_flags); 2018 if ((new_stp->ls_flags & NFSLCK_RECLAIM) && !error && 2019 nfsrv_checkstable(clp)) 2020 error = NFSERR_NOGRACE; 2021 2022 /* 2023 * If none of the above errors occurred, let repstat be 2024 * returned. 2025 */ 2026 if (repstat && !error) 2027 error = repstat; 2028 if (error) { 2029 NFSUNLOCKSTATE(); 2030 if (haslock) { 2031 NFSLOCKV4ROOTMUTEX(); 2032 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2033 NFSUNLOCKV4ROOTMUTEX(); 2034 } 2035 free((caddr_t)new_lfp, M_NFSDLOCKFILE); 2036 return (error); 2037 } 2038 2039 /* 2040 * If vp == NULL, the file doesn't exist yet, so return ok. 2041 * (This always happens on the first pass, so haslock must be 0.) 2042 */ 2043 if (vp == NULL) { 2044 NFSUNLOCKSTATE(); 2045 FREE((caddr_t)new_lfp, M_NFSDLOCKFILE); 2046 return (0); 2047 } 2048 2049 /* 2050 * Get the structure for the underlying file. 2051 */ 2052 if (getfhret) 2053 error = getfhret; 2054 else 2055 error = nfsrv_getlockfile(new_stp->ls_flags, &new_lfp, &lfp, 2056 NULL, 0); 2057 if (new_lfp) 2058 FREE((caddr_t)new_lfp, M_NFSDLOCKFILE); 2059 if (error) { 2060 NFSUNLOCKSTATE(); 2061 if (haslock) { 2062 NFSLOCKV4ROOTMUTEX(); 2063 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2064 NFSUNLOCKV4ROOTMUTEX(); 2065 } 2066 return (error); 2067 } 2068 2069 /* 2070 * Search for a conflicting open/share. 2071 */ 2072 if (new_stp->ls_flags & NFSLCK_DELEGCUR) { 2073 /* 2074 * For Delegate_Cur, search for the matching Delegation, 2075 * which indicates no conflict. 2076 * An old delegation should have been recovered by the 2077 * client doing a Claim_DELEGATE_Prev, so I won't let 2078 * it match and return NFSERR_EXPIRED. Should I let it 2079 * match? 2080 */ 2081 LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) { 2082 if (!(stp->ls_flags & NFSLCK_OLDDELEG) && 2083 stateidp->seqid == stp->ls_stateid.seqid && 2084 !NFSBCMP(stateidp->other, stp->ls_stateid.other, 2085 NFSX_STATEIDOTHER)) 2086 break; 2087 } 2088 if (stp == LIST_END(&lfp->lf_deleg) || 2089 ((new_stp->ls_flags & NFSLCK_WRITEACCESS) && 2090 (stp->ls_flags & NFSLCK_DELEGREAD))) { 2091 NFSUNLOCKSTATE(); 2092 if (haslock) { 2093 NFSLOCKV4ROOTMUTEX(); 2094 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2095 NFSUNLOCKV4ROOTMUTEX(); 2096 } 2097 return (NFSERR_EXPIRED); 2098 } 2099 } 2100 2101 /* 2102 * Check for access/deny bit conflicts. I check for the same 2103 * owner as well, in case the client didn't bother. 2104 */ 2105 LIST_FOREACH(stp, &lfp->lf_open, ls_file) { 2106 if (!(new_stp->ls_flags & NFSLCK_DELEGCUR) && 2107 (((new_stp->ls_flags & NFSLCK_ACCESSBITS) & 2108 ((stp->ls_flags>>NFSLCK_SHIFT) & NFSLCK_ACCESSBITS))|| 2109 ((stp->ls_flags & NFSLCK_ACCESSBITS) & 2110 ((new_stp->ls_flags>>NFSLCK_SHIFT)&NFSLCK_ACCESSBITS)))){ 2111 ret = nfsrv_clientconflict(stp->ls_clp,&haslock,vp,p); 2112 if (ret) { 2113 /* 2114 * nfsrv_clientconflict() unlocks 2115 * state when it returns non-zero. 2116 */ 2117 goto tryagain; 2118 } 2119 if (new_stp->ls_flags & NFSLCK_RECLAIM) 2120 error = NFSERR_RECLAIMCONFLICT; 2121 else 2122 error = NFSERR_SHAREDENIED; 2123 NFSUNLOCKSTATE(); 2124 if (haslock) { 2125 NFSLOCKV4ROOTMUTEX(); 2126 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2127 NFSUNLOCKV4ROOTMUTEX(); 2128 } 2129 return (error); 2130 } 2131 } 2132 2133 /* 2134 * Check for a conflicting delegation. If one is found, call 2135 * nfsrv_delegconflict() to handle it. If the v4root lock hasn't 2136 * been set yet, it will get the lock. Otherwise, it will recall 2137 * the delegation. Then, we try try again... 2138 * (If NFSLCK_DELEGCUR is set, it has a delegation, so there 2139 * isn't a conflict.) 2140 * I currently believe the conflict algorithm to be: 2141 * For Open with Read Access and Deny None 2142 * - there is a conflict iff a different client has a write delegation 2143 * For Open with other Write Access or any Deny except None 2144 * - there is a conflict if a different client has any delegation 2145 * - there is a conflict if the same client has a read delegation 2146 * (The current concensus is that this last case should be 2147 * considered a conflict since the client with a read delegation 2148 * could have done an Open with ReadAccess and WriteDeny 2149 * locally and then not have checked for the WriteDeny.) 2150 * Don't check for a Reclaim, since that will be dealt with 2151 * by nfsrv_openctrl(). 2152 */ 2153 if (!(new_stp->ls_flags & 2154 (NFSLCK_DELEGPREV | NFSLCK_DELEGCUR | NFSLCK_RECLAIM))) { 2155 stp = LIST_FIRST(&lfp->lf_deleg); 2156 while (stp != LIST_END(&lfp->lf_deleg)) { 2157 nstp = LIST_NEXT(stp, ls_file); 2158 if ((readonly && stp->ls_clp != clp && 2159 (stp->ls_flags & NFSLCK_DELEGWRITE)) || 2160 (!readonly && (stp->ls_clp != clp || 2161 (stp->ls_flags & NFSLCK_DELEGREAD)))) { 2162 ret = nfsrv_delegconflict(stp, &haslock, p, vp); 2163 if (ret) { 2164 /* 2165 * nfsrv_delegconflict() unlocks state 2166 * when it returns non-zero. 2167 */ 2168 if (ret == -1) 2169 goto tryagain; 2170 return (ret); 2171 } 2172 } 2173 stp = nstp; 2174 } 2175 } 2176 NFSUNLOCKSTATE(); 2177 if (haslock) { 2178 NFSLOCKV4ROOTMUTEX(); 2179 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2180 NFSUNLOCKV4ROOTMUTEX(); 2181 } 2182 return (0); 2183 } 2184 2185 /* 2186 * Open control function to create/update open state for an open. 2187 */ 2188 APPLESTATIC int 2189 nfsrv_openctrl(struct nfsrv_descript *nd, vnode_t vp, 2190 struct nfsstate **new_stpp, nfsquad_t clientid, nfsv4stateid_t *stateidp, 2191 nfsv4stateid_t *delegstateidp, u_int32_t *rflagsp, struct nfsexstuff *exp, 2192 NFSPROC_T *p, u_quad_t filerev) 2193 { 2194 struct nfsstate *new_stp = *new_stpp; 2195 struct nfsstate *stp, *nstp; 2196 struct nfsstate *openstp = NULL, *new_open, *ownerstp, *new_deleg; 2197 struct nfslockfile *lfp, *new_lfp; 2198 struct nfsclient *clp; 2199 int error, haslock = 0, ret, delegate = 1, writedeleg = 1; 2200 int readonly = 0, cbret = 1, getfhret = 0; 2201 2202 if ((new_stp->ls_flags & NFSLCK_SHAREBITS) == NFSLCK_READACCESS) 2203 readonly = 1; 2204 /* 2205 * Check for restart conditions (client and server). 2206 * (Paranoia, should have been detected by nfsrv_opencheck().) 2207 * If an error does show up, return NFSERR_EXPIRED, since the 2208 * the seqid# has already been incremented. 2209 */ 2210 error = nfsrv_checkrestart(clientid, new_stp->ls_flags, 2211 &new_stp->ls_stateid, 0); 2212 if (error) { 2213 printf("Nfsd: openctrl unexpected restart err=%d\n", 2214 error); 2215 return (NFSERR_EXPIRED); 2216 } 2217 2218 tryagain: 2219 MALLOC(new_lfp, struct nfslockfile *, sizeof (struct nfslockfile), 2220 M_NFSDLOCKFILE, M_WAITOK); 2221 MALLOC(new_open, struct nfsstate *, sizeof (struct nfsstate), 2222 M_NFSDSTATE, M_WAITOK); 2223 MALLOC(new_deleg, struct nfsstate *, sizeof (struct nfsstate), 2224 M_NFSDSTATE, M_WAITOK); 2225 getfhret = nfsrv_getlockfh(vp, new_stp->ls_flags, &new_lfp, 2226 NULL, p); 2227 NFSLOCKSTATE(); 2228 /* 2229 * Get the client structure. Since the linked lists could be changed 2230 * by other nfsd processes if this process does a tsleep(), one of 2231 * two things must be done. 2232 * 1 - don't tsleep() 2233 * or 2234 * 2 - get the nfsv4_lock() { indicated by haslock == 1 } 2235 * before using the lists, since this lock stops the other 2236 * nfsd. This should only be used for rare cases, since it 2237 * essentially single threads the nfsd. 2238 * At this time, it is only done for cases where the stable 2239 * storage file must be written prior to completion of state 2240 * expiration. 2241 */ 2242 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, 2243 (nfsquad_t)((u_quad_t)0), NULL, p); 2244 if (!error && (clp->lc_flags & LCL_NEEDSCBNULL) && 2245 clp->lc_program) { 2246 /* 2247 * This happens on the first open for a client 2248 * that supports callbacks. 2249 */ 2250 NFSUNLOCKSTATE(); 2251 /* 2252 * Although nfsrv_docallback() will sleep, clp won't 2253 * go away, since they are only removed when the 2254 * nfsv4_lock() has blocked the nfsd threads. The 2255 * fields in clp can change, but having multiple 2256 * threads do this Null callback RPC should be 2257 * harmless. 2258 */ 2259 cbret = nfsrv_docallback(clp, NFSV4PROC_CBNULL, 2260 NULL, 0, NULL, NULL, NULL, p); 2261 NFSLOCKSTATE(); 2262 clp->lc_flags &= ~LCL_NEEDSCBNULL; 2263 if (!cbret) 2264 clp->lc_flags |= LCL_CALLBACKSON; 2265 } 2266 2267 /* 2268 * Look up the open owner. See if it needs confirmation and 2269 * check the seq#, as required. 2270 */ 2271 if (!error) 2272 nfsrv_getowner(&clp->lc_open, new_stp, &ownerstp); 2273 2274 if (error) { 2275 NFSUNLOCKSTATE(); 2276 printf("Nfsd: openctrl unexpected state err=%d\n", 2277 error); 2278 free((caddr_t)new_lfp, M_NFSDLOCKFILE); 2279 free((caddr_t)new_open, M_NFSDSTATE); 2280 free((caddr_t)new_deleg, M_NFSDSTATE); 2281 if (haslock) { 2282 NFSLOCKV4ROOTMUTEX(); 2283 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2284 NFSUNLOCKV4ROOTMUTEX(); 2285 } 2286 return (NFSERR_EXPIRED); 2287 } 2288 2289 if (new_stp->ls_flags & NFSLCK_RECLAIM) 2290 nfsrv_markstable(clp); 2291 2292 /* 2293 * Get the structure for the underlying file. 2294 */ 2295 if (getfhret) 2296 error = getfhret; 2297 else 2298 error = nfsrv_getlockfile(new_stp->ls_flags, &new_lfp, &lfp, 2299 NULL, 0); 2300 if (new_lfp) 2301 FREE((caddr_t)new_lfp, M_NFSDLOCKFILE); 2302 if (error) { 2303 NFSUNLOCKSTATE(); 2304 printf("Nfsd openctrl unexpected getlockfile err=%d\n", 2305 error); 2306 free((caddr_t)new_open, M_NFSDSTATE); 2307 free((caddr_t)new_deleg, M_NFSDSTATE); 2308 if (haslock) { 2309 NFSLOCKV4ROOTMUTEX(); 2310 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2311 NFSUNLOCKV4ROOTMUTEX(); 2312 } 2313 return (error); 2314 } 2315 2316 /* 2317 * Search for a conflicting open/share. 2318 */ 2319 if (new_stp->ls_flags & NFSLCK_DELEGCUR) { 2320 /* 2321 * For Delegate_Cur, search for the matching Delegation, 2322 * which indicates no conflict. 2323 * An old delegation should have been recovered by the 2324 * client doing a Claim_DELEGATE_Prev, so I won't let 2325 * it match and return NFSERR_EXPIRED. Should I let it 2326 * match? 2327 */ 2328 LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) { 2329 if (!(stp->ls_flags & NFSLCK_OLDDELEG) && 2330 stateidp->seqid == stp->ls_stateid.seqid && 2331 !NFSBCMP(stateidp->other, stp->ls_stateid.other, 2332 NFSX_STATEIDOTHER)) 2333 break; 2334 } 2335 if (stp == LIST_END(&lfp->lf_deleg) || 2336 ((new_stp->ls_flags & NFSLCK_WRITEACCESS) && 2337 (stp->ls_flags & NFSLCK_DELEGREAD))) { 2338 NFSUNLOCKSTATE(); 2339 printf("Nfsd openctrl unexpected expiry\n"); 2340 free((caddr_t)new_open, M_NFSDSTATE); 2341 free((caddr_t)new_deleg, M_NFSDSTATE); 2342 if (haslock) { 2343 NFSLOCKV4ROOTMUTEX(); 2344 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2345 NFSUNLOCKV4ROOTMUTEX(); 2346 } 2347 return (NFSERR_EXPIRED); 2348 } 2349 2350 /* 2351 * Don't issue a Delegation, since one already exists and 2352 * delay delegation timeout, as required. 2353 */ 2354 delegate = 0; 2355 nfsrv_delaydelegtimeout(stp); 2356 } 2357 2358 /* 2359 * Check for access/deny bit conflicts. I also check for the 2360 * same owner, since the client might not have bothered to check. 2361 * Also, note an open for the same file and owner, if found, 2362 * which is all we do here for Delegate_Cur, since conflict 2363 * checking is already done. 2364 */ 2365 LIST_FOREACH(stp, &lfp->lf_open, ls_file) { 2366 if (ownerstp && stp->ls_openowner == ownerstp) 2367 openstp = stp; 2368 if (!(new_stp->ls_flags & NFSLCK_DELEGCUR)) { 2369 /* 2370 * If another client has the file open, the only 2371 * delegation that can be issued is a Read delegation 2372 * and only if it is a Read open with Deny none. 2373 */ 2374 if (clp != stp->ls_clp) { 2375 if ((stp->ls_flags & NFSLCK_SHAREBITS) == 2376 NFSLCK_READACCESS) 2377 writedeleg = 0; 2378 else 2379 delegate = 0; 2380 } 2381 if(((new_stp->ls_flags & NFSLCK_ACCESSBITS) & 2382 ((stp->ls_flags>>NFSLCK_SHIFT) & NFSLCK_ACCESSBITS))|| 2383 ((stp->ls_flags & NFSLCK_ACCESSBITS) & 2384 ((new_stp->ls_flags>>NFSLCK_SHIFT)&NFSLCK_ACCESSBITS))){ 2385 ret = nfsrv_clientconflict(stp->ls_clp,&haslock,vp,p); 2386 if (ret) { 2387 /* 2388 * nfsrv_clientconflict() unlocks state 2389 * when it returns non-zero. 2390 */ 2391 free((caddr_t)new_open, M_NFSDSTATE); 2392 free((caddr_t)new_deleg, M_NFSDSTATE); 2393 openstp = NULL; 2394 goto tryagain; 2395 } 2396 if (new_stp->ls_flags & NFSLCK_RECLAIM) 2397 error = NFSERR_RECLAIMCONFLICT; 2398 else 2399 error = NFSERR_SHAREDENIED; 2400 NFSUNLOCKSTATE(); 2401 if (haslock) { 2402 NFSLOCKV4ROOTMUTEX(); 2403 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2404 NFSUNLOCKV4ROOTMUTEX(); 2405 } 2406 free((caddr_t)new_open, M_NFSDSTATE); 2407 free((caddr_t)new_deleg, M_NFSDSTATE); 2408 printf("nfsd openctrl unexpected client cnfl\n"); 2409 return (error); 2410 } 2411 } 2412 } 2413 2414 /* 2415 * Check for a conflicting delegation. If one is found, call 2416 * nfsrv_delegconflict() to handle it. If the v4root lock hasn't 2417 * been set yet, it will get the lock. Otherwise, it will recall 2418 * the delegation. Then, we try try again... 2419 * (If NFSLCK_DELEGCUR is set, it has a delegation, so there 2420 * isn't a conflict.) 2421 * I currently believe the conflict algorithm to be: 2422 * For Open with Read Access and Deny None 2423 * - there is a conflict iff a different client has a write delegation 2424 * For Open with other Write Access or any Deny except None 2425 * - there is a conflict if a different client has any delegation 2426 * - there is a conflict if the same client has a read delegation 2427 * (The current concensus is that this last case should be 2428 * considered a conflict since the client with a read delegation 2429 * could have done an Open with ReadAccess and WriteDeny 2430 * locally and then not have checked for the WriteDeny.) 2431 */ 2432 if (!(new_stp->ls_flags & (NFSLCK_DELEGPREV | NFSLCK_DELEGCUR))) { 2433 stp = LIST_FIRST(&lfp->lf_deleg); 2434 while (stp != LIST_END(&lfp->lf_deleg)) { 2435 nstp = LIST_NEXT(stp, ls_file); 2436 if (stp->ls_clp != clp && (stp->ls_flags & NFSLCK_DELEGREAD)) 2437 writedeleg = 0; 2438 else 2439 delegate = 0; 2440 if ((readonly && stp->ls_clp != clp && 2441 (stp->ls_flags & NFSLCK_DELEGWRITE)) || 2442 (!readonly && (stp->ls_clp != clp || 2443 (stp->ls_flags & NFSLCK_DELEGREAD)))) { 2444 if (new_stp->ls_flags & NFSLCK_RECLAIM) { 2445 delegate = 2; 2446 } else { 2447 ret = nfsrv_delegconflict(stp, &haslock, p, vp); 2448 if (ret) { 2449 /* 2450 * nfsrv_delegconflict() unlocks state 2451 * when it returns non-zero. 2452 */ 2453 printf("Nfsd openctrl unexpected deleg cnfl\n"); 2454 free((caddr_t)new_open, M_NFSDSTATE); 2455 free((caddr_t)new_deleg, M_NFSDSTATE); 2456 if (ret == -1) { 2457 openstp = NULL; 2458 goto tryagain; 2459 } 2460 return (ret); 2461 } 2462 } 2463 } 2464 stp = nstp; 2465 } 2466 } 2467 2468 /* 2469 * We only get here if there was no open that conflicted. 2470 * If an open for the owner exists, or in the access/deny bits. 2471 * Otherwise it is a new open. If the open_owner hasn't been 2472 * confirmed, replace the open with the new one needing confirmation, 2473 * otherwise add the open. 2474 */ 2475 if (new_stp->ls_flags & NFSLCK_DELEGPREV) { 2476 /* 2477 * Handle NFSLCK_DELEGPREV by searching the old delegations for 2478 * a match. If found, just move the old delegation to the current 2479 * delegation list and issue open. If not found, return 2480 * NFSERR_EXPIRED. 2481 */ 2482 LIST_FOREACH(stp, &clp->lc_olddeleg, ls_list) { 2483 if (stp->ls_lfp == lfp) { 2484 /* Found it */ 2485 if (stp->ls_clp != clp) 2486 panic("olddeleg clp"); 2487 LIST_REMOVE(stp, ls_list); 2488 LIST_REMOVE(stp, ls_hash); 2489 stp->ls_flags &= ~NFSLCK_OLDDELEG; 2490 stp->ls_stateid.seqid = delegstateidp->seqid = 0; 2491 stp->ls_stateid.other[0] = delegstateidp->other[0] = 2492 clp->lc_clientid.lval[0]; 2493 stp->ls_stateid.other[1] = delegstateidp->other[1] = 2494 clp->lc_clientid.lval[1]; 2495 stp->ls_stateid.other[2] = delegstateidp->other[2] = 2496 nfsrv_nextstateindex(clp); 2497 stp->ls_compref = nd->nd_compref; 2498 LIST_INSERT_HEAD(&clp->lc_deleg, stp, ls_list); 2499 LIST_INSERT_HEAD(NFSSTATEHASH(clp, 2500 stp->ls_stateid), stp, ls_hash); 2501 if (stp->ls_flags & NFSLCK_DELEGWRITE) 2502 *rflagsp |= NFSV4OPEN_WRITEDELEGATE; 2503 else 2504 *rflagsp |= NFSV4OPEN_READDELEGATE; 2505 clp->lc_delegtime = NFSD_MONOSEC + 2506 nfsrv_lease + NFSRV_LEASEDELTA; 2507 2508 /* 2509 * Now, do the associated open. 2510 */ 2511 new_open->ls_stateid.seqid = 0; 2512 new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0]; 2513 new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1]; 2514 new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp); 2515 new_open->ls_flags = (new_stp->ls_flags&NFSLCK_DENYBITS)| 2516 NFSLCK_OPEN; 2517 if (stp->ls_flags & NFSLCK_DELEGWRITE) 2518 new_open->ls_flags |= (NFSLCK_READACCESS | 2519 NFSLCK_WRITEACCESS); 2520 else 2521 new_open->ls_flags |= NFSLCK_READACCESS; 2522 new_open->ls_uid = new_stp->ls_uid; 2523 new_open->ls_lfp = lfp; 2524 new_open->ls_clp = clp; 2525 LIST_INIT(&new_open->ls_open); 2526 LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file); 2527 LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid), 2528 new_open, ls_hash); 2529 /* 2530 * and handle the open owner 2531 */ 2532 if (ownerstp) { 2533 new_open->ls_openowner = ownerstp; 2534 LIST_INSERT_HEAD(&ownerstp->ls_open,new_open,ls_list); 2535 } else { 2536 new_open->ls_openowner = new_stp; 2537 new_stp->ls_flags = 0; 2538 nfsrvd_refcache(new_stp->ls_op); 2539 new_stp->ls_noopens = 0; 2540 LIST_INIT(&new_stp->ls_open); 2541 LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list); 2542 LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list); 2543 *new_stpp = NULL; 2544 newnfsstats.srvopenowners++; 2545 nfsrv_openpluslock++; 2546 } 2547 openstp = new_open; 2548 new_open = NULL; 2549 newnfsstats.srvopens++; 2550 nfsrv_openpluslock++; 2551 break; 2552 } 2553 } 2554 if (stp == LIST_END(&clp->lc_olddeleg)) 2555 error = NFSERR_EXPIRED; 2556 } else if (new_stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) { 2557 /* 2558 * Scan to see that no delegation for this client and file 2559 * doesn't already exist. 2560 * There also shouldn't yet be an Open for this file and 2561 * openowner. 2562 */ 2563 LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) { 2564 if (stp->ls_clp == clp) 2565 break; 2566 } 2567 if (stp == LIST_END(&lfp->lf_deleg) && openstp == NULL) { 2568 /* 2569 * This is the Claim_Previous case with a delegation 2570 * type != Delegate_None. 2571 */ 2572 /* 2573 * First, add the delegation. (Although we must issue the 2574 * delegation, we can also ask for an immediate return.) 2575 */ 2576 new_deleg->ls_stateid.seqid = delegstateidp->seqid = 0; 2577 new_deleg->ls_stateid.other[0] = delegstateidp->other[0] = 2578 clp->lc_clientid.lval[0]; 2579 new_deleg->ls_stateid.other[1] = delegstateidp->other[1] = 2580 clp->lc_clientid.lval[1]; 2581 new_deleg->ls_stateid.other[2] = delegstateidp->other[2] = 2582 nfsrv_nextstateindex(clp); 2583 if (new_stp->ls_flags & NFSLCK_DELEGWRITE) { 2584 new_deleg->ls_flags = (NFSLCK_DELEGWRITE | 2585 NFSLCK_READACCESS | NFSLCK_WRITEACCESS); 2586 *rflagsp |= NFSV4OPEN_WRITEDELEGATE; 2587 } else { 2588 new_deleg->ls_flags = (NFSLCK_DELEGREAD | 2589 NFSLCK_READACCESS); 2590 *rflagsp |= NFSV4OPEN_READDELEGATE; 2591 } 2592 new_deleg->ls_uid = new_stp->ls_uid; 2593 new_deleg->ls_lfp = lfp; 2594 new_deleg->ls_clp = clp; 2595 new_deleg->ls_filerev = filerev; 2596 new_deleg->ls_compref = nd->nd_compref; 2597 LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file); 2598 LIST_INSERT_HEAD(NFSSTATEHASH(clp, 2599 new_deleg->ls_stateid), new_deleg, ls_hash); 2600 LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list); 2601 new_deleg = NULL; 2602 if (delegate == 2 || nfsrv_issuedelegs == 0 || 2603 (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) != 2604 LCL_CALLBACKSON || 2605 NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) || 2606 !NFSVNO_DELEGOK(vp)) 2607 *rflagsp |= NFSV4OPEN_RECALL; 2608 newnfsstats.srvdelegates++; 2609 nfsrv_openpluslock++; 2610 nfsrv_delegatecnt++; 2611 2612 /* 2613 * Now, do the associated open. 2614 */ 2615 new_open->ls_stateid.seqid = 0; 2616 new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0]; 2617 new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1]; 2618 new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp); 2619 new_open->ls_flags = (new_stp->ls_flags & NFSLCK_DENYBITS) | 2620 NFSLCK_OPEN; 2621 if (new_stp->ls_flags & NFSLCK_DELEGWRITE) 2622 new_open->ls_flags |= (NFSLCK_READACCESS | 2623 NFSLCK_WRITEACCESS); 2624 else 2625 new_open->ls_flags |= NFSLCK_READACCESS; 2626 new_open->ls_uid = new_stp->ls_uid; 2627 new_open->ls_lfp = lfp; 2628 new_open->ls_clp = clp; 2629 LIST_INIT(&new_open->ls_open); 2630 LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file); 2631 LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid), 2632 new_open, ls_hash); 2633 /* 2634 * and handle the open owner 2635 */ 2636 if (ownerstp) { 2637 new_open->ls_openowner = ownerstp; 2638 LIST_INSERT_HEAD(&ownerstp->ls_open, new_open, ls_list); 2639 } else { 2640 new_open->ls_openowner = new_stp; 2641 new_stp->ls_flags = 0; 2642 nfsrvd_refcache(new_stp->ls_op); 2643 new_stp->ls_noopens = 0; 2644 LIST_INIT(&new_stp->ls_open); 2645 LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list); 2646 LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list); 2647 *new_stpp = NULL; 2648 newnfsstats.srvopenowners++; 2649 nfsrv_openpluslock++; 2650 } 2651 openstp = new_open; 2652 new_open = NULL; 2653 newnfsstats.srvopens++; 2654 nfsrv_openpluslock++; 2655 } else { 2656 error = NFSERR_RECLAIMCONFLICT; 2657 } 2658 } else if (ownerstp) { 2659 if (ownerstp->ls_flags & NFSLCK_NEEDSCONFIRM) { 2660 /* Replace the open */ 2661 if (ownerstp->ls_op) 2662 nfsrvd_derefcache(ownerstp->ls_op); 2663 ownerstp->ls_op = new_stp->ls_op; 2664 nfsrvd_refcache(ownerstp->ls_op); 2665 ownerstp->ls_seq = new_stp->ls_seq; 2666 *rflagsp |= NFSV4OPEN_RESULTCONFIRM; 2667 stp = LIST_FIRST(&ownerstp->ls_open); 2668 stp->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS) | 2669 NFSLCK_OPEN; 2670 stp->ls_stateid.seqid = 0; 2671 stp->ls_uid = new_stp->ls_uid; 2672 if (lfp != stp->ls_lfp) { 2673 LIST_REMOVE(stp, ls_file); 2674 LIST_INSERT_HEAD(&lfp->lf_open, stp, ls_file); 2675 stp->ls_lfp = lfp; 2676 } 2677 openstp = stp; 2678 } else if (openstp) { 2679 openstp->ls_flags |= (new_stp->ls_flags & NFSLCK_SHAREBITS); 2680 openstp->ls_stateid.seqid++; 2681 2682 /* 2683 * This is where we can choose to issue a delegation. 2684 */ 2685 if (delegate && nfsrv_issuedelegs && 2686 writedeleg && !NFSVNO_EXRDONLY(exp) && 2687 (nfsrv_writedelegifpos || !readonly) && 2688 (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) == 2689 LCL_CALLBACKSON && 2690 !NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) && 2691 NFSVNO_DELEGOK(vp)) { 2692 new_deleg->ls_stateid.seqid = delegstateidp->seqid = 0; 2693 new_deleg->ls_stateid.other[0] = delegstateidp->other[0] 2694 = clp->lc_clientid.lval[0]; 2695 new_deleg->ls_stateid.other[1] = delegstateidp->other[1] 2696 = clp->lc_clientid.lval[1]; 2697 new_deleg->ls_stateid.other[2] = delegstateidp->other[2] 2698 = nfsrv_nextstateindex(clp); 2699 new_deleg->ls_flags = (NFSLCK_DELEGWRITE | 2700 NFSLCK_READACCESS | NFSLCK_WRITEACCESS); 2701 *rflagsp |= NFSV4OPEN_WRITEDELEGATE; 2702 new_deleg->ls_uid = new_stp->ls_uid; 2703 new_deleg->ls_lfp = lfp; 2704 new_deleg->ls_clp = clp; 2705 new_deleg->ls_filerev = filerev; 2706 new_deleg->ls_compref = nd->nd_compref; 2707 LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file); 2708 LIST_INSERT_HEAD(NFSSTATEHASH(clp, 2709 new_deleg->ls_stateid), new_deleg, ls_hash); 2710 LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list); 2711 new_deleg = NULL; 2712 newnfsstats.srvdelegates++; 2713 nfsrv_openpluslock++; 2714 nfsrv_delegatecnt++; 2715 } 2716 } else { 2717 new_open->ls_stateid.seqid = 0; 2718 new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0]; 2719 new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1]; 2720 new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp); 2721 new_open->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS)| 2722 NFSLCK_OPEN; 2723 new_open->ls_uid = new_stp->ls_uid; 2724 new_open->ls_openowner = ownerstp; 2725 new_open->ls_lfp = lfp; 2726 new_open->ls_clp = clp; 2727 LIST_INIT(&new_open->ls_open); 2728 LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file); 2729 LIST_INSERT_HEAD(&ownerstp->ls_open, new_open, ls_list); 2730 LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid), 2731 new_open, ls_hash); 2732 openstp = new_open; 2733 new_open = NULL; 2734 newnfsstats.srvopens++; 2735 nfsrv_openpluslock++; 2736 2737 /* 2738 * This is where we can choose to issue a delegation. 2739 */ 2740 if (delegate && nfsrv_issuedelegs && 2741 (writedeleg || readonly) && 2742 (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) == 2743 LCL_CALLBACKSON && 2744 !NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) && 2745 NFSVNO_DELEGOK(vp)) { 2746 new_deleg->ls_stateid.seqid = delegstateidp->seqid = 0; 2747 new_deleg->ls_stateid.other[0] = delegstateidp->other[0] 2748 = clp->lc_clientid.lval[0]; 2749 new_deleg->ls_stateid.other[1] = delegstateidp->other[1] 2750 = clp->lc_clientid.lval[1]; 2751 new_deleg->ls_stateid.other[2] = delegstateidp->other[2] 2752 = nfsrv_nextstateindex(clp); 2753 if (writedeleg && !NFSVNO_EXRDONLY(exp) && 2754 (nfsrv_writedelegifpos || !readonly)) { 2755 new_deleg->ls_flags = (NFSLCK_DELEGWRITE | 2756 NFSLCK_READACCESS | NFSLCK_WRITEACCESS); 2757 *rflagsp |= NFSV4OPEN_WRITEDELEGATE; 2758 } else { 2759 new_deleg->ls_flags = (NFSLCK_DELEGREAD | 2760 NFSLCK_READACCESS); 2761 *rflagsp |= NFSV4OPEN_READDELEGATE; 2762 } 2763 new_deleg->ls_uid = new_stp->ls_uid; 2764 new_deleg->ls_lfp = lfp; 2765 new_deleg->ls_clp = clp; 2766 new_deleg->ls_filerev = filerev; 2767 new_deleg->ls_compref = nd->nd_compref; 2768 LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file); 2769 LIST_INSERT_HEAD(NFSSTATEHASH(clp, 2770 new_deleg->ls_stateid), new_deleg, ls_hash); 2771 LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list); 2772 new_deleg = NULL; 2773 newnfsstats.srvdelegates++; 2774 nfsrv_openpluslock++; 2775 nfsrv_delegatecnt++; 2776 } 2777 } 2778 } else { 2779 /* 2780 * New owner case. Start the open_owner sequence with a 2781 * Needs confirmation (unless a reclaim) and hang the 2782 * new open off it. 2783 */ 2784 new_open->ls_stateid.seqid = 0; 2785 new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0]; 2786 new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1]; 2787 new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp); 2788 new_open->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS) | 2789 NFSLCK_OPEN; 2790 new_open->ls_uid = new_stp->ls_uid; 2791 LIST_INIT(&new_open->ls_open); 2792 new_open->ls_openowner = new_stp; 2793 new_open->ls_lfp = lfp; 2794 new_open->ls_clp = clp; 2795 LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file); 2796 if (new_stp->ls_flags & NFSLCK_RECLAIM) { 2797 new_stp->ls_flags = 0; 2798 } else { 2799 *rflagsp |= NFSV4OPEN_RESULTCONFIRM; 2800 new_stp->ls_flags = NFSLCK_NEEDSCONFIRM; 2801 } 2802 nfsrvd_refcache(new_stp->ls_op); 2803 new_stp->ls_noopens = 0; 2804 LIST_INIT(&new_stp->ls_open); 2805 LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list); 2806 LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list); 2807 LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid), 2808 new_open, ls_hash); 2809 openstp = new_open; 2810 new_open = NULL; 2811 *new_stpp = NULL; 2812 newnfsstats.srvopens++; 2813 nfsrv_openpluslock++; 2814 newnfsstats.srvopenowners++; 2815 nfsrv_openpluslock++; 2816 } 2817 if (!error) { 2818 stateidp->seqid = openstp->ls_stateid.seqid; 2819 stateidp->other[0] = openstp->ls_stateid.other[0]; 2820 stateidp->other[1] = openstp->ls_stateid.other[1]; 2821 stateidp->other[2] = openstp->ls_stateid.other[2]; 2822 } 2823 NFSUNLOCKSTATE(); 2824 if (haslock) { 2825 NFSLOCKV4ROOTMUTEX(); 2826 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2827 NFSUNLOCKV4ROOTMUTEX(); 2828 } 2829 if (new_open) 2830 FREE((caddr_t)new_open, M_NFSDSTATE); 2831 if (new_deleg) 2832 FREE((caddr_t)new_deleg, M_NFSDSTATE); 2833 return (error); 2834 } 2835 2836 /* 2837 * Open update. Does the confirm, downgrade and close. 2838 */ 2839 APPLESTATIC int 2840 nfsrv_openupdate(vnode_t vp, struct nfsstate *new_stp, nfsquad_t clientid, 2841 nfsv4stateid_t *stateidp, struct nfsrv_descript *nd, NFSPROC_T *p) 2842 { 2843 struct nfsstate *stp, *ownerstp; 2844 struct nfsclient *clp; 2845 struct nfslockfile *lfp; 2846 u_int32_t bits; 2847 int error, gotstate = 0, len = 0; 2848 u_char client[NFSV4_OPAQUELIMIT]; 2849 2850 /* 2851 * Check for restart conditions (client and server). 2852 */ 2853 error = nfsrv_checkrestart(clientid, new_stp->ls_flags, 2854 &new_stp->ls_stateid, 0); 2855 if (error) 2856 return (error); 2857 2858 NFSLOCKSTATE(); 2859 /* 2860 * Get the open structure via clientid and stateid. 2861 */ 2862 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, 2863 (nfsquad_t)((u_quad_t)0), NULL, p); 2864 if (!error) 2865 error = nfsrv_getstate(clp, &new_stp->ls_stateid, 2866 new_stp->ls_flags, &stp); 2867 2868 /* 2869 * Sanity check the open. 2870 */ 2871 if (!error && (!(stp->ls_flags & NFSLCK_OPEN) || 2872 (!(new_stp->ls_flags & NFSLCK_CONFIRM) && 2873 (stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM)) || 2874 ((new_stp->ls_flags & NFSLCK_CONFIRM) && 2875 (!(stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM))))) 2876 error = NFSERR_BADSTATEID; 2877 2878 if (!error) 2879 error = nfsrv_checkseqid(nd, new_stp->ls_seq, 2880 stp->ls_openowner, new_stp->ls_op); 2881 if (!error && stp->ls_stateid.seqid != new_stp->ls_stateid.seqid && 2882 !(new_stp->ls_flags & NFSLCK_CONFIRM)) 2883 error = NFSERR_OLDSTATEID; 2884 if (!error && vnode_vtype(vp) != VREG) { 2885 if (vnode_vtype(vp) == VDIR) 2886 error = NFSERR_ISDIR; 2887 else 2888 error = NFSERR_INVAL; 2889 } 2890 2891 if (error) { 2892 /* 2893 * If a client tries to confirm an Open with a bad 2894 * seqid# and there are no byte range locks or other Opens 2895 * on the openowner, just throw it away, so the next use of the 2896 * openowner will start a fresh seq#. 2897 */ 2898 if (error == NFSERR_BADSEQID && 2899 (new_stp->ls_flags & NFSLCK_CONFIRM) && 2900 nfsrv_nootherstate(stp)) 2901 nfsrv_freeopenowner(stp->ls_openowner, 0, p); 2902 NFSUNLOCKSTATE(); 2903 return (error); 2904 } 2905 2906 /* 2907 * Set the return stateid. 2908 */ 2909 stateidp->seqid = stp->ls_stateid.seqid + 1; 2910 stateidp->other[0] = stp->ls_stateid.other[0]; 2911 stateidp->other[1] = stp->ls_stateid.other[1]; 2912 stateidp->other[2] = stp->ls_stateid.other[2]; 2913 /* 2914 * Now, handle the three cases. 2915 */ 2916 if (new_stp->ls_flags & NFSLCK_CONFIRM) { 2917 /* 2918 * If the open doesn't need confirmation, it seems to me that 2919 * there is a client error, but I'll just log it and keep going? 2920 */ 2921 if (!(stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM)) 2922 printf("Nfsv4d: stray open confirm\n"); 2923 stp->ls_openowner->ls_flags = 0; 2924 stp->ls_stateid.seqid++; 2925 if (!(clp->lc_flags & LCL_STAMPEDSTABLE)) { 2926 clp->lc_flags |= LCL_STAMPEDSTABLE; 2927 len = clp->lc_idlen; 2928 NFSBCOPY(clp->lc_id, client, len); 2929 gotstate = 1; 2930 } 2931 NFSUNLOCKSTATE(); 2932 } else if (new_stp->ls_flags & NFSLCK_CLOSE) { 2933 ownerstp = stp->ls_openowner; 2934 lfp = stp->ls_lfp; 2935 if (nfsrv_dolocallocks != 0 && !LIST_EMPTY(&stp->ls_open)) { 2936 /* Get the lf lock */ 2937 nfsrv_locklf(lfp); 2938 NFSUNLOCKSTATE(); 2939 if (nfsrv_freeopen(stp, vp, 1, p) == 0) { 2940 NFSLOCKSTATE(); 2941 nfsrv_unlocklf(lfp); 2942 NFSUNLOCKSTATE(); 2943 } 2944 } else { 2945 (void) nfsrv_freeopen(stp, NULL, 0, p); 2946 NFSUNLOCKSTATE(); 2947 } 2948 } else { 2949 /* 2950 * Update the share bits, making sure that the new set are a 2951 * subset of the old ones. 2952 */ 2953 bits = (new_stp->ls_flags & NFSLCK_SHAREBITS); 2954 if (~(stp->ls_flags) & bits) { 2955 NFSUNLOCKSTATE(); 2956 return (NFSERR_INVAL); 2957 } 2958 stp->ls_flags = (bits | NFSLCK_OPEN); 2959 stp->ls_stateid.seqid++; 2960 NFSUNLOCKSTATE(); 2961 } 2962 2963 /* 2964 * If the client just confirmed its first open, write a timestamp 2965 * to the stable storage file. 2966 */ 2967 if (gotstate) 2968 nfsrv_writestable(client, len, NFSNST_NEWSTATE, p); 2969 return (error); 2970 } 2971 2972 /* 2973 * Delegation update. Does the purge and return. 2974 */ 2975 APPLESTATIC int 2976 nfsrv_delegupdate(nfsquad_t clientid, nfsv4stateid_t *stateidp, 2977 vnode_t vp, int op, struct ucred *cred, NFSPROC_T *p) 2978 { 2979 struct nfsstate *stp; 2980 struct nfsclient *clp; 2981 int error; 2982 fhandle_t fh; 2983 2984 /* 2985 * Do a sanity check against the file handle for DelegReturn. 2986 */ 2987 if (vp) { 2988 error = nfsvno_getfh(vp, &fh, p); 2989 if (error) 2990 return (error); 2991 } 2992 /* 2993 * Check for restart conditions (client and server). 2994 */ 2995 if (op == NFSV4OP_DELEGRETURN) 2996 error = nfsrv_checkrestart(clientid, NFSLCK_DELEGRETURN, 2997 stateidp, 0); 2998 else 2999 error = nfsrv_checkrestart(clientid, NFSLCK_DELEGPURGE, 3000 stateidp, 0); 3001 3002 NFSLOCKSTATE(); 3003 /* 3004 * Get the open structure via clientid and stateid. 3005 */ 3006 if (!error) 3007 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, 3008 (nfsquad_t)((u_quad_t)0), NULL, p); 3009 if (error) { 3010 if (error == NFSERR_CBPATHDOWN) 3011 error = 0; 3012 if (error == NFSERR_STALECLIENTID && op == NFSV4OP_DELEGRETURN) 3013 error = NFSERR_STALESTATEID; 3014 } 3015 if (!error && op == NFSV4OP_DELEGRETURN) { 3016 error = nfsrv_getstate(clp, stateidp, NFSLCK_DELEGRETURN, &stp); 3017 if (!error && stp->ls_stateid.seqid != stateidp->seqid) 3018 error = NFSERR_OLDSTATEID; 3019 } 3020 /* 3021 * NFSERR_EXPIRED means that the state has gone away, 3022 * so Delegations have been purged. Just return ok. 3023 */ 3024 if (error == NFSERR_EXPIRED && op == NFSV4OP_DELEGPURGE) { 3025 NFSUNLOCKSTATE(); 3026 return (0); 3027 } 3028 if (error) { 3029 NFSUNLOCKSTATE(); 3030 return (error); 3031 } 3032 3033 if (op == NFSV4OP_DELEGRETURN) { 3034 if (NFSBCMP((caddr_t)&fh, (caddr_t)&stp->ls_lfp->lf_fh, 3035 sizeof (fhandle_t))) { 3036 NFSUNLOCKSTATE(); 3037 return (NFSERR_BADSTATEID); 3038 } 3039 nfsrv_freedeleg(stp); 3040 } else { 3041 nfsrv_freedeleglist(&clp->lc_olddeleg); 3042 } 3043 NFSUNLOCKSTATE(); 3044 return (0); 3045 } 3046 3047 /* 3048 * Release lock owner. 3049 */ 3050 APPLESTATIC int 3051 nfsrv_releaselckown(struct nfsstate *new_stp, nfsquad_t clientid, 3052 NFSPROC_T *p) 3053 { 3054 struct nfsstate *stp, *nstp, *openstp, *ownstp; 3055 struct nfsclient *clp; 3056 int error; 3057 3058 /* 3059 * Check for restart conditions (client and server). 3060 */ 3061 error = nfsrv_checkrestart(clientid, new_stp->ls_flags, 3062 &new_stp->ls_stateid, 0); 3063 if (error) 3064 return (error); 3065 3066 NFSLOCKSTATE(); 3067 /* 3068 * Get the lock owner by name. 3069 */ 3070 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, 3071 (nfsquad_t)((u_quad_t)0), NULL, p); 3072 if (error) { 3073 NFSUNLOCKSTATE(); 3074 return (error); 3075 } 3076 LIST_FOREACH(ownstp, &clp->lc_open, ls_list) { 3077 LIST_FOREACH(openstp, &ownstp->ls_open, ls_list) { 3078 stp = LIST_FIRST(&openstp->ls_open); 3079 while (stp != LIST_END(&openstp->ls_open)) { 3080 nstp = LIST_NEXT(stp, ls_list); 3081 /* 3082 * If the owner matches, check for locks and 3083 * then free or return an error. 3084 */ 3085 if (stp->ls_ownerlen == new_stp->ls_ownerlen && 3086 !NFSBCMP(stp->ls_owner, new_stp->ls_owner, 3087 stp->ls_ownerlen)){ 3088 if (LIST_EMPTY(&stp->ls_lock)) { 3089 nfsrv_freelockowner(stp, NULL, 0, p); 3090 } else { 3091 NFSUNLOCKSTATE(); 3092 return (NFSERR_LOCKSHELD); 3093 } 3094 } 3095 stp = nstp; 3096 } 3097 } 3098 } 3099 NFSUNLOCKSTATE(); 3100 return (0); 3101 } 3102 3103 /* 3104 * Get the file handle for a lock structure. 3105 */ 3106 static int 3107 nfsrv_getlockfh(vnode_t vp, u_short flags, 3108 struct nfslockfile **new_lfpp, fhandle_t *nfhp, NFSPROC_T *p) 3109 { 3110 fhandle_t *fhp = NULL; 3111 struct nfslockfile *new_lfp; 3112 int error; 3113 3114 /* 3115 * For lock, use the new nfslock structure, otherwise just 3116 * a fhandle_t on the stack. 3117 */ 3118 if (flags & NFSLCK_OPEN) { 3119 new_lfp = *new_lfpp; 3120 fhp = &new_lfp->lf_fh; 3121 } else if (nfhp) { 3122 fhp = nfhp; 3123 } else { 3124 panic("nfsrv_getlockfh"); 3125 } 3126 error = nfsvno_getfh(vp, fhp, p); 3127 return (error); 3128 } 3129 3130 /* 3131 * Get an nfs lock structure. Allocate one, as required, and return a 3132 * pointer to it. 3133 * Returns an NFSERR_xxx upon failure or -1 to indicate no current lock. 3134 */ 3135 static int 3136 nfsrv_getlockfile(u_short flags, struct nfslockfile **new_lfpp, 3137 struct nfslockfile **lfpp, fhandle_t *nfhp, int lockit) 3138 { 3139 struct nfslockfile *lfp; 3140 fhandle_t *fhp = NULL, *tfhp; 3141 struct nfslockhashhead *hp; 3142 struct nfslockfile *new_lfp = NULL; 3143 3144 /* 3145 * For lock, use the new nfslock structure, otherwise just 3146 * a fhandle_t on the stack. 3147 */ 3148 if (flags & NFSLCK_OPEN) { 3149 new_lfp = *new_lfpp; 3150 fhp = &new_lfp->lf_fh; 3151 } else if (nfhp) { 3152 fhp = nfhp; 3153 } else { 3154 panic("nfsrv_getlockfile"); 3155 } 3156 3157 hp = NFSLOCKHASH(fhp); 3158 LIST_FOREACH(lfp, hp, lf_hash) { 3159 tfhp = &lfp->lf_fh; 3160 if (NFSVNO_CMPFH(fhp, tfhp)) { 3161 if (lockit) 3162 nfsrv_locklf(lfp); 3163 *lfpp = lfp; 3164 return (0); 3165 } 3166 } 3167 if (!(flags & NFSLCK_OPEN)) 3168 return (-1); 3169 3170 /* 3171 * No match, so chain the new one into the list. 3172 */ 3173 LIST_INIT(&new_lfp->lf_open); 3174 LIST_INIT(&new_lfp->lf_lock); 3175 LIST_INIT(&new_lfp->lf_deleg); 3176 LIST_INIT(&new_lfp->lf_locallock); 3177 LIST_INIT(&new_lfp->lf_rollback); 3178 new_lfp->lf_locallock_lck.nfslock_usecnt = 0; 3179 new_lfp->lf_locallock_lck.nfslock_lock = 0; 3180 new_lfp->lf_usecount = 0; 3181 LIST_INSERT_HEAD(hp, new_lfp, lf_hash); 3182 *lfpp = new_lfp; 3183 *new_lfpp = NULL; 3184 return (0); 3185 } 3186 3187 /* 3188 * This function adds a nfslock lock structure to the list for the associated 3189 * nfsstate and nfslockfile structures. It will be inserted after the 3190 * entry pointed at by insert_lop. 3191 */ 3192 static void 3193 nfsrv_insertlock(struct nfslock *new_lop, struct nfslock *insert_lop, 3194 struct nfsstate *stp, struct nfslockfile *lfp) 3195 { 3196 struct nfslock *lop, *nlop; 3197 3198 new_lop->lo_stp = stp; 3199 new_lop->lo_lfp = lfp; 3200 3201 if (stp != NULL) { 3202 /* Insert in increasing lo_first order */ 3203 lop = LIST_FIRST(&lfp->lf_lock); 3204 if (lop == LIST_END(&lfp->lf_lock) || 3205 new_lop->lo_first <= lop->lo_first) { 3206 LIST_INSERT_HEAD(&lfp->lf_lock, new_lop, lo_lckfile); 3207 } else { 3208 nlop = LIST_NEXT(lop, lo_lckfile); 3209 while (nlop != LIST_END(&lfp->lf_lock) && 3210 nlop->lo_first < new_lop->lo_first) { 3211 lop = nlop; 3212 nlop = LIST_NEXT(lop, lo_lckfile); 3213 } 3214 LIST_INSERT_AFTER(lop, new_lop, lo_lckfile); 3215 } 3216 } else { 3217 new_lop->lo_lckfile.le_prev = NULL; /* list not used */ 3218 } 3219 3220 /* 3221 * Insert after insert_lop, which is overloaded as stp or lfp for 3222 * an empty list. 3223 */ 3224 if (stp == NULL && (struct nfslockfile *)insert_lop == lfp) 3225 LIST_INSERT_HEAD(&lfp->lf_locallock, new_lop, lo_lckowner); 3226 else if ((struct nfsstate *)insert_lop == stp) 3227 LIST_INSERT_HEAD(&stp->ls_lock, new_lop, lo_lckowner); 3228 else 3229 LIST_INSERT_AFTER(insert_lop, new_lop, lo_lckowner); 3230 if (stp != NULL) { 3231 newnfsstats.srvlocks++; 3232 nfsrv_openpluslock++; 3233 } 3234 } 3235 3236 /* 3237 * This function updates the locking for a lock owner and given file. It 3238 * maintains a list of lock ranges ordered on increasing file offset that 3239 * are NFSLCK_READ or NFSLCK_WRITE and non-overlapping (aka POSIX style). 3240 * It always adds new_lop to the list and sometimes uses the one pointed 3241 * at by other_lopp. 3242 */ 3243 static void 3244 nfsrv_updatelock(struct nfsstate *stp, struct nfslock **new_lopp, 3245 struct nfslock **other_lopp, struct nfslockfile *lfp) 3246 { 3247 struct nfslock *new_lop = *new_lopp; 3248 struct nfslock *lop, *tlop, *ilop; 3249 struct nfslock *other_lop = *other_lopp; 3250 int unlock = 0, myfile = 0; 3251 u_int64_t tmp; 3252 3253 /* 3254 * Work down the list until the lock is merged. 3255 */ 3256 if (new_lop->lo_flags & NFSLCK_UNLOCK) 3257 unlock = 1; 3258 if (stp != NULL) { 3259 ilop = (struct nfslock *)stp; 3260 lop = LIST_FIRST(&stp->ls_lock); 3261 } else { 3262 ilop = (struct nfslock *)lfp; 3263 lop = LIST_FIRST(&lfp->lf_locallock); 3264 } 3265 while (lop != NULL) { 3266 /* 3267 * Only check locks for this file that aren't before the start of 3268 * new lock's range. 3269 */ 3270 if (lop->lo_lfp == lfp) { 3271 myfile = 1; 3272 if (lop->lo_end >= new_lop->lo_first) { 3273 if (new_lop->lo_end < lop->lo_first) { 3274 /* 3275 * If the new lock ends before the start of the 3276 * current lock's range, no merge, just insert 3277 * the new lock. 3278 */ 3279 break; 3280 } 3281 if (new_lop->lo_flags == lop->lo_flags || 3282 (new_lop->lo_first <= lop->lo_first && 3283 new_lop->lo_end >= lop->lo_end)) { 3284 /* 3285 * This lock can be absorbed by the new lock/unlock. 3286 * This happens when it covers the entire range 3287 * of the old lock or is contiguous 3288 * with the old lock and is of the same type or an 3289 * unlock. 3290 */ 3291 if (lop->lo_first < new_lop->lo_first) 3292 new_lop->lo_first = lop->lo_first; 3293 if (lop->lo_end > new_lop->lo_end) 3294 new_lop->lo_end = lop->lo_end; 3295 tlop = lop; 3296 lop = LIST_NEXT(lop, lo_lckowner); 3297 nfsrv_freenfslock(tlop); 3298 continue; 3299 } 3300 3301 /* 3302 * All these cases are for contiguous locks that are not the 3303 * same type, so they can't be merged. 3304 */ 3305 if (new_lop->lo_first <= lop->lo_first) { 3306 /* 3307 * This case is where the new lock overlaps with the 3308 * first part of the old lock. Move the start of the 3309 * old lock to just past the end of the new lock. The 3310 * new lock will be inserted in front of the old, since 3311 * ilop hasn't been updated. (We are done now.) 3312 */ 3313 lop->lo_first = new_lop->lo_end; 3314 break; 3315 } 3316 if (new_lop->lo_end >= lop->lo_end) { 3317 /* 3318 * This case is where the new lock overlaps with the 3319 * end of the old lock's range. Move the old lock's 3320 * end to just before the new lock's first and insert 3321 * the new lock after the old lock. 3322 * Might not be done yet, since the new lock could 3323 * overlap further locks with higher ranges. 3324 */ 3325 lop->lo_end = new_lop->lo_first; 3326 ilop = lop; 3327 lop = LIST_NEXT(lop, lo_lckowner); 3328 continue; 3329 } 3330 /* 3331 * The final case is where the new lock's range is in the 3332 * middle of the current lock's and splits the current lock 3333 * up. Use *other_lopp to handle the second part of the 3334 * split old lock range. (We are done now.) 3335 * For unlock, we use new_lop as other_lop and tmp, since 3336 * other_lop and new_lop are the same for this case. 3337 * We noted the unlock case above, so we don't need 3338 * new_lop->lo_flags any longer. 3339 */ 3340 tmp = new_lop->lo_first; 3341 if (other_lop == NULL) { 3342 if (!unlock) 3343 panic("nfsd srv update unlock"); 3344 other_lop = new_lop; 3345 *new_lopp = NULL; 3346 } 3347 other_lop->lo_first = new_lop->lo_end; 3348 other_lop->lo_end = lop->lo_end; 3349 other_lop->lo_flags = lop->lo_flags; 3350 other_lop->lo_stp = stp; 3351 other_lop->lo_lfp = lfp; 3352 lop->lo_end = tmp; 3353 nfsrv_insertlock(other_lop, lop, stp, lfp); 3354 *other_lopp = NULL; 3355 ilop = lop; 3356 break; 3357 } 3358 } 3359 ilop = lop; 3360 lop = LIST_NEXT(lop, lo_lckowner); 3361 if (myfile && (lop == NULL || lop->lo_lfp != lfp)) 3362 break; 3363 } 3364 3365 /* 3366 * Insert the new lock in the list at the appropriate place. 3367 */ 3368 if (!unlock) { 3369 nfsrv_insertlock(new_lop, ilop, stp, lfp); 3370 *new_lopp = NULL; 3371 } 3372 } 3373 3374 /* 3375 * This function handles sequencing of locks, etc. 3376 * It returns an error that indicates what the caller should do. 3377 */ 3378 static int 3379 nfsrv_checkseqid(struct nfsrv_descript *nd, u_int32_t seqid, 3380 struct nfsstate *stp, struct nfsrvcache *op) 3381 { 3382 3383 if (op != nd->nd_rp) 3384 panic("nfsrvstate checkseqid"); 3385 if (!(op->rc_flag & RC_INPROG)) 3386 panic("nfsrvstate not inprog"); 3387 if (stp->ls_op && stp->ls_op->rc_refcnt <= 0) { 3388 printf("refcnt=%d\n", stp->ls_op->rc_refcnt); 3389 panic("nfsrvstate op refcnt"); 3390 } 3391 if ((stp->ls_seq + 1) == seqid) { 3392 if (stp->ls_op) 3393 nfsrvd_derefcache(stp->ls_op); 3394 stp->ls_op = op; 3395 nfsrvd_refcache(op); 3396 stp->ls_seq = seqid; 3397 return (0); 3398 } else if (stp->ls_seq == seqid && stp->ls_op && 3399 op->rc_xid == stp->ls_op->rc_xid && 3400 op->rc_refcnt == 0 && 3401 op->rc_reqlen == stp->ls_op->rc_reqlen && 3402 op->rc_cksum == stp->ls_op->rc_cksum) { 3403 if (stp->ls_op->rc_flag & RC_INPROG) 3404 return (NFSERR_DONTREPLY); 3405 nd->nd_rp = stp->ls_op; 3406 nd->nd_rp->rc_flag |= RC_INPROG; 3407 nfsrvd_delcache(op); 3408 return (NFSERR_REPLYFROMCACHE); 3409 } 3410 return (NFSERR_BADSEQID); 3411 } 3412 3413 /* 3414 * Get the client ip address for callbacks. If the strings can't be parsed, 3415 * just set lc_program to 0 to indicate no callbacks are possible. 3416 * (For cases where the address can't be parsed or is 0.0.0.0.0.0, set 3417 * the address to the client's transport address. This won't be used 3418 * for callbacks, but can be printed out by newnfsstats for info.) 3419 * Return error if the xdr can't be parsed, 0 otherwise. 3420 */ 3421 APPLESTATIC int 3422 nfsrv_getclientipaddr(struct nfsrv_descript *nd, struct nfsclient *clp) 3423 { 3424 u_int32_t *tl; 3425 u_char *cp, *cp2; 3426 int i, j; 3427 struct sockaddr_in *rad, *sad; 3428 u_char protocol[5], addr[24]; 3429 int error = 0, cantparse = 0; 3430 union { 3431 u_long ival; 3432 u_char cval[4]; 3433 } ip; 3434 union { 3435 u_short sval; 3436 u_char cval[2]; 3437 } port; 3438 3439 rad = NFSSOCKADDR(clp->lc_req.nr_nam, struct sockaddr_in *); 3440 rad->sin_family = AF_INET; 3441 rad->sin_len = sizeof (struct sockaddr_in); 3442 rad->sin_addr.s_addr = 0; 3443 rad->sin_port = 0; 3444 clp->lc_req.nr_client = NULL; 3445 clp->lc_req.nr_lock = 0; 3446 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 3447 i = fxdr_unsigned(int, *tl); 3448 if (i >= 3 && i <= 4) { 3449 error = nfsrv_mtostr(nd, protocol, i); 3450 if (error) 3451 goto nfsmout; 3452 if (!strcmp(protocol, "tcp")) { 3453 clp->lc_flags |= LCL_TCPCALLBACK; 3454 clp->lc_req.nr_sotype = SOCK_STREAM; 3455 clp->lc_req.nr_soproto = IPPROTO_TCP; 3456 } else if (!strcmp(protocol, "udp")) { 3457 clp->lc_req.nr_sotype = SOCK_DGRAM; 3458 clp->lc_req.nr_soproto = IPPROTO_UDP; 3459 } else { 3460 cantparse = 1; 3461 } 3462 } else { 3463 cantparse = 1; 3464 if (i > 0) { 3465 error = nfsm_advance(nd, NFSM_RNDUP(i), -1); 3466 if (error) 3467 goto nfsmout; 3468 } 3469 } 3470 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 3471 i = fxdr_unsigned(int, *tl); 3472 if (i < 0) { 3473 error = NFSERR_BADXDR; 3474 goto nfsmout; 3475 } else if (i == 0) { 3476 cantparse = 1; 3477 } else if (!cantparse && i <= 23 && i >= 11) { 3478 error = nfsrv_mtostr(nd, addr, i); 3479 if (error) 3480 goto nfsmout; 3481 3482 /* 3483 * Parse out the address fields. We expect 6 decimal numbers 3484 * separated by '.'s. 3485 */ 3486 cp = addr; 3487 i = 0; 3488 while (*cp && i < 6) { 3489 cp2 = cp; 3490 while (*cp2 && *cp2 != '.') 3491 cp2++; 3492 if (*cp2) 3493 *cp2++ = '\0'; 3494 else if (i != 5) { 3495 cantparse = 1; 3496 break; 3497 } 3498 j = nfsrv_getipnumber(cp); 3499 if (j >= 0) { 3500 if (i < 4) 3501 ip.cval[3 - i] = j; 3502 else 3503 port.cval[5 - i] = j; 3504 } else { 3505 cantparse = 1; 3506 break; 3507 } 3508 cp = cp2; 3509 i++; 3510 } 3511 if (!cantparse) { 3512 if (ip.ival != 0x0) { 3513 rad->sin_addr.s_addr = htonl(ip.ival); 3514 rad->sin_port = htons(port.sval); 3515 } else { 3516 cantparse = 1; 3517 } 3518 } 3519 } else { 3520 cantparse = 1; 3521 if (i > 0) { 3522 error = nfsm_advance(nd, NFSM_RNDUP(i), -1); 3523 if (error) 3524 goto nfsmout; 3525 } 3526 } 3527 if (cantparse) { 3528 sad = NFSSOCKADDR(nd->nd_nam, struct sockaddr_in *); 3529 rad->sin_addr.s_addr = sad->sin_addr.s_addr; 3530 rad->sin_port = 0x0; 3531 clp->lc_program = 0; 3532 } 3533 nfsmout: 3534 return (error); 3535 } 3536 3537 /* 3538 * Turn a string of up to three decimal digits into a number. Return -1 upon 3539 * error. 3540 */ 3541 static int 3542 nfsrv_getipnumber(u_char *cp) 3543 { 3544 int i = 0, j = 0; 3545 3546 while (*cp) { 3547 if (j > 2 || *cp < '0' || *cp > '9') 3548 return (-1); 3549 i *= 10; 3550 i += (*cp - '0'); 3551 cp++; 3552 j++; 3553 } 3554 if (i < 256) 3555 return (i); 3556 return (-1); 3557 } 3558 3559 /* 3560 * This function checks for restart conditions. 3561 */ 3562 static int 3563 nfsrv_checkrestart(nfsquad_t clientid, u_int32_t flags, 3564 nfsv4stateid_t *stateidp, int specialid) 3565 { 3566 int ret; 3567 3568 /* 3569 * First check for a server restart. Open, LockT, ReleaseLockOwner 3570 * and DelegPurge have a clientid, the rest a stateid. 3571 */ 3572 if (flags & 3573 (NFSLCK_OPEN | NFSLCK_TEST | NFSLCK_RELEASE | NFSLCK_DELEGPURGE)) { 3574 if (clientid.lval[0] != nfsrvboottime) 3575 return (NFSERR_STALECLIENTID); 3576 } else if (stateidp->other[0] != nfsrvboottime && 3577 specialid == 0) 3578 return (NFSERR_STALESTATEID); 3579 3580 /* 3581 * Read, Write, Setattr and LockT can return NFSERR_GRACE and do 3582 * not use a lock/open owner seqid#, so the check can be done now. 3583 * (The others will be checked, as required, later.) 3584 */ 3585 if (!(flags & (NFSLCK_CHECK | NFSLCK_TEST))) 3586 return (0); 3587 3588 NFSLOCKSTATE(); 3589 ret = nfsrv_checkgrace(flags); 3590 NFSUNLOCKSTATE(); 3591 return (ret); 3592 } 3593 3594 /* 3595 * Check for grace. 3596 */ 3597 static int 3598 nfsrv_checkgrace(u_int32_t flags) 3599 { 3600 3601 if (nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) { 3602 if (flags & NFSLCK_RECLAIM) 3603 return (NFSERR_NOGRACE); 3604 } else { 3605 if (!(flags & NFSLCK_RECLAIM)) 3606 return (NFSERR_GRACE); 3607 3608 /* 3609 * If grace is almost over and we are still getting Reclaims, 3610 * extend grace a bit. 3611 */ 3612 if ((NFSD_MONOSEC + NFSRV_LEASEDELTA) > 3613 nfsrv_stablefirst.nsf_eograce) 3614 nfsrv_stablefirst.nsf_eograce = NFSD_MONOSEC + 3615 NFSRV_LEASEDELTA; 3616 } 3617 return (0); 3618 } 3619 3620 /* 3621 * Do a server callback. 3622 */ 3623 static int 3624 nfsrv_docallback(struct nfsclient *clp, int procnum, 3625 nfsv4stateid_t *stateidp, int trunc, fhandle_t *fhp, 3626 struct nfsvattr *nap, nfsattrbit_t *attrbitp, NFSPROC_T *p) 3627 { 3628 mbuf_t m; 3629 u_int32_t *tl; 3630 struct nfsrv_descript nfsd, *nd = &nfsd; 3631 struct ucred *cred; 3632 int error = 0; 3633 u_int32_t callback; 3634 3635 cred = newnfs_getcred(); 3636 NFSLOCKSTATE(); /* mostly for lc_cbref++ */ 3637 if (clp->lc_flags & LCL_NEEDSCONFIRM) { 3638 NFSUNLOCKSTATE(); 3639 panic("docallb"); 3640 } 3641 clp->lc_cbref++; 3642 3643 /* 3644 * Fill the callback program# and version into the request 3645 * structure for newnfs_connect() to use. 3646 */ 3647 clp->lc_req.nr_prog = clp->lc_program; 3648 clp->lc_req.nr_vers = NFSV4_CBVERS; 3649 3650 /* 3651 * First, fill in some of the fields of nd and cr. 3652 */ 3653 nd->nd_flag = ND_NFSV4; 3654 if (clp->lc_flags & LCL_GSS) 3655 nd->nd_flag |= ND_KERBV; 3656 nd->nd_repstat = 0; 3657 cred->cr_uid = clp->lc_uid; 3658 cred->cr_gid = clp->lc_gid; 3659 callback = clp->lc_callback; 3660 NFSUNLOCKSTATE(); 3661 cred->cr_ngroups = 1; 3662 3663 /* 3664 * Get the first mbuf for the request. 3665 */ 3666 MGET(m, M_WAIT, MT_DATA); 3667 mbuf_setlen(m, 0); 3668 nd->nd_mreq = nd->nd_mb = m; 3669 nd->nd_bpos = NFSMTOD(m, caddr_t); 3670 3671 /* 3672 * and build the callback request. 3673 */ 3674 if (procnum == NFSV4OP_CBGETATTR) { 3675 nd->nd_procnum = NFSV4PROC_CBCOMPOUND; 3676 (void) nfsm_strtom(nd, "CB Getattr", 10); 3677 NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 3678 *tl++ = txdr_unsigned(NFSV4_MINORVERSION); 3679 *tl++ = txdr_unsigned(callback); 3680 *tl++ = txdr_unsigned(1); 3681 *tl = txdr_unsigned(NFSV4OP_CBGETATTR); 3682 (void) nfsm_fhtom(nd, (u_int8_t *)fhp, NFSX_MYFH, 0); 3683 (void) nfsrv_putattrbit(nd, attrbitp); 3684 } else if (procnum == NFSV4OP_CBRECALL) { 3685 nd->nd_procnum = NFSV4PROC_CBCOMPOUND; 3686 (void) nfsm_strtom(nd, "CB Recall", 9); 3687 NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED + NFSX_STATEID); 3688 *tl++ = txdr_unsigned(NFSV4_MINORVERSION); 3689 *tl++ = txdr_unsigned(callback); 3690 *tl++ = txdr_unsigned(1); 3691 *tl++ = txdr_unsigned(NFSV4OP_CBRECALL); 3692 *tl++ = txdr_unsigned(stateidp->seqid); 3693 NFSBCOPY((caddr_t)stateidp->other, (caddr_t)tl, 3694 NFSX_STATEIDOTHER); 3695 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 3696 if (trunc) 3697 *tl = newnfs_true; 3698 else 3699 *tl = newnfs_false; 3700 (void) nfsm_fhtom(nd, (u_int8_t *)fhp, NFSX_MYFH, 0); 3701 } else { 3702 nd->nd_procnum = NFSV4PROC_CBNULL; 3703 } 3704 3705 /* 3706 * Call newnfs_connect(), as required, and then newnfs_request(). 3707 */ 3708 (void) newnfs_sndlock(&clp->lc_req.nr_lock); 3709 if (clp->lc_req.nr_client == NULL) { 3710 if (nd->nd_procnum == NFSV4PROC_CBNULL) 3711 error = newnfs_connect(NULL, &clp->lc_req, cred, 3712 NULL, 1); 3713 else 3714 error = newnfs_connect(NULL, &clp->lc_req, cred, 3715 NULL, 3); 3716 } 3717 newnfs_sndunlock(&clp->lc_req.nr_lock); 3718 if (!error) { 3719 error = newnfs_request(nd, NULL, clp, &clp->lc_req, NULL, 3720 NULL, cred, clp->lc_program, NFSV4_CBVERS, NULL, 1, NULL); 3721 } 3722 NFSFREECRED(cred); 3723 3724 /* 3725 * If error is set here, the Callback path isn't working 3726 * properly, so twiddle the appropriate LCL_ flags. 3727 * (nd_repstat != 0 indicates the Callback path is working, 3728 * but the callback failed on the client.) 3729 */ 3730 if (error) { 3731 /* 3732 * Mark the callback pathway down, which disabled issuing 3733 * of delegations and gets Renew to return NFSERR_CBPATHDOWN. 3734 */ 3735 NFSLOCKSTATE(); 3736 clp->lc_flags |= LCL_CBDOWN; 3737 NFSUNLOCKSTATE(); 3738 } else { 3739 /* 3740 * Callback worked. If the callback path was down, disable 3741 * callbacks, so no more delegations will be issued. (This 3742 * is done on the assumption that the callback pathway is 3743 * flakey.) 3744 */ 3745 NFSLOCKSTATE(); 3746 if (clp->lc_flags & LCL_CBDOWN) 3747 clp->lc_flags &= ~(LCL_CBDOWN | LCL_CALLBACKSON); 3748 NFSUNLOCKSTATE(); 3749 if (nd->nd_repstat) 3750 error = nd->nd_repstat; 3751 else if (procnum == NFSV4OP_CBGETATTR) 3752 error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, 3753 NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, 3754 p, NULL); 3755 mbuf_freem(nd->nd_mrep); 3756 } 3757 NFSLOCKSTATE(); 3758 clp->lc_cbref--; 3759 if ((clp->lc_flags & LCL_WAKEUPWANTED) && clp->lc_cbref == 0) { 3760 clp->lc_flags &= ~LCL_WAKEUPWANTED; 3761 NFSUNLOCKSTATE(); 3762 wakeup((caddr_t)clp); 3763 } else { 3764 NFSUNLOCKSTATE(); 3765 } 3766 return (error); 3767 } 3768 3769 /* 3770 * Return the next index# for a clientid. Mostly just increment and return 3771 * the next one, but... if the 32bit unsigned does actually wrap around, 3772 * it should be rebooted. 3773 * At an average rate of one new client per second, it will wrap around in 3774 * approximately 136 years. (I think the server will have been shut 3775 * down or rebooted before then.) 3776 */ 3777 static u_int32_t 3778 nfsrv_nextclientindex(void) 3779 { 3780 static u_int32_t client_index = 0; 3781 3782 client_index++; 3783 if (client_index != 0) 3784 return (client_index); 3785 3786 printf("%s: out of clientids\n", __func__); 3787 return (client_index); 3788 } 3789 3790 /* 3791 * Return the next index# for a stateid. Mostly just increment and return 3792 * the next one, but... if the 32bit unsigned does actually wrap around 3793 * (will a BSD server stay up that long?), find 3794 * new start and end values. 3795 */ 3796 static u_int32_t 3797 nfsrv_nextstateindex(struct nfsclient *clp) 3798 { 3799 struct nfsstate *stp; 3800 int i; 3801 u_int32_t canuse, min_index, max_index; 3802 3803 if (!(clp->lc_flags & LCL_INDEXNOTOK)) { 3804 clp->lc_stateindex++; 3805 if (clp->lc_stateindex != clp->lc_statemaxindex) 3806 return (clp->lc_stateindex); 3807 } 3808 3809 /* 3810 * Yuck, we've hit the end. 3811 * Look for a new min and max. 3812 */ 3813 min_index = 0; 3814 max_index = 0xffffffff; 3815 for (i = 0; i < NFSSTATEHASHSIZE; i++) { 3816 LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) { 3817 if (stp->ls_stateid.other[2] > 0x80000000) { 3818 if (stp->ls_stateid.other[2] < max_index) 3819 max_index = stp->ls_stateid.other[2]; 3820 } else { 3821 if (stp->ls_stateid.other[2] > min_index) 3822 min_index = stp->ls_stateid.other[2]; 3823 } 3824 } 3825 } 3826 3827 /* 3828 * Yikes, highly unlikely, but I'll handle it anyhow. 3829 */ 3830 if (min_index == 0x80000000 && max_index == 0x80000001) { 3831 canuse = 0; 3832 /* 3833 * Loop around until we find an unused entry. Return that 3834 * and set LCL_INDEXNOTOK, so the search will continue next time. 3835 * (This is one of those rare cases where a goto is the 3836 * cleanest way to code the loop.) 3837 */ 3838 tryagain: 3839 for (i = 0; i < NFSSTATEHASHSIZE; i++) { 3840 LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) { 3841 if (stp->ls_stateid.other[2] == canuse) { 3842 canuse++; 3843 goto tryagain; 3844 } 3845 } 3846 } 3847 clp->lc_flags |= LCL_INDEXNOTOK; 3848 return (canuse); 3849 } 3850 3851 /* 3852 * Ok to start again from min + 1. 3853 */ 3854 clp->lc_stateindex = min_index + 1; 3855 clp->lc_statemaxindex = max_index; 3856 clp->lc_flags &= ~LCL_INDEXNOTOK; 3857 return (clp->lc_stateindex); 3858 } 3859 3860 /* 3861 * The following functions handle the stable storage file that deals with 3862 * the edge conditions described in RFC3530 Sec. 8.6.3. 3863 * The file is as follows: 3864 * - a single record at the beginning that has the lease time of the 3865 * previous server instance (before the last reboot) and the nfsrvboottime 3866 * values for the previous server boots. 3867 * These previous boot times are used to ensure that the current 3868 * nfsrvboottime does not, somehow, get set to a previous one. 3869 * (This is important so that Stale ClientIDs and StateIDs can 3870 * be recognized.) 3871 * The number of previous nfsvrboottime values preceeds the list. 3872 * - followed by some number of appended records with: 3873 * - client id string 3874 * - flag that indicates it is a record revoking state via lease 3875 * expiration or similar 3876 * OR has successfully acquired state. 3877 * These structures vary in length, with the client string at the end, up 3878 * to NFSV4_OPAQUELIMIT in size. 3879 * 3880 * At the end of the grace period, the file is truncated, the first 3881 * record is rewritten with updated information and any acquired state 3882 * records for successful reclaims of state are written. 3883 * 3884 * Subsequent records are appended when the first state is issued to 3885 * a client and when state is revoked for a client. 3886 * 3887 * When reading the file in, state issued records that come later in 3888 * the file override older ones, since the append log is in cronological order. 3889 * If, for some reason, the file can't be read, the grace period is 3890 * immediately terminated and all reclaims get NFSERR_NOGRACE. 3891 */ 3892 3893 /* 3894 * Read in the stable storage file. Called by nfssvc() before the nfsd 3895 * processes start servicing requests. 3896 */ 3897 APPLESTATIC void 3898 nfsrv_setupstable(NFSPROC_T *p) 3899 { 3900 struct nfsrv_stablefirst *sf = &nfsrv_stablefirst; 3901 struct nfsrv_stable *sp, *nsp; 3902 struct nfst_rec *tsp; 3903 int error, i, tryagain; 3904 off_t off = 0; 3905 int aresid, len; 3906 struct timeval curtime; 3907 3908 /* 3909 * If NFSNSF_UPDATEDONE is set, this is a restart of the nfsds without 3910 * a reboot, so state has not been lost. 3911 */ 3912 if (sf->nsf_flags & NFSNSF_UPDATEDONE) 3913 return; 3914 /* 3915 * Set Grace over just until the file reads successfully. 3916 */ 3917 NFSGETTIME(&curtime); 3918 nfsrvboottime = curtime.tv_sec; 3919 LIST_INIT(&sf->nsf_head); 3920 sf->nsf_flags = (NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK); 3921 sf->nsf_eograce = NFSD_MONOSEC + NFSRV_LEASEDELTA; 3922 if (sf->nsf_fp == NULL) 3923 return; 3924 error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp), 3925 (caddr_t)&sf->nsf_rec, sizeof (struct nfsf_rec), off, UIO_SYSSPACE, 3926 0, NFSFPCRED(sf->nsf_fp), &aresid, p); 3927 if (error || aresid || sf->nsf_numboots == 0 || 3928 sf->nsf_numboots > NFSNSF_MAXNUMBOOTS) 3929 return; 3930 3931 /* 3932 * Now, read in the boottimes. 3933 */ 3934 sf->nsf_bootvals = (time_t *)malloc((sf->nsf_numboots + 1) * 3935 sizeof (time_t), M_TEMP, M_WAITOK); 3936 off = sizeof (struct nfsf_rec); 3937 error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp), 3938 (caddr_t)sf->nsf_bootvals, sf->nsf_numboots * sizeof (time_t), off, 3939 UIO_SYSSPACE, 0, NFSFPCRED(sf->nsf_fp), &aresid, p); 3940 if (error || aresid) { 3941 free((caddr_t)sf->nsf_bootvals, M_TEMP); 3942 sf->nsf_bootvals = NULL; 3943 return; 3944 } 3945 3946 /* 3947 * Make sure this nfsrvboottime is different from all recorded 3948 * previous ones. 3949 */ 3950 do { 3951 tryagain = 0; 3952 for (i = 0; i < sf->nsf_numboots; i++) { 3953 if (nfsrvboottime == sf->nsf_bootvals[i]) { 3954 nfsrvboottime++; 3955 tryagain = 1; 3956 break; 3957 } 3958 } 3959 } while (tryagain); 3960 3961 sf->nsf_flags |= NFSNSF_OK; 3962 off += (sf->nsf_numboots * sizeof (time_t)); 3963 3964 /* 3965 * Read through the file, building a list of records for grace 3966 * checking. 3967 * Each record is between sizeof (struct nfst_rec) and 3968 * sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1 3969 * and is actually sizeof (struct nfst_rec) + nst_len - 1. 3970 */ 3971 tsp = (struct nfst_rec *)malloc(sizeof (struct nfst_rec) + 3972 NFSV4_OPAQUELIMIT - 1, M_TEMP, M_WAITOK); 3973 do { 3974 error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp), 3975 (caddr_t)tsp, sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1, 3976 off, UIO_SYSSPACE, 0, NFSFPCRED(sf->nsf_fp), &aresid, p); 3977 len = (sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1) - aresid; 3978 if (error || (len > 0 && (len < sizeof (struct nfst_rec) || 3979 len < (sizeof (struct nfst_rec) + tsp->len - 1)))) { 3980 /* 3981 * Yuck, the file has been corrupted, so just return 3982 * after clearing out any restart state, so the grace period 3983 * is over. 3984 */ 3985 LIST_FOREACH_SAFE(sp, &sf->nsf_head, nst_list, nsp) { 3986 LIST_REMOVE(sp, nst_list); 3987 free((caddr_t)sp, M_TEMP); 3988 } 3989 free((caddr_t)tsp, M_TEMP); 3990 sf->nsf_flags &= ~NFSNSF_OK; 3991 free((caddr_t)sf->nsf_bootvals, M_TEMP); 3992 sf->nsf_bootvals = NULL; 3993 return; 3994 } 3995 if (len > 0) { 3996 off += sizeof (struct nfst_rec) + tsp->len - 1; 3997 /* 3998 * Search the list for a matching client. 3999 */ 4000 LIST_FOREACH(sp, &sf->nsf_head, nst_list) { 4001 if (tsp->len == sp->nst_len && 4002 !NFSBCMP(tsp->client, sp->nst_client, tsp->len)) 4003 break; 4004 } 4005 if (sp == LIST_END(&sf->nsf_head)) { 4006 sp = (struct nfsrv_stable *)malloc(tsp->len + 4007 sizeof (struct nfsrv_stable) - 1, M_TEMP, 4008 M_WAITOK); 4009 NFSBCOPY((caddr_t)tsp, (caddr_t)&sp->nst_rec, 4010 sizeof (struct nfst_rec) + tsp->len - 1); 4011 LIST_INSERT_HEAD(&sf->nsf_head, sp, nst_list); 4012 } else { 4013 if (tsp->flag == NFSNST_REVOKE) 4014 sp->nst_flag |= NFSNST_REVOKE; 4015 else 4016 /* 4017 * A subsequent timestamp indicates the client 4018 * did a setclientid/confirm and any previous 4019 * revoke is no longer relevant. 4020 */ 4021 sp->nst_flag &= ~NFSNST_REVOKE; 4022 } 4023 } 4024 } while (len > 0); 4025 free((caddr_t)tsp, M_TEMP); 4026 sf->nsf_flags = NFSNSF_OK; 4027 sf->nsf_eograce = NFSD_MONOSEC + sf->nsf_lease + 4028 NFSRV_LEASEDELTA; 4029 } 4030 4031 /* 4032 * Update the stable storage file, now that the grace period is over. 4033 */ 4034 APPLESTATIC void 4035 nfsrv_updatestable(NFSPROC_T *p) 4036 { 4037 struct nfsrv_stablefirst *sf = &nfsrv_stablefirst; 4038 struct nfsrv_stable *sp, *nsp; 4039 int i; 4040 struct nfsvattr nva; 4041 vnode_t vp; 4042 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 500000) 4043 mount_t mp = NULL; 4044 #endif 4045 int error; 4046 4047 if (sf->nsf_fp == NULL || (sf->nsf_flags & NFSNSF_UPDATEDONE)) 4048 return; 4049 sf->nsf_flags |= NFSNSF_UPDATEDONE; 4050 /* 4051 * Ok, we need to rewrite the stable storage file. 4052 * - truncate to 0 length 4053 * - write the new first structure 4054 * - loop through the data structures, writing out any that 4055 * have timestamps older than the old boot 4056 */ 4057 if (sf->nsf_bootvals) { 4058 sf->nsf_numboots++; 4059 for (i = sf->nsf_numboots - 2; i >= 0; i--) 4060 sf->nsf_bootvals[i + 1] = sf->nsf_bootvals[i]; 4061 } else { 4062 sf->nsf_numboots = 1; 4063 sf->nsf_bootvals = (time_t *)malloc(sizeof (time_t), 4064 M_TEMP, M_WAITOK); 4065 } 4066 sf->nsf_bootvals[0] = nfsrvboottime; 4067 sf->nsf_lease = nfsrv_lease; 4068 NFSVNO_ATTRINIT(&nva); 4069 NFSVNO_SETATTRVAL(&nva, size, 0); 4070 vp = NFSFPVNODE(sf->nsf_fp); 4071 NFS_STARTWRITE(vp, &mp); 4072 NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY, p); 4073 error = nfsvno_setattr(vp, &nva, NFSFPCRED(sf->nsf_fp), p, NULL); 4074 NFS_ENDWRITE(mp); 4075 NFSVOPUNLOCK(vp, 0, p); 4076 if (!error) 4077 error = NFSD_RDWR(UIO_WRITE, vp, 4078 (caddr_t)&sf->nsf_rec, sizeof (struct nfsf_rec), (off_t)0, 4079 UIO_SYSSPACE, IO_SYNC, NFSFPCRED(sf->nsf_fp), NULL, p); 4080 if (!error) 4081 error = NFSD_RDWR(UIO_WRITE, vp, 4082 (caddr_t)sf->nsf_bootvals, 4083 sf->nsf_numboots * sizeof (time_t), 4084 (off_t)(sizeof (struct nfsf_rec)), 4085 UIO_SYSSPACE, IO_SYNC, NFSFPCRED(sf->nsf_fp), NULL, p); 4086 free((caddr_t)sf->nsf_bootvals, M_TEMP); 4087 sf->nsf_bootvals = NULL; 4088 if (error) { 4089 sf->nsf_flags &= ~NFSNSF_OK; 4090 printf("EEK! Can't write NfsV4 stable storage file\n"); 4091 return; 4092 } 4093 sf->nsf_flags |= NFSNSF_OK; 4094 4095 /* 4096 * Loop through the list and write out timestamp records for 4097 * any clients that successfully reclaimed state. 4098 */ 4099 LIST_FOREACH_SAFE(sp, &sf->nsf_head, nst_list, nsp) { 4100 if (sp->nst_flag & NFSNST_GOTSTATE) { 4101 nfsrv_writestable(sp->nst_client, sp->nst_len, 4102 NFSNST_NEWSTATE, p); 4103 sp->nst_clp->lc_flags |= LCL_STAMPEDSTABLE; 4104 } 4105 LIST_REMOVE(sp, nst_list); 4106 free((caddr_t)sp, M_TEMP); 4107 } 4108 } 4109 4110 /* 4111 * Append a record to the stable storage file. 4112 */ 4113 APPLESTATIC void 4114 nfsrv_writestable(u_char *client, int len, int flag, NFSPROC_T *p) 4115 { 4116 struct nfsrv_stablefirst *sf = &nfsrv_stablefirst; 4117 struct nfst_rec *sp; 4118 int error; 4119 4120 if (!(sf->nsf_flags & NFSNSF_OK) || sf->nsf_fp == NULL) 4121 return; 4122 sp = (struct nfst_rec *)malloc(sizeof (struct nfst_rec) + 4123 len - 1, M_TEMP, M_WAITOK); 4124 sp->len = len; 4125 NFSBCOPY(client, sp->client, len); 4126 sp->flag = flag; 4127 error = NFSD_RDWR(UIO_WRITE, NFSFPVNODE(sf->nsf_fp), 4128 (caddr_t)sp, sizeof (struct nfst_rec) + len - 1, (off_t)0, 4129 UIO_SYSSPACE, (IO_SYNC | IO_APPEND), NFSFPCRED(sf->nsf_fp), NULL, p); 4130 free((caddr_t)sp, M_TEMP); 4131 if (error) { 4132 sf->nsf_flags &= ~NFSNSF_OK; 4133 printf("EEK! Can't write NfsV4 stable storage file\n"); 4134 } 4135 } 4136 4137 /* 4138 * This function is called during the grace period to mark a client 4139 * that successfully reclaimed state. 4140 */ 4141 static void 4142 nfsrv_markstable(struct nfsclient *clp) 4143 { 4144 struct nfsrv_stable *sp; 4145 4146 /* 4147 * First find the client structure. 4148 */ 4149 LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) { 4150 if (sp->nst_len == clp->lc_idlen && 4151 !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len)) 4152 break; 4153 } 4154 if (sp == LIST_END(&nfsrv_stablefirst.nsf_head)) 4155 return; 4156 4157 /* 4158 * Now, just mark it and set the nfsclient back pointer. 4159 */ 4160 sp->nst_flag |= NFSNST_GOTSTATE; 4161 sp->nst_clp = clp; 4162 } 4163 4164 /* 4165 * This function is called for a reclaim, to see if it gets grace. 4166 * It returns 0 if a reclaim is allowed, 1 otherwise. 4167 */ 4168 static int 4169 nfsrv_checkstable(struct nfsclient *clp) 4170 { 4171 struct nfsrv_stable *sp; 4172 4173 /* 4174 * First, find the entry for the client. 4175 */ 4176 LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) { 4177 if (sp->nst_len == clp->lc_idlen && 4178 !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len)) 4179 break; 4180 } 4181 4182 /* 4183 * If not in the list, state was revoked or no state was issued 4184 * since the previous reboot, a reclaim is denied. 4185 */ 4186 if (sp == LIST_END(&nfsrv_stablefirst.nsf_head) || 4187 (sp->nst_flag & NFSNST_REVOKE) || 4188 !(nfsrv_stablefirst.nsf_flags & NFSNSF_OK)) 4189 return (1); 4190 return (0); 4191 } 4192 4193 /* 4194 * Test for and try to clear out a conflicting client. This is called by 4195 * nfsrv_lockctrl() and nfsrv_openctrl() when conflicts with other clients 4196 * a found. 4197 * The trick here is that it can't revoke a conflicting client with an 4198 * expired lease unless it holds the v4root lock, so... 4199 * If no v4root lock, get the lock and return 1 to indicate "try again". 4200 * Return 0 to indicate the conflict can't be revoked and 1 to indicate 4201 * the revocation worked and the conflicting client is "bye, bye", so it 4202 * can be tried again. 4203 * Unlocks State before a non-zero value is returned. 4204 */ 4205 static int 4206 nfsrv_clientconflict(struct nfsclient *clp, int *haslockp, __unused vnode_t vp, 4207 NFSPROC_T *p) 4208 { 4209 int gotlock; 4210 4211 /* 4212 * If lease hasn't expired, we can't fix it. 4213 */ 4214 if (clp->lc_expiry >= NFSD_MONOSEC || 4215 !(nfsrv_stablefirst.nsf_flags & NFSNSF_UPDATEDONE)) 4216 return (0); 4217 if (*haslockp == 0) { 4218 NFSUNLOCKSTATE(); 4219 NFSVOPUNLOCK(vp, 0, p); 4220 NFSLOCKV4ROOTMUTEX(); 4221 nfsv4_relref(&nfsv4rootfs_lock); 4222 do { 4223 gotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 4224 NFSV4ROOTLOCKMUTEXPTR); 4225 } while (!gotlock); 4226 NFSUNLOCKV4ROOTMUTEX(); 4227 NFSLOCKSTATE(); /* to avoid a race with */ 4228 NFSUNLOCKSTATE(); /* nfsrv_servertimer() */ 4229 *haslockp = 1; 4230 NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY, p); 4231 return (1); 4232 } 4233 NFSUNLOCKSTATE(); 4234 4235 /* 4236 * Ok, we can expire the conflicting client. 4237 */ 4238 nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p); 4239 nfsrv_cleanclient(clp, p); 4240 nfsrv_freedeleglist(&clp->lc_deleg); 4241 nfsrv_freedeleglist(&clp->lc_olddeleg); 4242 LIST_REMOVE(clp, lc_hash); 4243 nfsrv_zapclient(clp, p); 4244 return (1); 4245 } 4246 4247 4248 /* 4249 * Resolve a delegation conflict. 4250 * Returns 0 to indicate the conflict was resolved without sleeping. 4251 * Return -1 to indicate that the caller should check for conflicts again. 4252 * Return > 0 for an error that should be returned, normally NFSERR_DELAY. 4253 * 4254 * Also, manipulate the nfsv4root_lock, as required. It isn't changed 4255 * for a return of 0, since there was no sleep and it could be required 4256 * later. It is released for a return of NFSERR_DELAY, since the caller 4257 * will return that error. It is released when a sleep was done waiting 4258 * for the delegation to be returned or expire (so that other nfsds can 4259 * handle ops). Then, it must be acquired for the write to stable storage. 4260 * (This function is somewhat similar to nfsrv_clientconflict(), but 4261 * the semantics differ in a couple of subtle ways. The return of 0 4262 * indicates the conflict was resolved without sleeping here, not 4263 * that the conflict can't be resolved and the handling of nfsv4root_lock 4264 * differs, as noted above.) 4265 * Unlocks State before returning a non-zero value. 4266 */ 4267 static int 4268 nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, NFSPROC_T *p, 4269 __unused vnode_t vp) 4270 { 4271 struct nfsclient *clp = stp->ls_clp; 4272 int gotlock, error, retrycnt, zapped_clp; 4273 nfsv4stateid_t tstateid; 4274 fhandle_t tfh; 4275 4276 /* 4277 * If the conflict is with an old delegation... 4278 */ 4279 if (stp->ls_flags & NFSLCK_OLDDELEG) { 4280 /* 4281 * You can delete it, if it has expired. 4282 */ 4283 if (clp->lc_delegtime < NFSD_MONOSEC) { 4284 nfsrv_freedeleg(stp); 4285 NFSUNLOCKSTATE(); 4286 return (-1); 4287 } 4288 NFSUNLOCKSTATE(); 4289 /* 4290 * During this delay, the old delegation could expire or it 4291 * could be recovered by the client via an Open with 4292 * CLAIM_DELEGATE_PREV. 4293 * Release the nfsv4root_lock, if held. 4294 */ 4295 if (*haslockp) { 4296 *haslockp = 0; 4297 NFSLOCKV4ROOTMUTEX(); 4298 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4299 NFSUNLOCKV4ROOTMUTEX(); 4300 } 4301 return (NFSERR_DELAY); 4302 } 4303 4304 /* 4305 * It's a current delegation, so: 4306 * - check to see if the delegation has expired 4307 * - if so, get the v4root lock and then expire it 4308 */ 4309 if (!(stp->ls_flags & NFSLCK_DELEGRECALL)) { 4310 /* 4311 * - do a recall callback, since not yet done 4312 * For now, never allow truncate to be set. To use 4313 * truncate safely, it must be guaranteed that the 4314 * Remove, Rename or Setattr with size of 0 will 4315 * succeed and that would require major changes to 4316 * the VFS/Vnode OPs. 4317 * Set the expiry time large enough so that it won't expire 4318 * until after the callback, then set it correctly, once 4319 * the callback is done. (The delegation will now time 4320 * out whether or not the Recall worked ok. The timeout 4321 * will be extended when ops are done on the delegation 4322 * stateid, up to the timelimit.) 4323 */ 4324 stp->ls_delegtime = NFSD_MONOSEC + (2 * nfsrv_lease) + 4325 NFSRV_LEASEDELTA; 4326 stp->ls_delegtimelimit = NFSD_MONOSEC + (6 * nfsrv_lease) + 4327 NFSRV_LEASEDELTA; 4328 stp->ls_flags |= NFSLCK_DELEGRECALL; 4329 4330 /* 4331 * Loop NFSRV_CBRETRYCNT times while the CBRecall replies 4332 * NFSERR_BADSTATEID or NFSERR_BADHANDLE. This is done 4333 * in order to try and avoid a race that could happen 4334 * when a CBRecall request passed the Open reply with 4335 * the delegation in it when transitting the network. 4336 * Since nfsrv_docallback will sleep, don't use stp after 4337 * the call. 4338 */ 4339 NFSBCOPY((caddr_t)&stp->ls_stateid, (caddr_t)&tstateid, 4340 sizeof (tstateid)); 4341 NFSBCOPY((caddr_t)&stp->ls_lfp->lf_fh, (caddr_t)&tfh, 4342 sizeof (tfh)); 4343 NFSUNLOCKSTATE(); 4344 if (*haslockp) { 4345 *haslockp = 0; 4346 NFSLOCKV4ROOTMUTEX(); 4347 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4348 NFSUNLOCKV4ROOTMUTEX(); 4349 } 4350 retrycnt = 0; 4351 do { 4352 error = nfsrv_docallback(clp, NFSV4OP_CBRECALL, 4353 &tstateid, 0, &tfh, NULL, NULL, p); 4354 retrycnt++; 4355 } while ((error == NFSERR_BADSTATEID || 4356 error == NFSERR_BADHANDLE) && retrycnt < NFSV4_CBRETRYCNT); 4357 return (NFSERR_DELAY); 4358 } 4359 4360 if (clp->lc_expiry >= NFSD_MONOSEC && 4361 stp->ls_delegtime >= NFSD_MONOSEC) { 4362 NFSUNLOCKSTATE(); 4363 /* 4364 * A recall has been done, but it has not yet expired. 4365 * So, RETURN_DELAY. 4366 */ 4367 if (*haslockp) { 4368 *haslockp = 0; 4369 NFSLOCKV4ROOTMUTEX(); 4370 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4371 NFSUNLOCKV4ROOTMUTEX(); 4372 } 4373 return (NFSERR_DELAY); 4374 } 4375 4376 /* 4377 * If we don't yet have the lock, just get it and then return, 4378 * since we need that before deleting expired state, such as 4379 * this delegation. 4380 * When getting the lock, unlock the vnode, so other nfsds that 4381 * are in progress, won't get stuck waiting for the vnode lock. 4382 */ 4383 if (*haslockp == 0) { 4384 NFSUNLOCKSTATE(); 4385 NFSVOPUNLOCK(vp, 0, p); 4386 NFSLOCKV4ROOTMUTEX(); 4387 nfsv4_relref(&nfsv4rootfs_lock); 4388 do { 4389 gotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL, 4390 NFSV4ROOTLOCKMUTEXPTR); 4391 } while (!gotlock); 4392 NFSUNLOCKV4ROOTMUTEX(); 4393 NFSLOCKSTATE(); /* to avoid a race with */ 4394 NFSUNLOCKSTATE(); /* nfsrv_servertimer() */ 4395 *haslockp = 1; 4396 NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY, p); 4397 return (-1); 4398 } 4399 4400 NFSUNLOCKSTATE(); 4401 /* 4402 * Ok, we can delete the expired delegation. 4403 * First, write the Revoke record to stable storage and then 4404 * clear out the conflict. 4405 * Since all other nfsd threads are now blocked, we can safely 4406 * sleep without the state changing. 4407 */ 4408 nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p); 4409 if (clp->lc_expiry < NFSD_MONOSEC) { 4410 nfsrv_cleanclient(clp, p); 4411 nfsrv_freedeleglist(&clp->lc_deleg); 4412 nfsrv_freedeleglist(&clp->lc_olddeleg); 4413 LIST_REMOVE(clp, lc_hash); 4414 zapped_clp = 1; 4415 } else { 4416 nfsrv_freedeleg(stp); 4417 zapped_clp = 0; 4418 } 4419 if (zapped_clp) 4420 nfsrv_zapclient(clp, p); 4421 return (-1); 4422 } 4423 4424 /* 4425 * Check for a remove allowed, if remove is set to 1 and get rid of 4426 * delegations. 4427 */ 4428 APPLESTATIC int 4429 nfsrv_checkremove(vnode_t vp, int remove, NFSPROC_T *p) 4430 { 4431 struct nfsstate *stp; 4432 struct nfslockfile *lfp; 4433 int error, haslock = 0; 4434 fhandle_t nfh; 4435 4436 /* 4437 * First, get the lock file structure. 4438 * (A return of -1 means no associated state, so remove ok.) 4439 */ 4440 error = nfsrv_getlockfh(vp, NFSLCK_CHECK, NULL, &nfh, p); 4441 tryagain: 4442 NFSLOCKSTATE(); 4443 if (!error) 4444 error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh, 0); 4445 if (error) { 4446 NFSUNLOCKSTATE(); 4447 if (haslock) { 4448 NFSLOCKV4ROOTMUTEX(); 4449 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4450 NFSUNLOCKV4ROOTMUTEX(); 4451 } 4452 if (error == -1) 4453 return (0); 4454 return (error); 4455 } 4456 4457 /* 4458 * Now, we must Recall any delegations. 4459 */ 4460 error = nfsrv_cleandeleg(vp, lfp, NULL, &haslock, p); 4461 if (error) { 4462 /* 4463 * nfsrv_cleandeleg() unlocks state for non-zero 4464 * return. 4465 */ 4466 if (error == -1) 4467 goto tryagain; 4468 if (haslock) { 4469 NFSLOCKV4ROOTMUTEX(); 4470 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4471 NFSUNLOCKV4ROOTMUTEX(); 4472 } 4473 return (error); 4474 } 4475 4476 /* 4477 * Now, look for a conflicting open share. 4478 */ 4479 if (remove) { 4480 LIST_FOREACH(stp, &lfp->lf_open, ls_file) { 4481 if (stp->ls_flags & NFSLCK_WRITEDENY) { 4482 error = NFSERR_FILEOPEN; 4483 break; 4484 } 4485 } 4486 } 4487 4488 NFSUNLOCKSTATE(); 4489 if (haslock) { 4490 NFSLOCKV4ROOTMUTEX(); 4491 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4492 NFSUNLOCKV4ROOTMUTEX(); 4493 } 4494 return (error); 4495 } 4496 4497 /* 4498 * Clear out all delegations for the file referred to by lfp. 4499 * May return NFSERR_DELAY, if there will be a delay waiting for 4500 * delegations to expire. 4501 * Returns -1 to indicate it slept while recalling a delegation. 4502 * This function has the side effect of deleting the nfslockfile structure, 4503 * if it no longer has associated state and didn't have to sleep. 4504 * Unlocks State before a non-zero value is returned. 4505 */ 4506 static int 4507 nfsrv_cleandeleg(vnode_t vp, struct nfslockfile *lfp, 4508 struct nfsclient *clp, int *haslockp, NFSPROC_T *p) 4509 { 4510 struct nfsstate *stp, *nstp; 4511 int ret; 4512 4513 stp = LIST_FIRST(&lfp->lf_deleg); 4514 while (stp != LIST_END(&lfp->lf_deleg)) { 4515 nstp = LIST_NEXT(stp, ls_file); 4516 if (stp->ls_clp != clp) { 4517 ret = nfsrv_delegconflict(stp, haslockp, p, vp); 4518 if (ret) { 4519 /* 4520 * nfsrv_delegconflict() unlocks state 4521 * when it returns non-zero. 4522 */ 4523 return (ret); 4524 } 4525 } 4526 stp = nstp; 4527 } 4528 return (0); 4529 } 4530 4531 /* 4532 * There are certain operations that, when being done outside of NFSv4, 4533 * require that any NFSv4 delegation for the file be recalled. 4534 * This function is to be called for those cases: 4535 * VOP_RENAME() - When a delegation is being recalled for any reason, 4536 * the client may have to do Opens against the server, using the file's 4537 * final component name. If the file has been renamed on the server, 4538 * that component name will be incorrect and the Open will fail. 4539 * VOP_REMOVE() - Theoretically, a client could Open a file after it has 4540 * been removed on the server, if there is a delegation issued to 4541 * that client for the file. I say "theoretically" since clients 4542 * normally do an Access Op before the Open and that Access Op will 4543 * fail with ESTALE. Note that NFSv2 and 3 don't even do Opens, so 4544 * they will detect the file's removal in the same manner. (There is 4545 * one case where RFC3530 allows a client to do an Open without first 4546 * doing an Access Op, which is passage of a check against the ACE 4547 * returned with a Write delegation, but current practice is to ignore 4548 * the ACE and always do an Access Op.) 4549 * Since the functions can only be called with an unlocked vnode, this 4550 * can't be done at this time. 4551 * VOP_ADVLOCK() - When a client holds a delegation, it can issue byte range 4552 * locks locally in the client, which are not visible to the server. To 4553 * deal with this, issuing of delegations for a vnode must be disabled 4554 * and all delegations for the vnode recalled. This is done via the 4555 * second function, using the VV_DISABLEDELEG vflag on the vnode. 4556 */ 4557 APPLESTATIC void 4558 nfsd_recalldelegation(vnode_t vp, NFSPROC_T *p) 4559 { 4560 struct timespec mytime; 4561 int32_t starttime; 4562 int error; 4563 4564 KASSERT(!VOP_ISLOCKED(vp), ("vp %p is locked", vp)); 4565 4566 /* 4567 * First, check to see if the server is currently running and it has 4568 * been called for a regular file when issuing delegations. 4569 */ 4570 if (newnfs_numnfsd == 0 || vp->v_type != VREG || 4571 nfsrv_issuedelegs == 0) 4572 return; 4573 4574 /* 4575 * Now, call nfsrv_checkremove() in a loop while it returns 4576 * NFSERR_DELAY. Return upon any other error or when timed out. 4577 */ 4578 NFSGETNANOTIME(&mytime); 4579 starttime = (u_int32_t)mytime.tv_sec; 4580 do { 4581 error = nfsrv_checkremove(vp, 0, p); 4582 if (error == NFSERR_DELAY) { 4583 NFSGETNANOTIME(&mytime); 4584 if (((u_int32_t)mytime.tv_sec - starttime) > 4585 NFS_REMOVETIMEO && 4586 ((u_int32_t)mytime.tv_sec - starttime) < 4587 100000) 4588 return; 4589 /* Sleep for a short period of time */ 4590 (void) nfs_catnap(PZERO, 0, "nfsremove"); 4591 } 4592 } while (error == NFSERR_DELAY); 4593 } 4594 4595 APPLESTATIC void 4596 nfsd_disabledelegation(vnode_t vp, NFSPROC_T *p) 4597 { 4598 4599 #ifdef VV_DISABLEDELEG 4600 /* 4601 * First, flag issuance of delegations disabled. 4602 */ 4603 atomic_set_long(&vp->v_vflag, VV_DISABLEDELEG); 4604 #endif 4605 4606 /* 4607 * Then call nfsd_recalldelegation() to get rid of all extant 4608 * delegations. 4609 */ 4610 nfsd_recalldelegation(vp, p); 4611 } 4612 4613 /* 4614 * Check for conflicting locks, etc. and then get rid of delegations. 4615 * (At one point I thought that I should get rid of delegations for any 4616 * Setattr, since it could potentially disallow the I/O op (read or write) 4617 * allowed by the delegation. However, Setattr Ops that aren't changing 4618 * the size get a stateid of all 0s, so you can't tell if it is a delegation 4619 * for the same client or a different one, so I decided to only get rid 4620 * of delegations for other clients when the size is being changed.) 4621 * In general, a Setattr can disable NFS I/O Ops that are outstanding, such 4622 * as Write backs, even if there is no delegation, so it really isn't any 4623 * different?) 4624 */ 4625 APPLESTATIC int 4626 nfsrv_checksetattr(vnode_t vp, struct nfsrv_descript *nd, 4627 nfsv4stateid_t *stateidp, struct nfsvattr *nvap, nfsattrbit_t *attrbitp, 4628 struct nfsexstuff *exp, NFSPROC_T *p) 4629 { 4630 struct nfsstate st, *stp = &st; 4631 struct nfslock lo, *lop = &lo; 4632 int error = 0; 4633 nfsquad_t clientid; 4634 4635 if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SIZE)) { 4636 stp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS); 4637 lop->lo_first = nvap->na_size; 4638 } else { 4639 stp->ls_flags = 0; 4640 lop->lo_first = 0; 4641 } 4642 if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNER) || 4643 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP) || 4644 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_MODE) || 4645 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_ACL)) 4646 stp->ls_flags |= NFSLCK_SETATTR; 4647 if (stp->ls_flags == 0) 4648 return (0); 4649 lop->lo_end = NFS64BITSSET; 4650 lop->lo_flags = NFSLCK_WRITE; 4651 stp->ls_ownerlen = 0; 4652 stp->ls_op = NULL; 4653 stp->ls_uid = nd->nd_cred->cr_uid; 4654 stp->ls_stateid.seqid = stateidp->seqid; 4655 clientid.lval[0] = stp->ls_stateid.other[0] = stateidp->other[0]; 4656 clientid.lval[1] = stp->ls_stateid.other[1] = stateidp->other[1]; 4657 stp->ls_stateid.other[2] = stateidp->other[2]; 4658 error = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid, 4659 stateidp, exp, nd, p); 4660 return (error); 4661 } 4662 4663 /* 4664 * Check for a write delegation and do a CBGETATTR if there is one, updating 4665 * the attributes, as required. 4666 * Should I return an error if I can't get the attributes? (For now, I'll 4667 * just return ok. 4668 */ 4669 APPLESTATIC int 4670 nfsrv_checkgetattr(struct nfsrv_descript *nd, vnode_t vp, 4671 struct nfsvattr *nvap, nfsattrbit_t *attrbitp, struct ucred *cred, 4672 NFSPROC_T *p) 4673 { 4674 struct nfsstate *stp; 4675 struct nfslockfile *lfp; 4676 struct nfsclient *clp; 4677 struct nfsvattr nva; 4678 fhandle_t nfh; 4679 int error; 4680 nfsattrbit_t cbbits; 4681 u_quad_t delegfilerev; 4682 4683 NFSCBGETATTR_ATTRBIT(attrbitp, &cbbits); 4684 if (!NFSNONZERO_ATTRBIT(&cbbits)) 4685 return (0); 4686 4687 /* 4688 * Get the lock file structure. 4689 * (A return of -1 means no associated state, so return ok.) 4690 */ 4691 error = nfsrv_getlockfh(vp, NFSLCK_CHECK, NULL, &nfh, p); 4692 NFSLOCKSTATE(); 4693 if (!error) 4694 error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh, 0); 4695 if (error) { 4696 NFSUNLOCKSTATE(); 4697 if (error == -1) 4698 return (0); 4699 return (error); 4700 } 4701 4702 /* 4703 * Now, look for a write delegation. 4704 */ 4705 LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) { 4706 if (stp->ls_flags & NFSLCK_DELEGWRITE) 4707 break; 4708 } 4709 if (stp == LIST_END(&lfp->lf_deleg)) { 4710 NFSUNLOCKSTATE(); 4711 return (0); 4712 } 4713 clp = stp->ls_clp; 4714 delegfilerev = stp->ls_filerev; 4715 4716 /* 4717 * If the Write delegation was issued as a part of this Compound RPC 4718 * or if we have an Implied Clientid (used in a previous Op in this 4719 * compound) and it is the client the delegation was issued to, 4720 * just return ok. 4721 * I also assume that it is from the same client iff the network 4722 * host IP address is the same as the callback address. (Not 4723 * exactly correct by the RFC, but avoids a lot of Getattr 4724 * callbacks.) 4725 */ 4726 if (nd->nd_compref == stp->ls_compref || 4727 ((nd->nd_flag & ND_IMPLIEDCLID) && 4728 clp->lc_clientid.qval == nd->nd_clientid.qval) || 4729 nfsaddr2_match(clp->lc_req.nr_nam, nd->nd_nam)) { 4730 NFSUNLOCKSTATE(); 4731 return (0); 4732 } 4733 4734 /* 4735 * We are now done with the delegation state structure, 4736 * so the statelock can be released and we can now tsleep(). 4737 */ 4738 4739 /* 4740 * Now, we must do the CB Getattr callback, to see if Change or Size 4741 * has changed. 4742 */ 4743 if (clp->lc_expiry >= NFSD_MONOSEC) { 4744 NFSUNLOCKSTATE(); 4745 NFSVNO_ATTRINIT(&nva); 4746 nva.na_filerev = NFS64BITSSET; 4747 error = nfsrv_docallback(clp, NFSV4OP_CBGETATTR, NULL, 4748 0, &nfh, &nva, &cbbits, p); 4749 if (!error) { 4750 if ((nva.na_filerev != NFS64BITSSET && 4751 nva.na_filerev > delegfilerev) || 4752 (NFSVNO_ISSETSIZE(&nva) && 4753 nva.na_size != nvap->na_size)) { 4754 nfsvno_updfilerev(vp, nvap, cred, p); 4755 if (NFSVNO_ISSETSIZE(&nva)) 4756 nvap->na_size = nva.na_size; 4757 } 4758 } 4759 } else { 4760 NFSUNLOCKSTATE(); 4761 } 4762 return (0); 4763 } 4764 4765 /* 4766 * This function looks for openowners that haven't had any opens for 4767 * a while and throws them away. Called by an nfsd when NFSNSF_NOOPENS 4768 * is set. 4769 */ 4770 APPLESTATIC void 4771 nfsrv_throwawayopens(NFSPROC_T *p) 4772 { 4773 struct nfsclient *clp, *nclp; 4774 struct nfsstate *stp, *nstp; 4775 int i; 4776 4777 NFSLOCKSTATE(); 4778 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NOOPENS; 4779 /* 4780 * For each client... 4781 */ 4782 for (i = 0; i < NFSCLIENTHASHSIZE; i++) { 4783 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, nclp) { 4784 LIST_FOREACH_SAFE(stp, &clp->lc_open, ls_list, nstp) { 4785 if (LIST_EMPTY(&stp->ls_open) && 4786 (stp->ls_noopens > NFSNOOPEN || 4787 (nfsrv_openpluslock * 2) > 4788 NFSRV_V4STATELIMIT)) 4789 nfsrv_freeopenowner(stp, 0, p); 4790 } 4791 } 4792 } 4793 NFSUNLOCKSTATE(); 4794 } 4795 4796 /* 4797 * This function checks to see if the credentials are the same. 4798 * Returns 1 for not same, 0 otherwise. 4799 */ 4800 static int 4801 nfsrv_notsamecredname(struct nfsrv_descript *nd, struct nfsclient *clp) 4802 { 4803 4804 if (nd->nd_flag & ND_GSS) { 4805 if (!(clp->lc_flags & LCL_GSS)) 4806 return (1); 4807 if (clp->lc_flags & LCL_NAME) { 4808 if (nd->nd_princlen != clp->lc_namelen || 4809 NFSBCMP(nd->nd_principal, clp->lc_name, 4810 clp->lc_namelen)) 4811 return (1); 4812 else 4813 return (0); 4814 } 4815 if (nd->nd_cred->cr_uid == clp->lc_uid) 4816 return (0); 4817 else 4818 return (1); 4819 } else if (clp->lc_flags & LCL_GSS) 4820 return (1); 4821 /* 4822 * For AUTH_SYS, allow the same uid or root. (This is underspecified 4823 * in RFC3530, which talks about principals, but doesn't say anything 4824 * about uids for AUTH_SYS.) 4825 */ 4826 if (nd->nd_cred->cr_uid == clp->lc_uid || nd->nd_cred->cr_uid == 0) 4827 return (0); 4828 else 4829 return (1); 4830 } 4831 4832 /* 4833 * Calculate the lease expiry time. 4834 */ 4835 static time_t 4836 nfsrv_leaseexpiry(void) 4837 { 4838 struct timeval curtime; 4839 4840 NFSGETTIME(&curtime); 4841 if (nfsrv_stablefirst.nsf_eograce > NFSD_MONOSEC) 4842 return (NFSD_MONOSEC + 2 * (nfsrv_lease + NFSRV_LEASEDELTA)); 4843 return (NFSD_MONOSEC + nfsrv_lease + NFSRV_LEASEDELTA); 4844 } 4845 4846 /* 4847 * Delay the delegation timeout as far as ls_delegtimelimit, as required. 4848 */ 4849 static void 4850 nfsrv_delaydelegtimeout(struct nfsstate *stp) 4851 { 4852 4853 if ((stp->ls_flags & NFSLCK_DELEGRECALL) == 0) 4854 return; 4855 4856 if ((stp->ls_delegtime + 15) > NFSD_MONOSEC && 4857 stp->ls_delegtime < stp->ls_delegtimelimit) { 4858 stp->ls_delegtime += nfsrv_lease; 4859 if (stp->ls_delegtime > stp->ls_delegtimelimit) 4860 stp->ls_delegtime = stp->ls_delegtimelimit; 4861 } 4862 } 4863 4864 /* 4865 * This function checks to see if there is any other state associated 4866 * with the openowner for this Open. 4867 * It returns 1 if there is no other state, 0 otherwise. 4868 */ 4869 static int 4870 nfsrv_nootherstate(struct nfsstate *stp) 4871 { 4872 struct nfsstate *tstp; 4873 4874 LIST_FOREACH(tstp, &stp->ls_openowner->ls_open, ls_list) { 4875 if (tstp != stp || !LIST_EMPTY(&tstp->ls_lock)) 4876 return (0); 4877 } 4878 return (1); 4879 } 4880 4881 /* 4882 * Create a list of lock deltas (changes to local byte range locking 4883 * that can be rolled back using the list) and apply the changes via 4884 * nfsvno_advlock(). Optionally, lock the list. It is expected that either 4885 * the rollback or update function will be called after this. 4886 * It returns an error (and rolls back, as required), if any nfsvno_advlock() 4887 * call fails. If it returns an error, it will unlock the list. 4888 */ 4889 static int 4890 nfsrv_locallock(vnode_t vp, struct nfslockfile *lfp, int flags, 4891 uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p) 4892 { 4893 struct nfslock *lop, *nlop; 4894 int error = 0; 4895 4896 /* Loop through the list of locks. */ 4897 lop = LIST_FIRST(&lfp->lf_locallock); 4898 while (first < end && lop != NULL) { 4899 nlop = LIST_NEXT(lop, lo_lckowner); 4900 if (first >= lop->lo_end) { 4901 /* not there yet */ 4902 lop = nlop; 4903 } else if (first < lop->lo_first) { 4904 /* new one starts before entry in list */ 4905 if (end <= lop->lo_first) { 4906 /* no overlap between old and new */ 4907 error = nfsrv_dolocal(vp, lfp, flags, 4908 NFSLCK_UNLOCK, first, end, cfp, p); 4909 if (error != 0) 4910 break; 4911 first = end; 4912 } else { 4913 /* handle fragment overlapped with new one */ 4914 error = nfsrv_dolocal(vp, lfp, flags, 4915 NFSLCK_UNLOCK, first, lop->lo_first, cfp, 4916 p); 4917 if (error != 0) 4918 break; 4919 first = lop->lo_first; 4920 } 4921 } else { 4922 /* new one overlaps this entry in list */ 4923 if (end <= lop->lo_end) { 4924 /* overlaps all of new one */ 4925 error = nfsrv_dolocal(vp, lfp, flags, 4926 lop->lo_flags, first, end, cfp, p); 4927 if (error != 0) 4928 break; 4929 first = end; 4930 } else { 4931 /* handle fragment overlapped with new one */ 4932 error = nfsrv_dolocal(vp, lfp, flags, 4933 lop->lo_flags, first, lop->lo_end, cfp, p); 4934 if (error != 0) 4935 break; 4936 first = lop->lo_end; 4937 lop = nlop; 4938 } 4939 } 4940 } 4941 if (first < end && error == 0) 4942 /* handle fragment past end of list */ 4943 error = nfsrv_dolocal(vp, lfp, flags, NFSLCK_UNLOCK, first, 4944 end, cfp, p); 4945 return (error); 4946 } 4947 4948 /* 4949 * Local lock unlock. Unlock all byte ranges that are no longer locked 4950 * by NFSv4. 4951 */ 4952 static void 4953 nfsrv_localunlock(vnode_t vp, struct nfslockfile *lfp, uint64_t init_first, 4954 uint64_t init_end, NFSPROC_T *p) 4955 { 4956 struct nfslock *lop; 4957 4958 uint64_t first, end; 4959 4960 first = init_first; 4961 end = init_end; 4962 while (first < init_end) { 4963 /* Loop through all nfs locks, adjusting first and end */ 4964 LIST_FOREACH(lop, &lfp->lf_lock, lo_lckfile) { 4965 if (first >= lop->lo_first && 4966 first < lop->lo_end) 4967 /* Overlaps initial part */ 4968 first = lop->lo_end; 4969 else if (end > lop->lo_first && 4970 lop->lo_first >= first) 4971 /* Begins before end and past first */ 4972 end = lop->lo_first; 4973 if (first >= end) 4974 /* shrunk to 0 so this iteration is done */ 4975 break; 4976 } 4977 if (first < end) { 4978 /* Unlock this segment */ 4979 (void) nfsrv_dolocal(vp, lfp, NFSLCK_UNLOCK, 4980 NFSLCK_READ, first, end, NULL, p); 4981 nfsrv_locallock_commit(lfp, NFSLCK_UNLOCK, 4982 first, end); 4983 } 4984 /* and move on to the rest of the range */ 4985 first = end; 4986 end = init_end; 4987 } 4988 } 4989 4990 /* 4991 * Do the local lock operation and update the rollback list, as required. 4992 * Perform the rollback and return the error if nfsvno_advlock() fails. 4993 */ 4994 static int 4995 nfsrv_dolocal(vnode_t vp, struct nfslockfile *lfp, int flags, int oldflags, 4996 uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p) 4997 { 4998 struct nfsrollback *rlp; 4999 int error, ltype, oldltype; 5000 5001 if (flags & NFSLCK_WRITE) 5002 ltype = F_WRLCK; 5003 else if (flags & NFSLCK_READ) 5004 ltype = F_RDLCK; 5005 else 5006 ltype = F_UNLCK; 5007 if (oldflags & NFSLCK_WRITE) 5008 oldltype = F_WRLCK; 5009 else if (oldflags & NFSLCK_READ) 5010 oldltype = F_RDLCK; 5011 else 5012 oldltype = F_UNLCK; 5013 if (ltype == oldltype || (oldltype == F_WRLCK && ltype == F_RDLCK)) 5014 /* nothing to do */ 5015 return (0); 5016 error = nfsvno_advlock(vp, ltype, first, end, p); 5017 if (error != 0) { 5018 if (cfp != NULL) { 5019 cfp->cl_clientid.lval[0] = 0; 5020 cfp->cl_clientid.lval[1] = 0; 5021 cfp->cl_first = 0; 5022 cfp->cl_end = NFS64BITSSET; 5023 cfp->cl_flags = NFSLCK_WRITE; 5024 cfp->cl_ownerlen = 5; 5025 NFSBCOPY("LOCAL", cfp->cl_owner, 5); 5026 } 5027 nfsrv_locallock_rollback(vp, lfp, p); 5028 } else if (ltype != F_UNLCK) { 5029 rlp = malloc(sizeof (struct nfsrollback), M_NFSDROLLBACK, 5030 M_WAITOK); 5031 rlp->rlck_first = first; 5032 rlp->rlck_end = end; 5033 rlp->rlck_type = oldltype; 5034 LIST_INSERT_HEAD(&lfp->lf_rollback, rlp, rlck_list); 5035 } 5036 return (error); 5037 } 5038 5039 /* 5040 * Roll back local lock changes and free up the rollback list. 5041 */ 5042 static void 5043 nfsrv_locallock_rollback(vnode_t vp, struct nfslockfile *lfp, NFSPROC_T *p) 5044 { 5045 struct nfsrollback *rlp, *nrlp; 5046 5047 LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, nrlp) { 5048 (void) nfsvno_advlock(vp, rlp->rlck_type, rlp->rlck_first, 5049 rlp->rlck_end, p); 5050 free(rlp, M_NFSDROLLBACK); 5051 } 5052 LIST_INIT(&lfp->lf_rollback); 5053 } 5054 5055 /* 5056 * Update local lock list and delete rollback list (ie now committed to the 5057 * local locks). Most of the work is done by the internal function. 5058 */ 5059 static void 5060 nfsrv_locallock_commit(struct nfslockfile *lfp, int flags, uint64_t first, 5061 uint64_t end) 5062 { 5063 struct nfsrollback *rlp, *nrlp; 5064 struct nfslock *new_lop, *other_lop; 5065 5066 new_lop = malloc(sizeof (struct nfslock), M_NFSDLOCK, M_WAITOK); 5067 if (flags & (NFSLCK_READ | NFSLCK_WRITE)) 5068 other_lop = malloc(sizeof (struct nfslock), M_NFSDLOCK, 5069 M_WAITOK); 5070 else 5071 other_lop = NULL; 5072 new_lop->lo_flags = flags; 5073 new_lop->lo_first = first; 5074 new_lop->lo_end = end; 5075 nfsrv_updatelock(NULL, &new_lop, &other_lop, lfp); 5076 if (new_lop != NULL) 5077 free(new_lop, M_NFSDLOCK); 5078 if (other_lop != NULL) 5079 free(other_lop, M_NFSDLOCK); 5080 5081 /* and get rid of the rollback list */ 5082 LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, nrlp) 5083 free(rlp, M_NFSDROLLBACK); 5084 LIST_INIT(&lfp->lf_rollback); 5085 } 5086 5087 /* 5088 * Lock the struct nfslockfile for local lock updating. 5089 */ 5090 static void 5091 nfsrv_locklf(struct nfslockfile *lfp) 5092 { 5093 int gotlock; 5094 5095 /* lf_usecount ensures *lfp won't be free'd */ 5096 lfp->lf_usecount++; 5097 do { 5098 gotlock = nfsv4_lock(&lfp->lf_locallock_lck, 1, NULL, 5099 NFSSTATEMUTEXPTR); 5100 } while (gotlock == 0); 5101 lfp->lf_usecount--; 5102 } 5103 5104 /* 5105 * Unlock the struct nfslockfile after local lock updating. 5106 */ 5107 static void 5108 nfsrv_unlocklf(struct nfslockfile *lfp) 5109 { 5110 5111 nfsv4_unlock(&lfp->lf_locallock_lck, 0); 5112 } 5113 5114