Deleted Added
full compact
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 ---