xref: /freebsd/sys/fs/nfsserver/nfs_nfsdstate.c (revision 6574b8ed19b093f0af09501d2c9676c28993cb97)
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 			error = NFSERR_BADSTATEID;
1633 	      if (error == 0 &&
1634 		  (stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) &&
1635 		  getlckret == 0 && stp->ls_lfp != lfp)
1636 			error = NFSERR_BADSTATEID;
1637 
1638 	      /*
1639 	       * If the lockowner stateid doesn't refer to the same file,
1640 	       * I believe that is considered ok, since some clients will
1641 	       * only create a single lockowner and use that for all locks
1642 	       * on all files.
1643 	       * For now, log it as a diagnostic, instead of considering it
1644 	       * a BadStateid.
1645 	       */
1646 	      if (error == 0 && (stp->ls_flags &
1647 		  (NFSLCK_OPEN | NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) == 0 &&
1648 		  getlckret == 0 && stp->ls_lfp != lfp) {
1649 #ifdef DIAGNOSTIC
1650 		  printf("Got a lock statid for different file open\n");
1651 #endif
1652 		  /*
1653 		  error = NFSERR_BADSTATEID;
1654 		  */
1655 	      }
1656 
1657 	      if (error == 0) {
1658 		    if (new_stp->ls_flags & NFSLCK_OPENTOLOCK) {
1659 			/*
1660 			 * If haslock set, we've already checked the seqid.
1661 			 */
1662 			if (!haslock) {
1663 			    if (stp->ls_flags & NFSLCK_OPEN)
1664 				error = nfsrv_checkseqid(nd, new_stp->ls_seq,
1665 				    stp->ls_openowner, new_stp->ls_op);
1666 			    else
1667 				error = NFSERR_BADSTATEID;
1668 			}
1669 			if (!error)
1670 			    nfsrv_getowner(&stp->ls_open, new_stp, &lckstp);
1671 			if (lckstp)
1672 			    /*
1673 			     * I believe this should be an error, but it
1674 			     * isn't obvious what NFSERR_xxx would be
1675 			     * appropriate, so I'll use NFSERR_INVAL for now.
1676 			     */
1677 			    error = NFSERR_INVAL;
1678 			else
1679 			    lckstp = new_stp;
1680 		    } else if (new_stp->ls_flags&(NFSLCK_LOCK|NFSLCK_UNLOCK)) {
1681 			/*
1682 			 * If haslock set, ditto above.
1683 			 */
1684 			if (!haslock) {
1685 			    if (stp->ls_flags & NFSLCK_OPEN)
1686 				error = NFSERR_BADSTATEID;
1687 			    else
1688 				error = nfsrv_checkseqid(nd, new_stp->ls_seq,
1689 				    stp, new_stp->ls_op);
1690 			}
1691 			lckstp = stp;
1692 		    } else {
1693 			lckstp = stp;
1694 		    }
1695 	      }
1696 	      /*
1697 	       * If the seqid part of the stateid isn't the same, return
1698 	       * NFSERR_OLDSTATEID for cases other than I/O Ops.
1699 	       * For I/O Ops, only return NFSERR_OLDSTATEID if
1700 	       * nfsrv_returnoldstateid is set. (The concensus on the email
1701 	       * list was that most clients would prefer to not receive
1702 	       * NFSERR_OLDSTATEID for I/O Ops, but the RFC suggests that that
1703 	       * is what will happen, so I use the nfsrv_returnoldstateid to
1704 	       * allow for either server configuration.)
1705 	       */
1706 	      if (!error && stp->ls_stateid.seqid!=new_stp->ls_stateid.seqid &&
1707 		  (((nd->nd_flag & ND_NFSV41) == 0 &&
1708 		   (!(new_stp->ls_flags & NFSLCK_CHECK) ||
1709 		    nfsrv_returnoldstateid)) ||
1710 		   ((nd->nd_flag & ND_NFSV41) != 0 &&
1711 		    new_stp->ls_stateid.seqid != 0)))
1712 		    error = NFSERR_OLDSTATEID;
1713 	    }
1714 	}
1715 
1716 	/*
1717 	 * Now we can check for grace.
1718 	 */
1719 	if (!error)
1720 		error = nfsrv_checkgrace(nd, clp, new_stp->ls_flags);
1721 	if ((new_stp->ls_flags & NFSLCK_RECLAIM) && !error &&
1722 		nfsrv_checkstable(clp))
1723 		error = NFSERR_NOGRACE;
1724 	/*
1725 	 * If we successfully Reclaimed state, note that.
1726 	 */
1727 	if ((new_stp->ls_flags & NFSLCK_RECLAIM) && !error)
1728 		nfsrv_markstable(clp);
1729 
1730 	/*
1731 	 * At this point, either error == NFSERR_BADSTATEID or the
1732 	 * seqid# has been updated, so we can return any error.
1733 	 * If error == 0, there may be an error in:
1734 	 *    nd_repstat - Set by the calling function.
1735 	 *    reterr - Set above, if getting the nfslockfile structure
1736 	 *       or acquiring the local lock failed.
1737 	 *    (If both of these are set, nd_repstat should probably be
1738 	 *     returned, since that error was detected before this
1739 	 *     function call.)
1740 	 */
1741 	if (error != 0 || nd->nd_repstat != 0 || reterr != 0) {
1742 		if (error == 0) {
1743 			if (nd->nd_repstat != 0)
1744 				error = nd->nd_repstat;
1745 			else
1746 				error = reterr;
1747 		}
1748 		if (filestruct_locked != 0) {
1749 			/* Roll back local locks. */
1750 			NFSUNLOCKSTATE();
1751 			nfsrv_locallock_rollback(vp, lfp, p);
1752 			NFSLOCKSTATE();
1753 			nfsrv_unlocklf(lfp);
1754 		}
1755 		NFSUNLOCKSTATE();
1756 		goto out;
1757 	}
1758 
1759 	/*
1760 	 * Check the nfsrv_getlockfile return.
1761 	 * Returned -1 if no structure found.
1762 	 */
1763 	if (getlckret == -1) {
1764 		error = NFSERR_EXPIRED;
1765 		/*
1766 		 * Called from lockt, so no lock is OK.
1767 		 */
1768 		if (new_stp->ls_flags & NFSLCK_TEST) {
1769 			error = 0;
1770 		} else if (new_stp->ls_flags &
1771 		    (NFSLCK_CHECK | NFSLCK_SETATTR)) {
1772 			/*
1773 			 * Called to check for a lock, OK if the stateid is all
1774 			 * 1s or all 0s, but there should be an nfsstate
1775 			 * otherwise.
1776 			 * (ie. If there is no open, I'll assume no share
1777 			 *  deny bits.)
1778 			 */
1779 			if (specialid)
1780 				error = 0;
1781 			else
1782 				error = NFSERR_BADSTATEID;
1783 		}
1784 		NFSUNLOCKSTATE();
1785 		goto out;
1786 	}
1787 
1788 	/*
1789 	 * For NFSLCK_CHECK and NFSLCK_LOCK, test for a share conflict.
1790 	 * For NFSLCK_CHECK, allow a read if write access is granted,
1791 	 * but check for a deny. For NFSLCK_LOCK, require correct access,
1792 	 * which implies a conflicting deny can't exist.
1793 	 */
1794 	if (new_stp->ls_flags & (NFSLCK_CHECK | NFSLCK_LOCK)) {
1795 	    /*
1796 	     * Four kinds of state id:
1797 	     * - specialid (all 0s or all 1s), only for NFSLCK_CHECK
1798 	     * - stateid for an open
1799 	     * - stateid for a delegation
1800 	     * - stateid for a lock owner
1801 	     */
1802 	    if (!specialid) {
1803 		if (stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) {
1804 		    delegation = 1;
1805 		    mystp = stp;
1806 		    nfsrv_delaydelegtimeout(stp);
1807 	        } else if (stp->ls_flags & NFSLCK_OPEN) {
1808 		    mystp = stp;
1809 		} else {
1810 		    mystp = stp->ls_openstp;
1811 		}
1812 		/*
1813 		 * If locking or checking, require correct access
1814 		 * bit set.
1815 		 */
1816 		if (((new_stp->ls_flags & NFSLCK_LOCK) &&
1817 		     !((new_lop->lo_flags >> NFSLCK_LOCKSHIFT) &
1818 		       mystp->ls_flags & NFSLCK_ACCESSBITS)) ||
1819 		    ((new_stp->ls_flags & (NFSLCK_CHECK|NFSLCK_READACCESS)) ==
1820 		      (NFSLCK_CHECK | NFSLCK_READACCESS) &&
1821 		     !(mystp->ls_flags & NFSLCK_READACCESS)) ||
1822 		    ((new_stp->ls_flags & (NFSLCK_CHECK|NFSLCK_WRITEACCESS)) ==
1823 		      (NFSLCK_CHECK | NFSLCK_WRITEACCESS) &&
1824 		     !(mystp->ls_flags & NFSLCK_WRITEACCESS))) {
1825 			if (filestruct_locked != 0) {
1826 				/* Roll back local locks. */
1827 				NFSUNLOCKSTATE();
1828 				nfsrv_locallock_rollback(vp, lfp, p);
1829 				NFSLOCKSTATE();
1830 				nfsrv_unlocklf(lfp);
1831 			}
1832 			NFSUNLOCKSTATE();
1833 			error = NFSERR_OPENMODE;
1834 			goto out;
1835 		}
1836 	    } else
1837 		mystp = NULL;
1838 	    if ((new_stp->ls_flags & NFSLCK_CHECK) && !delegation) {
1839 		/*
1840 		 * Check for a conflicting deny bit.
1841 		 */
1842 		LIST_FOREACH(tstp, &lfp->lf_open, ls_file) {
1843 		    if (tstp != mystp) {
1844 			bits = tstp->ls_flags;
1845 			bits >>= NFSLCK_SHIFT;
1846 			if (new_stp->ls_flags & bits & NFSLCK_ACCESSBITS) {
1847 			    ret = nfsrv_clientconflict(tstp->ls_clp, &haslock,
1848 				vp, p);
1849 			    if (ret == 1) {
1850 				/*
1851 				* nfsrv_clientconflict unlocks state
1852 				 * when it returns non-zero.
1853 				 */
1854 				lckstp = NULL;
1855 				goto tryagain;
1856 			    }
1857 			    if (ret == 0)
1858 				NFSUNLOCKSTATE();
1859 			    if (ret == 2)
1860 				error = NFSERR_PERM;
1861 			    else
1862 				error = NFSERR_OPENMODE;
1863 			    goto out;
1864 			}
1865 		    }
1866 		}
1867 
1868 		/* We're outta here */
1869 		NFSUNLOCKSTATE();
1870 		goto out;
1871 	    }
1872 	}
1873 
1874 	/*
1875 	 * For setattr, just get rid of all the Delegations for other clients.
1876 	 */
1877 	if (new_stp->ls_flags & NFSLCK_SETATTR) {
1878 		ret = nfsrv_cleandeleg(vp, lfp, clp, &haslock, p);
1879 		if (ret) {
1880 			/*
1881 			 * nfsrv_cleandeleg() unlocks state when it
1882 			 * returns non-zero.
1883 			 */
1884 			if (ret == -1) {
1885 				lckstp = NULL;
1886 				goto tryagain;
1887 			}
1888 			error = ret;
1889 			goto out;
1890 		}
1891 		if (!(new_stp->ls_flags & NFSLCK_CHECK) ||
1892 		    (LIST_EMPTY(&lfp->lf_open) && LIST_EMPTY(&lfp->lf_lock) &&
1893 		     LIST_EMPTY(&lfp->lf_deleg))) {
1894 			NFSUNLOCKSTATE();
1895 			goto out;
1896 		}
1897 	}
1898 
1899 	/*
1900 	 * Check for a conflicting delegation. If one is found, call
1901 	 * nfsrv_delegconflict() to handle it. If the v4root lock hasn't
1902 	 * been set yet, it will get the lock. Otherwise, it will recall
1903 	 * the delegation. Then, we try try again...
1904 	 * I currently believe the conflict algorithm to be:
1905 	 * For Lock Ops (Lock/LockT/LockU)
1906 	 * - there is a conflict iff a different client has a write delegation
1907 	 * For Reading (Read Op)
1908 	 * - there is a conflict iff a different client has a write delegation
1909 	 *   (the specialids are always a different client)
1910 	 * For Writing (Write/Setattr of size)
1911 	 * - there is a conflict if a different client has any delegation
1912 	 * - there is a conflict if the same client has a read delegation
1913 	 *   (I don't understand why this isn't allowed, but that seems to be
1914 	 *    the current concensus?)
1915 	 */
1916 	tstp = LIST_FIRST(&lfp->lf_deleg);
1917 	while (tstp != LIST_END(&lfp->lf_deleg)) {
1918 	    nstp = LIST_NEXT(tstp, ls_file);
1919 	    if ((((new_stp->ls_flags&(NFSLCK_LOCK|NFSLCK_UNLOCK|NFSLCK_TEST))||
1920 		 ((new_stp->ls_flags & NFSLCK_CHECK) &&
1921 		  (new_lop->lo_flags & NFSLCK_READ))) &&
1922 		  clp != tstp->ls_clp &&
1923 		 (tstp->ls_flags & NFSLCK_DELEGWRITE)) ||
1924 		 ((new_stp->ls_flags & NFSLCK_CHECK) &&
1925 		   (new_lop->lo_flags & NFSLCK_WRITE) &&
1926 		  (clp != tstp->ls_clp ||
1927 		   (tstp->ls_flags & NFSLCK_DELEGREAD)))) {
1928 		if (filestruct_locked != 0) {
1929 			/* Roll back local locks. */
1930 			NFSUNLOCKSTATE();
1931 			nfsrv_locallock_rollback(vp, lfp, p);
1932 			NFSLOCKSTATE();
1933 			nfsrv_unlocklf(lfp);
1934 		}
1935 		ret = nfsrv_delegconflict(tstp, &haslock, p, vp);
1936 		if (ret) {
1937 		    /*
1938 		     * nfsrv_delegconflict unlocks state when it
1939 		     * returns non-zero, which it always does.
1940 		     */
1941 		    if (other_lop) {
1942 			FREE((caddr_t)other_lop, M_NFSDLOCK);
1943 			other_lop = NULL;
1944 		    }
1945 		    if (ret == -1) {
1946 			lckstp = NULL;
1947 			goto tryagain;
1948 		    }
1949 		    error = ret;
1950 		    goto out;
1951 		}
1952 		/* Never gets here. */
1953 	    }
1954 	    tstp = nstp;
1955 	}
1956 
1957 	/*
1958 	 * Handle the unlock case by calling nfsrv_updatelock().
1959 	 * (Should I have done some access checking above for unlock? For now,
1960 	 *  just let it happen.)
1961 	 */
1962 	if (new_stp->ls_flags & NFSLCK_UNLOCK) {
1963 		first = new_lop->lo_first;
1964 		end = new_lop->lo_end;
1965 		nfsrv_updatelock(stp, new_lopp, &other_lop, lfp);
1966 		stateidp->seqid = ++(stp->ls_stateid.seqid);
1967 		if ((nd->nd_flag & ND_NFSV41) != 0 && stateidp->seqid == 0)
1968 			stateidp->seqid = stp->ls_stateid.seqid = 1;
1969 		stateidp->other[0] = stp->ls_stateid.other[0];
1970 		stateidp->other[1] = stp->ls_stateid.other[1];
1971 		stateidp->other[2] = stp->ls_stateid.other[2];
1972 		if (filestruct_locked != 0) {
1973 			NFSUNLOCKSTATE();
1974 			/* Update the local locks. */
1975 			nfsrv_localunlock(vp, lfp, first, end, p);
1976 			NFSLOCKSTATE();
1977 			nfsrv_unlocklf(lfp);
1978 		}
1979 		NFSUNLOCKSTATE();
1980 		goto out;
1981 	}
1982 
1983 	/*
1984 	 * Search for a conflicting lock. A lock conflicts if:
1985 	 * - the lock range overlaps and
1986 	 * - at least one lock is a write lock and
1987 	 * - it is not owned by the same lock owner
1988 	 */
1989 	if (!delegation) {
1990 	  LIST_FOREACH(lop, &lfp->lf_lock, lo_lckfile) {
1991 	    if (new_lop->lo_end > lop->lo_first &&
1992 		new_lop->lo_first < lop->lo_end &&
1993 		(new_lop->lo_flags == NFSLCK_WRITE ||
1994 		 lop->lo_flags == NFSLCK_WRITE) &&
1995 		lckstp != lop->lo_stp &&
1996 		(clp != lop->lo_stp->ls_clp ||
1997 		 lckstp->ls_ownerlen != lop->lo_stp->ls_ownerlen ||
1998 		 NFSBCMP(lckstp->ls_owner, lop->lo_stp->ls_owner,
1999 		    lckstp->ls_ownerlen))) {
2000 		if (other_lop) {
2001 		    FREE((caddr_t)other_lop, M_NFSDLOCK);
2002 		    other_lop = NULL;
2003 		}
2004 		ret = nfsrv_clientconflict(lop->lo_stp->ls_clp,&haslock,vp,p);
2005 		if (ret == 1) {
2006 		    if (filestruct_locked != 0) {
2007 			/* Roll back local locks. */
2008 			nfsrv_locallock_rollback(vp, lfp, p);
2009 			NFSLOCKSTATE();
2010 			nfsrv_unlocklf(lfp);
2011 			NFSUNLOCKSTATE();
2012 		    }
2013 		    /*
2014 		     * nfsrv_clientconflict() unlocks state when it
2015 		     * returns non-zero.
2016 		     */
2017 		    lckstp = NULL;
2018 		    goto tryagain;
2019 		}
2020 		/*
2021 		 * Found a conflicting lock, so record the conflict and
2022 		 * return the error.
2023 		 */
2024 		if (cfp != NULL && ret == 0) {
2025 		    cfp->cl_clientid.lval[0]=lop->lo_stp->ls_stateid.other[0];
2026 		    cfp->cl_clientid.lval[1]=lop->lo_stp->ls_stateid.other[1];
2027 		    cfp->cl_first = lop->lo_first;
2028 		    cfp->cl_end = lop->lo_end;
2029 		    cfp->cl_flags = lop->lo_flags;
2030 		    cfp->cl_ownerlen = lop->lo_stp->ls_ownerlen;
2031 		    NFSBCOPY(lop->lo_stp->ls_owner, cfp->cl_owner,
2032 			cfp->cl_ownerlen);
2033 		}
2034 		if (ret == 2)
2035 		    error = NFSERR_PERM;
2036 		else if (new_stp->ls_flags & NFSLCK_RECLAIM)
2037 		    error = NFSERR_RECLAIMCONFLICT;
2038 		else if (new_stp->ls_flags & NFSLCK_CHECK)
2039 		    error = NFSERR_LOCKED;
2040 		else
2041 		    error = NFSERR_DENIED;
2042 		if (filestruct_locked != 0 && ret == 0) {
2043 			/* Roll back local locks. */
2044 			NFSUNLOCKSTATE();
2045 			nfsrv_locallock_rollback(vp, lfp, p);
2046 			NFSLOCKSTATE();
2047 			nfsrv_unlocklf(lfp);
2048 		}
2049 		if (ret == 0)
2050 			NFSUNLOCKSTATE();
2051 		goto out;
2052 	    }
2053 	  }
2054 	}
2055 
2056 	/*
2057 	 * We only get here if there was no lock that conflicted.
2058 	 */
2059 	if (new_stp->ls_flags & (NFSLCK_TEST | NFSLCK_CHECK)) {
2060 		NFSUNLOCKSTATE();
2061 		goto out;
2062 	}
2063 
2064 	/*
2065 	 * We only get here when we are creating or modifying a lock.
2066 	 * There are two variants:
2067 	 * - exist_lock_owner where lock_owner exists
2068 	 * - open_to_lock_owner with new lock_owner
2069 	 */
2070 	first = new_lop->lo_first;
2071 	end = new_lop->lo_end;
2072 	lock_flags = new_lop->lo_flags;
2073 	if (!(new_stp->ls_flags & NFSLCK_OPENTOLOCK)) {
2074 		nfsrv_updatelock(lckstp, new_lopp, &other_lop, lfp);
2075 		stateidp->seqid = ++(lckstp->ls_stateid.seqid);
2076 		if ((nd->nd_flag & ND_NFSV41) != 0 && stateidp->seqid == 0)
2077 			stateidp->seqid = lckstp->ls_stateid.seqid = 1;
2078 		stateidp->other[0] = lckstp->ls_stateid.other[0];
2079 		stateidp->other[1] = lckstp->ls_stateid.other[1];
2080 		stateidp->other[2] = lckstp->ls_stateid.other[2];
2081 	} else {
2082 		/*
2083 		 * The new open_to_lock_owner case.
2084 		 * Link the new nfsstate into the lists.
2085 		 */
2086 		new_stp->ls_seq = new_stp->ls_opentolockseq;
2087 		nfsrvd_refcache(new_stp->ls_op);
2088 		stateidp->seqid = new_stp->ls_stateid.seqid = 1;
2089 		stateidp->other[0] = new_stp->ls_stateid.other[0] =
2090 		    clp->lc_clientid.lval[0];
2091 		stateidp->other[1] = new_stp->ls_stateid.other[1] =
2092 		    clp->lc_clientid.lval[1];
2093 		stateidp->other[2] = new_stp->ls_stateid.other[2] =
2094 		    nfsrv_nextstateindex(clp);
2095 		new_stp->ls_clp = clp;
2096 		LIST_INIT(&new_stp->ls_lock);
2097 		new_stp->ls_openstp = stp;
2098 		new_stp->ls_lfp = lfp;
2099 		nfsrv_insertlock(new_lop, (struct nfslock *)new_stp, new_stp,
2100 		    lfp);
2101 		LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_stp->ls_stateid),
2102 		    new_stp, ls_hash);
2103 		LIST_INSERT_HEAD(&stp->ls_open, new_stp, ls_list);
2104 		*new_lopp = NULL;
2105 		*new_stpp = NULL;
2106 		newnfsstats.srvlockowners++;
2107 		nfsrv_openpluslock++;
2108 	}
2109 	if (filestruct_locked != 0) {
2110 		NFSUNLOCKSTATE();
2111 		nfsrv_locallock_commit(lfp, lock_flags, first, end);
2112 		NFSLOCKSTATE();
2113 		nfsrv_unlocklf(lfp);
2114 	}
2115 	NFSUNLOCKSTATE();
2116 
2117 out:
2118 	if (haslock) {
2119 		NFSLOCKV4ROOTMUTEX();
2120 		nfsv4_unlock(&nfsv4rootfs_lock, 1);
2121 		NFSUNLOCKV4ROOTMUTEX();
2122 	}
2123 	if (other_lop)
2124 		FREE((caddr_t)other_lop, M_NFSDLOCK);
2125 	NFSEXITCODE2(error, nd);
2126 	return (error);
2127 }
2128 
2129 /*
2130  * Check for state errors for Open.
2131  * repstat is passed back out as an error if more critical errors
2132  * are not detected.
2133  */
2134 APPLESTATIC int
2135 nfsrv_opencheck(nfsquad_t clientid, nfsv4stateid_t *stateidp,
2136     struct nfsstate *new_stp, vnode_t vp, struct nfsrv_descript *nd,
2137     NFSPROC_T *p, int repstat)
2138 {
2139 	struct nfsstate *stp, *nstp;
2140 	struct nfsclient *clp;
2141 	struct nfsstate *ownerstp;
2142 	struct nfslockfile *lfp, *new_lfp;
2143 	int error = 0, haslock = 0, ret, readonly = 0, getfhret = 0;
2144 
2145 	if ((new_stp->ls_flags & NFSLCK_SHAREBITS) == NFSLCK_READACCESS)
2146 		readonly = 1;
2147 	/*
2148 	 * Check for restart conditions (client and server).
2149 	 */
2150 	error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
2151 		&new_stp->ls_stateid, 0);
2152 	if (error)
2153 		goto out;
2154 
2155 	/*
2156 	 * Check for state resource limit exceeded.
2157 	 * Technically this should be SMP protected, but the worst
2158 	 * case error is "out by one or two" on the count when it
2159 	 * returns NFSERR_RESOURCE and the limit is just a rather
2160 	 * arbitrary high water mark, so no harm is done.
2161 	 */
2162 	if (nfsrv_openpluslock > NFSRV_V4STATELIMIT) {
2163 		error = NFSERR_RESOURCE;
2164 		goto out;
2165 	}
2166 
2167 tryagain:
2168 	MALLOC(new_lfp, struct nfslockfile *, sizeof (struct nfslockfile),
2169 	    M_NFSDLOCKFILE, M_WAITOK);
2170 	if (vp)
2171 		getfhret = nfsrv_getlockfh(vp, new_stp->ls_flags, new_lfp,
2172 		    NULL, p);
2173 	NFSLOCKSTATE();
2174 	/*
2175 	 * Get the nfsclient structure.
2176 	 */
2177 	error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
2178 	    (nfsquad_t)((u_quad_t)0), 0, nd, p);
2179 
2180 	/*
2181 	 * Look up the open owner. See if it needs confirmation and
2182 	 * check the seq#, as required.
2183 	 */
2184 	if (!error)
2185 		nfsrv_getowner(&clp->lc_open, new_stp, &ownerstp);
2186 
2187 	if (!error && ownerstp) {
2188 		error = nfsrv_checkseqid(nd, new_stp->ls_seq, ownerstp,
2189 		    new_stp->ls_op);
2190 		/*
2191 		 * If the OpenOwner hasn't been confirmed, assume the
2192 		 * old one was a replay and this one is ok.
2193 		 * See: RFC3530 Sec. 14.2.18.
2194 		 */
2195 		if (error == NFSERR_BADSEQID &&
2196 		    (ownerstp->ls_flags & NFSLCK_NEEDSCONFIRM))
2197 			error = 0;
2198 	}
2199 
2200 	/*
2201 	 * Check for grace.
2202 	 */
2203 	if (!error)
2204 		error = nfsrv_checkgrace(nd, clp, new_stp->ls_flags);
2205 	if ((new_stp->ls_flags & NFSLCK_RECLAIM) && !error &&
2206 		nfsrv_checkstable(clp))
2207 		error = NFSERR_NOGRACE;
2208 
2209 	/*
2210 	 * If none of the above errors occurred, let repstat be
2211 	 * returned.
2212 	 */
2213 	if (repstat && !error)
2214 		error = repstat;
2215 	if (error) {
2216 		NFSUNLOCKSTATE();
2217 		if (haslock) {
2218 			NFSLOCKV4ROOTMUTEX();
2219 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
2220 			NFSUNLOCKV4ROOTMUTEX();
2221 		}
2222 		free((caddr_t)new_lfp, M_NFSDLOCKFILE);
2223 		goto out;
2224 	}
2225 
2226 	/*
2227 	 * If vp == NULL, the file doesn't exist yet, so return ok.
2228 	 * (This always happens on the first pass, so haslock must be 0.)
2229 	 */
2230 	if (vp == NULL) {
2231 		NFSUNLOCKSTATE();
2232 		FREE((caddr_t)new_lfp, M_NFSDLOCKFILE);
2233 		goto out;
2234 	}
2235 
2236 	/*
2237 	 * Get the structure for the underlying file.
2238 	 */
2239 	if (getfhret)
2240 		error = getfhret;
2241 	else
2242 		error = nfsrv_getlockfile(new_stp->ls_flags, &new_lfp, &lfp,
2243 		    NULL, 0);
2244 	if (new_lfp)
2245 		FREE((caddr_t)new_lfp, M_NFSDLOCKFILE);
2246 	if (error) {
2247 		NFSUNLOCKSTATE();
2248 		if (haslock) {
2249 			NFSLOCKV4ROOTMUTEX();
2250 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
2251 			NFSUNLOCKV4ROOTMUTEX();
2252 		}
2253 		goto out;
2254 	}
2255 
2256 	/*
2257 	 * Search for a conflicting open/share.
2258 	 */
2259 	if (new_stp->ls_flags & NFSLCK_DELEGCUR) {
2260 	    /*
2261 	     * For Delegate_Cur, search for the matching Delegation,
2262 	     * which indicates no conflict.
2263 	     * An old delegation should have been recovered by the
2264 	     * client doing a Claim_DELEGATE_Prev, so I won't let
2265 	     * it match and return NFSERR_EXPIRED. Should I let it
2266 	     * match?
2267 	     */
2268 	    LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) {
2269 		if (!(stp->ls_flags & NFSLCK_OLDDELEG) &&
2270 		    (((nd->nd_flag & ND_NFSV41) != 0 &&
2271 		    stateidp->seqid == 0) ||
2272 		    stateidp->seqid == stp->ls_stateid.seqid) &&
2273 		    !NFSBCMP(stateidp->other, stp->ls_stateid.other,
2274 			  NFSX_STATEIDOTHER))
2275 			break;
2276 	    }
2277 	    if (stp == LIST_END(&lfp->lf_deleg) ||
2278 		((new_stp->ls_flags & NFSLCK_WRITEACCESS) &&
2279 		 (stp->ls_flags & NFSLCK_DELEGREAD))) {
2280 		NFSUNLOCKSTATE();
2281 		if (haslock) {
2282 			NFSLOCKV4ROOTMUTEX();
2283 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
2284 			NFSUNLOCKV4ROOTMUTEX();
2285 		}
2286 		error = NFSERR_EXPIRED;
2287 		goto out;
2288 	    }
2289 	}
2290 
2291 	/*
2292 	 * Check for access/deny bit conflicts. I check for the same
2293 	 * owner as well, in case the client didn't bother.
2294 	 */
2295 	LIST_FOREACH(stp, &lfp->lf_open, ls_file) {
2296 		if (!(new_stp->ls_flags & NFSLCK_DELEGCUR) &&
2297 		    (((new_stp->ls_flags & NFSLCK_ACCESSBITS) &
2298 		      ((stp->ls_flags>>NFSLCK_SHIFT) & NFSLCK_ACCESSBITS))||
2299 		     ((stp->ls_flags & NFSLCK_ACCESSBITS) &
2300 		      ((new_stp->ls_flags>>NFSLCK_SHIFT)&NFSLCK_ACCESSBITS)))){
2301 			ret = nfsrv_clientconflict(stp->ls_clp,&haslock,vp,p);
2302 			if (ret == 1) {
2303 				/*
2304 				 * nfsrv_clientconflict() unlocks
2305 				 * state when it returns non-zero.
2306 				 */
2307 				goto tryagain;
2308 			}
2309 			if (ret == 2)
2310 				error = NFSERR_PERM;
2311 			else if (new_stp->ls_flags & NFSLCK_RECLAIM)
2312 				error = NFSERR_RECLAIMCONFLICT;
2313 			else
2314 				error = NFSERR_SHAREDENIED;
2315 			if (ret == 0)
2316 				NFSUNLOCKSTATE();
2317 			if (haslock) {
2318 				NFSLOCKV4ROOTMUTEX();
2319 				nfsv4_unlock(&nfsv4rootfs_lock, 1);
2320 				NFSUNLOCKV4ROOTMUTEX();
2321 			}
2322 			goto out;
2323 		}
2324 	}
2325 
2326 	/*
2327 	 * Check for a conflicting delegation. If one is found, call
2328 	 * nfsrv_delegconflict() to handle it. If the v4root lock hasn't
2329 	 * been set yet, it will get the lock. Otherwise, it will recall
2330 	 * the delegation. Then, we try try again...
2331 	 * (If NFSLCK_DELEGCUR is set, it has a delegation, so there
2332 	 *  isn't a conflict.)
2333 	 * I currently believe the conflict algorithm to be:
2334 	 * For Open with Read Access and Deny None
2335 	 * - there is a conflict iff a different client has a write delegation
2336 	 * For Open with other Write Access or any Deny except None
2337 	 * - there is a conflict if a different client has any delegation
2338 	 * - there is a conflict if the same client has a read delegation
2339 	 *   (The current concensus is that this last case should be
2340 	 *    considered a conflict since the client with a read delegation
2341 	 *    could have done an Open with ReadAccess and WriteDeny
2342 	 *    locally and then not have checked for the WriteDeny.)
2343 	 * Don't check for a Reclaim, since that will be dealt with
2344 	 * by nfsrv_openctrl().
2345 	 */
2346 	if (!(new_stp->ls_flags &
2347 		(NFSLCK_DELEGPREV | NFSLCK_DELEGCUR | NFSLCK_RECLAIM))) {
2348 	    stp = LIST_FIRST(&lfp->lf_deleg);
2349 	    while (stp != LIST_END(&lfp->lf_deleg)) {
2350 		nstp = LIST_NEXT(stp, ls_file);
2351 		if ((readonly && stp->ls_clp != clp &&
2352 		       (stp->ls_flags & NFSLCK_DELEGWRITE)) ||
2353 		    (!readonly && (stp->ls_clp != clp ||
2354 		         (stp->ls_flags & NFSLCK_DELEGREAD)))) {
2355 			ret = nfsrv_delegconflict(stp, &haslock, p, vp);
2356 			if (ret) {
2357 			    /*
2358 			     * nfsrv_delegconflict() unlocks state
2359 			     * when it returns non-zero.
2360 			     */
2361 			    if (ret == -1)
2362 				goto tryagain;
2363 			    error = ret;
2364 			    goto out;
2365 			}
2366 		}
2367 		stp = nstp;
2368 	    }
2369 	}
2370 	NFSUNLOCKSTATE();
2371 	if (haslock) {
2372 		NFSLOCKV4ROOTMUTEX();
2373 		nfsv4_unlock(&nfsv4rootfs_lock, 1);
2374 		NFSUNLOCKV4ROOTMUTEX();
2375 	}
2376 
2377 out:
2378 	NFSEXITCODE2(error, nd);
2379 	return (error);
2380 }
2381 
2382 /*
2383  * Open control function to create/update open state for an open.
2384  */
2385 APPLESTATIC int
2386 nfsrv_openctrl(struct nfsrv_descript *nd, vnode_t vp,
2387     struct nfsstate **new_stpp, nfsquad_t clientid, nfsv4stateid_t *stateidp,
2388     nfsv4stateid_t *delegstateidp, u_int32_t *rflagsp, struct nfsexstuff *exp,
2389     NFSPROC_T *p, u_quad_t filerev)
2390 {
2391 	struct nfsstate *new_stp = *new_stpp;
2392 	struct nfsstate *stp, *nstp;
2393 	struct nfsstate *openstp = NULL, *new_open, *ownerstp, *new_deleg;
2394 	struct nfslockfile *lfp, *new_lfp;
2395 	struct nfsclient *clp;
2396 	int error = 0, haslock = 0, ret, delegate = 1, writedeleg = 1;
2397 	int readonly = 0, cbret = 1, getfhret = 0;
2398 
2399 	if ((new_stp->ls_flags & NFSLCK_SHAREBITS) == NFSLCK_READACCESS)
2400 		readonly = 1;
2401 	/*
2402 	 * Check for restart conditions (client and server).
2403 	 * (Paranoia, should have been detected by nfsrv_opencheck().)
2404 	 * If an error does show up, return NFSERR_EXPIRED, since the
2405 	 * the seqid# has already been incremented.
2406 	 */
2407 	error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
2408 	    &new_stp->ls_stateid, 0);
2409 	if (error) {
2410 		printf("Nfsd: openctrl unexpected restart err=%d\n",
2411 		    error);
2412 		error = NFSERR_EXPIRED;
2413 		goto out;
2414 	}
2415 
2416 tryagain:
2417 	MALLOC(new_lfp, struct nfslockfile *, sizeof (struct nfslockfile),
2418 	    M_NFSDLOCKFILE, M_WAITOK);
2419 	MALLOC(new_open, struct nfsstate *, sizeof (struct nfsstate),
2420 	    M_NFSDSTATE, M_WAITOK);
2421 	MALLOC(new_deleg, struct nfsstate *, sizeof (struct nfsstate),
2422 	    M_NFSDSTATE, M_WAITOK);
2423 	getfhret = nfsrv_getlockfh(vp, new_stp->ls_flags, new_lfp,
2424 	    NULL, p);
2425 	NFSLOCKSTATE();
2426 	/*
2427 	 * Get the client structure. Since the linked lists could be changed
2428 	 * by other nfsd processes if this process does a tsleep(), one of
2429 	 * two things must be done.
2430 	 * 1 - don't tsleep()
2431 	 * or
2432 	 * 2 - get the nfsv4_lock() { indicated by haslock == 1 }
2433 	 *     before using the lists, since this lock stops the other
2434 	 *     nfsd. This should only be used for rare cases, since it
2435 	 *     essentially single threads the nfsd.
2436 	 *     At this time, it is only done for cases where the stable
2437 	 *     storage file must be written prior to completion of state
2438 	 *     expiration.
2439 	 */
2440 	error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
2441 	    (nfsquad_t)((u_quad_t)0), 0, nd, p);
2442 	if (!error && (clp->lc_flags & LCL_NEEDSCBNULL) &&
2443 	    clp->lc_program) {
2444 		/*
2445 		 * This happens on the first open for a client
2446 		 * that supports callbacks.
2447 		 */
2448 		NFSUNLOCKSTATE();
2449 		/*
2450 		 * Although nfsrv_docallback() will sleep, clp won't
2451 		 * go away, since they are only removed when the
2452 		 * nfsv4_lock() has blocked the nfsd threads. The
2453 		 * fields in clp can change, but having multiple
2454 		 * threads do this Null callback RPC should be
2455 		 * harmless.
2456 		 */
2457 		cbret = nfsrv_docallback(clp, NFSV4PROC_CBNULL,
2458 		    NULL, 0, NULL, NULL, NULL, p);
2459 		NFSLOCKSTATE();
2460 		clp->lc_flags &= ~LCL_NEEDSCBNULL;
2461 		if (!cbret)
2462 			clp->lc_flags |= LCL_CALLBACKSON;
2463 	}
2464 
2465 	/*
2466 	 * Look up the open owner. See if it needs confirmation and
2467 	 * check the seq#, as required.
2468 	 */
2469 	if (!error)
2470 		nfsrv_getowner(&clp->lc_open, new_stp, &ownerstp);
2471 
2472 	if (error) {
2473 		NFSUNLOCKSTATE();
2474 		printf("Nfsd: openctrl unexpected state err=%d\n",
2475 			error);
2476 		free((caddr_t)new_lfp, M_NFSDLOCKFILE);
2477 		free((caddr_t)new_open, M_NFSDSTATE);
2478 		free((caddr_t)new_deleg, M_NFSDSTATE);
2479 		if (haslock) {
2480 			NFSLOCKV4ROOTMUTEX();
2481 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
2482 			NFSUNLOCKV4ROOTMUTEX();
2483 		}
2484 		error = NFSERR_EXPIRED;
2485 		goto out;
2486 	}
2487 
2488 	if (new_stp->ls_flags & NFSLCK_RECLAIM)
2489 		nfsrv_markstable(clp);
2490 
2491 	/*
2492 	 * Get the structure for the underlying file.
2493 	 */
2494 	if (getfhret)
2495 		error = getfhret;
2496 	else
2497 		error = nfsrv_getlockfile(new_stp->ls_flags, &new_lfp, &lfp,
2498 		    NULL, 0);
2499 	if (new_lfp)
2500 		FREE((caddr_t)new_lfp, M_NFSDLOCKFILE);
2501 	if (error) {
2502 		NFSUNLOCKSTATE();
2503 		printf("Nfsd openctrl unexpected getlockfile err=%d\n",
2504 		    error);
2505 		free((caddr_t)new_open, M_NFSDSTATE);
2506 		free((caddr_t)new_deleg, M_NFSDSTATE);
2507 		if (haslock) {
2508 			NFSLOCKV4ROOTMUTEX();
2509 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
2510 			NFSUNLOCKV4ROOTMUTEX();
2511 		}
2512 		goto out;
2513 	}
2514 
2515 	/*
2516 	 * Search for a conflicting open/share.
2517 	 */
2518 	if (new_stp->ls_flags & NFSLCK_DELEGCUR) {
2519 	    /*
2520 	     * For Delegate_Cur, search for the matching Delegation,
2521 	     * which indicates no conflict.
2522 	     * An old delegation should have been recovered by the
2523 	     * client doing a Claim_DELEGATE_Prev, so I won't let
2524 	     * it match and return NFSERR_EXPIRED. Should I let it
2525 	     * match?
2526 	     */
2527 	    LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) {
2528 		if (!(stp->ls_flags & NFSLCK_OLDDELEG) &&
2529 		    (((nd->nd_flag & ND_NFSV41) != 0 &&
2530 		    stateidp->seqid == 0) ||
2531 		    stateidp->seqid == stp->ls_stateid.seqid) &&
2532 		    !NFSBCMP(stateidp->other, stp->ls_stateid.other,
2533 			NFSX_STATEIDOTHER))
2534 			break;
2535 	    }
2536 	    if (stp == LIST_END(&lfp->lf_deleg) ||
2537 		((new_stp->ls_flags & NFSLCK_WRITEACCESS) &&
2538 		 (stp->ls_flags & NFSLCK_DELEGREAD))) {
2539 		NFSUNLOCKSTATE();
2540 		printf("Nfsd openctrl unexpected expiry\n");
2541 		free((caddr_t)new_open, M_NFSDSTATE);
2542 		free((caddr_t)new_deleg, M_NFSDSTATE);
2543 		if (haslock) {
2544 			NFSLOCKV4ROOTMUTEX();
2545 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
2546 			NFSUNLOCKV4ROOTMUTEX();
2547 		}
2548 		error = NFSERR_EXPIRED;
2549 		goto out;
2550 	    }
2551 
2552 	    /*
2553 	     * Don't issue a Delegation, since one already exists and
2554 	     * delay delegation timeout, as required.
2555 	     */
2556 	    delegate = 0;
2557 	    nfsrv_delaydelegtimeout(stp);
2558 	}
2559 
2560 	/*
2561 	 * Check for access/deny bit conflicts. I also check for the
2562 	 * same owner, since the client might not have bothered to check.
2563 	 * Also, note an open for the same file and owner, if found,
2564 	 * which is all we do here for Delegate_Cur, since conflict
2565 	 * checking is already done.
2566 	 */
2567 	LIST_FOREACH(stp, &lfp->lf_open, ls_file) {
2568 		if (ownerstp && stp->ls_openowner == ownerstp)
2569 			openstp = stp;
2570 		if (!(new_stp->ls_flags & NFSLCK_DELEGCUR)) {
2571 		    /*
2572 		     * If another client has the file open, the only
2573 		     * delegation that can be issued is a Read delegation
2574 		     * and only if it is a Read open with Deny none.
2575 		     */
2576 		    if (clp != stp->ls_clp) {
2577 			if ((stp->ls_flags & NFSLCK_SHAREBITS) ==
2578 			    NFSLCK_READACCESS)
2579 			    writedeleg = 0;
2580 			else
2581 			    delegate = 0;
2582 		    }
2583 		    if(((new_stp->ls_flags & NFSLCK_ACCESSBITS) &
2584 		        ((stp->ls_flags>>NFSLCK_SHIFT) & NFSLCK_ACCESSBITS))||
2585 		       ((stp->ls_flags & NFSLCK_ACCESSBITS) &
2586 		        ((new_stp->ls_flags>>NFSLCK_SHIFT)&NFSLCK_ACCESSBITS))){
2587 			ret = nfsrv_clientconflict(stp->ls_clp,&haslock,vp,p);
2588 			if (ret == 1) {
2589 				/*
2590 				 * nfsrv_clientconflict() unlocks state
2591 				 * when it returns non-zero.
2592 				 */
2593 				free((caddr_t)new_open, M_NFSDSTATE);
2594 				free((caddr_t)new_deleg, M_NFSDSTATE);
2595 				openstp = NULL;
2596 				goto tryagain;
2597 			}
2598 			if (ret == 2)
2599 				error = NFSERR_PERM;
2600 			else if (new_stp->ls_flags & NFSLCK_RECLAIM)
2601 				error = NFSERR_RECLAIMCONFLICT;
2602 			else
2603 				error = NFSERR_SHAREDENIED;
2604 			if (ret == 0)
2605 				NFSUNLOCKSTATE();
2606 			if (haslock) {
2607 				NFSLOCKV4ROOTMUTEX();
2608 				nfsv4_unlock(&nfsv4rootfs_lock, 1);
2609 				NFSUNLOCKV4ROOTMUTEX();
2610 			}
2611 			free((caddr_t)new_open, M_NFSDSTATE);
2612 			free((caddr_t)new_deleg, M_NFSDSTATE);
2613 			printf("nfsd openctrl unexpected client cnfl\n");
2614 			goto out;
2615 		    }
2616 		}
2617 	}
2618 
2619 	/*
2620 	 * Check for a conflicting delegation. If one is found, call
2621 	 * nfsrv_delegconflict() to handle it. If the v4root lock hasn't
2622 	 * been set yet, it will get the lock. Otherwise, it will recall
2623 	 * the delegation. Then, we try try again...
2624 	 * (If NFSLCK_DELEGCUR is set, it has a delegation, so there
2625 	 *  isn't a conflict.)
2626 	 * I currently believe the conflict algorithm to be:
2627 	 * For Open with Read Access and Deny None
2628 	 * - there is a conflict iff a different client has a write delegation
2629 	 * For Open with other Write Access or any Deny except None
2630 	 * - there is a conflict if a different client has any delegation
2631 	 * - there is a conflict if the same client has a read delegation
2632 	 *   (The current concensus is that this last case should be
2633 	 *    considered a conflict since the client with a read delegation
2634 	 *    could have done an Open with ReadAccess and WriteDeny
2635 	 *    locally and then not have checked for the WriteDeny.)
2636 	 */
2637 	if (!(new_stp->ls_flags & (NFSLCK_DELEGPREV | NFSLCK_DELEGCUR))) {
2638 	    stp = LIST_FIRST(&lfp->lf_deleg);
2639 	    while (stp != LIST_END(&lfp->lf_deleg)) {
2640 		nstp = LIST_NEXT(stp, ls_file);
2641 		if (stp->ls_clp != clp && (stp->ls_flags & NFSLCK_DELEGREAD))
2642 			writedeleg = 0;
2643 		else
2644 			delegate = 0;
2645 		if ((readonly && stp->ls_clp != clp &&
2646 		       (stp->ls_flags & NFSLCK_DELEGWRITE)) ||
2647 		    (!readonly && (stp->ls_clp != clp ||
2648 		         (stp->ls_flags & NFSLCK_DELEGREAD)))) {
2649 		    if (new_stp->ls_flags & NFSLCK_RECLAIM) {
2650 			delegate = 2;
2651 		    } else {
2652 			ret = nfsrv_delegconflict(stp, &haslock, p, vp);
2653 			if (ret) {
2654 			    /*
2655 			     * nfsrv_delegconflict() unlocks state
2656 			     * when it returns non-zero.
2657 			     */
2658 			    printf("Nfsd openctrl unexpected deleg cnfl\n");
2659 			    free((caddr_t)new_open, M_NFSDSTATE);
2660 			    free((caddr_t)new_deleg, M_NFSDSTATE);
2661 			    if (ret == -1) {
2662 				openstp = NULL;
2663 				goto tryagain;
2664 			    }
2665 			    error = ret;
2666 			    goto out;
2667 			}
2668 		    }
2669 		}
2670 		stp = nstp;
2671 	    }
2672 	}
2673 
2674 	/*
2675 	 * We only get here if there was no open that conflicted.
2676 	 * If an open for the owner exists, or in the access/deny bits.
2677 	 * Otherwise it is a new open. If the open_owner hasn't been
2678 	 * confirmed, replace the open with the new one needing confirmation,
2679 	 * otherwise add the open.
2680 	 */
2681 	if (new_stp->ls_flags & NFSLCK_DELEGPREV) {
2682 	    /*
2683 	     * Handle NFSLCK_DELEGPREV by searching the old delegations for
2684 	     * a match. If found, just move the old delegation to the current
2685 	     * delegation list and issue open. If not found, return
2686 	     * NFSERR_EXPIRED.
2687 	     */
2688 	    LIST_FOREACH(stp, &clp->lc_olddeleg, ls_list) {
2689 		if (stp->ls_lfp == lfp) {
2690 		    /* Found it */
2691 		    if (stp->ls_clp != clp)
2692 			panic("olddeleg clp");
2693 		    LIST_REMOVE(stp, ls_list);
2694 		    LIST_REMOVE(stp, ls_hash);
2695 		    stp->ls_flags &= ~NFSLCK_OLDDELEG;
2696 		    stp->ls_stateid.seqid = delegstateidp->seqid = 1;
2697 		    stp->ls_stateid.other[0] = delegstateidp->other[0] =
2698 			clp->lc_clientid.lval[0];
2699 		    stp->ls_stateid.other[1] = delegstateidp->other[1] =
2700 			clp->lc_clientid.lval[1];
2701 		    stp->ls_stateid.other[2] = delegstateidp->other[2] =
2702 			nfsrv_nextstateindex(clp);
2703 		    stp->ls_compref = nd->nd_compref;
2704 		    LIST_INSERT_HEAD(&clp->lc_deleg, stp, ls_list);
2705 		    LIST_INSERT_HEAD(NFSSTATEHASH(clp,
2706 			stp->ls_stateid), stp, ls_hash);
2707 		    if (stp->ls_flags & NFSLCK_DELEGWRITE)
2708 			*rflagsp |= NFSV4OPEN_WRITEDELEGATE;
2709 		    else
2710 			*rflagsp |= NFSV4OPEN_READDELEGATE;
2711 		    clp->lc_delegtime = NFSD_MONOSEC +
2712 			nfsrv_lease + NFSRV_LEASEDELTA;
2713 
2714 		    /*
2715 		     * Now, do the associated open.
2716 		     */
2717 		    new_open->ls_stateid.seqid = 1;
2718 		    new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0];
2719 		    new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1];
2720 		    new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp);
2721 		    new_open->ls_flags = (new_stp->ls_flags&NFSLCK_DENYBITS)|
2722 			NFSLCK_OPEN;
2723 		    if (stp->ls_flags & NFSLCK_DELEGWRITE)
2724 			new_open->ls_flags |= (NFSLCK_READACCESS |
2725 			    NFSLCK_WRITEACCESS);
2726 		    else
2727 			new_open->ls_flags |= NFSLCK_READACCESS;
2728 		    new_open->ls_uid = new_stp->ls_uid;
2729 		    new_open->ls_lfp = lfp;
2730 		    new_open->ls_clp = clp;
2731 		    LIST_INIT(&new_open->ls_open);
2732 		    LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file);
2733 		    LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid),
2734 			new_open, ls_hash);
2735 		    /*
2736 		     * and handle the open owner
2737 		     */
2738 		    if (ownerstp) {
2739 			new_open->ls_openowner = ownerstp;
2740 			LIST_INSERT_HEAD(&ownerstp->ls_open,new_open,ls_list);
2741 		    } else {
2742 			new_open->ls_openowner = new_stp;
2743 			new_stp->ls_flags = 0;
2744 			nfsrvd_refcache(new_stp->ls_op);
2745 			new_stp->ls_noopens = 0;
2746 			LIST_INIT(&new_stp->ls_open);
2747 			LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list);
2748 			LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list);
2749 			*new_stpp = NULL;
2750 			newnfsstats.srvopenowners++;
2751 			nfsrv_openpluslock++;
2752 		    }
2753 		    openstp = new_open;
2754 		    new_open = NULL;
2755 		    newnfsstats.srvopens++;
2756 		    nfsrv_openpluslock++;
2757 		    break;
2758 		}
2759 	    }
2760 	    if (stp == LIST_END(&clp->lc_olddeleg))
2761 		error = NFSERR_EXPIRED;
2762 	} else if (new_stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) {
2763 	    /*
2764 	     * Scan to see that no delegation for this client and file
2765 	     * doesn't already exist.
2766 	     * There also shouldn't yet be an Open for this file and
2767 	     * openowner.
2768 	     */
2769 	    LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) {
2770 		if (stp->ls_clp == clp)
2771 		    break;
2772 	    }
2773 	    if (stp == LIST_END(&lfp->lf_deleg) && openstp == NULL) {
2774 		/*
2775 		 * This is the Claim_Previous case with a delegation
2776 		 * type != Delegate_None.
2777 		 */
2778 		/*
2779 		 * First, add the delegation. (Although we must issue the
2780 		 * delegation, we can also ask for an immediate return.)
2781 		 */
2782 		new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1;
2783 		new_deleg->ls_stateid.other[0] = delegstateidp->other[0] =
2784 		    clp->lc_clientid.lval[0];
2785 		new_deleg->ls_stateid.other[1] = delegstateidp->other[1] =
2786 		    clp->lc_clientid.lval[1];
2787 		new_deleg->ls_stateid.other[2] = delegstateidp->other[2] =
2788 		    nfsrv_nextstateindex(clp);
2789 		if (new_stp->ls_flags & NFSLCK_DELEGWRITE) {
2790 		    new_deleg->ls_flags = (NFSLCK_DELEGWRITE |
2791 			NFSLCK_READACCESS | NFSLCK_WRITEACCESS);
2792 		    *rflagsp |= NFSV4OPEN_WRITEDELEGATE;
2793 		} else {
2794 		    new_deleg->ls_flags = (NFSLCK_DELEGREAD |
2795 			NFSLCK_READACCESS);
2796 		    *rflagsp |= NFSV4OPEN_READDELEGATE;
2797 		}
2798 		new_deleg->ls_uid = new_stp->ls_uid;
2799 		new_deleg->ls_lfp = lfp;
2800 		new_deleg->ls_clp = clp;
2801 		new_deleg->ls_filerev = filerev;
2802 		new_deleg->ls_compref = nd->nd_compref;
2803 		LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file);
2804 		LIST_INSERT_HEAD(NFSSTATEHASH(clp,
2805 		    new_deleg->ls_stateid), new_deleg, ls_hash);
2806 		LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list);
2807 		new_deleg = NULL;
2808 		if (delegate == 2 || nfsrv_issuedelegs == 0 ||
2809 		    (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) !=
2810 		     LCL_CALLBACKSON ||
2811 		    NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) ||
2812 		    !NFSVNO_DELEGOK(vp))
2813 		    *rflagsp |= NFSV4OPEN_RECALL;
2814 		newnfsstats.srvdelegates++;
2815 		nfsrv_openpluslock++;
2816 		nfsrv_delegatecnt++;
2817 
2818 		/*
2819 		 * Now, do the associated open.
2820 		 */
2821 		new_open->ls_stateid.seqid = 1;
2822 		new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0];
2823 		new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1];
2824 		new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp);
2825 		new_open->ls_flags = (new_stp->ls_flags & NFSLCK_DENYBITS) |
2826 		    NFSLCK_OPEN;
2827 		if (new_stp->ls_flags & NFSLCK_DELEGWRITE)
2828 			new_open->ls_flags |= (NFSLCK_READACCESS |
2829 			    NFSLCK_WRITEACCESS);
2830 		else
2831 			new_open->ls_flags |= NFSLCK_READACCESS;
2832 		new_open->ls_uid = new_stp->ls_uid;
2833 		new_open->ls_lfp = lfp;
2834 		new_open->ls_clp = clp;
2835 		LIST_INIT(&new_open->ls_open);
2836 		LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file);
2837 		LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid),
2838 		   new_open, ls_hash);
2839 		/*
2840 		 * and handle the open owner
2841 		 */
2842 		if (ownerstp) {
2843 		    new_open->ls_openowner = ownerstp;
2844 		    LIST_INSERT_HEAD(&ownerstp->ls_open, new_open, ls_list);
2845 		} else {
2846 		    new_open->ls_openowner = new_stp;
2847 		    new_stp->ls_flags = 0;
2848 		    nfsrvd_refcache(new_stp->ls_op);
2849 		    new_stp->ls_noopens = 0;
2850 		    LIST_INIT(&new_stp->ls_open);
2851 		    LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list);
2852 		    LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list);
2853 		    *new_stpp = NULL;
2854 		    newnfsstats.srvopenowners++;
2855 		    nfsrv_openpluslock++;
2856 		}
2857 		openstp = new_open;
2858 		new_open = NULL;
2859 		newnfsstats.srvopens++;
2860 		nfsrv_openpluslock++;
2861 	    } else {
2862 		error = NFSERR_RECLAIMCONFLICT;
2863 	    }
2864 	} else if (ownerstp) {
2865 		if (ownerstp->ls_flags & NFSLCK_NEEDSCONFIRM) {
2866 		    /* Replace the open */
2867 		    if (ownerstp->ls_op)
2868 			nfsrvd_derefcache(ownerstp->ls_op);
2869 		    ownerstp->ls_op = new_stp->ls_op;
2870 		    nfsrvd_refcache(ownerstp->ls_op);
2871 		    ownerstp->ls_seq = new_stp->ls_seq;
2872 		    *rflagsp |= NFSV4OPEN_RESULTCONFIRM;
2873 		    stp = LIST_FIRST(&ownerstp->ls_open);
2874 		    stp->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS) |
2875 			NFSLCK_OPEN;
2876 		    stp->ls_stateid.seqid = 1;
2877 		    stp->ls_uid = new_stp->ls_uid;
2878 		    if (lfp != stp->ls_lfp) {
2879 			LIST_REMOVE(stp, ls_file);
2880 			LIST_INSERT_HEAD(&lfp->lf_open, stp, ls_file);
2881 			stp->ls_lfp = lfp;
2882 		    }
2883 		    openstp = stp;
2884 		} else if (openstp) {
2885 		    openstp->ls_flags |= (new_stp->ls_flags & NFSLCK_SHAREBITS);
2886 		    openstp->ls_stateid.seqid++;
2887 		    if ((nd->nd_flag & ND_NFSV41) != 0 &&
2888 			openstp->ls_stateid.seqid == 0)
2889 			openstp->ls_stateid.seqid = 1;
2890 
2891 		    /*
2892 		     * This is where we can choose to issue a delegation.
2893 		     */
2894 		    if (delegate == 0 || writedeleg == 0 ||
2895 			NFSVNO_EXRDONLY(exp) || (readonly != 0 &&
2896 			nfsrv_writedelegifpos == 0) ||
2897 			!NFSVNO_DELEGOK(vp) ||
2898 			(new_stp->ls_flags & NFSLCK_WANTRDELEG) != 0 ||
2899 			(clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) !=
2900 			 LCL_CALLBACKSON)
2901 			*rflagsp |= NFSV4OPEN_WDCONTENTION;
2902 		    else if (nfsrv_issuedelegs == 0 ||
2903 			NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt))
2904 			*rflagsp |= NFSV4OPEN_WDRESOURCE;
2905 		    else if ((new_stp->ls_flags & NFSLCK_WANTNODELEG) != 0)
2906 			*rflagsp |= NFSV4OPEN_WDNOTWANTED;
2907 		    else {
2908 			new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1;
2909 			new_deleg->ls_stateid.other[0] = delegstateidp->other[0]
2910 			    = clp->lc_clientid.lval[0];
2911 			new_deleg->ls_stateid.other[1] = delegstateidp->other[1]
2912 			    = clp->lc_clientid.lval[1];
2913 			new_deleg->ls_stateid.other[2] = delegstateidp->other[2]
2914 			    = nfsrv_nextstateindex(clp);
2915 			new_deleg->ls_flags = (NFSLCK_DELEGWRITE |
2916 			    NFSLCK_READACCESS | NFSLCK_WRITEACCESS);
2917 			*rflagsp |= NFSV4OPEN_WRITEDELEGATE;
2918 			new_deleg->ls_uid = new_stp->ls_uid;
2919 			new_deleg->ls_lfp = lfp;
2920 			new_deleg->ls_clp = clp;
2921 			new_deleg->ls_filerev = filerev;
2922 			new_deleg->ls_compref = nd->nd_compref;
2923 			LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file);
2924 			LIST_INSERT_HEAD(NFSSTATEHASH(clp,
2925 			    new_deleg->ls_stateid), new_deleg, ls_hash);
2926 			LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list);
2927 			new_deleg = NULL;
2928 			newnfsstats.srvdelegates++;
2929 			nfsrv_openpluslock++;
2930 			nfsrv_delegatecnt++;
2931 		    }
2932 		} else {
2933 		    new_open->ls_stateid.seqid = 1;
2934 		    new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0];
2935 		    new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1];
2936 		    new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp);
2937 		    new_open->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS)|
2938 			NFSLCK_OPEN;
2939 		    new_open->ls_uid = new_stp->ls_uid;
2940 		    new_open->ls_openowner = ownerstp;
2941 		    new_open->ls_lfp = lfp;
2942 		    new_open->ls_clp = clp;
2943 		    LIST_INIT(&new_open->ls_open);
2944 		    LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file);
2945 		    LIST_INSERT_HEAD(&ownerstp->ls_open, new_open, ls_list);
2946 		    LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid),
2947 			new_open, ls_hash);
2948 		    openstp = new_open;
2949 		    new_open = NULL;
2950 		    newnfsstats.srvopens++;
2951 		    nfsrv_openpluslock++;
2952 
2953 		    /*
2954 		     * This is where we can choose to issue a delegation.
2955 		     */
2956 		    if (delegate == 0 || (writedeleg == 0 && readonly == 0) ||
2957 			!NFSVNO_DELEGOK(vp) ||
2958 			(clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) !=
2959 			 LCL_CALLBACKSON)
2960 			*rflagsp |= NFSV4OPEN_WDCONTENTION;
2961 		    else if (nfsrv_issuedelegs == 0 ||
2962 			NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt))
2963 			*rflagsp |= NFSV4OPEN_WDRESOURCE;
2964 		    else if ((new_stp->ls_flags & NFSLCK_WANTNODELEG) != 0)
2965 			*rflagsp |= NFSV4OPEN_WDNOTWANTED;
2966 		    else {
2967 			new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1;
2968 			new_deleg->ls_stateid.other[0] = delegstateidp->other[0]
2969 			    = clp->lc_clientid.lval[0];
2970 			new_deleg->ls_stateid.other[1] = delegstateidp->other[1]
2971 			    = clp->lc_clientid.lval[1];
2972 			new_deleg->ls_stateid.other[2] = delegstateidp->other[2]
2973 			    = nfsrv_nextstateindex(clp);
2974 			if (writedeleg && !NFSVNO_EXRDONLY(exp) &&
2975 			    (nfsrv_writedelegifpos || !readonly) &&
2976 			    (new_stp->ls_flags & NFSLCK_WANTRDELEG) == 0) {
2977 			    new_deleg->ls_flags = (NFSLCK_DELEGWRITE |
2978 				NFSLCK_READACCESS | NFSLCK_WRITEACCESS);
2979 			    *rflagsp |= NFSV4OPEN_WRITEDELEGATE;
2980 			} else {
2981 			    new_deleg->ls_flags = (NFSLCK_DELEGREAD |
2982 				NFSLCK_READACCESS);
2983 			    *rflagsp |= NFSV4OPEN_READDELEGATE;
2984 			}
2985 			new_deleg->ls_uid = new_stp->ls_uid;
2986 			new_deleg->ls_lfp = lfp;
2987 			new_deleg->ls_clp = clp;
2988 			new_deleg->ls_filerev = filerev;
2989 			new_deleg->ls_compref = nd->nd_compref;
2990 			LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file);
2991 			LIST_INSERT_HEAD(NFSSTATEHASH(clp,
2992 			    new_deleg->ls_stateid), new_deleg, ls_hash);
2993 			LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list);
2994 			new_deleg = NULL;
2995 			newnfsstats.srvdelegates++;
2996 			nfsrv_openpluslock++;
2997 			nfsrv_delegatecnt++;
2998 		    }
2999 		}
3000 	} else {
3001 		/*
3002 		 * New owner case. Start the open_owner sequence with a
3003 		 * Needs confirmation (unless a reclaim) and hang the
3004 		 * new open off it.
3005 		 */
3006 		new_open->ls_stateid.seqid = 1;
3007 		new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0];
3008 		new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1];
3009 		new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp);
3010 		new_open->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS) |
3011 		    NFSLCK_OPEN;
3012 		new_open->ls_uid = new_stp->ls_uid;
3013 		LIST_INIT(&new_open->ls_open);
3014 		new_open->ls_openowner = new_stp;
3015 		new_open->ls_lfp = lfp;
3016 		new_open->ls_clp = clp;
3017 		LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file);
3018 		if (new_stp->ls_flags & NFSLCK_RECLAIM) {
3019 			new_stp->ls_flags = 0;
3020 		} else if ((nd->nd_flag & ND_NFSV41) != 0) {
3021 			/* NFSv4.1 never needs confirmation. */
3022 			new_stp->ls_flags = 0;
3023 
3024 			/*
3025 			 * This is where we can choose to issue a delegation.
3026 			 */
3027 			if (delegate && nfsrv_issuedelegs &&
3028 			    (writedeleg || readonly) &&
3029 			    (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) ==
3030 			     LCL_CALLBACKSON &&
3031 			    !NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) &&
3032 			    NFSVNO_DELEGOK(vp) &&
3033 			    ((nd->nd_flag & ND_NFSV41) == 0 ||
3034 			     (new_stp->ls_flags & NFSLCK_WANTNODELEG) == 0)) {
3035 				new_deleg->ls_stateid.seqid =
3036 				    delegstateidp->seqid = 1;
3037 				new_deleg->ls_stateid.other[0] =
3038 				    delegstateidp->other[0]
3039 				    = clp->lc_clientid.lval[0];
3040 				new_deleg->ls_stateid.other[1] =
3041 				    delegstateidp->other[1]
3042 				    = clp->lc_clientid.lval[1];
3043 				new_deleg->ls_stateid.other[2] =
3044 				    delegstateidp->other[2]
3045 				    = nfsrv_nextstateindex(clp);
3046 				if (writedeleg && !NFSVNO_EXRDONLY(exp) &&
3047 				    (nfsrv_writedelegifpos || !readonly) &&
3048 				    ((nd->nd_flag & ND_NFSV41) == 0 ||
3049 				     (new_stp->ls_flags & NFSLCK_WANTRDELEG) ==
3050 				     0)) {
3051 					new_deleg->ls_flags =
3052 					    (NFSLCK_DELEGWRITE |
3053 					     NFSLCK_READACCESS |
3054 					     NFSLCK_WRITEACCESS);
3055 					*rflagsp |= NFSV4OPEN_WRITEDELEGATE;
3056 				} else {
3057 					new_deleg->ls_flags =
3058 					    (NFSLCK_DELEGREAD |
3059 					     NFSLCK_READACCESS);
3060 					*rflagsp |= NFSV4OPEN_READDELEGATE;
3061 				}
3062 				new_deleg->ls_uid = new_stp->ls_uid;
3063 				new_deleg->ls_lfp = lfp;
3064 				new_deleg->ls_clp = clp;
3065 				new_deleg->ls_filerev = filerev;
3066 				new_deleg->ls_compref = nd->nd_compref;
3067 				LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg,
3068 				    ls_file);
3069 				LIST_INSERT_HEAD(NFSSTATEHASH(clp,
3070 				    new_deleg->ls_stateid), new_deleg, ls_hash);
3071 				LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg,
3072 				    ls_list);
3073 				new_deleg = NULL;
3074 				newnfsstats.srvdelegates++;
3075 				nfsrv_openpluslock++;
3076 				nfsrv_delegatecnt++;
3077 			}
3078 		} else {
3079 			*rflagsp |= NFSV4OPEN_RESULTCONFIRM;
3080 			new_stp->ls_flags = NFSLCK_NEEDSCONFIRM;
3081 		}
3082 		nfsrvd_refcache(new_stp->ls_op);
3083 		new_stp->ls_noopens = 0;
3084 		LIST_INIT(&new_stp->ls_open);
3085 		LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list);
3086 		LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list);
3087 		LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid),
3088 		    new_open, ls_hash);
3089 		openstp = new_open;
3090 		new_open = NULL;
3091 		*new_stpp = NULL;
3092 		newnfsstats.srvopens++;
3093 		nfsrv_openpluslock++;
3094 		newnfsstats.srvopenowners++;
3095 		nfsrv_openpluslock++;
3096 	}
3097 	if (!error) {
3098 		stateidp->seqid = openstp->ls_stateid.seqid;
3099 		stateidp->other[0] = openstp->ls_stateid.other[0];
3100 		stateidp->other[1] = openstp->ls_stateid.other[1];
3101 		stateidp->other[2] = openstp->ls_stateid.other[2];
3102 	}
3103 	NFSUNLOCKSTATE();
3104 	if (haslock) {
3105 		NFSLOCKV4ROOTMUTEX();
3106 		nfsv4_unlock(&nfsv4rootfs_lock, 1);
3107 		NFSUNLOCKV4ROOTMUTEX();
3108 	}
3109 	if (new_open)
3110 		FREE((caddr_t)new_open, M_NFSDSTATE);
3111 	if (new_deleg)
3112 		FREE((caddr_t)new_deleg, M_NFSDSTATE);
3113 
3114 out:
3115 	NFSEXITCODE2(error, nd);
3116 	return (error);
3117 }
3118 
3119 /*
3120  * Open update. Does the confirm, downgrade and close.
3121  */
3122 APPLESTATIC int
3123 nfsrv_openupdate(vnode_t vp, struct nfsstate *new_stp, nfsquad_t clientid,
3124     nfsv4stateid_t *stateidp, struct nfsrv_descript *nd, NFSPROC_T *p)
3125 {
3126 	struct nfsstate *stp, *ownerstp;
3127 	struct nfsclient *clp;
3128 	struct nfslockfile *lfp;
3129 	u_int32_t bits;
3130 	int error = 0, gotstate = 0, len = 0;
3131 	u_char client[NFSV4_OPAQUELIMIT];
3132 
3133 	/*
3134 	 * Check for restart conditions (client and server).
3135 	 */
3136 	error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
3137 	    &new_stp->ls_stateid, 0);
3138 	if (error)
3139 		goto out;
3140 
3141 	NFSLOCKSTATE();
3142 	/*
3143 	 * Get the open structure via clientid and stateid.
3144 	 */
3145 	error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
3146 	    (nfsquad_t)((u_quad_t)0), 0, nd, p);
3147 	if (!error)
3148 		error = nfsrv_getstate(clp, &new_stp->ls_stateid,
3149 		    new_stp->ls_flags, &stp);
3150 
3151 	/*
3152 	 * Sanity check the open.
3153 	 */
3154 	if (!error && (!(stp->ls_flags & NFSLCK_OPEN) ||
3155 		(!(new_stp->ls_flags & NFSLCK_CONFIRM) &&
3156 		 (stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM)) ||
3157 		((new_stp->ls_flags & NFSLCK_CONFIRM) &&
3158 		 (!(stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM)))))
3159 		error = NFSERR_BADSTATEID;
3160 
3161 	if (!error)
3162 		error = nfsrv_checkseqid(nd, new_stp->ls_seq,
3163 		    stp->ls_openowner, new_stp->ls_op);
3164 	if (!error && stp->ls_stateid.seqid != new_stp->ls_stateid.seqid &&
3165 	    (((nd->nd_flag & ND_NFSV41) == 0 &&
3166 	      !(new_stp->ls_flags & NFSLCK_CONFIRM)) ||
3167 	     ((nd->nd_flag & ND_NFSV41) != 0 &&
3168 	      new_stp->ls_stateid.seqid != 0)))
3169 		error = NFSERR_OLDSTATEID;
3170 	if (!error && vnode_vtype(vp) != VREG) {
3171 		if (vnode_vtype(vp) == VDIR)
3172 			error = NFSERR_ISDIR;
3173 		else
3174 			error = NFSERR_INVAL;
3175 	}
3176 
3177 	if (error) {
3178 		/*
3179 		 * If a client tries to confirm an Open with a bad
3180 		 * seqid# and there are no byte range locks or other Opens
3181 		 * on the openowner, just throw it away, so the next use of the
3182 		 * openowner will start a fresh seq#.
3183 		 */
3184 		if (error == NFSERR_BADSEQID &&
3185 		    (new_stp->ls_flags & NFSLCK_CONFIRM) &&
3186 		    nfsrv_nootherstate(stp))
3187 			nfsrv_freeopenowner(stp->ls_openowner, 0, p);
3188 		NFSUNLOCKSTATE();
3189 		goto out;
3190 	}
3191 
3192 	/*
3193 	 * Set the return stateid.
3194 	 */
3195 	stateidp->seqid = stp->ls_stateid.seqid + 1;
3196 	if ((nd->nd_flag & ND_NFSV41) != 0 && stateidp->seqid == 0)
3197 		stateidp->seqid = 1;
3198 	stateidp->other[0] = stp->ls_stateid.other[0];
3199 	stateidp->other[1] = stp->ls_stateid.other[1];
3200 	stateidp->other[2] = stp->ls_stateid.other[2];
3201 	/*
3202 	 * Now, handle the three cases.
3203 	 */
3204 	if (new_stp->ls_flags & NFSLCK_CONFIRM) {
3205 		/*
3206 		 * If the open doesn't need confirmation, it seems to me that
3207 		 * there is a client error, but I'll just log it and keep going?
3208 		 */
3209 		if (!(stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM))
3210 			printf("Nfsv4d: stray open confirm\n");
3211 		stp->ls_openowner->ls_flags = 0;
3212 		stp->ls_stateid.seqid++;
3213 		if ((nd->nd_flag & ND_NFSV41) != 0 &&
3214 		    stp->ls_stateid.seqid == 0)
3215 			stp->ls_stateid.seqid = 1;
3216 		if (!(clp->lc_flags & LCL_STAMPEDSTABLE)) {
3217 			clp->lc_flags |= LCL_STAMPEDSTABLE;
3218 			len = clp->lc_idlen;
3219 			NFSBCOPY(clp->lc_id, client, len);
3220 			gotstate = 1;
3221 		}
3222 		NFSUNLOCKSTATE();
3223 	} else if (new_stp->ls_flags & NFSLCK_CLOSE) {
3224 		ownerstp = stp->ls_openowner;
3225 		lfp = stp->ls_lfp;
3226 		if (nfsrv_dolocallocks != 0 && !LIST_EMPTY(&stp->ls_open)) {
3227 			/* Get the lf lock */
3228 			nfsrv_locklf(lfp);
3229 			NFSUNLOCKSTATE();
3230 			if (nfsrv_freeopen(stp, vp, 1, p) == 0) {
3231 				NFSLOCKSTATE();
3232 				nfsrv_unlocklf(lfp);
3233 				NFSUNLOCKSTATE();
3234 			}
3235 		} else {
3236 			(void) nfsrv_freeopen(stp, NULL, 0, p);
3237 			NFSUNLOCKSTATE();
3238 		}
3239 	} else {
3240 		/*
3241 		 * Update the share bits, making sure that the new set are a
3242 		 * subset of the old ones.
3243 		 */
3244 		bits = (new_stp->ls_flags & NFSLCK_SHAREBITS);
3245 		if (~(stp->ls_flags) & bits) {
3246 			NFSUNLOCKSTATE();
3247 			error = NFSERR_INVAL;
3248 			goto out;
3249 		}
3250 		stp->ls_flags = (bits | NFSLCK_OPEN);
3251 		stp->ls_stateid.seqid++;
3252 		if ((nd->nd_flag & ND_NFSV41) != 0 &&
3253 		    stp->ls_stateid.seqid == 0)
3254 			stp->ls_stateid.seqid = 1;
3255 		NFSUNLOCKSTATE();
3256 	}
3257 
3258 	/*
3259 	 * If the client just confirmed its first open, write a timestamp
3260 	 * to the stable storage file.
3261 	 */
3262 	if (gotstate != 0) {
3263 		nfsrv_writestable(client, len, NFSNST_NEWSTATE, p);
3264 		nfsrv_backupstable();
3265 	}
3266 
3267 out:
3268 	NFSEXITCODE2(error, nd);
3269 	return (error);
3270 }
3271 
3272 /*
3273  * Delegation update. Does the purge and return.
3274  */
3275 APPLESTATIC int
3276 nfsrv_delegupdate(struct nfsrv_descript *nd, nfsquad_t clientid,
3277     nfsv4stateid_t *stateidp, vnode_t vp, int op, struct ucred *cred,
3278     NFSPROC_T *p)
3279 {
3280 	struct nfsstate *stp;
3281 	struct nfsclient *clp;
3282 	int error = 0;
3283 	fhandle_t fh;
3284 
3285 	/*
3286 	 * Do a sanity check against the file handle for DelegReturn.
3287 	 */
3288 	if (vp) {
3289 		error = nfsvno_getfh(vp, &fh, p);
3290 		if (error)
3291 			goto out;
3292 	}
3293 	/*
3294 	 * Check for restart conditions (client and server).
3295 	 */
3296 	if (op == NFSV4OP_DELEGRETURN)
3297 		error = nfsrv_checkrestart(clientid, NFSLCK_DELEGRETURN,
3298 			stateidp, 0);
3299 	else
3300 		error = nfsrv_checkrestart(clientid, NFSLCK_DELEGPURGE,
3301 			stateidp, 0);
3302 
3303 	NFSLOCKSTATE();
3304 	/*
3305 	 * Get the open structure via clientid and stateid.
3306 	 */
3307 	if (!error)
3308 	    error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
3309 		(nfsquad_t)((u_quad_t)0), 0, nd, p);
3310 	if (error) {
3311 		if (error == NFSERR_CBPATHDOWN)
3312 			error = 0;
3313 		if (error == NFSERR_STALECLIENTID && op == NFSV4OP_DELEGRETURN)
3314 			error = NFSERR_STALESTATEID;
3315 	}
3316 	if (!error && op == NFSV4OP_DELEGRETURN) {
3317 	    error = nfsrv_getstate(clp, stateidp, NFSLCK_DELEGRETURN, &stp);
3318 	    if (!error && stp->ls_stateid.seqid != stateidp->seqid &&
3319 		((nd->nd_flag & ND_NFSV41) == 0 || stateidp->seqid != 0))
3320 		error = NFSERR_OLDSTATEID;
3321 	}
3322 	/*
3323 	 * NFSERR_EXPIRED means that the state has gone away,
3324 	 * so Delegations have been purged. Just return ok.
3325 	 */
3326 	if (error == NFSERR_EXPIRED && op == NFSV4OP_DELEGPURGE) {
3327 		NFSUNLOCKSTATE();
3328 		error = 0;
3329 		goto out;
3330 	}
3331 	if (error) {
3332 		NFSUNLOCKSTATE();
3333 		goto out;
3334 	}
3335 
3336 	if (op == NFSV4OP_DELEGRETURN) {
3337 		if (NFSBCMP((caddr_t)&fh, (caddr_t)&stp->ls_lfp->lf_fh,
3338 		    sizeof (fhandle_t))) {
3339 			NFSUNLOCKSTATE();
3340 			error = NFSERR_BADSTATEID;
3341 			goto out;
3342 		}
3343 		nfsrv_freedeleg(stp);
3344 	} else {
3345 		nfsrv_freedeleglist(&clp->lc_olddeleg);
3346 	}
3347 	NFSUNLOCKSTATE();
3348 	error = 0;
3349 
3350 out:
3351 	NFSEXITCODE(error);
3352 	return (error);
3353 }
3354 
3355 /*
3356  * Release lock owner.
3357  */
3358 APPLESTATIC int
3359 nfsrv_releaselckown(struct nfsstate *new_stp, nfsquad_t clientid,
3360     NFSPROC_T *p)
3361 {
3362 	struct nfsstate *stp, *nstp, *openstp, *ownstp;
3363 	struct nfsclient *clp;
3364 	int error = 0;
3365 
3366 	/*
3367 	 * Check for restart conditions (client and server).
3368 	 */
3369 	error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
3370 	    &new_stp->ls_stateid, 0);
3371 	if (error)
3372 		goto out;
3373 
3374 	NFSLOCKSTATE();
3375 	/*
3376 	 * Get the lock owner by name.
3377 	 */
3378 	error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
3379 	    (nfsquad_t)((u_quad_t)0), 0, NULL, p);
3380 	if (error) {
3381 		NFSUNLOCKSTATE();
3382 		goto out;
3383 	}
3384 	LIST_FOREACH(ownstp, &clp->lc_open, ls_list) {
3385 	    LIST_FOREACH(openstp, &ownstp->ls_open, ls_list) {
3386 		stp = LIST_FIRST(&openstp->ls_open);
3387 		while (stp != LIST_END(&openstp->ls_open)) {
3388 		    nstp = LIST_NEXT(stp, ls_list);
3389 		    /*
3390 		     * If the owner matches, check for locks and
3391 		     * then free or return an error.
3392 		     */
3393 		    if (stp->ls_ownerlen == new_stp->ls_ownerlen &&
3394 			!NFSBCMP(stp->ls_owner, new_stp->ls_owner,
3395 			 stp->ls_ownerlen)){
3396 			if (LIST_EMPTY(&stp->ls_lock)) {
3397 			    nfsrv_freelockowner(stp, NULL, 0, p);
3398 			} else {
3399 			    NFSUNLOCKSTATE();
3400 			    error = NFSERR_LOCKSHELD;
3401 			    goto out;
3402 			}
3403 		    }
3404 		    stp = nstp;
3405 		}
3406 	    }
3407 	}
3408 	NFSUNLOCKSTATE();
3409 
3410 out:
3411 	NFSEXITCODE(error);
3412 	return (error);
3413 }
3414 
3415 /*
3416  * Get the file handle for a lock structure.
3417  */
3418 static int
3419 nfsrv_getlockfh(vnode_t vp, u_short flags, struct nfslockfile *new_lfp,
3420     fhandle_t *nfhp, NFSPROC_T *p)
3421 {
3422 	fhandle_t *fhp = NULL;
3423 	int error;
3424 
3425 	/*
3426 	 * For lock, use the new nfslock structure, otherwise just
3427 	 * a fhandle_t on the stack.
3428 	 */
3429 	if (flags & NFSLCK_OPEN) {
3430 		KASSERT(new_lfp != NULL, ("nfsrv_getlockfh: new_lfp NULL"));
3431 		fhp = &new_lfp->lf_fh;
3432 	} else if (nfhp) {
3433 		fhp = nfhp;
3434 	} else {
3435 		panic("nfsrv_getlockfh");
3436 	}
3437 	error = nfsvno_getfh(vp, fhp, p);
3438 	NFSEXITCODE(error);
3439 	return (error);
3440 }
3441 
3442 /*
3443  * Get an nfs lock structure. Allocate one, as required, and return a
3444  * pointer to it.
3445  * Returns an NFSERR_xxx upon failure or -1 to indicate no current lock.
3446  */
3447 static int
3448 nfsrv_getlockfile(u_short flags, struct nfslockfile **new_lfpp,
3449     struct nfslockfile **lfpp, fhandle_t *nfhp, int lockit)
3450 {
3451 	struct nfslockfile *lfp;
3452 	fhandle_t *fhp = NULL, *tfhp;
3453 	struct nfslockhashhead *hp;
3454 	struct nfslockfile *new_lfp = NULL;
3455 
3456 	/*
3457 	 * For lock, use the new nfslock structure, otherwise just
3458 	 * a fhandle_t on the stack.
3459 	 */
3460 	if (flags & NFSLCK_OPEN) {
3461 		new_lfp = *new_lfpp;
3462 		fhp = &new_lfp->lf_fh;
3463 	} else if (nfhp) {
3464 		fhp = nfhp;
3465 	} else {
3466 		panic("nfsrv_getlockfile");
3467 	}
3468 
3469 	hp = NFSLOCKHASH(fhp);
3470 	LIST_FOREACH(lfp, hp, lf_hash) {
3471 		tfhp = &lfp->lf_fh;
3472 		if (NFSVNO_CMPFH(fhp, tfhp)) {
3473 			if (lockit)
3474 				nfsrv_locklf(lfp);
3475 			*lfpp = lfp;
3476 			return (0);
3477 		}
3478 	}
3479 	if (!(flags & NFSLCK_OPEN))
3480 		return (-1);
3481 
3482 	/*
3483 	 * No match, so chain the new one into the list.
3484 	 */
3485 	LIST_INIT(&new_lfp->lf_open);
3486 	LIST_INIT(&new_lfp->lf_lock);
3487 	LIST_INIT(&new_lfp->lf_deleg);
3488 	LIST_INIT(&new_lfp->lf_locallock);
3489 	LIST_INIT(&new_lfp->lf_rollback);
3490 	new_lfp->lf_locallock_lck.nfslock_usecnt = 0;
3491 	new_lfp->lf_locallock_lck.nfslock_lock = 0;
3492 	new_lfp->lf_usecount = 0;
3493 	LIST_INSERT_HEAD(hp, new_lfp, lf_hash);
3494 	*lfpp = new_lfp;
3495 	*new_lfpp = NULL;
3496 	return (0);
3497 }
3498 
3499 /*
3500  * This function adds a nfslock lock structure to the list for the associated
3501  * nfsstate and nfslockfile structures. It will be inserted after the
3502  * entry pointed at by insert_lop.
3503  */
3504 static void
3505 nfsrv_insertlock(struct nfslock *new_lop, struct nfslock *insert_lop,
3506     struct nfsstate *stp, struct nfslockfile *lfp)
3507 {
3508 	struct nfslock *lop, *nlop;
3509 
3510 	new_lop->lo_stp = stp;
3511 	new_lop->lo_lfp = lfp;
3512 
3513 	if (stp != NULL) {
3514 		/* Insert in increasing lo_first order */
3515 		lop = LIST_FIRST(&lfp->lf_lock);
3516 		if (lop == LIST_END(&lfp->lf_lock) ||
3517 		    new_lop->lo_first <= lop->lo_first) {
3518 			LIST_INSERT_HEAD(&lfp->lf_lock, new_lop, lo_lckfile);
3519 		} else {
3520 			nlop = LIST_NEXT(lop, lo_lckfile);
3521 			while (nlop != LIST_END(&lfp->lf_lock) &&
3522 			       nlop->lo_first < new_lop->lo_first) {
3523 				lop = nlop;
3524 				nlop = LIST_NEXT(lop, lo_lckfile);
3525 			}
3526 			LIST_INSERT_AFTER(lop, new_lop, lo_lckfile);
3527 		}
3528 	} else {
3529 		new_lop->lo_lckfile.le_prev = NULL;	/* list not used */
3530 	}
3531 
3532 	/*
3533 	 * Insert after insert_lop, which is overloaded as stp or lfp for
3534 	 * an empty list.
3535 	 */
3536 	if (stp == NULL && (struct nfslockfile *)insert_lop == lfp)
3537 		LIST_INSERT_HEAD(&lfp->lf_locallock, new_lop, lo_lckowner);
3538 	else if ((struct nfsstate *)insert_lop == stp)
3539 		LIST_INSERT_HEAD(&stp->ls_lock, new_lop, lo_lckowner);
3540 	else
3541 		LIST_INSERT_AFTER(insert_lop, new_lop, lo_lckowner);
3542 	if (stp != NULL) {
3543 		newnfsstats.srvlocks++;
3544 		nfsrv_openpluslock++;
3545 	}
3546 }
3547 
3548 /*
3549  * This function updates the locking for a lock owner and given file. It
3550  * maintains a list of lock ranges ordered on increasing file offset that
3551  * are NFSLCK_READ or NFSLCK_WRITE and non-overlapping (aka POSIX style).
3552  * It always adds new_lop to the list and sometimes uses the one pointed
3553  * at by other_lopp.
3554  */
3555 static void
3556 nfsrv_updatelock(struct nfsstate *stp, struct nfslock **new_lopp,
3557     struct nfslock **other_lopp, struct nfslockfile *lfp)
3558 {
3559 	struct nfslock *new_lop = *new_lopp;
3560 	struct nfslock *lop, *tlop, *ilop;
3561 	struct nfslock *other_lop = *other_lopp;
3562 	int unlock = 0, myfile = 0;
3563 	u_int64_t tmp;
3564 
3565 	/*
3566 	 * Work down the list until the lock is merged.
3567 	 */
3568 	if (new_lop->lo_flags & NFSLCK_UNLOCK)
3569 		unlock = 1;
3570 	if (stp != NULL) {
3571 		ilop = (struct nfslock *)stp;
3572 		lop = LIST_FIRST(&stp->ls_lock);
3573 	} else {
3574 		ilop = (struct nfslock *)lfp;
3575 		lop = LIST_FIRST(&lfp->lf_locallock);
3576 	}
3577 	while (lop != NULL) {
3578 	    /*
3579 	     * Only check locks for this file that aren't before the start of
3580 	     * new lock's range.
3581 	     */
3582 	    if (lop->lo_lfp == lfp) {
3583 	      myfile = 1;
3584 	      if (lop->lo_end >= new_lop->lo_first) {
3585 		if (new_lop->lo_end < lop->lo_first) {
3586 			/*
3587 			 * If the new lock ends before the start of the
3588 			 * current lock's range, no merge, just insert
3589 			 * the new lock.
3590 			 */
3591 			break;
3592 		}
3593 		if (new_lop->lo_flags == lop->lo_flags ||
3594 		    (new_lop->lo_first <= lop->lo_first &&
3595 		     new_lop->lo_end >= lop->lo_end)) {
3596 			/*
3597 			 * This lock can be absorbed by the new lock/unlock.
3598 			 * This happens when it covers the entire range
3599 			 * of the old lock or is contiguous
3600 			 * with the old lock and is of the same type or an
3601 			 * unlock.
3602 			 */
3603 			if (lop->lo_first < new_lop->lo_first)
3604 				new_lop->lo_first = lop->lo_first;
3605 			if (lop->lo_end > new_lop->lo_end)
3606 				new_lop->lo_end = lop->lo_end;
3607 			tlop = lop;
3608 			lop = LIST_NEXT(lop, lo_lckowner);
3609 			nfsrv_freenfslock(tlop);
3610 			continue;
3611 		}
3612 
3613 		/*
3614 		 * All these cases are for contiguous locks that are not the
3615 		 * same type, so they can't be merged.
3616 		 */
3617 		if (new_lop->lo_first <= lop->lo_first) {
3618 			/*
3619 			 * This case is where the new lock overlaps with the
3620 			 * first part of the old lock. Move the start of the
3621 			 * old lock to just past the end of the new lock. The
3622 			 * new lock will be inserted in front of the old, since
3623 			 * ilop hasn't been updated. (We are done now.)
3624 			 */
3625 			lop->lo_first = new_lop->lo_end;
3626 			break;
3627 		}
3628 		if (new_lop->lo_end >= lop->lo_end) {
3629 			/*
3630 			 * This case is where the new lock overlaps with the
3631 			 * end of the old lock's range. Move the old lock's
3632 			 * end to just before the new lock's first and insert
3633 			 * the new lock after the old lock.
3634 			 * Might not be done yet, since the new lock could
3635 			 * overlap further locks with higher ranges.
3636 			 */
3637 			lop->lo_end = new_lop->lo_first;
3638 			ilop = lop;
3639 			lop = LIST_NEXT(lop, lo_lckowner);
3640 			continue;
3641 		}
3642 		/*
3643 		 * The final case is where the new lock's range is in the
3644 		 * middle of the current lock's and splits the current lock
3645 		 * up. Use *other_lopp to handle the second part of the
3646 		 * split old lock range. (We are done now.)
3647 		 * For unlock, we use new_lop as other_lop and tmp, since
3648 		 * other_lop and new_lop are the same for this case.
3649 		 * We noted the unlock case above, so we don't need
3650 		 * new_lop->lo_flags any longer.
3651 		 */
3652 		tmp = new_lop->lo_first;
3653 		if (other_lop == NULL) {
3654 			if (!unlock)
3655 				panic("nfsd srv update unlock");
3656 			other_lop = new_lop;
3657 			*new_lopp = NULL;
3658 		}
3659 		other_lop->lo_first = new_lop->lo_end;
3660 		other_lop->lo_end = lop->lo_end;
3661 		other_lop->lo_flags = lop->lo_flags;
3662 		other_lop->lo_stp = stp;
3663 		other_lop->lo_lfp = lfp;
3664 		lop->lo_end = tmp;
3665 		nfsrv_insertlock(other_lop, lop, stp, lfp);
3666 		*other_lopp = NULL;
3667 		ilop = lop;
3668 		break;
3669 	      }
3670 	    }
3671 	    ilop = lop;
3672 	    lop = LIST_NEXT(lop, lo_lckowner);
3673 	    if (myfile && (lop == NULL || lop->lo_lfp != lfp))
3674 		break;
3675 	}
3676 
3677 	/*
3678 	 * Insert the new lock in the list at the appropriate place.
3679 	 */
3680 	if (!unlock) {
3681 		nfsrv_insertlock(new_lop, ilop, stp, lfp);
3682 		*new_lopp = NULL;
3683 	}
3684 }
3685 
3686 /*
3687  * This function handles sequencing of locks, etc.
3688  * It returns an error that indicates what the caller should do.
3689  */
3690 static int
3691 nfsrv_checkseqid(struct nfsrv_descript *nd, u_int32_t seqid,
3692     struct nfsstate *stp, struct nfsrvcache *op)
3693 {
3694 	int error = 0;
3695 
3696 	if ((nd->nd_flag & ND_NFSV41) != 0)
3697 		/* NFSv4.1 ignores the open_seqid and lock_seqid. */
3698 		goto out;
3699 	if (op != nd->nd_rp)
3700 		panic("nfsrvstate checkseqid");
3701 	if (!(op->rc_flag & RC_INPROG))
3702 		panic("nfsrvstate not inprog");
3703 	if (stp->ls_op && stp->ls_op->rc_refcnt <= 0) {
3704 		printf("refcnt=%d\n", stp->ls_op->rc_refcnt);
3705 		panic("nfsrvstate op refcnt");
3706 	}
3707 	if ((stp->ls_seq + 1) == seqid) {
3708 		if (stp->ls_op)
3709 			nfsrvd_derefcache(stp->ls_op);
3710 		stp->ls_op = op;
3711 		nfsrvd_refcache(op);
3712 		stp->ls_seq = seqid;
3713 		goto out;
3714 	} else if (stp->ls_seq == seqid && stp->ls_op &&
3715 		op->rc_xid == stp->ls_op->rc_xid &&
3716 		op->rc_refcnt == 0 &&
3717 		op->rc_reqlen == stp->ls_op->rc_reqlen &&
3718 		op->rc_cksum == stp->ls_op->rc_cksum) {
3719 		if (stp->ls_op->rc_flag & RC_INPROG) {
3720 			error = NFSERR_DONTREPLY;
3721 			goto out;
3722 		}
3723 		nd->nd_rp = stp->ls_op;
3724 		nd->nd_rp->rc_flag |= RC_INPROG;
3725 		nfsrvd_delcache(op);
3726 		error = NFSERR_REPLYFROMCACHE;
3727 		goto out;
3728 	}
3729 	error = NFSERR_BADSEQID;
3730 
3731 out:
3732 	NFSEXITCODE2(error, nd);
3733 	return (error);
3734 }
3735 
3736 /*
3737  * Get the client ip address for callbacks. If the strings can't be parsed,
3738  * just set lc_program to 0 to indicate no callbacks are possible.
3739  * (For cases where the address can't be parsed or is 0.0.0.0.0.0, set
3740  *  the address to the client's transport address. This won't be used
3741  *  for callbacks, but can be printed out by newnfsstats for info.)
3742  * Return error if the xdr can't be parsed, 0 otherwise.
3743  */
3744 APPLESTATIC int
3745 nfsrv_getclientipaddr(struct nfsrv_descript *nd, struct nfsclient *clp)
3746 {
3747 	u_int32_t *tl;
3748 	u_char *cp, *cp2;
3749 	int i, j;
3750 	struct sockaddr_in *rad, *sad;
3751 	u_char protocol[5], addr[24];
3752 	int error = 0, cantparse = 0;
3753 	union {
3754 		u_long ival;
3755 		u_char cval[4];
3756 	} ip;
3757 	union {
3758 		u_short sval;
3759 		u_char cval[2];
3760 	} port;
3761 
3762 	rad = NFSSOCKADDR(clp->lc_req.nr_nam, struct sockaddr_in *);
3763 	rad->sin_family = AF_INET;
3764 	rad->sin_len = sizeof (struct sockaddr_in);
3765 	rad->sin_addr.s_addr = 0;
3766 	rad->sin_port = 0;
3767 	clp->lc_req.nr_client = NULL;
3768 	clp->lc_req.nr_lock = 0;
3769 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
3770 	i = fxdr_unsigned(int, *tl);
3771 	if (i >= 3 && i <= 4) {
3772 		error = nfsrv_mtostr(nd, protocol, i);
3773 		if (error)
3774 			goto nfsmout;
3775 		if (!strcmp(protocol, "tcp")) {
3776 			clp->lc_flags |= LCL_TCPCALLBACK;
3777 			clp->lc_req.nr_sotype = SOCK_STREAM;
3778 			clp->lc_req.nr_soproto = IPPROTO_TCP;
3779 		} else if (!strcmp(protocol, "udp")) {
3780 			clp->lc_req.nr_sotype = SOCK_DGRAM;
3781 			clp->lc_req.nr_soproto = IPPROTO_UDP;
3782 		} else {
3783 			cantparse = 1;
3784 		}
3785 	} else {
3786 		cantparse = 1;
3787 		if (i > 0) {
3788 			error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
3789 			if (error)
3790 				goto nfsmout;
3791 		}
3792 	}
3793 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
3794 	i = fxdr_unsigned(int, *tl);
3795 	if (i < 0) {
3796 		error = NFSERR_BADXDR;
3797 		goto nfsmout;
3798 	} else if (i == 0) {
3799 		cantparse = 1;
3800 	} else if (!cantparse && i <= 23 && i >= 11) {
3801 		error = nfsrv_mtostr(nd, addr, i);
3802 		if (error)
3803 			goto nfsmout;
3804 
3805 		/*
3806 		 * Parse out the address fields. We expect 6 decimal numbers
3807 		 * separated by '.'s.
3808 		 */
3809 		cp = addr;
3810 		i = 0;
3811 		while (*cp && i < 6) {
3812 			cp2 = cp;
3813 			while (*cp2 && *cp2 != '.')
3814 				cp2++;
3815 			if (*cp2)
3816 				*cp2++ = '\0';
3817 			else if (i != 5) {
3818 				cantparse = 1;
3819 				break;
3820 			}
3821 			j = nfsrv_getipnumber(cp);
3822 			if (j >= 0) {
3823 				if (i < 4)
3824 					ip.cval[3 - i] = j;
3825 				else
3826 					port.cval[5 - i] = j;
3827 			} else {
3828 				cantparse = 1;
3829 				break;
3830 			}
3831 			cp = cp2;
3832 			i++;
3833 		}
3834 		if (!cantparse) {
3835 			if (ip.ival != 0x0) {
3836 				rad->sin_addr.s_addr = htonl(ip.ival);
3837 				rad->sin_port = htons(port.sval);
3838 			} else {
3839 				cantparse = 1;
3840 			}
3841 		}
3842 	} else {
3843 		cantparse = 1;
3844 		if (i > 0) {
3845 			error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
3846 			if (error)
3847 				goto nfsmout;
3848 		}
3849 	}
3850 	if (cantparse) {
3851 		sad = NFSSOCKADDR(nd->nd_nam, struct sockaddr_in *);
3852 		rad->sin_addr.s_addr = sad->sin_addr.s_addr;
3853 		rad->sin_port = 0x0;
3854 		clp->lc_program = 0;
3855 	}
3856 nfsmout:
3857 	NFSEXITCODE2(error, nd);
3858 	return (error);
3859 }
3860 
3861 /*
3862  * Turn a string of up to three decimal digits into a number. Return -1 upon
3863  * error.
3864  */
3865 static int
3866 nfsrv_getipnumber(u_char *cp)
3867 {
3868 	int i = 0, j = 0;
3869 
3870 	while (*cp) {
3871 		if (j > 2 || *cp < '0' || *cp > '9')
3872 			return (-1);
3873 		i *= 10;
3874 		i += (*cp - '0');
3875 		cp++;
3876 		j++;
3877 	}
3878 	if (i < 256)
3879 		return (i);
3880 	return (-1);
3881 }
3882 
3883 /*
3884  * This function checks for restart conditions.
3885  */
3886 static int
3887 nfsrv_checkrestart(nfsquad_t clientid, u_int32_t flags,
3888     nfsv4stateid_t *stateidp, int specialid)
3889 {
3890 	int ret = 0;
3891 
3892 	/*
3893 	 * First check for a server restart. Open, LockT, ReleaseLockOwner
3894 	 * and DelegPurge have a clientid, the rest a stateid.
3895 	 */
3896 	if (flags &
3897 	    (NFSLCK_OPEN | NFSLCK_TEST | NFSLCK_RELEASE | NFSLCK_DELEGPURGE)) {
3898 		if (clientid.lval[0] != nfsrvboottime) {
3899 			ret = NFSERR_STALECLIENTID;
3900 			goto out;
3901 		}
3902 	} else if (stateidp->other[0] != nfsrvboottime &&
3903 		specialid == 0) {
3904 		ret = NFSERR_STALESTATEID;
3905 		goto out;
3906 	}
3907 
3908 	/*
3909 	 * Read, Write, Setattr and LockT can return NFSERR_GRACE and do
3910 	 * not use a lock/open owner seqid#, so the check can be done now.
3911 	 * (The others will be checked, as required, later.)
3912 	 */
3913 	if (!(flags & (NFSLCK_CHECK | NFSLCK_TEST)))
3914 		goto out;
3915 
3916 	NFSLOCKSTATE();
3917 	ret = nfsrv_checkgrace(NULL, NULL, flags);
3918 	NFSUNLOCKSTATE();
3919 
3920 out:
3921 	NFSEXITCODE(ret);
3922 	return (ret);
3923 }
3924 
3925 /*
3926  * Check for grace.
3927  */
3928 static int
3929 nfsrv_checkgrace(struct nfsrv_descript *nd, struct nfsclient *clp,
3930     u_int32_t flags)
3931 {
3932 	int error = 0;
3933 
3934 	if ((nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) != 0) {
3935 		if (flags & NFSLCK_RECLAIM) {
3936 			error = NFSERR_NOGRACE;
3937 			goto out;
3938 		}
3939 	} else {
3940 		if (!(flags & NFSLCK_RECLAIM)) {
3941 			error = NFSERR_GRACE;
3942 			goto out;
3943 		}
3944 		if (nd != NULL && clp != NULL &&
3945 		    (nd->nd_flag & ND_NFSV41) != 0 &&
3946 		    (clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0) {
3947 			error = NFSERR_NOGRACE;
3948 			goto out;
3949 		}
3950 
3951 		/*
3952 		 * If grace is almost over and we are still getting Reclaims,
3953 		 * extend grace a bit.
3954 		 */
3955 		if ((NFSD_MONOSEC + NFSRV_LEASEDELTA) >
3956 		    nfsrv_stablefirst.nsf_eograce)
3957 			nfsrv_stablefirst.nsf_eograce = NFSD_MONOSEC +
3958 				NFSRV_LEASEDELTA;
3959 	}
3960 
3961 out:
3962 	NFSEXITCODE(error);
3963 	return (error);
3964 }
3965 
3966 /*
3967  * Do a server callback.
3968  */
3969 static int
3970 nfsrv_docallback(struct nfsclient *clp, int procnum,
3971     nfsv4stateid_t *stateidp, int trunc, fhandle_t *fhp,
3972     struct nfsvattr *nap, nfsattrbit_t *attrbitp, NFSPROC_T *p)
3973 {
3974 	mbuf_t m;
3975 	u_int32_t *tl;
3976 	struct nfsrv_descript nfsd, *nd = &nfsd;
3977 	struct ucred *cred;
3978 	int error = 0;
3979 	u_int32_t callback;
3980 	struct nfsdsession *sep = NULL;
3981 
3982 	cred = newnfs_getcred();
3983 	NFSLOCKSTATE();	/* mostly for lc_cbref++ */
3984 	if (clp->lc_flags & LCL_NEEDSCONFIRM) {
3985 		NFSUNLOCKSTATE();
3986 		panic("docallb");
3987 	}
3988 	clp->lc_cbref++;
3989 
3990 	/*
3991 	 * Fill the callback program# and version into the request
3992 	 * structure for newnfs_connect() to use.
3993 	 */
3994 	clp->lc_req.nr_prog = clp->lc_program;
3995 #ifdef notnow
3996 	if ((clp->lc_flags & LCL_NFSV41) != 0)
3997 		clp->lc_req.nr_vers = NFSV41_CBVERS;
3998 	else
3999 #endif
4000 		clp->lc_req.nr_vers = NFSV4_CBVERS;
4001 
4002 	/*
4003 	 * First, fill in some of the fields of nd and cr.
4004 	 */
4005 	nd->nd_flag = ND_NFSV4;
4006 	if (clp->lc_flags & LCL_GSS)
4007 		nd->nd_flag |= ND_KERBV;
4008 	if ((clp->lc_flags & LCL_NFSV41) != 0)
4009 		nd->nd_flag |= ND_NFSV41;
4010 	nd->nd_repstat = 0;
4011 	cred->cr_uid = clp->lc_uid;
4012 	cred->cr_gid = clp->lc_gid;
4013 	callback = clp->lc_callback;
4014 	NFSUNLOCKSTATE();
4015 	cred->cr_ngroups = 1;
4016 
4017 	/*
4018 	 * Get the first mbuf for the request.
4019 	 */
4020 	MGET(m, M_WAITOK, MT_DATA);
4021 	mbuf_setlen(m, 0);
4022 	nd->nd_mreq = nd->nd_mb = m;
4023 	nd->nd_bpos = NFSMTOD(m, caddr_t);
4024 
4025 	/*
4026 	 * and build the callback request.
4027 	 */
4028 	if (procnum == NFSV4OP_CBGETATTR) {
4029 		nd->nd_procnum = NFSV4PROC_CBCOMPOUND;
4030 		error = nfsrv_cbcallargs(nd, clp, callback, NFSV4OP_CBGETATTR,
4031 		    "CB Getattr", &sep);
4032 		if (error != 0) {
4033 			mbuf_freem(nd->nd_mreq);
4034 			goto errout;
4035 		}
4036 		(void)nfsm_fhtom(nd, (u_int8_t *)fhp, NFSX_MYFH, 0);
4037 		(void)nfsrv_putattrbit(nd, attrbitp);
4038 	} else if (procnum == NFSV4OP_CBRECALL) {
4039 		nd->nd_procnum = NFSV4PROC_CBCOMPOUND;
4040 		error = nfsrv_cbcallargs(nd, clp, callback, NFSV4OP_CBRECALL,
4041 		    "CB Recall", &sep);
4042 		if (error != 0) {
4043 			mbuf_freem(nd->nd_mreq);
4044 			goto errout;
4045 		}
4046 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_STATEID);
4047 		*tl++ = txdr_unsigned(stateidp->seqid);
4048 		NFSBCOPY((caddr_t)stateidp->other, (caddr_t)tl,
4049 		    NFSX_STATEIDOTHER);
4050 		tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
4051 		if (trunc)
4052 			*tl = newnfs_true;
4053 		else
4054 			*tl = newnfs_false;
4055 		(void)nfsm_fhtom(nd, (u_int8_t *)fhp, NFSX_MYFH, 0);
4056 	} else if (procnum == NFSV4PROC_CBNULL) {
4057 		nd->nd_procnum = NFSV4PROC_CBNULL;
4058 		if ((clp->lc_flags & LCL_NFSV41) != 0) {
4059 			error = nfsv4_getcbsession(clp, &sep);
4060 			if (error != 0) {
4061 				mbuf_freem(nd->nd_mreq);
4062 				goto errout;
4063 			}
4064 		}
4065 	} else {
4066 		error = NFSERR_SERVERFAULT;
4067 		mbuf_freem(nd->nd_mreq);
4068 		goto errout;
4069 	}
4070 
4071 	/*
4072 	 * Call newnfs_connect(), as required, and then newnfs_request().
4073 	 */
4074 	(void) newnfs_sndlock(&clp->lc_req.nr_lock);
4075 	if (clp->lc_req.nr_client == NULL) {
4076 		if ((clp->lc_flags & LCL_NFSV41) != 0)
4077 			error = ECONNREFUSED;
4078 		else if (nd->nd_procnum == NFSV4PROC_CBNULL)
4079 			error = newnfs_connect(NULL, &clp->lc_req, cred,
4080 			    NULL, 1);
4081 		else
4082 			error = newnfs_connect(NULL, &clp->lc_req, cred,
4083 			    NULL, 3);
4084 	}
4085 	newnfs_sndunlock(&clp->lc_req.nr_lock);
4086 	if (!error) {
4087 		if ((nd->nd_flag & ND_NFSV41) != 0) {
4088 			KASSERT(sep != NULL, ("sep NULL"));
4089 			error = newnfs_request(nd, NULL, clp, &clp->lc_req,
4090 			    NULL, NULL, cred, clp->lc_program,
4091 			    clp->lc_req.nr_vers, NULL, 1, NULL,
4092 			    &sep->sess_cbsess);
4093 			nfsrv_freesession(sep, NULL);
4094 		} else
4095 			error = newnfs_request(nd, NULL, clp, &clp->lc_req,
4096 			    NULL, NULL, cred, clp->lc_program,
4097 			    clp->lc_req.nr_vers, NULL, 1, NULL, NULL);
4098 	}
4099 errout:
4100 	NFSFREECRED(cred);
4101 
4102 	/*
4103 	 * If error is set here, the Callback path isn't working
4104 	 * properly, so twiddle the appropriate LCL_ flags.
4105 	 * (nd_repstat != 0 indicates the Callback path is working,
4106 	 *  but the callback failed on the client.)
4107 	 */
4108 	if (error) {
4109 		/*
4110 		 * Mark the callback pathway down, which disabled issuing
4111 		 * of delegations and gets Renew to return NFSERR_CBPATHDOWN.
4112 		 */
4113 		NFSLOCKSTATE();
4114 		clp->lc_flags |= LCL_CBDOWN;
4115 		NFSUNLOCKSTATE();
4116 	} else {
4117 		/*
4118 		 * Callback worked. If the callback path was down, disable
4119 		 * callbacks, so no more delegations will be issued. (This
4120 		 * is done on the assumption that the callback pathway is
4121 		 * flakey.)
4122 		 */
4123 		NFSLOCKSTATE();
4124 		if (clp->lc_flags & LCL_CBDOWN)
4125 			clp->lc_flags &= ~(LCL_CBDOWN | LCL_CALLBACKSON);
4126 		NFSUNLOCKSTATE();
4127 		if (nd->nd_repstat)
4128 			error = nd->nd_repstat;
4129 		else if (error == 0 && procnum == NFSV4OP_CBGETATTR)
4130 			error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0,
4131 			    NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL,
4132 			    p, NULL);
4133 		mbuf_freem(nd->nd_mrep);
4134 	}
4135 	NFSLOCKSTATE();
4136 	clp->lc_cbref--;
4137 	if ((clp->lc_flags & LCL_WAKEUPWANTED) && clp->lc_cbref == 0) {
4138 		clp->lc_flags &= ~LCL_WAKEUPWANTED;
4139 		wakeup(clp);
4140 	}
4141 	NFSUNLOCKSTATE();
4142 
4143 	NFSEXITCODE(error);
4144 	return (error);
4145 }
4146 
4147 /*
4148  * Set up the compound RPC for the callback.
4149  */
4150 static int
4151 nfsrv_cbcallargs(struct nfsrv_descript *nd, struct nfsclient *clp,
4152     uint32_t callback, int op, const char *optag, struct nfsdsession **sepp)
4153 {
4154 	uint32_t *tl;
4155 	int error, len;
4156 
4157 	len = strlen(optag);
4158 	(void)nfsm_strtom(nd, optag, len);
4159 	NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED);
4160 	if ((nd->nd_flag & ND_NFSV41) != 0) {
4161 		*tl++ = txdr_unsigned(NFSV41_MINORVERSION);
4162 		*tl++ = txdr_unsigned(callback);
4163 		*tl++ = txdr_unsigned(2);
4164 		*tl = txdr_unsigned(NFSV4OP_CBSEQUENCE);
4165 		error = nfsv4_setcbsequence(nd, clp, 1, sepp);
4166 		if (error != 0)
4167 			return (error);
4168 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
4169 		*tl = txdr_unsigned(op);
4170 	} else {
4171 		*tl++ = txdr_unsigned(NFSV4_MINORVERSION);
4172 		*tl++ = txdr_unsigned(callback);
4173 		*tl++ = txdr_unsigned(1);
4174 		*tl = txdr_unsigned(op);
4175 	}
4176 	return (0);
4177 }
4178 
4179 /*
4180  * Return the next index# for a clientid. Mostly just increment and return
4181  * the next one, but... if the 32bit unsigned does actually wrap around,
4182  * it should be rebooted.
4183  * At an average rate of one new client per second, it will wrap around in
4184  * approximately 136 years. (I think the server will have been shut
4185  * down or rebooted before then.)
4186  */
4187 static u_int32_t
4188 nfsrv_nextclientindex(void)
4189 {
4190 	static u_int32_t client_index = 0;
4191 
4192 	client_index++;
4193 	if (client_index != 0)
4194 		return (client_index);
4195 
4196 	printf("%s: out of clientids\n", __func__);
4197 	return (client_index);
4198 }
4199 
4200 /*
4201  * Return the next index# for a stateid. Mostly just increment and return
4202  * the next one, but... if the 32bit unsigned does actually wrap around
4203  * (will a BSD server stay up that long?), find
4204  * new start and end values.
4205  */
4206 static u_int32_t
4207 nfsrv_nextstateindex(struct nfsclient *clp)
4208 {
4209 	struct nfsstate *stp;
4210 	int i;
4211 	u_int32_t canuse, min_index, max_index;
4212 
4213 	if (!(clp->lc_flags & LCL_INDEXNOTOK)) {
4214 		clp->lc_stateindex++;
4215 		if (clp->lc_stateindex != clp->lc_statemaxindex)
4216 			return (clp->lc_stateindex);
4217 	}
4218 
4219 	/*
4220 	 * Yuck, we've hit the end.
4221 	 * Look for a new min and max.
4222 	 */
4223 	min_index = 0;
4224 	max_index = 0xffffffff;
4225 	for (i = 0; i < NFSSTATEHASHSIZE; i++) {
4226 	    LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) {
4227 		if (stp->ls_stateid.other[2] > 0x80000000) {
4228 		    if (stp->ls_stateid.other[2] < max_index)
4229 			max_index = stp->ls_stateid.other[2];
4230 		} else {
4231 		    if (stp->ls_stateid.other[2] > min_index)
4232 			min_index = stp->ls_stateid.other[2];
4233 		}
4234 	    }
4235 	}
4236 
4237 	/*
4238 	 * Yikes, highly unlikely, but I'll handle it anyhow.
4239 	 */
4240 	if (min_index == 0x80000000 && max_index == 0x80000001) {
4241 	    canuse = 0;
4242 	    /*
4243 	     * Loop around until we find an unused entry. Return that
4244 	     * and set LCL_INDEXNOTOK, so the search will continue next time.
4245 	     * (This is one of those rare cases where a goto is the
4246 	     *  cleanest way to code the loop.)
4247 	     */
4248 tryagain:
4249 	    for (i = 0; i < NFSSTATEHASHSIZE; i++) {
4250 		LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) {
4251 		    if (stp->ls_stateid.other[2] == canuse) {
4252 			canuse++;
4253 			goto tryagain;
4254 		    }
4255 		}
4256 	    }
4257 	    clp->lc_flags |= LCL_INDEXNOTOK;
4258 	    return (canuse);
4259 	}
4260 
4261 	/*
4262 	 * Ok to start again from min + 1.
4263 	 */
4264 	clp->lc_stateindex = min_index + 1;
4265 	clp->lc_statemaxindex = max_index;
4266 	clp->lc_flags &= ~LCL_INDEXNOTOK;
4267 	return (clp->lc_stateindex);
4268 }
4269 
4270 /*
4271  * The following functions handle the stable storage file that deals with
4272  * the edge conditions described in RFC3530 Sec. 8.6.3.
4273  * The file is as follows:
4274  * - a single record at the beginning that has the lease time of the
4275  *   previous server instance (before the last reboot) and the nfsrvboottime
4276  *   values for the previous server boots.
4277  *   These previous boot times are used to ensure that the current
4278  *   nfsrvboottime does not, somehow, get set to a previous one.
4279  *   (This is important so that Stale ClientIDs and StateIDs can
4280  *    be recognized.)
4281  *   The number of previous nfsvrboottime values preceeds the list.
4282  * - followed by some number of appended records with:
4283  *   - client id string
4284  *   - flag that indicates it is a record revoking state via lease
4285  *     expiration or similar
4286  *     OR has successfully acquired state.
4287  * These structures vary in length, with the client string at the end, up
4288  * to NFSV4_OPAQUELIMIT in size.
4289  *
4290  * At the end of the grace period, the file is truncated, the first
4291  * record is rewritten with updated information and any acquired state
4292  * records for successful reclaims of state are written.
4293  *
4294  * Subsequent records are appended when the first state is issued to
4295  * a client and when state is revoked for a client.
4296  *
4297  * When reading the file in, state issued records that come later in
4298  * the file override older ones, since the append log is in cronological order.
4299  * If, for some reason, the file can't be read, the grace period is
4300  * immediately terminated and all reclaims get NFSERR_NOGRACE.
4301  */
4302 
4303 /*
4304  * Read in the stable storage file. Called by nfssvc() before the nfsd
4305  * processes start servicing requests.
4306  */
4307 APPLESTATIC void
4308 nfsrv_setupstable(NFSPROC_T *p)
4309 {
4310 	struct nfsrv_stablefirst *sf = &nfsrv_stablefirst;
4311 	struct nfsrv_stable *sp, *nsp;
4312 	struct nfst_rec *tsp;
4313 	int error, i, tryagain;
4314 	off_t off = 0;
4315 	ssize_t aresid, len;
4316 
4317 	/*
4318 	 * If NFSNSF_UPDATEDONE is set, this is a restart of the nfsds without
4319 	 * a reboot, so state has not been lost.
4320 	 */
4321 	if (sf->nsf_flags & NFSNSF_UPDATEDONE)
4322 		return;
4323 	/*
4324 	 * Set Grace over just until the file reads successfully.
4325 	 */
4326 	nfsrvboottime = time_second;
4327 	LIST_INIT(&sf->nsf_head);
4328 	sf->nsf_flags = (NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK);
4329 	sf->nsf_eograce = NFSD_MONOSEC + NFSRV_LEASEDELTA;
4330 	if (sf->nsf_fp == NULL)
4331 		return;
4332 	error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp),
4333 	    (caddr_t)&sf->nsf_rec, sizeof (struct nfsf_rec), off, UIO_SYSSPACE,
4334 	    0, NFSFPCRED(sf->nsf_fp), &aresid, p);
4335 	if (error || aresid || sf->nsf_numboots == 0 ||
4336 		sf->nsf_numboots > NFSNSF_MAXNUMBOOTS)
4337 		return;
4338 
4339 	/*
4340 	 * Now, read in the boottimes.
4341 	 */
4342 	sf->nsf_bootvals = (time_t *)malloc((sf->nsf_numboots + 1) *
4343 		sizeof (time_t), M_TEMP, M_WAITOK);
4344 	off = sizeof (struct nfsf_rec);
4345 	error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp),
4346 	    (caddr_t)sf->nsf_bootvals, sf->nsf_numboots * sizeof (time_t), off,
4347 	    UIO_SYSSPACE, 0, NFSFPCRED(sf->nsf_fp), &aresid, p);
4348 	if (error || aresid) {
4349 		free((caddr_t)sf->nsf_bootvals, M_TEMP);
4350 		sf->nsf_bootvals = NULL;
4351 		return;
4352 	}
4353 
4354 	/*
4355 	 * Make sure this nfsrvboottime is different from all recorded
4356 	 * previous ones.
4357 	 */
4358 	do {
4359 		tryagain = 0;
4360 		for (i = 0; i < sf->nsf_numboots; i++) {
4361 			if (nfsrvboottime == sf->nsf_bootvals[i]) {
4362 				nfsrvboottime++;
4363 				tryagain = 1;
4364 				break;
4365 			}
4366 		}
4367 	} while (tryagain);
4368 
4369 	sf->nsf_flags |= NFSNSF_OK;
4370 	off += (sf->nsf_numboots * sizeof (time_t));
4371 
4372 	/*
4373 	 * Read through the file, building a list of records for grace
4374 	 * checking.
4375 	 * Each record is between sizeof (struct nfst_rec) and
4376 	 * sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1
4377 	 * and is actually sizeof (struct nfst_rec) + nst_len - 1.
4378 	 */
4379 	tsp = (struct nfst_rec *)malloc(sizeof (struct nfst_rec) +
4380 		NFSV4_OPAQUELIMIT - 1, M_TEMP, M_WAITOK);
4381 	do {
4382 	    error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp),
4383 	        (caddr_t)tsp, sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1,
4384 	        off, UIO_SYSSPACE, 0, NFSFPCRED(sf->nsf_fp), &aresid, p);
4385 	    len = (sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1) - aresid;
4386 	    if (error || (len > 0 && (len < sizeof (struct nfst_rec) ||
4387 		len < (sizeof (struct nfst_rec) + tsp->len - 1)))) {
4388 		/*
4389 		 * Yuck, the file has been corrupted, so just return
4390 		 * after clearing out any restart state, so the grace period
4391 		 * is over.
4392 		 */
4393 		LIST_FOREACH_SAFE(sp, &sf->nsf_head, nst_list, nsp) {
4394 			LIST_REMOVE(sp, nst_list);
4395 			free((caddr_t)sp, M_TEMP);
4396 		}
4397 		free((caddr_t)tsp, M_TEMP);
4398 		sf->nsf_flags &= ~NFSNSF_OK;
4399 		free((caddr_t)sf->nsf_bootvals, M_TEMP);
4400 		sf->nsf_bootvals = NULL;
4401 		return;
4402 	    }
4403 	    if (len > 0) {
4404 		off += sizeof (struct nfst_rec) + tsp->len - 1;
4405 		/*
4406 		 * Search the list for a matching client.
4407 		 */
4408 		LIST_FOREACH(sp, &sf->nsf_head, nst_list) {
4409 			if (tsp->len == sp->nst_len &&
4410 			    !NFSBCMP(tsp->client, sp->nst_client, tsp->len))
4411 				break;
4412 		}
4413 		if (sp == LIST_END(&sf->nsf_head)) {
4414 			sp = (struct nfsrv_stable *)malloc(tsp->len +
4415 				sizeof (struct nfsrv_stable) - 1, M_TEMP,
4416 				M_WAITOK);
4417 			NFSBCOPY((caddr_t)tsp, (caddr_t)&sp->nst_rec,
4418 				sizeof (struct nfst_rec) + tsp->len - 1);
4419 			LIST_INSERT_HEAD(&sf->nsf_head, sp, nst_list);
4420 		} else {
4421 			if (tsp->flag == NFSNST_REVOKE)
4422 				sp->nst_flag |= NFSNST_REVOKE;
4423 			else
4424 				/*
4425 				 * A subsequent timestamp indicates the client
4426 				 * did a setclientid/confirm and any previous
4427 				 * revoke is no longer relevant.
4428 				 */
4429 				sp->nst_flag &= ~NFSNST_REVOKE;
4430 		}
4431 	    }
4432 	} while (len > 0);
4433 	free((caddr_t)tsp, M_TEMP);
4434 	sf->nsf_flags = NFSNSF_OK;
4435 	sf->nsf_eograce = NFSD_MONOSEC + sf->nsf_lease +
4436 		NFSRV_LEASEDELTA;
4437 }
4438 
4439 /*
4440  * Update the stable storage file, now that the grace period is over.
4441  */
4442 APPLESTATIC void
4443 nfsrv_updatestable(NFSPROC_T *p)
4444 {
4445 	struct nfsrv_stablefirst *sf = &nfsrv_stablefirst;
4446 	struct nfsrv_stable *sp, *nsp;
4447 	int i;
4448 	struct nfsvattr nva;
4449 	vnode_t vp;
4450 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 500000)
4451 	mount_t mp = NULL;
4452 #endif
4453 	int error;
4454 
4455 	if (sf->nsf_fp == NULL || (sf->nsf_flags & NFSNSF_UPDATEDONE))
4456 		return;
4457 	sf->nsf_flags |= NFSNSF_UPDATEDONE;
4458 	/*
4459 	 * Ok, we need to rewrite the stable storage file.
4460 	 * - truncate to 0 length
4461 	 * - write the new first structure
4462 	 * - loop through the data structures, writing out any that
4463 	 *   have timestamps older than the old boot
4464 	 */
4465 	if (sf->nsf_bootvals) {
4466 		sf->nsf_numboots++;
4467 		for (i = sf->nsf_numboots - 2; i >= 0; i--)
4468 			sf->nsf_bootvals[i + 1] = sf->nsf_bootvals[i];
4469 	} else {
4470 		sf->nsf_numboots = 1;
4471 		sf->nsf_bootvals = (time_t *)malloc(sizeof (time_t),
4472 			M_TEMP, M_WAITOK);
4473 	}
4474 	sf->nsf_bootvals[0] = nfsrvboottime;
4475 	sf->nsf_lease = nfsrv_lease;
4476 	NFSVNO_ATTRINIT(&nva);
4477 	NFSVNO_SETATTRVAL(&nva, size, 0);
4478 	vp = NFSFPVNODE(sf->nsf_fp);
4479 	vn_start_write(vp, &mp, V_WAIT);
4480 	if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) {
4481 		error = nfsvno_setattr(vp, &nva, NFSFPCRED(sf->nsf_fp), p,
4482 		    NULL);
4483 		NFSVOPUNLOCK(vp, 0);
4484 	} else
4485 		error = EPERM;
4486 	vn_finished_write(mp);
4487 	if (!error)
4488 	    error = NFSD_RDWR(UIO_WRITE, vp,
4489 		(caddr_t)&sf->nsf_rec, sizeof (struct nfsf_rec), (off_t)0,
4490 		UIO_SYSSPACE, IO_SYNC, NFSFPCRED(sf->nsf_fp), NULL, p);
4491 	if (!error)
4492 	    error = NFSD_RDWR(UIO_WRITE, vp,
4493 		(caddr_t)sf->nsf_bootvals,
4494 		sf->nsf_numboots * sizeof (time_t),
4495 		(off_t)(sizeof (struct nfsf_rec)),
4496 		UIO_SYSSPACE, IO_SYNC, NFSFPCRED(sf->nsf_fp), NULL, p);
4497 	free((caddr_t)sf->nsf_bootvals, M_TEMP);
4498 	sf->nsf_bootvals = NULL;
4499 	if (error) {
4500 		sf->nsf_flags &= ~NFSNSF_OK;
4501 		printf("EEK! Can't write NfsV4 stable storage file\n");
4502 		return;
4503 	}
4504 	sf->nsf_flags |= NFSNSF_OK;
4505 
4506 	/*
4507 	 * Loop through the list and write out timestamp records for
4508 	 * any clients that successfully reclaimed state.
4509 	 */
4510 	LIST_FOREACH_SAFE(sp, &sf->nsf_head, nst_list, nsp) {
4511 		if (sp->nst_flag & NFSNST_GOTSTATE) {
4512 			nfsrv_writestable(sp->nst_client, sp->nst_len,
4513 				NFSNST_NEWSTATE, p);
4514 			sp->nst_clp->lc_flags |= LCL_STAMPEDSTABLE;
4515 		}
4516 		LIST_REMOVE(sp, nst_list);
4517 		free((caddr_t)sp, M_TEMP);
4518 	}
4519 	nfsrv_backupstable();
4520 }
4521 
4522 /*
4523  * Append a record to the stable storage file.
4524  */
4525 APPLESTATIC void
4526 nfsrv_writestable(u_char *client, int len, int flag, NFSPROC_T *p)
4527 {
4528 	struct nfsrv_stablefirst *sf = &nfsrv_stablefirst;
4529 	struct nfst_rec *sp;
4530 	int error;
4531 
4532 	if (!(sf->nsf_flags & NFSNSF_OK) || sf->nsf_fp == NULL)
4533 		return;
4534 	sp = (struct nfst_rec *)malloc(sizeof (struct nfst_rec) +
4535 		len - 1, M_TEMP, M_WAITOK);
4536 	sp->len = len;
4537 	NFSBCOPY(client, sp->client, len);
4538 	sp->flag = flag;
4539 	error = NFSD_RDWR(UIO_WRITE, NFSFPVNODE(sf->nsf_fp),
4540 	    (caddr_t)sp, sizeof (struct nfst_rec) + len - 1, (off_t)0,
4541 	    UIO_SYSSPACE, (IO_SYNC | IO_APPEND), NFSFPCRED(sf->nsf_fp), NULL, p);
4542 	free((caddr_t)sp, M_TEMP);
4543 	if (error) {
4544 		sf->nsf_flags &= ~NFSNSF_OK;
4545 		printf("EEK! Can't write NfsV4 stable storage file\n");
4546 	}
4547 }
4548 
4549 /*
4550  * This function is called during the grace period to mark a client
4551  * that successfully reclaimed state.
4552  */
4553 static void
4554 nfsrv_markstable(struct nfsclient *clp)
4555 {
4556 	struct nfsrv_stable *sp;
4557 
4558 	/*
4559 	 * First find the client structure.
4560 	 */
4561 	LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) {
4562 		if (sp->nst_len == clp->lc_idlen &&
4563 		    !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len))
4564 			break;
4565 	}
4566 	if (sp == LIST_END(&nfsrv_stablefirst.nsf_head))
4567 		return;
4568 
4569 	/*
4570 	 * Now, just mark it and set the nfsclient back pointer.
4571 	 */
4572 	sp->nst_flag |= NFSNST_GOTSTATE;
4573 	sp->nst_clp = clp;
4574 }
4575 
4576 /*
4577  * This function is called for a reclaim, to see if it gets grace.
4578  * It returns 0 if a reclaim is allowed, 1 otherwise.
4579  */
4580 static int
4581 nfsrv_checkstable(struct nfsclient *clp)
4582 {
4583 	struct nfsrv_stable *sp;
4584 
4585 	/*
4586 	 * First, find the entry for the client.
4587 	 */
4588 	LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) {
4589 		if (sp->nst_len == clp->lc_idlen &&
4590 		    !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len))
4591 			break;
4592 	}
4593 
4594 	/*
4595 	 * If not in the list, state was revoked or no state was issued
4596 	 * since the previous reboot, a reclaim is denied.
4597 	 */
4598 	if (sp == LIST_END(&nfsrv_stablefirst.nsf_head) ||
4599 	    (sp->nst_flag & NFSNST_REVOKE) ||
4600 	    !(nfsrv_stablefirst.nsf_flags & NFSNSF_OK))
4601 		return (1);
4602 	return (0);
4603 }
4604 
4605 /*
4606  * Test for and try to clear out a conflicting client. This is called by
4607  * nfsrv_lockctrl() and nfsrv_openctrl() when conflicts with other clients
4608  * a found.
4609  * The trick here is that it can't revoke a conflicting client with an
4610  * expired lease unless it holds the v4root lock, so...
4611  * If no v4root lock, get the lock and return 1 to indicate "try again".
4612  * Return 0 to indicate the conflict can't be revoked and 1 to indicate
4613  * the revocation worked and the conflicting client is "bye, bye", so it
4614  * can be tried again.
4615  * Return 2 to indicate that the vnode is VI_DOOMED after NFSVOPLOCK().
4616  * Unlocks State before a non-zero value is returned.
4617  */
4618 static int
4619 nfsrv_clientconflict(struct nfsclient *clp, int *haslockp, vnode_t vp,
4620     NFSPROC_T *p)
4621 {
4622 	int gotlock, lktype;
4623 
4624 	/*
4625 	 * If lease hasn't expired, we can't fix it.
4626 	 */
4627 	if (clp->lc_expiry >= NFSD_MONOSEC ||
4628 	    !(nfsrv_stablefirst.nsf_flags & NFSNSF_UPDATEDONE))
4629 		return (0);
4630 	if (*haslockp == 0) {
4631 		NFSUNLOCKSTATE();
4632 		lktype = NFSVOPISLOCKED(vp);
4633 		NFSVOPUNLOCK(vp, 0);
4634 		NFSLOCKV4ROOTMUTEX();
4635 		nfsv4_relref(&nfsv4rootfs_lock);
4636 		do {
4637 			gotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
4638 			    NFSV4ROOTLOCKMUTEXPTR, NULL);
4639 		} while (!gotlock);
4640 		NFSUNLOCKV4ROOTMUTEX();
4641 		*haslockp = 1;
4642 		NFSVOPLOCK(vp, lktype | LK_RETRY);
4643 		if ((vp->v_iflag & VI_DOOMED) != 0)
4644 			return (2);
4645 		else
4646 			return (1);
4647 	}
4648 	NFSUNLOCKSTATE();
4649 
4650 	/*
4651 	 * Ok, we can expire the conflicting client.
4652 	 */
4653 	nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p);
4654 	nfsrv_backupstable();
4655 	nfsrv_cleanclient(clp, p);
4656 	nfsrv_freedeleglist(&clp->lc_deleg);
4657 	nfsrv_freedeleglist(&clp->lc_olddeleg);
4658 	LIST_REMOVE(clp, lc_hash);
4659 	nfsrv_zapclient(clp, p);
4660 	return (1);
4661 }
4662 
4663 /*
4664  * Resolve a delegation conflict.
4665  * Returns 0 to indicate the conflict was resolved without sleeping.
4666  * Return -1 to indicate that the caller should check for conflicts again.
4667  * Return > 0 for an error that should be returned, normally NFSERR_DELAY.
4668  *
4669  * Also, manipulate the nfsv4root_lock, as required. It isn't changed
4670  * for a return of 0, since there was no sleep and it could be required
4671  * later. It is released for a return of NFSERR_DELAY, since the caller
4672  * will return that error. It is released when a sleep was done waiting
4673  * for the delegation to be returned or expire (so that other nfsds can
4674  * handle ops). Then, it must be acquired for the write to stable storage.
4675  * (This function is somewhat similar to nfsrv_clientconflict(), but
4676  *  the semantics differ in a couple of subtle ways. The return of 0
4677  *  indicates the conflict was resolved without sleeping here, not
4678  *  that the conflict can't be resolved and the handling of nfsv4root_lock
4679  *  differs, as noted above.)
4680  * Unlocks State before returning a non-zero value.
4681  */
4682 static int
4683 nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, NFSPROC_T *p,
4684     vnode_t vp)
4685 {
4686 	struct nfsclient *clp = stp->ls_clp;
4687 	int gotlock, error, lktype, retrycnt, zapped_clp;
4688 	nfsv4stateid_t tstateid;
4689 	fhandle_t tfh;
4690 
4691 	/*
4692 	 * If the conflict is with an old delegation...
4693 	 */
4694 	if (stp->ls_flags & NFSLCK_OLDDELEG) {
4695 		/*
4696 		 * You can delete it, if it has expired.
4697 		 */
4698 		if (clp->lc_delegtime < NFSD_MONOSEC) {
4699 			nfsrv_freedeleg(stp);
4700 			NFSUNLOCKSTATE();
4701 			error = -1;
4702 			goto out;
4703 		}
4704 		NFSUNLOCKSTATE();
4705 		/*
4706 		 * During this delay, the old delegation could expire or it
4707 		 * could be recovered by the client via an Open with
4708 		 * CLAIM_DELEGATE_PREV.
4709 		 * Release the nfsv4root_lock, if held.
4710 		 */
4711 		if (*haslockp) {
4712 			*haslockp = 0;
4713 			NFSLOCKV4ROOTMUTEX();
4714 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
4715 			NFSUNLOCKV4ROOTMUTEX();
4716 		}
4717 		error = NFSERR_DELAY;
4718 		goto out;
4719 	}
4720 
4721 	/*
4722 	 * It's a current delegation, so:
4723 	 * - check to see if the delegation has expired
4724 	 *   - if so, get the v4root lock and then expire it
4725 	 */
4726 	if (!(stp->ls_flags & NFSLCK_DELEGRECALL)) {
4727 		/*
4728 		 * - do a recall callback, since not yet done
4729 		 * For now, never allow truncate to be set. To use
4730 		 * truncate safely, it must be guaranteed that the
4731 		 * Remove, Rename or Setattr with size of 0 will
4732 		 * succeed and that would require major changes to
4733 		 * the VFS/Vnode OPs.
4734 		 * Set the expiry time large enough so that it won't expire
4735 		 * until after the callback, then set it correctly, once
4736 		 * the callback is done. (The delegation will now time
4737 		 * out whether or not the Recall worked ok. The timeout
4738 		 * will be extended when ops are done on the delegation
4739 		 * stateid, up to the timelimit.)
4740 		 */
4741 		stp->ls_delegtime = NFSD_MONOSEC + (2 * nfsrv_lease) +
4742 		    NFSRV_LEASEDELTA;
4743 		stp->ls_delegtimelimit = NFSD_MONOSEC + (6 * nfsrv_lease) +
4744 		    NFSRV_LEASEDELTA;
4745 		stp->ls_flags |= NFSLCK_DELEGRECALL;
4746 
4747 		/*
4748 		 * Loop NFSRV_CBRETRYCNT times while the CBRecall replies
4749 		 * NFSERR_BADSTATEID or NFSERR_BADHANDLE. This is done
4750 		 * in order to try and avoid a race that could happen
4751 		 * when a CBRecall request passed the Open reply with
4752 		 * the delegation in it when transitting the network.
4753 		 * Since nfsrv_docallback will sleep, don't use stp after
4754 		 * the call.
4755 		 */
4756 		NFSBCOPY((caddr_t)&stp->ls_stateid, (caddr_t)&tstateid,
4757 		    sizeof (tstateid));
4758 		NFSBCOPY((caddr_t)&stp->ls_lfp->lf_fh, (caddr_t)&tfh,
4759 		    sizeof (tfh));
4760 		NFSUNLOCKSTATE();
4761 		if (*haslockp) {
4762 			*haslockp = 0;
4763 			NFSLOCKV4ROOTMUTEX();
4764 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
4765 			NFSUNLOCKV4ROOTMUTEX();
4766 		}
4767 		retrycnt = 0;
4768 		do {
4769 		    error = nfsrv_docallback(clp, NFSV4OP_CBRECALL,
4770 			&tstateid, 0, &tfh, NULL, NULL, p);
4771 		    retrycnt++;
4772 		} while ((error == NFSERR_BADSTATEID ||
4773 		    error == NFSERR_BADHANDLE) && retrycnt < NFSV4_CBRETRYCNT);
4774 		error = NFSERR_DELAY;
4775 		goto out;
4776 	}
4777 
4778 	if (clp->lc_expiry >= NFSD_MONOSEC &&
4779 	    stp->ls_delegtime >= NFSD_MONOSEC) {
4780 		NFSUNLOCKSTATE();
4781 		/*
4782 		 * A recall has been done, but it has not yet expired.
4783 		 * So, RETURN_DELAY.
4784 		 */
4785 		if (*haslockp) {
4786 			*haslockp = 0;
4787 			NFSLOCKV4ROOTMUTEX();
4788 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
4789 			NFSUNLOCKV4ROOTMUTEX();
4790 		}
4791 		error = NFSERR_DELAY;
4792 		goto out;
4793 	}
4794 
4795 	/*
4796 	 * If we don't yet have the lock, just get it and then return,
4797 	 * since we need that before deleting expired state, such as
4798 	 * this delegation.
4799 	 * When getting the lock, unlock the vnode, so other nfsds that
4800 	 * are in progress, won't get stuck waiting for the vnode lock.
4801 	 */
4802 	if (*haslockp == 0) {
4803 		NFSUNLOCKSTATE();
4804 		lktype = NFSVOPISLOCKED(vp);
4805 		NFSVOPUNLOCK(vp, 0);
4806 		NFSLOCKV4ROOTMUTEX();
4807 		nfsv4_relref(&nfsv4rootfs_lock);
4808 		do {
4809 			gotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
4810 			    NFSV4ROOTLOCKMUTEXPTR, NULL);
4811 		} while (!gotlock);
4812 		NFSUNLOCKV4ROOTMUTEX();
4813 		*haslockp = 1;
4814 		NFSVOPLOCK(vp, lktype | LK_RETRY);
4815 		if ((vp->v_iflag & VI_DOOMED) != 0) {
4816 			*haslockp = 0;
4817 			NFSLOCKV4ROOTMUTEX();
4818 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
4819 			NFSUNLOCKV4ROOTMUTEX();
4820 			error = NFSERR_PERM;
4821 			goto out;
4822 		}
4823 		error = -1;
4824 		goto out;
4825 	}
4826 
4827 	NFSUNLOCKSTATE();
4828 	/*
4829 	 * Ok, we can delete the expired delegation.
4830 	 * First, write the Revoke record to stable storage and then
4831 	 * clear out the conflict.
4832 	 * Since all other nfsd threads are now blocked, we can safely
4833 	 * sleep without the state changing.
4834 	 */
4835 	nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p);
4836 	nfsrv_backupstable();
4837 	if (clp->lc_expiry < NFSD_MONOSEC) {
4838 		nfsrv_cleanclient(clp, p);
4839 		nfsrv_freedeleglist(&clp->lc_deleg);
4840 		nfsrv_freedeleglist(&clp->lc_olddeleg);
4841 		LIST_REMOVE(clp, lc_hash);
4842 		zapped_clp = 1;
4843 	} else {
4844 		nfsrv_freedeleg(stp);
4845 		zapped_clp = 0;
4846 	}
4847 	if (zapped_clp)
4848 		nfsrv_zapclient(clp, p);
4849 	error = -1;
4850 
4851 out:
4852 	NFSEXITCODE(error);
4853 	return (error);
4854 }
4855 
4856 /*
4857  * Check for a remove allowed, if remove is set to 1 and get rid of
4858  * delegations.
4859  */
4860 APPLESTATIC int
4861 nfsrv_checkremove(vnode_t vp, int remove, NFSPROC_T *p)
4862 {
4863 	struct nfsstate *stp;
4864 	struct nfslockfile *lfp;
4865 	int error, haslock = 0;
4866 	fhandle_t nfh;
4867 
4868 	/*
4869 	 * First, get the lock file structure.
4870 	 * (A return of -1 means no associated state, so remove ok.)
4871 	 */
4872 	error = nfsrv_getlockfh(vp, NFSLCK_CHECK, NULL, &nfh, p);
4873 tryagain:
4874 	NFSLOCKSTATE();
4875 	if (!error)
4876 		error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh, 0);
4877 	if (error) {
4878 		NFSUNLOCKSTATE();
4879 		if (haslock) {
4880 			NFSLOCKV4ROOTMUTEX();
4881 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
4882 			NFSUNLOCKV4ROOTMUTEX();
4883 		}
4884 		if (error == -1)
4885 			error = 0;
4886 		goto out;
4887 	}
4888 
4889 	/*
4890 	 * Now, we must Recall any delegations.
4891 	 */
4892 	error = nfsrv_cleandeleg(vp, lfp, NULL, &haslock, p);
4893 	if (error) {
4894 		/*
4895 		 * nfsrv_cleandeleg() unlocks state for non-zero
4896 		 * return.
4897 		 */
4898 		if (error == -1)
4899 			goto tryagain;
4900 		if (haslock) {
4901 			NFSLOCKV4ROOTMUTEX();
4902 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
4903 			NFSUNLOCKV4ROOTMUTEX();
4904 		}
4905 		goto out;
4906 	}
4907 
4908 	/*
4909 	 * Now, look for a conflicting open share.
4910 	 */
4911 	if (remove) {
4912 		LIST_FOREACH(stp, &lfp->lf_open, ls_file) {
4913 			if (stp->ls_flags & NFSLCK_WRITEDENY) {
4914 				error = NFSERR_FILEOPEN;
4915 				break;
4916 			}
4917 		}
4918 	}
4919 
4920 	NFSUNLOCKSTATE();
4921 	if (haslock) {
4922 		NFSLOCKV4ROOTMUTEX();
4923 		nfsv4_unlock(&nfsv4rootfs_lock, 1);
4924 		NFSUNLOCKV4ROOTMUTEX();
4925 	}
4926 
4927 out:
4928 	NFSEXITCODE(error);
4929 	return (error);
4930 }
4931 
4932 /*
4933  * Clear out all delegations for the file referred to by lfp.
4934  * May return NFSERR_DELAY, if there will be a delay waiting for
4935  * delegations to expire.
4936  * Returns -1 to indicate it slept while recalling a delegation.
4937  * This function has the side effect of deleting the nfslockfile structure,
4938  * if it no longer has associated state and didn't have to sleep.
4939  * Unlocks State before a non-zero value is returned.
4940  */
4941 static int
4942 nfsrv_cleandeleg(vnode_t vp, struct nfslockfile *lfp,
4943     struct nfsclient *clp, int *haslockp, NFSPROC_T *p)
4944 {
4945 	struct nfsstate *stp, *nstp;
4946 	int ret = 0;
4947 
4948 	stp = LIST_FIRST(&lfp->lf_deleg);
4949 	while (stp != LIST_END(&lfp->lf_deleg)) {
4950 		nstp = LIST_NEXT(stp, ls_file);
4951 		if (stp->ls_clp != clp) {
4952 			ret = nfsrv_delegconflict(stp, haslockp, p, vp);
4953 			if (ret) {
4954 				/*
4955 				 * nfsrv_delegconflict() unlocks state
4956 				 * when it returns non-zero.
4957 				 */
4958 				goto out;
4959 			}
4960 		}
4961 		stp = nstp;
4962 	}
4963 out:
4964 	NFSEXITCODE(ret);
4965 	return (ret);
4966 }
4967 
4968 /*
4969  * There are certain operations that, when being done outside of NFSv4,
4970  * require that any NFSv4 delegation for the file be recalled.
4971  * This function is to be called for those cases:
4972  * VOP_RENAME() - When a delegation is being recalled for any reason,
4973  *	the client may have to do Opens against the server, using the file's
4974  *	final component name. If the file has been renamed on the server,
4975  *	that component name will be incorrect and the Open will fail.
4976  * VOP_REMOVE() - Theoretically, a client could Open a file after it has
4977  *	been removed on the server, if there is a delegation issued to
4978  *	that client for the file. I say "theoretically" since clients
4979  *	normally do an Access Op before the Open and that Access Op will
4980  *	fail with ESTALE. Note that NFSv2 and 3 don't even do Opens, so
4981  *	they will detect the file's removal in the same manner. (There is
4982  *	one case where RFC3530 allows a client to do an Open without first
4983  *	doing an Access Op, which is passage of a check against the ACE
4984  *	returned with a Write delegation, but current practice is to ignore
4985  *	the ACE and always do an Access Op.)
4986  *	Since the functions can only be called with an unlocked vnode, this
4987  *	can't be done at this time.
4988  * VOP_ADVLOCK() - When a client holds a delegation, it can issue byte range
4989  *	locks locally in the client, which are not visible to the server. To
4990  *	deal with this, issuing of delegations for a vnode must be disabled
4991  *	and all delegations for the vnode recalled. This is done via the
4992  *	second function, using the VV_DISABLEDELEG vflag on the vnode.
4993  */
4994 APPLESTATIC void
4995 nfsd_recalldelegation(vnode_t vp, NFSPROC_T *p)
4996 {
4997 	time_t starttime;
4998 	int error;
4999 
5000 	/*
5001 	 * First, check to see if the server is currently running and it has
5002 	 * been called for a regular file when issuing delegations.
5003 	 */
5004 	if (newnfs_numnfsd == 0 || vp->v_type != VREG ||
5005 	    nfsrv_issuedelegs == 0)
5006 		return;
5007 
5008 	KASSERT((NFSVOPISLOCKED(vp) != LK_EXCLUSIVE), ("vp %p is locked", vp));
5009 	/*
5010 	 * First, get a reference on the nfsv4rootfs_lock so that an
5011 	 * exclusive lock cannot be acquired by another thread.
5012 	 */
5013 	NFSLOCKV4ROOTMUTEX();
5014 	nfsv4_getref(&nfsv4rootfs_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, NULL);
5015 	NFSUNLOCKV4ROOTMUTEX();
5016 
5017 	/*
5018 	 * Now, call nfsrv_checkremove() in a loop while it returns
5019 	 * NFSERR_DELAY. Return upon any other error or when timed out.
5020 	 */
5021 	starttime = NFSD_MONOSEC;
5022 	do {
5023 		if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) {
5024 			error = nfsrv_checkremove(vp, 0, p);
5025 			NFSVOPUNLOCK(vp, 0);
5026 		} else
5027 			error = EPERM;
5028 		if (error == NFSERR_DELAY) {
5029 			if (NFSD_MONOSEC - starttime > NFS_REMOVETIMEO)
5030 				break;
5031 			/* Sleep for a short period of time */
5032 			(void) nfs_catnap(PZERO, 0, "nfsremove");
5033 		}
5034 	} while (error == NFSERR_DELAY);
5035 	NFSLOCKV4ROOTMUTEX();
5036 	nfsv4_relref(&nfsv4rootfs_lock);
5037 	NFSUNLOCKV4ROOTMUTEX();
5038 }
5039 
5040 APPLESTATIC void
5041 nfsd_disabledelegation(vnode_t vp, NFSPROC_T *p)
5042 {
5043 
5044 #ifdef VV_DISABLEDELEG
5045 	/*
5046 	 * First, flag issuance of delegations disabled.
5047 	 */
5048 	atomic_set_long(&vp->v_vflag, VV_DISABLEDELEG);
5049 #endif
5050 
5051 	/*
5052 	 * Then call nfsd_recalldelegation() to get rid of all extant
5053 	 * delegations.
5054 	 */
5055 	nfsd_recalldelegation(vp, p);
5056 }
5057 
5058 /*
5059  * Check for conflicting locks, etc. and then get rid of delegations.
5060  * (At one point I thought that I should get rid of delegations for any
5061  *  Setattr, since it could potentially disallow the I/O op (read or write)
5062  *  allowed by the delegation. However, Setattr Ops that aren't changing
5063  *  the size get a stateid of all 0s, so you can't tell if it is a delegation
5064  *  for the same client or a different one, so I decided to only get rid
5065  *  of delegations for other clients when the size is being changed.)
5066  * In general, a Setattr can disable NFS I/O Ops that are outstanding, such
5067  * as Write backs, even if there is no delegation, so it really isn't any
5068  * different?)
5069  */
5070 APPLESTATIC int
5071 nfsrv_checksetattr(vnode_t vp, struct nfsrv_descript *nd,
5072     nfsv4stateid_t *stateidp, struct nfsvattr *nvap, nfsattrbit_t *attrbitp,
5073     struct nfsexstuff *exp, NFSPROC_T *p)
5074 {
5075 	struct nfsstate st, *stp = &st;
5076 	struct nfslock lo, *lop = &lo;
5077 	int error = 0;
5078 	nfsquad_t clientid;
5079 
5080 	if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SIZE)) {
5081 		stp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS);
5082 		lop->lo_first = nvap->na_size;
5083 	} else {
5084 		stp->ls_flags = 0;
5085 		lop->lo_first = 0;
5086 	}
5087 	if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNER) ||
5088 	    NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP) ||
5089 	    NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_MODE) ||
5090 	    NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_ACL))
5091 		stp->ls_flags |= NFSLCK_SETATTR;
5092 	if (stp->ls_flags == 0)
5093 		goto out;
5094 	lop->lo_end = NFS64BITSSET;
5095 	lop->lo_flags = NFSLCK_WRITE;
5096 	stp->ls_ownerlen = 0;
5097 	stp->ls_op = NULL;
5098 	stp->ls_uid = nd->nd_cred->cr_uid;
5099 	stp->ls_stateid.seqid = stateidp->seqid;
5100 	clientid.lval[0] = stp->ls_stateid.other[0] = stateidp->other[0];
5101 	clientid.lval[1] = stp->ls_stateid.other[1] = stateidp->other[1];
5102 	stp->ls_stateid.other[2] = stateidp->other[2];
5103 	error = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid,
5104 	    stateidp, exp, nd, p);
5105 
5106 out:
5107 	NFSEXITCODE2(error, nd);
5108 	return (error);
5109 }
5110 
5111 /*
5112  * Check for a write delegation and do a CBGETATTR if there is one, updating
5113  * the attributes, as required.
5114  * Should I return an error if I can't get the attributes? (For now, I'll
5115  * just return ok.
5116  */
5117 APPLESTATIC int
5118 nfsrv_checkgetattr(struct nfsrv_descript *nd, vnode_t vp,
5119     struct nfsvattr *nvap, nfsattrbit_t *attrbitp, struct ucred *cred,
5120     NFSPROC_T *p)
5121 {
5122 	struct nfsstate *stp;
5123 	struct nfslockfile *lfp;
5124 	struct nfsclient *clp;
5125 	struct nfsvattr nva;
5126 	fhandle_t nfh;
5127 	int error = 0;
5128 	nfsattrbit_t cbbits;
5129 	u_quad_t delegfilerev;
5130 
5131 	NFSCBGETATTR_ATTRBIT(attrbitp, &cbbits);
5132 	if (!NFSNONZERO_ATTRBIT(&cbbits))
5133 		goto out;
5134 
5135 	/*
5136 	 * Get the lock file structure.
5137 	 * (A return of -1 means no associated state, so return ok.)
5138 	 */
5139 	error = nfsrv_getlockfh(vp, NFSLCK_CHECK, NULL, &nfh, p);
5140 	NFSLOCKSTATE();
5141 	if (!error)
5142 		error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh, 0);
5143 	if (error) {
5144 		NFSUNLOCKSTATE();
5145 		if (error == -1)
5146 			error = 0;
5147 		goto out;
5148 	}
5149 
5150 	/*
5151 	 * Now, look for a write delegation.
5152 	 */
5153 	LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) {
5154 		if (stp->ls_flags & NFSLCK_DELEGWRITE)
5155 			break;
5156 	}
5157 	if (stp == LIST_END(&lfp->lf_deleg)) {
5158 		NFSUNLOCKSTATE();
5159 		goto out;
5160 	}
5161 	clp = stp->ls_clp;
5162 	delegfilerev = stp->ls_filerev;
5163 
5164 	/*
5165 	 * If the Write delegation was issued as a part of this Compound RPC
5166 	 * or if we have an Implied Clientid (used in a previous Op in this
5167 	 * compound) and it is the client the delegation was issued to,
5168 	 * just return ok.
5169 	 * I also assume that it is from the same client iff the network
5170 	 * host IP address is the same as the callback address. (Not
5171 	 * exactly correct by the RFC, but avoids a lot of Getattr
5172 	 * callbacks.)
5173 	 */
5174 	if (nd->nd_compref == stp->ls_compref ||
5175 	    ((nd->nd_flag & ND_IMPLIEDCLID) &&
5176 	     clp->lc_clientid.qval == nd->nd_clientid.qval) ||
5177 	     nfsaddr2_match(clp->lc_req.nr_nam, nd->nd_nam)) {
5178 		NFSUNLOCKSTATE();
5179 		goto out;
5180 	}
5181 
5182 	/*
5183 	 * We are now done with the delegation state structure,
5184 	 * so the statelock can be released and we can now tsleep().
5185 	 */
5186 
5187 	/*
5188 	 * Now, we must do the CB Getattr callback, to see if Change or Size
5189 	 * has changed.
5190 	 */
5191 	if (clp->lc_expiry >= NFSD_MONOSEC) {
5192 		NFSUNLOCKSTATE();
5193 		NFSVNO_ATTRINIT(&nva);
5194 		nva.na_filerev = NFS64BITSSET;
5195 		error = nfsrv_docallback(clp, NFSV4OP_CBGETATTR, NULL,
5196 		    0, &nfh, &nva, &cbbits, p);
5197 		if (!error) {
5198 			if ((nva.na_filerev != NFS64BITSSET &&
5199 			    nva.na_filerev > delegfilerev) ||
5200 			    (NFSVNO_ISSETSIZE(&nva) &&
5201 			     nva.na_size != nvap->na_size)) {
5202 				error = nfsvno_updfilerev(vp, nvap, cred, p);
5203 				if (NFSVNO_ISSETSIZE(&nva))
5204 					nvap->na_size = nva.na_size;
5205 			}
5206 		} else
5207 			error = 0;	/* Ignore callback errors for now. */
5208 	} else {
5209 		NFSUNLOCKSTATE();
5210 	}
5211 
5212 out:
5213 	NFSEXITCODE2(error, nd);
5214 	return (error);
5215 }
5216 
5217 /*
5218  * This function looks for openowners that haven't had any opens for
5219  * a while and throws them away. Called by an nfsd when NFSNSF_NOOPENS
5220  * is set.
5221  */
5222 APPLESTATIC void
5223 nfsrv_throwawayopens(NFSPROC_T *p)
5224 {
5225 	struct nfsclient *clp, *nclp;
5226 	struct nfsstate *stp, *nstp;
5227 	int i;
5228 
5229 	NFSLOCKSTATE();
5230 	nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NOOPENS;
5231 	/*
5232 	 * For each client...
5233 	 */
5234 	for (i = 0; i < NFSCLIENTHASHSIZE; i++) {
5235 	    LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, nclp) {
5236 		LIST_FOREACH_SAFE(stp, &clp->lc_open, ls_list, nstp) {
5237 			if (LIST_EMPTY(&stp->ls_open) &&
5238 			    (stp->ls_noopens > NFSNOOPEN ||
5239 			     (nfsrv_openpluslock * 2) >
5240 			     NFSRV_V4STATELIMIT))
5241 				nfsrv_freeopenowner(stp, 0, p);
5242 		}
5243 	    }
5244 	}
5245 	NFSUNLOCKSTATE();
5246 }
5247 
5248 /*
5249  * This function checks to see if the credentials are the same.
5250  * Returns 1 for not same, 0 otherwise.
5251  */
5252 static int
5253 nfsrv_notsamecredname(struct nfsrv_descript *nd, struct nfsclient *clp)
5254 {
5255 
5256 	if (nd->nd_flag & ND_GSS) {
5257 		if (!(clp->lc_flags & LCL_GSS))
5258 			return (1);
5259 		if (clp->lc_flags & LCL_NAME) {
5260 			if (nd->nd_princlen != clp->lc_namelen ||
5261 			    NFSBCMP(nd->nd_principal, clp->lc_name,
5262 				clp->lc_namelen))
5263 				return (1);
5264 			else
5265 				return (0);
5266 		}
5267 		if (nd->nd_cred->cr_uid == clp->lc_uid)
5268 			return (0);
5269 		else
5270 			return (1);
5271 	} else if (clp->lc_flags & LCL_GSS)
5272 		return (1);
5273 	/*
5274 	 * For AUTH_SYS, allow the same uid or root. (This is underspecified
5275 	 * in RFC3530, which talks about principals, but doesn't say anything
5276 	 * about uids for AUTH_SYS.)
5277 	 */
5278 	if (nd->nd_cred->cr_uid == clp->lc_uid || nd->nd_cred->cr_uid == 0)
5279 		return (0);
5280 	else
5281 		return (1);
5282 }
5283 
5284 /*
5285  * Calculate the lease expiry time.
5286  */
5287 static time_t
5288 nfsrv_leaseexpiry(void)
5289 {
5290 
5291 	if (nfsrv_stablefirst.nsf_eograce > NFSD_MONOSEC)
5292 		return (NFSD_MONOSEC + 2 * (nfsrv_lease + NFSRV_LEASEDELTA));
5293 	return (NFSD_MONOSEC + nfsrv_lease + NFSRV_LEASEDELTA);
5294 }
5295 
5296 /*
5297  * Delay the delegation timeout as far as ls_delegtimelimit, as required.
5298  */
5299 static void
5300 nfsrv_delaydelegtimeout(struct nfsstate *stp)
5301 {
5302 
5303 	if ((stp->ls_flags & NFSLCK_DELEGRECALL) == 0)
5304 		return;
5305 
5306 	if ((stp->ls_delegtime + 15) > NFSD_MONOSEC &&
5307 	    stp->ls_delegtime < stp->ls_delegtimelimit) {
5308 		stp->ls_delegtime += nfsrv_lease;
5309 		if (stp->ls_delegtime > stp->ls_delegtimelimit)
5310 			stp->ls_delegtime = stp->ls_delegtimelimit;
5311 	}
5312 }
5313 
5314 /*
5315  * This function checks to see if there is any other state associated
5316  * with the openowner for this Open.
5317  * It returns 1 if there is no other state, 0 otherwise.
5318  */
5319 static int
5320 nfsrv_nootherstate(struct nfsstate *stp)
5321 {
5322 	struct nfsstate *tstp;
5323 
5324 	LIST_FOREACH(tstp, &stp->ls_openowner->ls_open, ls_list) {
5325 		if (tstp != stp || !LIST_EMPTY(&tstp->ls_lock))
5326 			return (0);
5327 	}
5328 	return (1);
5329 }
5330 
5331 /*
5332  * Create a list of lock deltas (changes to local byte range locking
5333  * that can be rolled back using the list) and apply the changes via
5334  * nfsvno_advlock(). Optionally, lock the list. It is expected that either
5335  * the rollback or update function will be called after this.
5336  * It returns an error (and rolls back, as required), if any nfsvno_advlock()
5337  * call fails. If it returns an error, it will unlock the list.
5338  */
5339 static int
5340 nfsrv_locallock(vnode_t vp, struct nfslockfile *lfp, int flags,
5341     uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p)
5342 {
5343 	struct nfslock *lop, *nlop;
5344 	int error = 0;
5345 
5346 	/* Loop through the list of locks. */
5347 	lop = LIST_FIRST(&lfp->lf_locallock);
5348 	while (first < end && lop != NULL) {
5349 		nlop = LIST_NEXT(lop, lo_lckowner);
5350 		if (first >= lop->lo_end) {
5351 			/* not there yet */
5352 			lop = nlop;
5353 		} else if (first < lop->lo_first) {
5354 			/* new one starts before entry in list */
5355 			if (end <= lop->lo_first) {
5356 				/* no overlap between old and new */
5357 				error = nfsrv_dolocal(vp, lfp, flags,
5358 				    NFSLCK_UNLOCK, first, end, cfp, p);
5359 				if (error != 0)
5360 					break;
5361 				first = end;
5362 			} else {
5363 				/* handle fragment overlapped with new one */
5364 				error = nfsrv_dolocal(vp, lfp, flags,
5365 				    NFSLCK_UNLOCK, first, lop->lo_first, cfp,
5366 				    p);
5367 				if (error != 0)
5368 					break;
5369 				first = lop->lo_first;
5370 			}
5371 		} else {
5372 			/* new one overlaps this entry in list */
5373 			if (end <= lop->lo_end) {
5374 				/* overlaps all of new one */
5375 				error = nfsrv_dolocal(vp, lfp, flags,
5376 				    lop->lo_flags, first, end, cfp, p);
5377 				if (error != 0)
5378 					break;
5379 				first = end;
5380 			} else {
5381 				/* handle fragment overlapped with new one */
5382 				error = nfsrv_dolocal(vp, lfp, flags,
5383 				    lop->lo_flags, first, lop->lo_end, cfp, p);
5384 				if (error != 0)
5385 					break;
5386 				first = lop->lo_end;
5387 				lop = nlop;
5388 			}
5389 		}
5390 	}
5391 	if (first < end && error == 0)
5392 		/* handle fragment past end of list */
5393 		error = nfsrv_dolocal(vp, lfp, flags, NFSLCK_UNLOCK, first,
5394 		    end, cfp, p);
5395 
5396 	NFSEXITCODE(error);
5397 	return (error);
5398 }
5399 
5400 /*
5401  * Local lock unlock. Unlock all byte ranges that are no longer locked
5402  * by NFSv4. To do this, unlock any subranges of first-->end that
5403  * do not overlap with the byte ranges of any lock in the lfp->lf_lock
5404  * list. This list has all locks for the file held by other
5405  * <clientid, lockowner> tuples. The list is ordered by increasing
5406  * lo_first value, but may have entries that overlap each other, for
5407  * the case of read locks.
5408  */
5409 static void
5410 nfsrv_localunlock(vnode_t vp, struct nfslockfile *lfp, uint64_t init_first,
5411     uint64_t init_end, NFSPROC_T *p)
5412 {
5413 	struct nfslock *lop;
5414 	uint64_t first, end, prevfirst;
5415 
5416 	first = init_first;
5417 	end = init_end;
5418 	while (first < init_end) {
5419 		/* Loop through all nfs locks, adjusting first and end */
5420 		prevfirst = 0;
5421 		LIST_FOREACH(lop, &lfp->lf_lock, lo_lckfile) {
5422 			KASSERT(prevfirst <= lop->lo_first,
5423 			    ("nfsv4 locks out of order"));
5424 			KASSERT(lop->lo_first < lop->lo_end,
5425 			    ("nfsv4 bogus lock"));
5426 			prevfirst = lop->lo_first;
5427 			if (first >= lop->lo_first &&
5428 			    first < lop->lo_end)
5429 				/*
5430 				 * Overlaps with initial part, so trim
5431 				 * off that initial part by moving first past
5432 				 * it.
5433 				 */
5434 				first = lop->lo_end;
5435 			else if (end > lop->lo_first &&
5436 			    lop->lo_first > first) {
5437 				/*
5438 				 * This lock defines the end of the
5439 				 * segment to unlock, so set end to the
5440 				 * start of it and break out of the loop.
5441 				 */
5442 				end = lop->lo_first;
5443 				break;
5444 			}
5445 			if (first >= end)
5446 				/*
5447 				 * There is no segment left to do, so
5448 				 * break out of this loop and then exit
5449 				 * the outer while() since first will be set
5450 				 * to end, which must equal init_end here.
5451 				 */
5452 				break;
5453 		}
5454 		if (first < end) {
5455 			/* Unlock this segment */
5456 			(void) nfsrv_dolocal(vp, lfp, NFSLCK_UNLOCK,
5457 			    NFSLCK_READ, first, end, NULL, p);
5458 			nfsrv_locallock_commit(lfp, NFSLCK_UNLOCK,
5459 			    first, end);
5460 		}
5461 		/*
5462 		 * Now move past this segment and look for any further
5463 		 * segment in the range, if there is one.
5464 		 */
5465 		first = end;
5466 		end = init_end;
5467 	}
5468 }
5469 
5470 /*
5471  * Do the local lock operation and update the rollback list, as required.
5472  * Perform the rollback and return the error if nfsvno_advlock() fails.
5473  */
5474 static int
5475 nfsrv_dolocal(vnode_t vp, struct nfslockfile *lfp, int flags, int oldflags,
5476     uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p)
5477 {
5478 	struct nfsrollback *rlp;
5479 	int error = 0, ltype, oldltype;
5480 
5481 	if (flags & NFSLCK_WRITE)
5482 		ltype = F_WRLCK;
5483 	else if (flags & NFSLCK_READ)
5484 		ltype = F_RDLCK;
5485 	else
5486 		ltype = F_UNLCK;
5487 	if (oldflags & NFSLCK_WRITE)
5488 		oldltype = F_WRLCK;
5489 	else if (oldflags & NFSLCK_READ)
5490 		oldltype = F_RDLCK;
5491 	else
5492 		oldltype = F_UNLCK;
5493 	if (ltype == oldltype || (oldltype == F_WRLCK && ltype == F_RDLCK))
5494 		/* nothing to do */
5495 		goto out;
5496 	error = nfsvno_advlock(vp, ltype, first, end, p);
5497 	if (error != 0) {
5498 		if (cfp != NULL) {
5499 			cfp->cl_clientid.lval[0] = 0;
5500 			cfp->cl_clientid.lval[1] = 0;
5501 			cfp->cl_first = 0;
5502 			cfp->cl_end = NFS64BITSSET;
5503 			cfp->cl_flags = NFSLCK_WRITE;
5504 			cfp->cl_ownerlen = 5;
5505 			NFSBCOPY("LOCAL", cfp->cl_owner, 5);
5506 		}
5507 		nfsrv_locallock_rollback(vp, lfp, p);
5508 	} else if (ltype != F_UNLCK) {
5509 		rlp = malloc(sizeof (struct nfsrollback), M_NFSDROLLBACK,
5510 		    M_WAITOK);
5511 		rlp->rlck_first = first;
5512 		rlp->rlck_end = end;
5513 		rlp->rlck_type = oldltype;
5514 		LIST_INSERT_HEAD(&lfp->lf_rollback, rlp, rlck_list);
5515 	}
5516 
5517 out:
5518 	NFSEXITCODE(error);
5519 	return (error);
5520 }
5521 
5522 /*
5523  * Roll back local lock changes and free up the rollback list.
5524  */
5525 static void
5526 nfsrv_locallock_rollback(vnode_t vp, struct nfslockfile *lfp, NFSPROC_T *p)
5527 {
5528 	struct nfsrollback *rlp, *nrlp;
5529 
5530 	LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, nrlp) {
5531 		(void) nfsvno_advlock(vp, rlp->rlck_type, rlp->rlck_first,
5532 		    rlp->rlck_end, p);
5533 		free(rlp, M_NFSDROLLBACK);
5534 	}
5535 	LIST_INIT(&lfp->lf_rollback);
5536 }
5537 
5538 /*
5539  * Update local lock list and delete rollback list (ie now committed to the
5540  * local locks). Most of the work is done by the internal function.
5541  */
5542 static void
5543 nfsrv_locallock_commit(struct nfslockfile *lfp, int flags, uint64_t first,
5544     uint64_t end)
5545 {
5546 	struct nfsrollback *rlp, *nrlp;
5547 	struct nfslock *new_lop, *other_lop;
5548 
5549 	new_lop = malloc(sizeof (struct nfslock), M_NFSDLOCK, M_WAITOK);
5550 	if (flags & (NFSLCK_READ | NFSLCK_WRITE))
5551 		other_lop = malloc(sizeof (struct nfslock), M_NFSDLOCK,
5552 		    M_WAITOK);
5553 	else
5554 		other_lop = NULL;
5555 	new_lop->lo_flags = flags;
5556 	new_lop->lo_first = first;
5557 	new_lop->lo_end = end;
5558 	nfsrv_updatelock(NULL, &new_lop, &other_lop, lfp);
5559 	if (new_lop != NULL)
5560 		free(new_lop, M_NFSDLOCK);
5561 	if (other_lop != NULL)
5562 		free(other_lop, M_NFSDLOCK);
5563 
5564 	/* and get rid of the rollback list */
5565 	LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, nrlp)
5566 		free(rlp, M_NFSDROLLBACK);
5567 	LIST_INIT(&lfp->lf_rollback);
5568 }
5569 
5570 /*
5571  * Lock the struct nfslockfile for local lock updating.
5572  */
5573 static void
5574 nfsrv_locklf(struct nfslockfile *lfp)
5575 {
5576 	int gotlock;
5577 
5578 	/* lf_usecount ensures *lfp won't be free'd */
5579 	lfp->lf_usecount++;
5580 	do {
5581 		gotlock = nfsv4_lock(&lfp->lf_locallock_lck, 1, NULL,
5582 		    NFSSTATEMUTEXPTR, NULL);
5583 	} while (gotlock == 0);
5584 	lfp->lf_usecount--;
5585 }
5586 
5587 /*
5588  * Unlock the struct nfslockfile after local lock updating.
5589  */
5590 static void
5591 nfsrv_unlocklf(struct nfslockfile *lfp)
5592 {
5593 
5594 	nfsv4_unlock(&lfp->lf_locallock_lck, 0);
5595 }
5596 
5597 /*
5598  * Clear out all state for the NFSv4 server.
5599  * Must be called by a thread that can sleep when no nfsds are running.
5600  */
5601 void
5602 nfsrv_throwawayallstate(NFSPROC_T *p)
5603 {
5604 	struct nfsclient *clp, *nclp;
5605 	struct nfslockfile *lfp, *nlfp;
5606 	int i;
5607 
5608 	/*
5609 	 * For each client, clean out the state and then free the structure.
5610 	 */
5611 	for (i = 0; i < NFSCLIENTHASHSIZE; i++) {
5612 		LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, nclp) {
5613 			nfsrv_cleanclient(clp, p);
5614 			nfsrv_freedeleglist(&clp->lc_deleg);
5615 			nfsrv_freedeleglist(&clp->lc_olddeleg);
5616 			free(clp, M_NFSDCLIENT);
5617 		}
5618 	}
5619 
5620 	/*
5621 	 * Also, free up any remaining lock file structures.
5622 	 */
5623 	for (i = 0; i < NFSLOCKHASHSIZE; i++) {
5624 		LIST_FOREACH_SAFE(lfp, &nfslockhash[i], lf_hash, nlfp) {
5625 			printf("nfsd unload: fnd a lock file struct\n");
5626 			nfsrv_freenfslockfile(lfp);
5627 		}
5628 	}
5629 }
5630 
5631 /*
5632  * Check the sequence# for the session and slot provided as an argument.
5633  * Also, renew the lease if the session will return NFS_OK.
5634  */
5635 int
5636 nfsrv_checksequence(struct nfsrv_descript *nd, uint32_t sequenceid,
5637     uint32_t *highest_slotidp, uint32_t *target_highest_slotidp, int cache_this,
5638     uint32_t *sflagsp, NFSPROC_T *p)
5639 {
5640 	struct nfsdsession *sep;
5641 	struct nfssessionhash *shp;
5642 	int error;
5643 	SVCXPRT *savxprt;
5644 
5645 	shp = NFSSESSIONHASH(nd->nd_sessionid);
5646 	NFSLOCKSESSION(shp);
5647 	sep = nfsrv_findsession(nd->nd_sessionid);
5648 	if (sep == NULL) {
5649 		NFSUNLOCKSESSION(shp);
5650 		return (NFSERR_BADSESSION);
5651 	}
5652 	error = nfsv4_seqsession(sequenceid, nd->nd_slotid, *highest_slotidp,
5653 	    sep->sess_slots, NULL, NFSV4_SLOTS - 1);
5654 	if (error != 0) {
5655 		NFSUNLOCKSESSION(shp);
5656 		return (error);
5657 	}
5658 	if (cache_this != 0)
5659 		nd->nd_flag |= ND_SAVEREPLY;
5660 	/* Renew the lease. */
5661 	sep->sess_clp->lc_expiry = nfsrv_leaseexpiry();
5662 	nd->nd_clientid.qval = sep->sess_clp->lc_clientid.qval;
5663 	nd->nd_flag |= ND_IMPLIEDCLID;
5664 
5665 	/*
5666 	 * If this session handles the backchannel, save the nd_xprt for this
5667 	 * RPC, since this is the one being used.
5668 	 */
5669 	if (sep->sess_cbsess.nfsess_xprt != NULL &&
5670 	    (sep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0) {
5671 		savxprt = sep->sess_cbsess.nfsess_xprt;
5672 		SVC_ACQUIRE(nd->nd_xprt);
5673 		nd->nd_xprt->xp_p2 = savxprt->xp_p2;
5674 		nd->nd_xprt->xp_idletimeout = 0;	/* Disable timeout. */
5675 		sep->sess_cbsess.nfsess_xprt = nd->nd_xprt;
5676 		SVC_RELEASE(savxprt);
5677 	}
5678 
5679 	*sflagsp = 0;
5680 	if (sep->sess_clp->lc_req.nr_client == NULL)
5681 		*sflagsp |= NFSV4SEQ_CBPATHDOWN;
5682 	NFSUNLOCKSESSION(shp);
5683 	if (error == NFSERR_EXPIRED) {
5684 		*sflagsp |= NFSV4SEQ_EXPIREDALLSTATEREVOKED;
5685 		error = 0;
5686 	} else if (error == NFSERR_ADMINREVOKED) {
5687 		*sflagsp |= NFSV4SEQ_ADMINSTATEREVOKED;
5688 		error = 0;
5689 	}
5690 	*highest_slotidp = *target_highest_slotidp = NFSV4_SLOTS - 1;
5691 	return (0);
5692 }
5693 
5694 /*
5695  * Check/set reclaim complete for this session/clientid.
5696  */
5697 int
5698 nfsrv_checkreclaimcomplete(struct nfsrv_descript *nd)
5699 {
5700 	struct nfsdsession *sep;
5701 	struct nfssessionhash *shp;
5702 	int error = 0;
5703 
5704 	shp = NFSSESSIONHASH(nd->nd_sessionid);
5705 	NFSLOCKSTATE();
5706 	NFSLOCKSESSION(shp);
5707 	sep = nfsrv_findsession(nd->nd_sessionid);
5708 	if (sep == NULL) {
5709 		NFSUNLOCKSESSION(shp);
5710 		NFSUNLOCKSTATE();
5711 		return (NFSERR_BADSESSION);
5712 	}
5713 
5714 	/* Check to see if reclaim complete has already happened. */
5715 	if ((sep->sess_clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0)
5716 		error = NFSERR_COMPLETEALREADY;
5717 	else
5718 		sep->sess_clp->lc_flags |= LCL_RECLAIMCOMPLETE;
5719 	NFSUNLOCKSESSION(shp);
5720 	NFSUNLOCKSTATE();
5721 	return (error);
5722 }
5723 
5724 /*
5725  * Cache the reply in a session slot.
5726  */
5727 void
5728 nfsrv_cache_session(uint8_t *sessionid, uint32_t slotid, int repstat,
5729    struct mbuf **m)
5730 {
5731 	struct nfsdsession *sep;
5732 	struct nfssessionhash *shp;
5733 
5734 	shp = NFSSESSIONHASH(sessionid);
5735 	NFSLOCKSESSION(shp);
5736 	sep = nfsrv_findsession(sessionid);
5737 	if (sep == NULL) {
5738 		NFSUNLOCKSESSION(shp);
5739 		printf("nfsrv_cache_session: no session\n");
5740 		m_freem(*m);
5741 		return;
5742 	}
5743 	nfsv4_seqsess_cacherep(slotid, sep->sess_slots, repstat, m);
5744 	NFSUNLOCKSESSION(shp);
5745 }
5746 
5747 /*
5748  * Search for a session that matches the sessionid.
5749  */
5750 static struct nfsdsession *
5751 nfsrv_findsession(uint8_t *sessionid)
5752 {
5753 	struct nfsdsession *sep;
5754 	struct nfssessionhash *shp;
5755 
5756 	shp = NFSSESSIONHASH(sessionid);
5757 	LIST_FOREACH(sep, &shp->list, sess_hash) {
5758 		if (!NFSBCMP(sessionid, sep->sess_sessionid, NFSX_V4SESSIONID))
5759 			break;
5760 	}
5761 	return (sep);
5762 }
5763 
5764 /*
5765  * Destroy a session.
5766  */
5767 int
5768 nfsrv_destroysession(struct nfsrv_descript *nd, uint8_t *sessionid)
5769 {
5770 	int error, samesess;
5771 
5772 	samesess = 0;
5773 	if (!NFSBCMP(sessionid, nd->nd_sessionid, NFSX_V4SESSIONID)) {
5774 		samesess = 1;
5775 		if ((nd->nd_flag & ND_LASTOP) == 0)
5776 			return (NFSERR_BADSESSION);
5777 	}
5778 	error = nfsrv_freesession(NULL, sessionid);
5779 	if (error == 0 && samesess != 0)
5780 		nd->nd_flag &= ~ND_HASSEQUENCE;
5781 	return (error);
5782 }
5783 
5784 /*
5785  * Free up a session structure.
5786  */
5787 static int
5788 nfsrv_freesession(struct nfsdsession *sep, uint8_t *sessionid)
5789 {
5790 	struct nfssessionhash *shp;
5791 	int i;
5792 
5793 	if (sep == NULL) {
5794 		shp = NFSSESSIONHASH(sessionid);
5795 		NFSLOCKSESSION(shp);
5796 		sep = nfsrv_findsession(sessionid);
5797 	} else {
5798 		shp = NFSSESSIONHASH(sep->sess_sessionid);
5799 		NFSLOCKSESSION(shp);
5800 	}
5801 	if (sep != NULL) {
5802 		NFSLOCKSTATE();
5803 		sep->sess_refcnt--;
5804 		if (sep->sess_refcnt > 0) {
5805 			NFSUNLOCKSTATE();
5806 			NFSUNLOCKSESSION(shp);
5807 			return (0);
5808 		}
5809 		LIST_REMOVE(sep, sess_hash);
5810 		LIST_REMOVE(sep, sess_list);
5811 		NFSUNLOCKSTATE();
5812 	}
5813 	NFSUNLOCKSESSION(shp);
5814 	if (sep == NULL)
5815 		return (NFSERR_BADSESSION);
5816 	for (i = 0; i < NFSV4_SLOTS; i++)
5817 		if (sep->sess_slots[i].nfssl_reply != NULL)
5818 			m_freem(sep->sess_slots[i].nfssl_reply);
5819 	if (sep->sess_cbsess.nfsess_xprt != NULL)
5820 		SVC_RELEASE(sep->sess_cbsess.nfsess_xprt);
5821 	free(sep, M_NFSDSESSION);
5822 	return (0);
5823 }
5824 
5825 /*
5826  * Free a stateid.
5827  * RFC5661 says that it should fail when there are associated opens, locks
5828  * or delegations. Since stateids represent opens, I don't see how you can
5829  * free an open stateid (it will be free'd when closed), so this function
5830  * only works for lock stateids (freeing the lock_owner) or delegations.
5831  */
5832 int
5833 nfsrv_freestateid(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp,
5834     NFSPROC_T *p)
5835 {
5836 	struct nfsclient *clp;
5837 	struct nfsstate *stp;
5838 	int error;
5839 
5840 	NFSLOCKSTATE();
5841 	/*
5842 	 * Look up the stateid
5843 	 */
5844 	error = nfsrv_getclient((nfsquad_t)((u_quad_t)0), CLOPS_RENEW, &clp,
5845 	    NULL, (nfsquad_t)((u_quad_t)0), 0, nd, p);
5846 	if (error == 0) {
5847 		/* First, check for a delegation. */
5848 		LIST_FOREACH(stp, &clp->lc_deleg, ls_list) {
5849 			if (!NFSBCMP(stp->ls_stateid.other, stateidp->other,
5850 			    NFSX_STATEIDOTHER))
5851 				break;
5852 		}
5853 		if (stp != NULL) {
5854 			nfsrv_freedeleg(stp);
5855 			NFSUNLOCKSTATE();
5856 			return (error);
5857 		}
5858 	}
5859 	/* Not a delegation, try for a lock_owner. */
5860 	if (error == 0)
5861 		error = nfsrv_getstate(clp, stateidp, 0, &stp);
5862 	if (error == 0 && ((stp->ls_flags & (NFSLCK_OPEN | NFSLCK_DELEGREAD |
5863 	    NFSLCK_DELEGWRITE)) != 0 || (stp->ls_flags & NFSLCK_LOCK) == 0))
5864 		/* Not a lock_owner stateid. */
5865 		error = NFSERR_LOCKSHELD;
5866 	if (error == 0 && !LIST_EMPTY(&stp->ls_lock))
5867 		error = NFSERR_LOCKSHELD;
5868 	if (error == 0)
5869 		nfsrv_freelockowner(stp, NULL, 0, p);
5870 	NFSUNLOCKSTATE();
5871 	return (error);
5872 }
5873 
5874 /*
5875  * Generate the xdr for an NFSv4.1 CBSequence Operation.
5876  */
5877 static int
5878 nfsv4_setcbsequence(struct nfsrv_descript *nd, struct nfsclient *clp,
5879     int dont_replycache, struct nfsdsession **sepp)
5880 {
5881 	struct nfsdsession *sep;
5882 	uint32_t *tl, slotseq = 0;
5883 	int maxslot, slotpos;
5884 	uint8_t sessionid[NFSX_V4SESSIONID];
5885 	int error;
5886 
5887 	error = nfsv4_getcbsession(clp, sepp);
5888 	if (error != 0)
5889 		return (error);
5890 	sep = *sepp;
5891 	(void)nfsv4_sequencelookup(NULL, &sep->sess_cbsess, &slotpos, &maxslot,
5892 	    &slotseq, sessionid);
5893 	KASSERT(maxslot >= 0, ("nfsv4_setcbsequence neg maxslot"));
5894 
5895 	/* Build the Sequence arguments. */
5896 	NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 5 * NFSX_UNSIGNED);
5897 	bcopy(sessionid, tl, NFSX_V4SESSIONID);
5898 	tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
5899 	nd->nd_slotseq = tl;
5900 	*tl++ = txdr_unsigned(slotseq);
5901 	*tl++ = txdr_unsigned(slotpos);
5902 	*tl++ = txdr_unsigned(maxslot);
5903 	if (dont_replycache == 0)
5904 		*tl++ = newnfs_true;
5905 	else
5906 		*tl++ = newnfs_false;
5907 	*tl = 0;			/* No referring call list, for now. */
5908 	nd->nd_flag |= ND_HASSEQUENCE;
5909 	return (0);
5910 }
5911 
5912 /*
5913  * Get a session for the callback.
5914  */
5915 static int
5916 nfsv4_getcbsession(struct nfsclient *clp, struct nfsdsession **sepp)
5917 {
5918 	struct nfsdsession *sep;
5919 
5920 	NFSLOCKSTATE();
5921 	LIST_FOREACH(sep, &clp->lc_session, sess_list) {
5922 		if ((sep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0)
5923 			break;
5924 	}
5925 	if (sep == NULL) {
5926 		NFSUNLOCKSTATE();
5927 		return (NFSERR_BADSESSION);
5928 	}
5929 	sep->sess_refcnt++;
5930 	*sepp = sep;
5931 	NFSUNLOCKSTATE();
5932 	return (0);
5933 }
5934 
5935