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