nfs_nfsdstate.c (224083) | nfs_nfsdstate.c (224086) |
---|---|
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 --- 12 unchanged lines hidden (view full) --- 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> | 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 --- 12 unchanged lines hidden (view full) --- 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: head/sys/fs/nfsserver/nfs_nfsdstate.c 224083 2011-07-16 08:05:41Z zack $"); | 29__FBSDID("$FreeBSD: head/sys/fs/nfsserver/nfs_nfsdstate.c 224086 2011-07-16 08:51:09Z zack $"); |
30 31#ifndef APPLEKEXT 32#include <fs/nfs/nfsport.h> 33 34struct nfsrv_stablefirst nfsrv_stablefirst; 35int nfsrv_issuedelegs = 0; 36int nfsrv_dolocallocks = 0; 37struct nfsv4lock nfsv4rootfs_lock; --- 92 unchanged lines hidden (view full) --- 130 * If returning a non-error, the clp structure must either be linked into 131 * the client list or free'd. 132 */ 133APPLESTATIC int 134nfsrv_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; | 30 31#ifndef APPLEKEXT 32#include <fs/nfs/nfsport.h> 33 34struct nfsrv_stablefirst nfsrv_stablefirst; 35int nfsrv_issuedelegs = 0; 36int nfsrv_dolocallocks = 0; 37struct nfsv4lock nfsv4rootfs_lock; --- 92 unchanged lines hidden (view full) --- 130 * If returning a non-error, the clp structure must either be linked into 131 * the client list or free'd. 132 */ 133APPLESTATIC int 134nfsrv_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; | 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 */ | 139 struct nfsstate *stp, *tstp; 140 struct sockaddr_in *sad, *rad; 141 int zapit = 0, gotit, hasstate = 0, igotlock; 142 static u_int64_t confirm_index = 0; 143 144 /* 145 * Check for state resource limit exceeded. 146 */ |
147 if (nfsrv_openpluslock > NFSRV_V4STATELIMIT) 148 return (NFSERR_RESOURCE); | 147 if (nfsrv_openpluslock > NFSRV_V4STATELIMIT) { 148 error = NFSERR_RESOURCE; 149 goto out; 150 } |
149 150 if (nfsrv_issuedelegs == 0 || 151 ((nd->nd_flag & ND_GSS) != 0 && nfsrv_nogsscallback != 0)) 152 /* 153 * Don't do callbacks when delegations are disabled or 154 * for AUTH_GSS unless enabled via nfsrv_nogsscallback. 155 * If establishing a callback connection is attempted 156 * when a firewall is blocking the callback path, the --- 66 unchanged lines hidden (view full) --- 223 nfsrv_openpluslock++; 224 nfsrv_clients++; 225 NFSLOCKV4ROOTMUTEX(); 226 nfsv4_unlock(&nfsv4rootfs_lock, 1); 227 NFSUNLOCKV4ROOTMUTEX(); 228 if (zapit) 229 nfsrv_zapclient(clp, p); 230 *new_clpp = NULL; | 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 --- 66 unchanged lines hidden (view full) --- 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; |
231 return (0); | 233 goto out; |
232 } 233 234 /* 235 * Now, handle the cases where the id is already issued. 236 */ 237 if (nfsrv_notsamecredname(nd, clp)) { 238 /* 239 * Check to see if there is expired state that should go away. --- 29 unchanged lines hidden (view full) --- 269 */ 270 sad = NFSSOCKADDR(new_clp->lc_req.nr_nam, struct sockaddr_in *); 271 rad = NFSSOCKADDR(clp->lc_req.nr_nam, struct sockaddr_in *); 272 sad->sin_addr.s_addr = rad->sin_addr.s_addr; 273 sad->sin_port = rad->sin_port; 274 NFSLOCKV4ROOTMUTEX(); 275 nfsv4_unlock(&nfsv4rootfs_lock, 1); 276 NFSUNLOCKV4ROOTMUTEX(); | 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. --- 29 unchanged lines hidden (view full) --- 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(); |
277 return (NFSERR_CLIDINUSE); | 279 error = NFSERR_CLIDINUSE; 280 goto out; |
278 } 279 } 280 281 if (NFSBCMP(new_clp->lc_verf, clp->lc_verf, NFSX_VERF)) { 282 /* 283 * If the verifier has changed, the client has rebooted 284 * and a new client id is issued. The old state info 285 * can be thrown away once the SETCLIENTID_CONFIRM occurs. --- 44 unchanged lines hidden (view full) --- 330 */ 331 while (clp->lc_cbref) { 332 clp->lc_flags |= LCL_WAKEUPWANTED; 333 (void) tsleep((caddr_t)clp, PZERO - 1, 334 "nfsd clp", 10 * hz); 335 } 336 nfsrv_zapclient(clp, p); 337 *new_clpp = NULL; | 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. --- 44 unchanged lines hidden (view full) --- 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; |
338 return (0); | 341 goto out; |
339 } 340 /* 341 * id and verifier match, so update the net address info 342 * and get rid of any existing callback authentication 343 * handle, so a new one will be acquired. 344 */ 345 LIST_REMOVE(clp, lc_hash); 346 new_clp->lc_flags |= (LCL_NEEDSCONFIRM | LCL_DONTCLEAN); --- 36 unchanged lines hidden (view full) --- 383 * completes. 384 */ 385 while (clp->lc_cbref) { 386 clp->lc_flags |= LCL_WAKEUPWANTED; 387 (void) tsleep((caddr_t)clp, PZERO - 1, "nfsd clp", 10 * hz); 388 } 389 nfsrv_zapclient(clp, p); 390 *new_clpp = NULL; | 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); --- 36 unchanged lines hidden (view full) --- 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; |
391 return (0); | 394 395out: 396 NFSEXITCODE2(error, nd); 397 return (error); |
392} 393 394/* 395 * Check to see if the client id exists and optionally confirm it. 396 */ 397APPLESTATIC int 398nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp, 399 nfsquad_t confirm, struct nfsrv_descript *nd, NFSPROC_T *p) 400{ 401 struct nfsclient *clp; 402 struct nfsstate *stp; 403 int i; 404 struct nfsclienthashhead *hp; 405 int error = 0, igotlock, doneok; 406 407 if (clpp) 408 *clpp = NULL; | 398} 399 400/* 401 * Check to see if the client id exists and optionally confirm it. 402 */ 403APPLESTATIC int 404nfsrv_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; |
409 if (nfsrvboottime != clientid.lval[0]) 410 return (NFSERR_STALECLIENTID); | 415 if (nfsrvboottime != clientid.lval[0]) { 416 error = NFSERR_STALECLIENTID; 417 goto out; 418 } |
411 412 /* 413 * If called with opflags == CLOPS_RENEW, the State Lock is 414 * already held. Otherwise, we need to get either that or, 415 * for the case of Confirm, lock out the nfsd threads. 416 */ 417 if (opflags & CLOPS_CONFIRM) { 418 NFSLOCKV4ROOTMUTEX(); --- 26 unchanged lines hidden (view full) --- 445 if (error) { 446 if (opflags & CLOPS_CONFIRM) { 447 NFSLOCKV4ROOTMUTEX(); 448 nfsv4_unlock(&nfsv4rootfs_lock, 1); 449 NFSUNLOCKV4ROOTMUTEX(); 450 } else if (opflags != CLOPS_RENEW) { 451 NFSUNLOCKSTATE(); 452 } | 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(); --- 26 unchanged lines hidden (view full) --- 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 } |
453 return (error); | 461 goto out; |
454 } 455 456 /* 457 * Perform any operations specified by the opflags. 458 */ 459 if (opflags & CLOPS_CONFIRM) { 460 if (clp->lc_confirm.qval != confirm.qval) 461 error = NFSERR_STALECLIENTID; --- 59 unchanged lines hidden (view full) --- 521 NFSLOCKV4ROOTMUTEX(); 522 nfsv4_unlock(&nfsv4rootfs_lock, 1); 523 NFSUNLOCKV4ROOTMUTEX(); 524 } else if (opflags != CLOPS_RENEW) { 525 NFSUNLOCKSTATE(); 526 } 527 if (clpp) 528 *clpp = clp; | 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; --- 59 unchanged lines hidden (view full) --- 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 538out: 539 NFSEXITCODE2(error, nd); |
|
529 return (error); 530} 531 532/* 533 * Called from the new nfssvc syscall to admin revoke a clientid. 534 * Returns 0 for success, error otherwise. 535 */ 536APPLESTATIC int 537nfsrv_adminrevoke(struct nfsd_clid *revokep, NFSPROC_T *p) 538{ 539 struct nfsclient *clp = NULL; | 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 */ 547APPLESTATIC int 548nfsrv_adminrevoke(struct nfsd_clid *revokep, NFSPROC_T *p) 549{ 550 struct nfsclient *clp = NULL; |
540 int i; | 551 int i, error = 0; |
541 int gotit, igotlock; 542 543 /* 544 * First, lock out the nfsd so that state won't change while the 545 * revocation record is being written to the stable storage restart 546 * file. 547 */ 548 NFSLOCKV4ROOTMUTEX(); --- 16 unchanged lines hidden (view full) --- 565 } 566 } 567 i++; 568 } 569 if (!gotit) { 570 NFSLOCKV4ROOTMUTEX(); 571 nfsv4_unlock(&nfsv4rootfs_lock, 0); 572 NFSUNLOCKV4ROOTMUTEX(); | 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(); --- 16 unchanged lines hidden (view full) --- 576 } 577 } 578 i++; 579 } 580 if (!gotit) { 581 NFSLOCKV4ROOTMUTEX(); 582 nfsv4_unlock(&nfsv4rootfs_lock, 0); 583 NFSUNLOCKV4ROOTMUTEX(); |
573 return (EPERM); | 584 error = EPERM; 585 goto out; |
574 } 575 576 /* 577 * Now, write out the revocation record 578 */ 579 nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p); 580 nfsrv_backupstable(); 581 582 /* 583 * and clear out the state, marking the clientid revoked. 584 */ 585 clp->lc_flags &= ~LCL_CALLBACKSON; 586 clp->lc_flags |= LCL_ADMINREVOKED; 587 nfsrv_cleanclient(clp, p); 588 nfsrv_freedeleglist(&clp->lc_deleg); 589 nfsrv_freedeleglist(&clp->lc_olddeleg); 590 NFSLOCKV4ROOTMUTEX(); 591 nfsv4_unlock(&nfsv4rootfs_lock, 0); 592 NFSUNLOCKV4ROOTMUTEX(); | 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(); |
593 return (0); | 605 606out: 607 NFSEXITCODE(error); 608 return (error); |
594} 595 596/* 597 * Dump out stats for all clients. Called from nfssvc(2), that is used 598 * newnfsstats. 599 */ 600APPLESTATIC void 601nfsrv_dumpclients(struct nfsd_dumpclients *dumpp, int maxcnt) --- 622 unchanged lines hidden (view full) --- 1224 * This function looks up an nfsstate structure via stateid. 1225 */ 1226static int 1227nfsrv_getstate(struct nfsclient *clp, nfsv4stateid_t *stateidp, __unused u_int32_t flags, 1228 struct nfsstate **stpp) 1229{ 1230 struct nfsstate *stp; 1231 struct nfsstatehead *hp; | 609} 610 611/* 612 * Dump out stats for all clients. Called from nfssvc(2), that is used 613 * newnfsstats. 614 */ 615APPLESTATIC void 616nfsrv_dumpclients(struct nfsd_dumpclients *dumpp, int maxcnt) --- 622 unchanged lines hidden (view full) --- 1239 * This function looks up an nfsstate structure via stateid. 1240 */ 1241static int 1242nfsrv_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; |
|
1232 1233 *stpp = NULL; 1234 hp = NFSSTATEHASH(clp, *stateidp); 1235 LIST_FOREACH(stp, hp, ls_hash) { 1236 if (!NFSBCMP(stp->ls_stateid.other, stateidp->other, 1237 NFSX_STATEIDOTHER)) 1238 break; 1239 } 1240 1241 /* 1242 * If no state id in list, return NFSERR_BADSTATEID. 1243 */ | 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 */ |
1244 if (stp == LIST_END(hp)) 1245 return (NFSERR_BADSTATEID); | 1260 if (stp == LIST_END(hp)) { 1261 error = NFSERR_BADSTATEID; 1262 goto out; 1263 } |
1246 *stpp = stp; | 1264 *stpp = stp; |
1247 return (0); | 1265 1266out: 1267 NFSEXITCODE(error); 1268 return (error); |
1248} 1249 1250/* 1251 * This function gets an nfsstate structure via owner string. 1252 */ 1253static void 1254nfsrv_getowner(struct nfsstatehead *hp, struct nfsstate *new_stp, 1255 struct nfsstate **stpp) --- 62 unchanged lines hidden (view full) --- 1318 } 1319 1320 /* 1321 * Check for restart conditions (client and server). 1322 */ 1323 error = nfsrv_checkrestart(clientid, new_stp->ls_flags, 1324 &new_stp->ls_stateid, specialid); 1325 if (error) | 1269} 1270 1271/* 1272 * This function gets an nfsstate structure via owner string. 1273 */ 1274static void 1275nfsrv_getowner(struct nfsstatehead *hp, struct nfsstate *new_stp, 1276 struct nfsstate **stpp) --- 62 unchanged lines hidden (view full) --- 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) |
1326 return (error); | 1347 goto out; |
1327 1328 /* 1329 * Check for state resource limit exceeded. 1330 */ 1331 if ((new_stp->ls_flags & NFSLCK_LOCK) && | 1348 1349 /* 1350 * Check for state resource limit exceeded. 1351 */ 1352 if ((new_stp->ls_flags & NFSLCK_LOCK) && |
1332 nfsrv_openpluslock > NFSRV_V4STATELIMIT) 1333 return (NFSERR_RESOURCE); | 1353 nfsrv_openpluslock > NFSRV_V4STATELIMIT) { 1354 error = NFSERR_RESOURCE; 1355 goto out; 1356 } |
1334 1335 /* 1336 * For the lock case, get another nfslock structure, 1337 * just in case we need it. 1338 * Malloc now, before we start sifting through the linked lists, 1339 * in case we have to wait for memory. 1340 */ 1341tryagain: --- 199 unchanged lines hidden (view full) --- 1541 if (filestruct_locked != 0) { 1542 /* Roll back local locks. */ 1543 NFSUNLOCKSTATE(); 1544 nfsrv_locallock_rollback(vp, lfp, p); 1545 NFSLOCKSTATE(); 1546 nfsrv_unlocklf(lfp); 1547 } 1548 NFSUNLOCKSTATE(); | 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 */ 1364tryagain: --- 199 unchanged lines hidden (view full) --- 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(); |
1549 if (other_lop) 1550 FREE((caddr_t)other_lop, M_NFSDLOCK); 1551 if (haslock) { 1552 NFSLOCKV4ROOTMUTEX(); 1553 nfsv4_unlock(&nfsv4rootfs_lock, 1); 1554 NFSUNLOCKV4ROOTMUTEX(); 1555 } 1556 return (error); | 1572 goto out; |
1557 } 1558 1559 /* 1560 * Check the nfsrv_getlockfile return. 1561 * Returned -1 if no structure found. 1562 */ 1563 if (getlckret == -1) { 1564 error = NFSERR_EXPIRED; --- 12 unchanged lines hidden (view full) --- 1577 * deny bits.) 1578 */ 1579 if (specialid) 1580 error = 0; 1581 else 1582 error = NFSERR_BADSTATEID; 1583 } 1584 NFSUNLOCKSTATE(); | 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; --- 12 unchanged lines hidden (view full) --- 1593 * deny bits.) 1594 */ 1595 if (specialid) 1596 error = 0; 1597 else 1598 error = NFSERR_BADSTATEID; 1599 } 1600 NFSUNLOCKSTATE(); |
1585 if (haslock) { 1586 NFSLOCKV4ROOTMUTEX(); 1587 nfsv4_unlock(&nfsv4rootfs_lock, 1); 1588 NFSUNLOCKV4ROOTMUTEX(); 1589 } 1590 /* 1591 * Called to lock or unlock, so the lock has gone away. 1592 */ 1593 return (error); | 1601 goto out; |
1594 } 1595 1596 /* 1597 * For NFSLCK_CHECK and NFSLCK_LOCK, test for a share conflict. 1598 * For NFSLCK_CHECK, allow a read if write access is granted, 1599 * but check for a deny. For NFSLCK_LOCK, require correct access, 1600 * which implies a conflicting deny can't exist. 1601 */ --- 31 unchanged lines hidden (view full) --- 1633 if (filestruct_locked != 0) { 1634 /* Roll back local locks. */ 1635 NFSUNLOCKSTATE(); 1636 nfsrv_locallock_rollback(vp, lfp, p); 1637 NFSLOCKSTATE(); 1638 nfsrv_unlocklf(lfp); 1639 } 1640 NFSUNLOCKSTATE(); | 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 */ --- 31 unchanged lines hidden (view full) --- 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(); |
1641 if (other_lop) 1642 FREE((caddr_t)other_lop, M_NFSDLOCK); 1643 if (haslock) { 1644 NFSLOCKV4ROOTMUTEX(); 1645 nfsv4_unlock(&nfsv4rootfs_lock, 1); 1646 NFSUNLOCKV4ROOTMUTEX(); 1647 } 1648 return (NFSERR_OPENMODE); | 1649 error = NFSERR_OPENMODE; 1650 goto out; |
1649 } 1650 } else 1651 mystp = NULL; 1652 if ((new_stp->ls_flags & NFSLCK_CHECK) && !delegation) { 1653 /* 1654 * Check for a conflicting deny bit. 1655 */ 1656 LIST_FOREACH(tstp, &lfp->lf_open, ls_file) { --- 8 unchanged lines hidden (view full) --- 1665 * nfsrv_clientconflict unlocks state 1666 * when it returns non-zero. 1667 */ 1668 lckstp = NULL; 1669 goto tryagain; 1670 } 1671 if (ret == 0) 1672 NFSUNLOCKSTATE(); | 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) { --- 8 unchanged lines hidden (view full) --- 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(); |
1673 if (haslock) { 1674 NFSLOCKV4ROOTMUTEX(); 1675 nfsv4_unlock(&nfsv4rootfs_lock, 1); 1676 NFSUNLOCKV4ROOTMUTEX(); 1677 } | |
1678 if (ret == 2) | 1675 if (ret == 2) |
1679 return (NFSERR_PERM); | 1676 error = NFSERR_PERM; |
1680 else | 1677 else |
1681 return (NFSERR_OPENMODE); | 1678 error = NFSERR_OPENMODE; 1679 goto out; |
1682 } 1683 } 1684 } 1685 1686 /* We're outta here */ 1687 NFSUNLOCKSTATE(); | 1680 } 1681 } 1682 } 1683 1684 /* We're outta here */ 1685 NFSUNLOCKSTATE(); |
1688 if (haslock) { 1689 NFSLOCKV4ROOTMUTEX(); 1690 nfsv4_unlock(&nfsv4rootfs_lock, 1); 1691 NFSUNLOCKV4ROOTMUTEX(); 1692 } 1693 return (0); | 1686 goto out; |
1694 } 1695 } 1696 1697 /* 1698 * For setattr, just get rid of all the Delegations for other clients. 1699 */ 1700 if (new_stp->ls_flags & NFSLCK_SETATTR) { 1701 ret = nfsrv_cleandeleg(vp, lfp, clp, &haslock, p); 1702 if (ret) { 1703 /* 1704 * nfsrv_cleandeleg() unlocks state when it 1705 * returns non-zero. 1706 */ 1707 if (ret == -1) { 1708 lckstp = NULL; 1709 goto tryagain; 1710 } | 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 } |
1711 return (ret); | 1704 error = ret; 1705 goto out; |
1712 } 1713 if (!(new_stp->ls_flags & NFSLCK_CHECK) || 1714 (LIST_EMPTY(&lfp->lf_open) && LIST_EMPTY(&lfp->lf_lock) && 1715 LIST_EMPTY(&lfp->lf_deleg))) { 1716 NFSUNLOCKSTATE(); | 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(); |
1717 if (haslock) { 1718 NFSLOCKV4ROOTMUTEX(); 1719 nfsv4_unlock(&nfsv4rootfs_lock, 1); 1720 NFSUNLOCKV4ROOTMUTEX(); 1721 } 1722 return (0); | 1711 goto out; |
1723 } 1724 } 1725 1726 /* 1727 * Check for a conflicting delegation. If one is found, call 1728 * nfsrv_delegconflict() to handle it. If the v4root lock hasn't 1729 * been set yet, it will get the lock. Otherwise, it will recall 1730 * the delegation. Then, we try try again... --- 37 unchanged lines hidden (view full) --- 1768 if (other_lop) { 1769 FREE((caddr_t)other_lop, M_NFSDLOCK); 1770 other_lop = NULL; 1771 } 1772 if (ret == -1) { 1773 lckstp = NULL; 1774 goto tryagain; 1775 } | 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... --- 37 unchanged lines hidden (view full) --- 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 } |
1776 return (ret); | 1765 error = ret; 1766 goto out; |
1777 } 1778 /* Never gets here. */ 1779 } 1780 tstp = nstp; 1781 } 1782 1783 /* 1784 * Handle the unlock case by calling nfsrv_updatelock(). --- 11 unchanged lines hidden (view full) --- 1796 if (filestruct_locked != 0) { 1797 NFSUNLOCKSTATE(); 1798 /* Update the local locks. */ 1799 nfsrv_localunlock(vp, lfp, first, end, p); 1800 NFSLOCKSTATE(); 1801 nfsrv_unlocklf(lfp); 1802 } 1803 NFSUNLOCKSTATE(); | 1767 } 1768 /* Never gets here. */ 1769 } 1770 tstp = nstp; 1771 } 1772 1773 /* 1774 * Handle the unlock case by calling nfsrv_updatelock(). --- 11 unchanged lines hidden (view full) --- 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(); |
1804 if (haslock) { 1805 NFSLOCKV4ROOTMUTEX(); 1806 nfsv4_unlock(&nfsv4rootfs_lock, 1); 1807 NFSUNLOCKV4ROOTMUTEX(); 1808 } 1809 return (0); | 1794 goto out; |
1810 } 1811 1812 /* 1813 * Search for a conflicting lock. A lock conflicts if: 1814 * - the lock range overlaps and 1815 * - at least one lock is a write lock and 1816 * - it is not owned by the same lock owner 1817 */ --- 54 unchanged lines hidden (view full) --- 1872 /* Roll back local locks. */ 1873 NFSUNLOCKSTATE(); 1874 nfsrv_locallock_rollback(vp, lfp, p); 1875 NFSLOCKSTATE(); 1876 nfsrv_unlocklf(lfp); 1877 } 1878 if (ret == 0) 1879 NFSUNLOCKSTATE(); | 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 */ --- 54 unchanged lines hidden (view full) --- 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(); |
1880 if (haslock) { 1881 NFSLOCKV4ROOTMUTEX(); 1882 nfsv4_unlock(&nfsv4rootfs_lock, 1); 1883 NFSUNLOCKV4ROOTMUTEX(); 1884 } 1885 return (error); | 1865 goto out; |
1886 } 1887 } 1888 } 1889 1890 /* 1891 * We only get here if there was no lock that conflicted. 1892 */ 1893 if (new_stp->ls_flags & (NFSLCK_TEST | NFSLCK_CHECK)) { 1894 NFSUNLOCKSTATE(); | 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(); |
1895 if (haslock) { 1896 NFSLOCKV4ROOTMUTEX(); 1897 nfsv4_unlock(&nfsv4rootfs_lock, 1); 1898 NFSUNLOCKV4ROOTMUTEX(); 1899 } 1900 return (0); | 1875 goto out; |
1901 } 1902 1903 /* 1904 * We only get here when we are creating or modifying a lock. 1905 * There are two variants: 1906 * - exist_lock_owner where lock_owner exists 1907 * - open_to_lock_owner with new lock_owner 1908 */ --- 36 unchanged lines hidden (view full) --- 1945 } 1946 if (filestruct_locked != 0) { 1947 NFSUNLOCKSTATE(); 1948 nfsrv_locallock_commit(lfp, lock_flags, first, end); 1949 NFSLOCKSTATE(); 1950 nfsrv_unlocklf(lfp); 1951 } 1952 NFSUNLOCKSTATE(); | 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 */ --- 36 unchanged lines hidden (view full) --- 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 1929out: |
|
1953 if (haslock) { 1954 NFSLOCKV4ROOTMUTEX(); 1955 nfsv4_unlock(&nfsv4rootfs_lock, 1); 1956 NFSUNLOCKV4ROOTMUTEX(); 1957 } 1958 if (other_lop) 1959 FREE((caddr_t)other_lop, M_NFSDLOCK); | 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); |
1960 return (0); | 1937 NFSEXITCODE2(error, nd); 1938 return (error); |
1961} 1962 1963/* 1964 * Check for state errors for Open. 1965 * repstat is passed back out as an error if more critical errors 1966 * are not detected. 1967 */ 1968APPLESTATIC int 1969nfsrv_opencheck(nfsquad_t clientid, nfsv4stateid_t *stateidp, 1970 struct nfsstate *new_stp, vnode_t vp, struct nfsrv_descript *nd, 1971 NFSPROC_T *p, int repstat) 1972{ 1973 struct nfsstate *stp, *nstp; 1974 struct nfsclient *clp; 1975 struct nfsstate *ownerstp; 1976 struct nfslockfile *lfp, *new_lfp; | 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 */ 1946APPLESTATIC int 1947nfsrv_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; |
1977 int error, haslock = 0, ret, readonly = 0, getfhret = 0; | 1955 int error = 0, haslock = 0, ret, readonly = 0, getfhret = 0; |
1978 1979 if ((new_stp->ls_flags & NFSLCK_SHAREBITS) == NFSLCK_READACCESS) 1980 readonly = 1; 1981 /* 1982 * Check for restart conditions (client and server). 1983 */ 1984 error = nfsrv_checkrestart(clientid, new_stp->ls_flags, 1985 &new_stp->ls_stateid, 0); 1986 if (error) | 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) |
1987 return (error); | 1965 goto out; |
1988 1989 /* 1990 * Check for state resource limit exceeded. 1991 * Technically this should be SMP protected, but the worst 1992 * case error is "out by one or two" on the count when it 1993 * returns NFSERR_RESOURCE and the limit is just a rather 1994 * arbitrary high water mark, so no harm is done. 1995 */ | 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 */ |
1996 if (nfsrv_openpluslock > NFSRV_V4STATELIMIT) 1997 return (NFSERR_RESOURCE); | 1974 if (nfsrv_openpluslock > NFSRV_V4STATELIMIT) { 1975 error = NFSERR_RESOURCE; 1976 goto out; 1977 } |
1998 1999tryagain: 2000 MALLOC(new_lfp, struct nfslockfile *, sizeof (struct nfslockfile), 2001 M_NFSDLOCKFILE, M_WAITOK); 2002 if (vp) 2003 getfhret = nfsrv_getlockfh(vp, new_stp->ls_flags, &new_lfp, 2004 NULL, p); 2005 NFSLOCKSTATE(); --- 41 unchanged lines hidden (view full) --- 2047 if (error) { 2048 NFSUNLOCKSTATE(); 2049 if (haslock) { 2050 NFSLOCKV4ROOTMUTEX(); 2051 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2052 NFSUNLOCKV4ROOTMUTEX(); 2053 } 2054 free((caddr_t)new_lfp, M_NFSDLOCKFILE); | 1978 1979tryagain: 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(); --- 41 unchanged lines hidden (view full) --- 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); |
2055 return (error); | 2035 goto out; |
2056 } 2057 2058 /* 2059 * If vp == NULL, the file doesn't exist yet, so return ok. 2060 * (This always happens on the first pass, so haslock must be 0.) 2061 */ 2062 if (vp == NULL) { 2063 NFSUNLOCKSTATE(); 2064 FREE((caddr_t)new_lfp, M_NFSDLOCKFILE); | 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); |
2065 return (0); | 2045 goto out; |
2066 } 2067 2068 /* 2069 * Get the structure for the underlying file. 2070 */ 2071 if (getfhret) 2072 error = getfhret; 2073 else 2074 error = nfsrv_getlockfile(new_stp->ls_flags, &new_lfp, &lfp, 2075 NULL, 0); 2076 if (new_lfp) 2077 FREE((caddr_t)new_lfp, M_NFSDLOCKFILE); 2078 if (error) { 2079 NFSUNLOCKSTATE(); 2080 if (haslock) { 2081 NFSLOCKV4ROOTMUTEX(); 2082 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2083 NFSUNLOCKV4ROOTMUTEX(); 2084 } | 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 } |
2085 return (error); | 2065 goto out; |
2086 } 2087 2088 /* 2089 * Search for a conflicting open/share. 2090 */ 2091 if (new_stp->ls_flags & NFSLCK_DELEGCUR) { 2092 /* 2093 * For Delegate_Cur, search for the matching Delegation, --- 14 unchanged lines hidden (view full) --- 2108 ((new_stp->ls_flags & NFSLCK_WRITEACCESS) && 2109 (stp->ls_flags & NFSLCK_DELEGREAD))) { 2110 NFSUNLOCKSTATE(); 2111 if (haslock) { 2112 NFSLOCKV4ROOTMUTEX(); 2113 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2114 NFSUNLOCKV4ROOTMUTEX(); 2115 } | 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, --- 14 unchanged lines hidden (view full) --- 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 } |
2116 return (NFSERR_EXPIRED); | 2096 error = NFSERR_EXPIRED; 2097 goto out; |
2117 } 2118 } 2119 2120 /* 2121 * Check for access/deny bit conflicts. I check for the same 2122 * owner as well, in case the client didn't bother. 2123 */ 2124 LIST_FOREACH(stp, &lfp->lf_open, ls_file) { --- 18 unchanged lines hidden (view full) --- 2143 error = NFSERR_SHAREDENIED; 2144 if (ret == 0) 2145 NFSUNLOCKSTATE(); 2146 if (haslock) { 2147 NFSLOCKV4ROOTMUTEX(); 2148 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2149 NFSUNLOCKV4ROOTMUTEX(); 2150 } | 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) { --- 18 unchanged lines hidden (view full) --- 2124 error = NFSERR_SHAREDENIED; 2125 if (ret == 0) 2126 NFSUNLOCKSTATE(); 2127 if (haslock) { 2128 NFSLOCKV4ROOTMUTEX(); 2129 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2130 NFSUNLOCKV4ROOTMUTEX(); 2131 } |
2151 return (error); | 2132 goto out; |
2152 } 2153 } 2154 2155 /* 2156 * Check for a conflicting delegation. If one is found, call 2157 * nfsrv_delegconflict() to handle it. If the v4root lock hasn't 2158 * been set yet, it will get the lock. Otherwise, it will recall 2159 * the delegation. Then, we try try again... --- 24 unchanged lines hidden (view full) --- 2184 ret = nfsrv_delegconflict(stp, &haslock, p, vp); 2185 if (ret) { 2186 /* 2187 * nfsrv_delegconflict() unlocks state 2188 * when it returns non-zero. 2189 */ 2190 if (ret == -1) 2191 goto tryagain; | 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... --- 24 unchanged lines hidden (view full) --- 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; |
2192 return (ret); | 2173 error = ret; 2174 goto out; |
2193 } 2194 } 2195 stp = nstp; 2196 } 2197 } 2198 NFSUNLOCKSTATE(); 2199 if (haslock) { 2200 NFSLOCKV4ROOTMUTEX(); 2201 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2202 NFSUNLOCKV4ROOTMUTEX(); 2203 } | 2175 } 2176 } 2177 stp = nstp; 2178 } 2179 } 2180 NFSUNLOCKSTATE(); 2181 if (haslock) { 2182 NFSLOCKV4ROOTMUTEX(); 2183 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2184 NFSUNLOCKV4ROOTMUTEX(); 2185 } |
2204 return (0); | 2186 2187out: 2188 NFSEXITCODE2(error, nd); 2189 return (error); |
2205} 2206 2207/* 2208 * Open control function to create/update open state for an open. 2209 */ 2210APPLESTATIC int 2211nfsrv_openctrl(struct nfsrv_descript *nd, vnode_t vp, 2212 struct nfsstate **new_stpp, nfsquad_t clientid, nfsv4stateid_t *stateidp, 2213 nfsv4stateid_t *delegstateidp, u_int32_t *rflagsp, struct nfsexstuff *exp, 2214 NFSPROC_T *p, u_quad_t filerev) 2215{ 2216 struct nfsstate *new_stp = *new_stpp; 2217 struct nfsstate *stp, *nstp; 2218 struct nfsstate *openstp = NULL, *new_open, *ownerstp, *new_deleg; 2219 struct nfslockfile *lfp, *new_lfp; 2220 struct nfsclient *clp; | 2190} 2191 2192/* 2193 * Open control function to create/update open state for an open. 2194 */ 2195APPLESTATIC int 2196nfsrv_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; |
2221 int error, haslock = 0, ret, delegate = 1, writedeleg = 1; | 2206 int error = 0, haslock = 0, ret, delegate = 1, writedeleg = 1; |
2222 int readonly = 0, cbret = 1, getfhret = 0; 2223 2224 if ((new_stp->ls_flags & NFSLCK_SHAREBITS) == NFSLCK_READACCESS) 2225 readonly = 1; 2226 /* 2227 * Check for restart conditions (client and server). 2228 * (Paranoia, should have been detected by nfsrv_opencheck().) 2229 * If an error does show up, return NFSERR_EXPIRED, since the 2230 * the seqid# has already been incremented. 2231 */ 2232 error = nfsrv_checkrestart(clientid, new_stp->ls_flags, 2233 &new_stp->ls_stateid, 0); 2234 if (error) { 2235 printf("Nfsd: openctrl unexpected restart err=%d\n", 2236 error); | 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); |
2237 return (NFSERR_EXPIRED); | 2222 error = NFSERR_EXPIRED; 2223 goto out; |
2238 } 2239 2240tryagain: 2241 MALLOC(new_lfp, struct nfslockfile *, sizeof (struct nfslockfile), 2242 M_NFSDLOCKFILE, M_WAITOK); 2243 MALLOC(new_open, struct nfsstate *, sizeof (struct nfsstate), 2244 M_NFSDSTATE, M_WAITOK); 2245 MALLOC(new_deleg, struct nfsstate *, sizeof (struct nfsstate), --- 54 unchanged lines hidden (view full) --- 2300 free((caddr_t)new_lfp, M_NFSDLOCKFILE); 2301 free((caddr_t)new_open, M_NFSDSTATE); 2302 free((caddr_t)new_deleg, M_NFSDSTATE); 2303 if (haslock) { 2304 NFSLOCKV4ROOTMUTEX(); 2305 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2306 NFSUNLOCKV4ROOTMUTEX(); 2307 } | 2224 } 2225 2226tryagain: 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), --- 54 unchanged lines hidden (view full) --- 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 } |
2308 return (NFSERR_EXPIRED); | 2294 error = NFSERR_EXPIRED; 2295 goto out; |
2309 } 2310 2311 if (new_stp->ls_flags & NFSLCK_RECLAIM) 2312 nfsrv_markstable(clp); 2313 2314 /* 2315 * Get the structure for the underlying file. 2316 */ --- 10 unchanged lines hidden (view full) --- 2327 error); 2328 free((caddr_t)new_open, M_NFSDSTATE); 2329 free((caddr_t)new_deleg, M_NFSDSTATE); 2330 if (haslock) { 2331 NFSLOCKV4ROOTMUTEX(); 2332 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2333 NFSUNLOCKV4ROOTMUTEX(); 2334 } | 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 */ --- 10 unchanged lines hidden (view full) --- 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 } |
2335 return (error); | 2322 goto out; |
2336 } 2337 2338 /* 2339 * Search for a conflicting open/share. 2340 */ 2341 if (new_stp->ls_flags & NFSLCK_DELEGCUR) { 2342 /* 2343 * For Delegate_Cur, search for the matching Delegation, --- 17 unchanged lines hidden (view full) --- 2361 printf("Nfsd openctrl unexpected expiry\n"); 2362 free((caddr_t)new_open, M_NFSDSTATE); 2363 free((caddr_t)new_deleg, M_NFSDSTATE); 2364 if (haslock) { 2365 NFSLOCKV4ROOTMUTEX(); 2366 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2367 NFSUNLOCKV4ROOTMUTEX(); 2368 } | 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, --- 17 unchanged lines hidden (view full) --- 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 } |
2369 return (NFSERR_EXPIRED); | 2356 error = NFSERR_EXPIRED; 2357 goto out; |
2370 } 2371 2372 /* 2373 * Don't issue a Delegation, since one already exists and 2374 * delay delegation timeout, as required. 2375 */ 2376 delegate = 0; 2377 nfsrv_delaydelegtimeout(stp); --- 48 unchanged lines hidden (view full) --- 2426 if (haslock) { 2427 NFSLOCKV4ROOTMUTEX(); 2428 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2429 NFSUNLOCKV4ROOTMUTEX(); 2430 } 2431 free((caddr_t)new_open, M_NFSDSTATE); 2432 free((caddr_t)new_deleg, M_NFSDSTATE); 2433 printf("nfsd openctrl unexpected client cnfl\n"); | 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); --- 48 unchanged lines hidden (view full) --- 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"); |
2434 return (error); | 2422 goto out; |
2435 } 2436 } 2437 } 2438 2439 /* 2440 * Check for a conflicting delegation. If one is found, call 2441 * nfsrv_delegconflict() to handle it. If the v4root lock hasn't 2442 * been set yet, it will get the lock. Otherwise, it will recall --- 34 unchanged lines hidden (view full) --- 2477 */ 2478 printf("Nfsd openctrl unexpected deleg cnfl\n"); 2479 free((caddr_t)new_open, M_NFSDSTATE); 2480 free((caddr_t)new_deleg, M_NFSDSTATE); 2481 if (ret == -1) { 2482 openstp = NULL; 2483 goto tryagain; 2484 } | 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 --- 34 unchanged lines hidden (view full) --- 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 } |
2485 return (ret); | 2473 error = ret; 2474 goto out; |
2486 } 2487 } 2488 } 2489 stp = nstp; 2490 } 2491 } 2492 2493 /* --- 356 unchanged lines hidden (view full) --- 2850 NFSLOCKV4ROOTMUTEX(); 2851 nfsv4_unlock(&nfsv4rootfs_lock, 1); 2852 NFSUNLOCKV4ROOTMUTEX(); 2853 } 2854 if (new_open) 2855 FREE((caddr_t)new_open, M_NFSDSTATE); 2856 if (new_deleg) 2857 FREE((caddr_t)new_deleg, M_NFSDSTATE); | 2475 } 2476 } 2477 } 2478 stp = nstp; 2479 } 2480 } 2481 2482 /* --- 356 unchanged lines hidden (view full) --- 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 2848out: 2849 NFSEXITCODE2(error, nd); |
|
2858 return (error); 2859} 2860 2861/* 2862 * Open update. Does the confirm, downgrade and close. 2863 */ 2864APPLESTATIC int 2865nfsrv_openupdate(vnode_t vp, struct nfsstate *new_stp, nfsquad_t clientid, 2866 nfsv4stateid_t *stateidp, struct nfsrv_descript *nd, NFSPROC_T *p) 2867{ 2868 struct nfsstate *stp, *ownerstp; 2869 struct nfsclient *clp; 2870 struct nfslockfile *lfp; 2871 u_int32_t bits; | 2850 return (error); 2851} 2852 2853/* 2854 * Open update. Does the confirm, downgrade and close. 2855 */ 2856APPLESTATIC int 2857nfsrv_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; |
2872 int error, gotstate = 0, len = 0; | 2864 int error = 0, gotstate = 0, len = 0; |
2873 u_char client[NFSV4_OPAQUELIMIT]; 2874 2875 /* 2876 * Check for restart conditions (client and server). 2877 */ 2878 error = nfsrv_checkrestart(clientid, new_stp->ls_flags, 2879 &new_stp->ls_stateid, 0); 2880 if (error) | 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) |
2881 return (error); | 2873 goto out; |
2882 2883 NFSLOCKSTATE(); 2884 /* 2885 * Get the open structure via clientid and stateid. 2886 */ 2887 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, 2888 (nfsquad_t)((u_quad_t)0), NULL, p); 2889 if (!error) --- 30 unchanged lines hidden (view full) --- 2920 * on the openowner, just throw it away, so the next use of the 2921 * openowner will start a fresh seq#. 2922 */ 2923 if (error == NFSERR_BADSEQID && 2924 (new_stp->ls_flags & NFSLCK_CONFIRM) && 2925 nfsrv_nootherstate(stp)) 2926 nfsrv_freeopenowner(stp->ls_openowner, 0, p); 2927 NFSUNLOCKSTATE(); | 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) --- 30 unchanged lines hidden (view full) --- 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(); |
2928 return (error); | 2920 goto out; |
2929 } 2930 2931 /* 2932 * Set the return stateid. 2933 */ 2934 stateidp->seqid = stp->ls_stateid.seqid + 1; 2935 stateidp->other[0] = stp->ls_stateid.other[0]; 2936 stateidp->other[1] = stp->ls_stateid.other[1]; --- 36 unchanged lines hidden (view full) --- 2973 } else { 2974 /* 2975 * Update the share bits, making sure that the new set are a 2976 * subset of the old ones. 2977 */ 2978 bits = (new_stp->ls_flags & NFSLCK_SHAREBITS); 2979 if (~(stp->ls_flags) & bits) { 2980 NFSUNLOCKSTATE(); | 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]; --- 36 unchanged lines hidden (view full) --- 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(); |
2981 return (NFSERR_INVAL); | 2973 error = NFSERR_INVAL; 2974 goto out; |
2982 } 2983 stp->ls_flags = (bits | NFSLCK_OPEN); 2984 stp->ls_stateid.seqid++; 2985 NFSUNLOCKSTATE(); 2986 } 2987 2988 /* 2989 * If the client just confirmed its first open, write a timestamp 2990 * to the stable storage file. 2991 */ 2992 if (gotstate != 0) { 2993 nfsrv_writestable(client, len, NFSNST_NEWSTATE, p); 2994 nfsrv_backupstable(); 2995 } | 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 2990out: 2991 NFSEXITCODE2(error, nd); |
|
2996 return (error); 2997} 2998 2999/* 3000 * Delegation update. Does the purge and return. 3001 */ 3002APPLESTATIC int 3003nfsrv_delegupdate(nfsquad_t clientid, nfsv4stateid_t *stateidp, 3004 vnode_t vp, int op, struct ucred *cred, NFSPROC_T *p) 3005{ 3006 struct nfsstate *stp; 3007 struct nfsclient *clp; | 2992 return (error); 2993} 2994 2995/* 2996 * Delegation update. Does the purge and return. 2997 */ 2998APPLESTATIC int 2999nfsrv_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; |
3008 int error; | 3004 int error = 0; |
3009 fhandle_t fh; 3010 3011 /* 3012 * Do a sanity check against the file handle for DelegReturn. 3013 */ 3014 if (vp) { 3015 error = nfsvno_getfh(vp, &fh, p); 3016 if (error) | 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) |
3017 return (error); | 3013 goto out; |
3018 } 3019 /* 3020 * Check for restart conditions (client and server). 3021 */ 3022 if (op == NFSV4OP_DELEGRETURN) 3023 error = nfsrv_checkrestart(clientid, NFSLCK_DELEGRETURN, 3024 stateidp, 0); 3025 else --- 19 unchanged lines hidden (view full) --- 3045 error = NFSERR_OLDSTATEID; 3046 } 3047 /* 3048 * NFSERR_EXPIRED means that the state has gone away, 3049 * so Delegations have been purged. Just return ok. 3050 */ 3051 if (error == NFSERR_EXPIRED && op == NFSV4OP_DELEGPURGE) { 3052 NFSUNLOCKSTATE(); | 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 --- 19 unchanged lines hidden (view full) --- 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(); |
3053 return (0); | 3049 error = 0; 3050 goto out; |
3054 } 3055 if (error) { 3056 NFSUNLOCKSTATE(); | 3051 } 3052 if (error) { 3053 NFSUNLOCKSTATE(); |
3057 return (error); | 3054 goto out; |
3058 } 3059 3060 if (op == NFSV4OP_DELEGRETURN) { 3061 if (NFSBCMP((caddr_t)&fh, (caddr_t)&stp->ls_lfp->lf_fh, 3062 sizeof (fhandle_t))) { 3063 NFSUNLOCKSTATE(); | 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(); |
3064 return (NFSERR_BADSTATEID); | 3061 error = NFSERR_BADSTATEID; 3062 goto out; |
3065 } 3066 nfsrv_freedeleg(stp); 3067 } else { 3068 nfsrv_freedeleglist(&clp->lc_olddeleg); 3069 } 3070 NFSUNLOCKSTATE(); | 3063 } 3064 nfsrv_freedeleg(stp); 3065 } else { 3066 nfsrv_freedeleglist(&clp->lc_olddeleg); 3067 } 3068 NFSUNLOCKSTATE(); |
3071 return (0); | 3069 error = 0; 3070 3071out: 3072 NFSEXITCODE(error); 3073 return (error); |
3072} 3073 3074/* 3075 * Release lock owner. 3076 */ 3077APPLESTATIC int 3078nfsrv_releaselckown(struct nfsstate *new_stp, nfsquad_t clientid, 3079 NFSPROC_T *p) 3080{ 3081 struct nfsstate *stp, *nstp, *openstp, *ownstp; 3082 struct nfsclient *clp; | 3074} 3075 3076/* 3077 * Release lock owner. 3078 */ 3079APPLESTATIC int 3080nfsrv_releaselckown(struct nfsstate *new_stp, nfsquad_t clientid, 3081 NFSPROC_T *p) 3082{ 3083 struct nfsstate *stp, *nstp, *openstp, *ownstp; 3084 struct nfsclient *clp; |
3083 int error; | 3085 int error = 0; |
3084 3085 /* 3086 * Check for restart conditions (client and server). 3087 */ 3088 error = nfsrv_checkrestart(clientid, new_stp->ls_flags, 3089 &new_stp->ls_stateid, 0); 3090 if (error) | 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) |
3091 return (error); | 3093 goto out; |
3092 3093 NFSLOCKSTATE(); 3094 /* 3095 * Get the lock owner by name. 3096 */ 3097 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, 3098 (nfsquad_t)((u_quad_t)0), NULL, p); 3099 if (error) { 3100 NFSUNLOCKSTATE(); | 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(); |
3101 return (error); | 3103 goto out; |
3102 } 3103 LIST_FOREACH(ownstp, &clp->lc_open, ls_list) { 3104 LIST_FOREACH(openstp, &ownstp->ls_open, ls_list) { 3105 stp = LIST_FIRST(&openstp->ls_open); 3106 while (stp != LIST_END(&openstp->ls_open)) { 3107 nstp = LIST_NEXT(stp, ls_list); 3108 /* 3109 * If the owner matches, check for locks and 3110 * then free or return an error. 3111 */ 3112 if (stp->ls_ownerlen == new_stp->ls_ownerlen && 3113 !NFSBCMP(stp->ls_owner, new_stp->ls_owner, 3114 stp->ls_ownerlen)){ 3115 if (LIST_EMPTY(&stp->ls_lock)) { 3116 nfsrv_freelockowner(stp, NULL, 0, p); 3117 } else { 3118 NFSUNLOCKSTATE(); | 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(); |
3119 return (NFSERR_LOCKSHELD); | 3121 error = NFSERR_LOCKSHELD; 3122 goto out; |
3120 } 3121 } 3122 stp = nstp; 3123 } 3124 } 3125 } 3126 NFSUNLOCKSTATE(); | 3123 } 3124 } 3125 stp = nstp; 3126 } 3127 } 3128 } 3129 NFSUNLOCKSTATE(); |
3127 return (0); | 3130 3131out: 3132 NFSEXITCODE(error); 3133 return (error); |
3128} 3129 3130/* 3131 * Get the file handle for a lock structure. 3132 */ 3133static int 3134nfsrv_getlockfh(vnode_t vp, u_short flags, 3135 struct nfslockfile **new_lfpp, fhandle_t *nfhp, NFSPROC_T *p) --- 10 unchanged lines hidden (view full) --- 3146 new_lfp = *new_lfpp; 3147 fhp = &new_lfp->lf_fh; 3148 } else if (nfhp) { 3149 fhp = nfhp; 3150 } else { 3151 panic("nfsrv_getlockfh"); 3152 } 3153 error = nfsvno_getfh(vp, fhp, p); | 3134} 3135 3136/* 3137 * Get the file handle for a lock structure. 3138 */ 3139static int 3140nfsrv_getlockfh(vnode_t vp, u_short flags, 3141 struct nfslockfile **new_lfpp, fhandle_t *nfhp, NFSPROC_T *p) --- 10 unchanged lines hidden (view full) --- 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); |
|
3154 return (error); 3155} 3156 3157/* 3158 * Get an nfs lock structure. Allocate one, as required, and return a 3159 * pointer to it. 3160 * Returns an NFSERR_xxx upon failure or -1 to indicate no current lock. 3161 */ --- 239 unchanged lines hidden (view full) --- 3401/* 3402 * This function handles sequencing of locks, etc. 3403 * It returns an error that indicates what the caller should do. 3404 */ 3405static int 3406nfsrv_checkseqid(struct nfsrv_descript *nd, u_int32_t seqid, 3407 struct nfsstate *stp, struct nfsrvcache *op) 3408{ | 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 */ --- 239 unchanged lines hidden (view full) --- 3408/* 3409 * This function handles sequencing of locks, etc. 3410 * It returns an error that indicates what the caller should do. 3411 */ 3412static int 3413nfsrv_checkseqid(struct nfsrv_descript *nd, u_int32_t seqid, 3414 struct nfsstate *stp, struct nfsrvcache *op) 3415{ |
3416 int error = 0; |
|
3409 3410 if (op != nd->nd_rp) 3411 panic("nfsrvstate checkseqid"); 3412 if (!(op->rc_flag & RC_INPROG)) 3413 panic("nfsrvstate not inprog"); 3414 if (stp->ls_op && stp->ls_op->rc_refcnt <= 0) { 3415 printf("refcnt=%d\n", stp->ls_op->rc_refcnt); 3416 panic("nfsrvstate op refcnt"); 3417 } 3418 if ((stp->ls_seq + 1) == seqid) { 3419 if (stp->ls_op) 3420 nfsrvd_derefcache(stp->ls_op); 3421 stp->ls_op = op; 3422 nfsrvd_refcache(op); 3423 stp->ls_seq = seqid; | 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; |
3424 return (0); | 3432 goto out; |
3425 } else if (stp->ls_seq == seqid && stp->ls_op && 3426 op->rc_xid == stp->ls_op->rc_xid && 3427 op->rc_refcnt == 0 && 3428 op->rc_reqlen == stp->ls_op->rc_reqlen && 3429 op->rc_cksum == stp->ls_op->rc_cksum) { | 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) { |
3430 if (stp->ls_op->rc_flag & RC_INPROG) 3431 return (NFSERR_DONTREPLY); | 3438 if (stp->ls_op->rc_flag & RC_INPROG) { 3439 error = NFSERR_DONTREPLY; 3440 goto out; 3441 } |
3432 nd->nd_rp = stp->ls_op; 3433 nd->nd_rp->rc_flag |= RC_INPROG; 3434 nfsrvd_delcache(op); | 3442 nd->nd_rp = stp->ls_op; 3443 nd->nd_rp->rc_flag |= RC_INPROG; 3444 nfsrvd_delcache(op); |
3435 return (NFSERR_REPLYFROMCACHE); | 3445 error = NFSERR_REPLYFROMCACHE; 3446 goto out; |
3436 } | 3447 } |
3437 return (NFSERR_BADSEQID); | 3448 error = NFSERR_BADSEQID; 3449 3450out: 3451 NFSEXITCODE2(error, nd); 3452 return (error); |
3438} 3439 3440/* 3441 * Get the client ip address for callbacks. If the strings can't be parsed, 3442 * just set lc_program to 0 to indicate no callbacks are possible. 3443 * (For cases where the address can't be parsed or is 0.0.0.0.0.0, set 3444 * the address to the client's transport address. This won't be used 3445 * for callbacks, but can be printed out by newnfsstats for info.) --- 107 unchanged lines hidden (view full) --- 3553 } 3554 if (cantparse) { 3555 sad = NFSSOCKADDR(nd->nd_nam, struct sockaddr_in *); 3556 rad->sin_addr.s_addr = sad->sin_addr.s_addr; 3557 rad->sin_port = 0x0; 3558 clp->lc_program = 0; 3559 } 3560nfsmout: | 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.) --- 107 unchanged lines hidden (view full) --- 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 } 3575nfsmout: |
3576 NFSEXITCODE2(error, nd); |
|
3561 return (error); 3562} 3563 3564/* 3565 * Turn a string of up to three decimal digits into a number. Return -1 upon 3566 * error. 3567 */ 3568static int --- 16 unchanged lines hidden (view full) --- 3585 3586/* 3587 * This function checks for restart conditions. 3588 */ 3589static int 3590nfsrv_checkrestart(nfsquad_t clientid, u_int32_t flags, 3591 nfsv4stateid_t *stateidp, int specialid) 3592{ | 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 */ 3584static int --- 16 unchanged lines hidden (view full) --- 3601 3602/* 3603 * This function checks for restart conditions. 3604 */ 3605static int 3606nfsrv_checkrestart(nfsquad_t clientid, u_int32_t flags, 3607 nfsv4stateid_t *stateidp, int specialid) 3608{ |
3593 int ret; | 3609 int ret = 0; |
3594 3595 /* 3596 * First check for a server restart. Open, LockT, ReleaseLockOwner 3597 * and DelegPurge have a clientid, the rest a stateid. 3598 */ 3599 if (flags & 3600 (NFSLCK_OPEN | NFSLCK_TEST | NFSLCK_RELEASE | NFSLCK_DELEGPURGE)) { | 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)) { |
3601 if (clientid.lval[0] != nfsrvboottime) 3602 return (NFSERR_STALECLIENTID); | 3617 if (clientid.lval[0] != nfsrvboottime) { 3618 ret = NFSERR_STALECLIENTID; 3619 goto out; 3620 } |
3603 } else if (stateidp->other[0] != nfsrvboottime && | 3621 } else if (stateidp->other[0] != nfsrvboottime && |
3604 specialid == 0) 3605 return (NFSERR_STALESTATEID); | 3622 specialid == 0) { 3623 ret = NFSERR_STALESTATEID; 3624 goto out; 3625 } |
3606 3607 /* 3608 * Read, Write, Setattr and LockT can return NFSERR_GRACE and do 3609 * not use a lock/open owner seqid#, so the check can be done now. 3610 * (The others will be checked, as required, later.) 3611 */ 3612 if (!(flags & (NFSLCK_CHECK | NFSLCK_TEST))) | 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))) |
3613 return (0); | 3633 goto out; |
3614 3615 NFSLOCKSTATE(); 3616 ret = nfsrv_checkgrace(flags); 3617 NFSUNLOCKSTATE(); | 3634 3635 NFSLOCKSTATE(); 3636 ret = nfsrv_checkgrace(flags); 3637 NFSUNLOCKSTATE(); |
3638 3639out: 3640 NFSEXITCODE(ret); |
|
3618 return (ret); 3619} 3620 3621/* 3622 * Check for grace. 3623 */ 3624static int 3625nfsrv_checkgrace(u_int32_t flags) 3626{ | 3641 return (ret); 3642} 3643 3644/* 3645 * Check for grace. 3646 */ 3647static int 3648nfsrv_checkgrace(u_int32_t flags) 3649{ |
3650 int error = 0; |
|
3627 3628 if (nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) { | 3651 3652 if (nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) { |
3629 if (flags & NFSLCK_RECLAIM) 3630 return (NFSERR_NOGRACE); | 3653 if (flags & NFSLCK_RECLAIM) { 3654 error = NFSERR_NOGRACE; 3655 goto out; 3656 } |
3631 } else { | 3657 } else { |
3632 if (!(flags & NFSLCK_RECLAIM)) 3633 return (NFSERR_GRACE); | 3658 if (!(flags & NFSLCK_RECLAIM)) { 3659 error = NFSERR_GRACE; 3660 goto out; 3661 } |
3634 3635 /* 3636 * If grace is almost over and we are still getting Reclaims, 3637 * extend grace a bit. 3638 */ 3639 if ((NFSD_MONOSEC + NFSRV_LEASEDELTA) > 3640 nfsrv_stablefirst.nsf_eograce) 3641 nfsrv_stablefirst.nsf_eograce = NFSD_MONOSEC + 3642 NFSRV_LEASEDELTA; 3643 } | 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 } |
3644 return (0); | 3672 3673out: 3674 NFSEXITCODE(error); 3675 return (error); |
3645} 3646 3647/* 3648 * Do a server callback. 3649 */ 3650static int 3651nfsrv_docallback(struct nfsclient *clp, int procnum, 3652 nfsv4stateid_t *stateidp, int trunc, fhandle_t *fhp, --- 132 unchanged lines hidden (view full) --- 3785 clp->lc_cbref--; 3786 if ((clp->lc_flags & LCL_WAKEUPWANTED) && clp->lc_cbref == 0) { 3787 clp->lc_flags &= ~LCL_WAKEUPWANTED; 3788 NFSUNLOCKSTATE(); 3789 wakeup((caddr_t)clp); 3790 } else { 3791 NFSUNLOCKSTATE(); 3792 } | 3676} 3677 3678/* 3679 * Do a server callback. 3680 */ 3681static int 3682nfsrv_docallback(struct nfsclient *clp, int procnum, 3683 nfsv4stateid_t *stateidp, int trunc, fhandle_t *fhp, --- 132 unchanged lines hidden (view full) --- 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); |
|
3793 return (error); 3794} 3795 3796/* 3797 * Return the next index# for a clientid. Mostly just increment and return 3798 * the next one, but... if the 32bit unsigned does actually wrap around, 3799 * it should be rebooted. 3800 * At an average rate of one new client per second, it will wrap around in --- 511 unchanged lines hidden (view full) --- 4312 */ 4313 if (stp->ls_flags & NFSLCK_OLDDELEG) { 4314 /* 4315 * You can delete it, if it has expired. 4316 */ 4317 if (clp->lc_delegtime < NFSD_MONOSEC) { 4318 nfsrv_freedeleg(stp); 4319 NFSUNLOCKSTATE(); | 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 --- 511 unchanged lines hidden (view full) --- 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(); |
4320 return (-1); | 4353 error = -1; 4354 goto out; |
4321 } 4322 NFSUNLOCKSTATE(); 4323 /* 4324 * During this delay, the old delegation could expire or it 4325 * could be recovered by the client via an Open with 4326 * CLAIM_DELEGATE_PREV. 4327 * Release the nfsv4root_lock, if held. 4328 */ 4329 if (*haslockp) { 4330 *haslockp = 0; 4331 NFSLOCKV4ROOTMUTEX(); 4332 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4333 NFSUNLOCKV4ROOTMUTEX(); 4334 } | 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 } |
4335 return (NFSERR_DELAY); | 4369 error = NFSERR_DELAY; 4370 goto out; |
4336 } 4337 4338 /* 4339 * It's a current delegation, so: 4340 * - check to see if the delegation has expired 4341 * - if so, get the v4root lock and then expire it 4342 */ 4343 if (!(stp->ls_flags & NFSLCK_DELEGRECALL)) { --- 39 unchanged lines hidden (view full) --- 4383 } 4384 retrycnt = 0; 4385 do { 4386 error = nfsrv_docallback(clp, NFSV4OP_CBRECALL, 4387 &tstateid, 0, &tfh, NULL, NULL, p); 4388 retrycnt++; 4389 } while ((error == NFSERR_BADSTATEID || 4390 error == NFSERR_BADHANDLE) && retrycnt < NFSV4_CBRETRYCNT); | 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)) { --- 39 unchanged lines hidden (view full) --- 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); |
4391 return (NFSERR_DELAY); | 4426 error = NFSERR_DELAY; 4427 goto out; |
4392 } 4393 4394 if (clp->lc_expiry >= NFSD_MONOSEC && 4395 stp->ls_delegtime >= NFSD_MONOSEC) { 4396 NFSUNLOCKSTATE(); 4397 /* 4398 * A recall has been done, but it has not yet expired. 4399 * So, RETURN_DELAY. 4400 */ 4401 if (*haslockp) { 4402 *haslockp = 0; 4403 NFSLOCKV4ROOTMUTEX(); 4404 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4405 NFSUNLOCKV4ROOTMUTEX(); 4406 } | 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 } |
4407 return (NFSERR_DELAY); | 4443 error = NFSERR_DELAY; 4444 goto out; |
4408 } 4409 4410 /* 4411 * If we don't yet have the lock, just get it and then return, 4412 * since we need that before deleting expired state, such as 4413 * this delegation. 4414 * When getting the lock, unlock the vnode, so other nfsds that 4415 * are in progress, won't get stuck waiting for the vnode lock. --- 11 unchanged lines hidden (view full) --- 4427 NFSUNLOCKV4ROOTMUTEX(); 4428 *haslockp = 1; 4429 NFSVOPLOCK(vp, lktype | LK_RETRY); 4430 if ((vp->v_iflag & VI_DOOMED) != 0) { 4431 *haslockp = 0; 4432 NFSLOCKV4ROOTMUTEX(); 4433 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4434 NFSUNLOCKV4ROOTMUTEX(); | 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. --- 11 unchanged lines hidden (view full) --- 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(); |
4435 return (NFSERR_PERM); | 4472 error = NFSERR_PERM; 4473 goto out; |
4436 } | 4474 } |
4437 return (-1); | 4475 error = -1; 4476 goto out; |
4438 } 4439 4440 NFSUNLOCKSTATE(); 4441 /* 4442 * Ok, we can delete the expired delegation. 4443 * First, write the Revoke record to stable storage and then 4444 * clear out the conflict. 4445 * Since all other nfsd threads are now blocked, we can safely --- 8 unchanged lines hidden (view full) --- 4454 LIST_REMOVE(clp, lc_hash); 4455 zapped_clp = 1; 4456 } else { 4457 nfsrv_freedeleg(stp); 4458 zapped_clp = 0; 4459 } 4460 if (zapped_clp) 4461 nfsrv_zapclient(clp, p); | 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 --- 8 unchanged lines hidden (view full) --- 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); |
4462 return (-1); | 4501 error = -1; 4502 4503out: 4504 NFSEXITCODE(error); 4505 return (error); |
4463} 4464 4465/* 4466 * Check for a remove allowed, if remove is set to 1 and get rid of 4467 * delegations. 4468 */ 4469APPLESTATIC int 4470nfsrv_checkremove(vnode_t vp, int remove, NFSPROC_T *p) --- 15 unchanged lines hidden (view full) --- 4486 if (error) { 4487 NFSUNLOCKSTATE(); 4488 if (haslock) { 4489 NFSLOCKV4ROOTMUTEX(); 4490 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4491 NFSUNLOCKV4ROOTMUTEX(); 4492 } 4493 if (error == -1) | 4506} 4507 4508/* 4509 * Check for a remove allowed, if remove is set to 1 and get rid of 4510 * delegations. 4511 */ 4512APPLESTATIC int 4513nfsrv_checkremove(vnode_t vp, int remove, NFSPROC_T *p) --- 15 unchanged lines hidden (view full) --- 4529 if (error) { 4530 NFSUNLOCKSTATE(); 4531 if (haslock) { 4532 NFSLOCKV4ROOTMUTEX(); 4533 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4534 NFSUNLOCKV4ROOTMUTEX(); 4535 } 4536 if (error == -1) |
4494 return (0); 4495 return (error); | 4537 error = 0; 4538 goto out; |
4496 } 4497 4498 /* 4499 * Now, we must Recall any delegations. 4500 */ 4501 error = nfsrv_cleandeleg(vp, lfp, NULL, &haslock, p); 4502 if (error) { 4503 /* 4504 * nfsrv_cleandeleg() unlocks state for non-zero 4505 * return. 4506 */ 4507 if (error == -1) 4508 goto tryagain; 4509 if (haslock) { 4510 NFSLOCKV4ROOTMUTEX(); 4511 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4512 NFSUNLOCKV4ROOTMUTEX(); 4513 } | 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 } |
4514 return (error); | 4557 goto out; |
4515 } 4516 4517 /* 4518 * Now, look for a conflicting open share. 4519 */ 4520 if (remove) { 4521 LIST_FOREACH(stp, &lfp->lf_open, ls_file) { 4522 if (stp->ls_flags & NFSLCK_WRITEDENY) { --- 4 unchanged lines hidden (view full) --- 4527 } 4528 4529 NFSUNLOCKSTATE(); 4530 if (haslock) { 4531 NFSLOCKV4ROOTMUTEX(); 4532 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4533 NFSUNLOCKV4ROOTMUTEX(); 4534 } | 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) { --- 4 unchanged lines hidden (view full) --- 4570 } 4571 4572 NFSUNLOCKSTATE(); 4573 if (haslock) { 4574 NFSLOCKV4ROOTMUTEX(); 4575 nfsv4_unlock(&nfsv4rootfs_lock, 1); 4576 NFSUNLOCKV4ROOTMUTEX(); 4577 } |
4578 4579out: 4580 NFSEXITCODE(error); |
|
4535 return (error); 4536} 4537 4538/* 4539 * Clear out all delegations for the file referred to by lfp. 4540 * May return NFSERR_DELAY, if there will be a delay waiting for 4541 * delegations to expire. 4542 * Returns -1 to indicate it slept while recalling a delegation. 4543 * This function has the side effect of deleting the nfslockfile structure, 4544 * if it no longer has associated state and didn't have to sleep. 4545 * Unlocks State before a non-zero value is returned. 4546 */ 4547static int 4548nfsrv_cleandeleg(vnode_t vp, struct nfslockfile *lfp, 4549 struct nfsclient *clp, int *haslockp, NFSPROC_T *p) 4550{ 4551 struct nfsstate *stp, *nstp; | 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 */ 4593static int 4594nfsrv_cleandeleg(vnode_t vp, struct nfslockfile *lfp, 4595 struct nfsclient *clp, int *haslockp, NFSPROC_T *p) 4596{ 4597 struct nfsstate *stp, *nstp; |
4552 int ret; | 4598 int ret = 0; |
4553 4554 stp = LIST_FIRST(&lfp->lf_deleg); 4555 while (stp != LIST_END(&lfp->lf_deleg)) { 4556 nstp = LIST_NEXT(stp, ls_file); 4557 if (stp->ls_clp != clp) { 4558 ret = nfsrv_delegconflict(stp, haslockp, p, vp); 4559 if (ret) { 4560 /* 4561 * nfsrv_delegconflict() unlocks state 4562 * when it returns non-zero. 4563 */ | 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 */ |
4564 return (ret); | 4610 goto out; |
4565 } 4566 } 4567 stp = nstp; 4568 } | 4611 } 4612 } 4613 stp = nstp; 4614 } |
4569 return (0); | 4615out: 4616 NFSEXITCODE(ret); 4617 return (ret); |
4570} 4571 4572/* 4573 * There are certain operations that, when being done outside of NFSv4, 4574 * require that any NFSv4 delegation for the file be recalled. 4575 * This function is to be called for those cases: 4576 * VOP_RENAME() - When a delegation is being recalled for any reason, 4577 * the client may have to do Opens against the server, using the file's --- 117 unchanged lines hidden (view full) --- 4695 lop->lo_first = 0; 4696 } 4697 if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNER) || 4698 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP) || 4699 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_MODE) || 4700 NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_ACL)) 4701 stp->ls_flags |= NFSLCK_SETATTR; 4702 if (stp->ls_flags == 0) | 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 --- 117 unchanged lines hidden (view full) --- 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) |
4703 return (0); | 4751 goto out; |
4704 lop->lo_end = NFS64BITSSET; 4705 lop->lo_flags = NFSLCK_WRITE; 4706 stp->ls_ownerlen = 0; 4707 stp->ls_op = NULL; 4708 stp->ls_uid = nd->nd_cred->cr_uid; 4709 stp->ls_stateid.seqid = stateidp->seqid; 4710 clientid.lval[0] = stp->ls_stateid.other[0] = stateidp->other[0]; 4711 clientid.lval[1] = stp->ls_stateid.other[1] = stateidp->other[1]; 4712 stp->ls_stateid.other[2] = stateidp->other[2]; 4713 error = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid, 4714 stateidp, exp, nd, p); | 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 4764out: 4765 NFSEXITCODE2(error, nd); |
|
4715 return (error); 4716} 4717 4718/* 4719 * Check for a write delegation and do a CBGETATTR if there is one, updating 4720 * the attributes, as required. 4721 * Should I return an error if I can't get the attributes? (For now, I'll 4722 * just return ok. 4723 */ 4724APPLESTATIC int 4725nfsrv_checkgetattr(struct nfsrv_descript *nd, vnode_t vp, 4726 struct nfsvattr *nvap, nfsattrbit_t *attrbitp, struct ucred *cred, 4727 NFSPROC_T *p) 4728{ 4729 struct nfsstate *stp; 4730 struct nfslockfile *lfp; 4731 struct nfsclient *clp; 4732 struct nfsvattr nva; 4733 fhandle_t nfh; | 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 */ 4775APPLESTATIC int 4776nfsrv_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; |
4734 int error; | 4785 int error = 0; |
4735 nfsattrbit_t cbbits; 4736 u_quad_t delegfilerev; 4737 4738 NFSCBGETATTR_ATTRBIT(attrbitp, &cbbits); 4739 if (!NFSNONZERO_ATTRBIT(&cbbits)) | 4786 nfsattrbit_t cbbits; 4787 u_quad_t delegfilerev; 4788 4789 NFSCBGETATTR_ATTRBIT(attrbitp, &cbbits); 4790 if (!NFSNONZERO_ATTRBIT(&cbbits)) |
4740 return (0); | 4791 goto out; |
4741 4742 /* 4743 * Get the lock file structure. 4744 * (A return of -1 means no associated state, so return ok.) 4745 */ 4746 error = nfsrv_getlockfh(vp, NFSLCK_CHECK, NULL, &nfh, p); 4747 NFSLOCKSTATE(); 4748 if (!error) 4749 error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh, 0); 4750 if (error) { 4751 NFSUNLOCKSTATE(); 4752 if (error == -1) | 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) |
4753 return (0); 4754 return (error); | 4804 error = 0; 4805 goto out; |
4755 } 4756 4757 /* 4758 * Now, look for a write delegation. 4759 */ 4760 LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) { 4761 if (stp->ls_flags & NFSLCK_DELEGWRITE) 4762 break; 4763 } 4764 if (stp == LIST_END(&lfp->lf_deleg)) { 4765 NFSUNLOCKSTATE(); | 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(); |
4766 return (0); | 4817 goto out; |
4767 } 4768 clp = stp->ls_clp; 4769 delegfilerev = stp->ls_filerev; 4770 4771 /* 4772 * If the Write delegation was issued as a part of this Compound RPC 4773 * or if we have an Implied Clientid (used in a previous Op in this 4774 * compound) and it is the client the delegation was issued to, 4775 * just return ok. 4776 * I also assume that it is from the same client iff the network 4777 * host IP address is the same as the callback address. (Not 4778 * exactly correct by the RFC, but avoids a lot of Getattr 4779 * callbacks.) 4780 */ 4781 if (nd->nd_compref == stp->ls_compref || 4782 ((nd->nd_flag & ND_IMPLIEDCLID) && 4783 clp->lc_clientid.qval == nd->nd_clientid.qval) || 4784 nfsaddr2_match(clp->lc_req.nr_nam, nd->nd_nam)) { 4785 NFSUNLOCKSTATE(); | 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(); |
4786 return (0); | 4837 goto out; |
4787 } 4788 4789 /* 4790 * We are now done with the delegation state structure, 4791 * so the statelock can be released and we can now tsleep(). 4792 */ 4793 4794 /* --- 14 unchanged lines hidden (view full) --- 4809 nfsvno_updfilerev(vp, nvap, cred, p); 4810 if (NFSVNO_ISSETSIZE(&nva)) 4811 nvap->na_size = nva.na_size; 4812 } 4813 } 4814 } else { 4815 NFSUNLOCKSTATE(); 4816 } | 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 /* --- 14 unchanged lines hidden (view full) --- 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 } |
4817 return (0); | 4868 error = 0; 4869 4870out: 4871 NFSEXITCODE2(error, nd); 4872 return (error); |
4818} 4819 4820/* 4821 * This function looks for openowners that haven't had any opens for 4822 * a while and throws them away. Called by an nfsd when NFSNSF_NOOPENS 4823 * is set. 4824 */ 4825APPLESTATIC void --- 166 unchanged lines hidden (view full) --- 4992 lop = nlop; 4993 } 4994 } 4995 } 4996 if (first < end && error == 0) 4997 /* handle fragment past end of list */ 4998 error = nfsrv_dolocal(vp, lfp, flags, NFSLCK_UNLOCK, first, 4999 end, cfp, p); | 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 */ 4880APPLESTATIC void --- 166 unchanged lines hidden (view full) --- 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); |
|
5000 return (error); 5001} 5002 5003/* 5004 * Local lock unlock. Unlock all byte ranges that are no longer locked 5005 * by NFSv4. To do this, unlock any subranges of first-->end that 5006 * do not overlap with the byte ranges of any lock in the lfp->lf_lock 5007 * list. This list has all locks for the file held by other --- 66 unchanged lines hidden (view full) --- 5074 * Do the local lock operation and update the rollback list, as required. 5075 * Perform the rollback and return the error if nfsvno_advlock() fails. 5076 */ 5077static int 5078nfsrv_dolocal(vnode_t vp, struct nfslockfile *lfp, int flags, int oldflags, 5079 uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p) 5080{ 5081 struct nfsrollback *rlp; | 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 --- 66 unchanged lines hidden (view full) --- 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 */ 5134static int 5135nfsrv_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; |
5082 int error, ltype, oldltype; | 5139 int error = 0, ltype, oldltype; |
5083 5084 if (flags & NFSLCK_WRITE) 5085 ltype = F_WRLCK; 5086 else if (flags & NFSLCK_READ) 5087 ltype = F_RDLCK; 5088 else 5089 ltype = F_UNLCK; 5090 if (oldflags & NFSLCK_WRITE) 5091 oldltype = F_WRLCK; 5092 else if (oldflags & NFSLCK_READ) 5093 oldltype = F_RDLCK; 5094 else 5095 oldltype = F_UNLCK; 5096 if (ltype == oldltype || (oldltype == F_WRLCK && ltype == F_RDLCK)) 5097 /* nothing to do */ | 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 */ |
5098 return (0); | 5155 goto out; |
5099 error = nfsvno_advlock(vp, ltype, first, end, p); 5100 if (error != 0) { 5101 if (cfp != NULL) { 5102 cfp->cl_clientid.lval[0] = 0; 5103 cfp->cl_clientid.lval[1] = 0; 5104 cfp->cl_first = 0; 5105 cfp->cl_end = NFS64BITSSET; 5106 cfp->cl_flags = NFSLCK_WRITE; --- 4 unchanged lines hidden (view full) --- 5111 } else if (ltype != F_UNLCK) { 5112 rlp = malloc(sizeof (struct nfsrollback), M_NFSDROLLBACK, 5113 M_WAITOK); 5114 rlp->rlck_first = first; 5115 rlp->rlck_end = end; 5116 rlp->rlck_type = oldltype; 5117 LIST_INSERT_HEAD(&lfp->lf_rollback, rlp, rlck_list); 5118 } | 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; --- 4 unchanged lines hidden (view full) --- 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 5177out: 5178 NFSEXITCODE(error); |
|
5119 return (error); 5120} 5121 5122/* 5123 * Roll back local lock changes and free up the rollback list. 5124 */ 5125static void 5126nfsrv_locallock_rollback(vnode_t vp, struct nfslockfile *lfp, NFSPROC_T *p) --- 104 unchanged lines hidden --- | 5179 return (error); 5180} 5181 5182/* 5183 * Roll back local lock changes and free up the rollback list. 5184 */ 5185static void 5186nfsrv_locallock_rollback(vnode_t vp, struct nfslockfile *lfp, NFSPROC_T *p) --- 104 unchanged lines hidden --- |