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