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