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